Archive

Archive for January, 2020

Exciting New Tools for Designers, January 2020

January 9th, 2020 No comments

We typically start the month with a roundup of new tools and resources for designers, but with the start of a new year (and new decade), we thought a roundup of things to help you get more organized would be appropriate.

Some of these tools have been around for a while with features you might not be using. Other tools are on the new side and offer great functionality. How many of these tools are part of your kit? Which ones will you resolve to use this year?

Here’s what you need to get organized this month and start 2020 off right.

Dropbox

Dropbox is one tool that’s hard to live without. Not only can you use it to manage files and share, you can also use it to run presentations directly with Zoom conferencing or in Slack. Free plans are enough to get started and upgraded plans provide greater storage capability for individuals or teams.

Working from multiple locations with desktop sync and sharing client files are features that make this tool something I use every day.

Feature you need to be using: Shared link expiration dates. When you share files via link, set an expiration date to ensure files aren’t hanging out with access indefinitely.

Slack

Slack is probably a tool that you are already using, but are you making the most of it? Channels, hashtags, and integrations are the key to ensuring that Slack works for you in the way you need it. Take the time to set these up for an efficient, and organized, workflow across multiple teams.

Feature you need to be using: Sync Slack and your Google Calendar for real-time away statuses that work for you.

Cloud Libraries

We all work from a variety of locations—home, work, on desktops and laptops—so cloud-based libraries are a must. Save common files in a location that you can access from anywhere.

Feature you need to be using: Adobe Creative Cloud comes with a place to save libraries, but you can save and connect library files from any cloud-based tool.

Trello

Trello is a free organization and collaboration tool for just about any project. Think of it as a giant project checklist that allows you (or other team members) to keep an eye on how anything from a website build to planning a trip. It works cross devices and isn’t hard to figure out.

Feature you need to be using: Workflow automatons with due date commands and rule-based triggers to make tedious processes happen on their own.

Google Keep

Google Keep is the notetaking app you always wanted. Take notes from any device—sync across all devices—and share or keep notes to yourself. You can take notes by typing, with photos or audio (and it will transcribe messages for you). The best part is this notes app is free and pretty much makes anything else you are using obsolete.

Feature you need to be using: Location, and time-based reminders help keep you on task just when you need it.

Grammarly

Grammarly saves time and effort by checking your messages, everything from documents to website content to emails or social media posts, as you type. Use it to avoid embarrassing mistakes in your writing.

Feature you need to be using: Emojis help you track the tone of your message so that it’s on point and audience-appropriate.

ClickUp

ClickUp takes all your other apps and merges them into a single location and dashboard for easy organization. You can use it to manage your own workspace (free) or collaborate with teams (paid plan). There are multiple views—I’m a big fan of the list option—and templates help jumpstart using the tool.

Feature you need to be using: Use the messages option to create tasks or comments. Boom!

Filing System

Nothing beats a solid filing system. The key benefit of a system is that you store files and folders in the same way every time, making it easier to find things later.

I keep folders first by year. Within annual folders are folders by client name. Then by project name. When projects are complete, I end up with two folders: WORKING and FINAL. Use the same format for naming files. (I use Client Name-Project-Year.)

Feature you need to be using: Date project files. Relying on “date modified” settings isn’t enough if you resave an old file by mistake.

Invoicely

Invoicely makes it easy to work as a freelance designer. The platform is made for sending invoices, managing clients, and allows you to accept online payments. It’s secure and offers a free plan (as well as a paid option).

Feature you need to be using: If you are trying to get organized, time tracking tools help you know just what an individual client costs. You can enter time, expense per client, and mileage so you can get a realistic picture of revenue by project.

HelloSign

HelloSign is for anyone dealing with documents that need signatures. Send and sign online with a platform that’s secure and easy for users to understand. Plus, you can sign items right from common tools such as Gmail or other G-Suite apps.

Feature you need to be using: Store all your signed documents in the interface so you can find them later. (HelloSign will also automatically send reminders if someone hasn’t signed a form.)

Traditional Planner + Online Calendar

Pair a paper planner with your online calendar to keep track of tasks (paper planner as a checklist) as well as events and appointments (online calendar). Daily deadlines are best managed when you can jot them down and check them off throughout the day. Plus, that note is right in front of you to stay focused.

Feature you need to be using: Try a weekly paper planner, tear off sheets, or a dry erase board for task management that doesn’t seem overwhelming.

WeTransfer

WeTransfer makes sending large files a lot easier. There’s nothing worse than a file getting lost in cyberspace because it’s too big for email. WeTransfer allows you to send and receive big files with just a click. (And you don’t have to have an account to download files.)

Feature you need to be using: Integrate WeTransfer with other tools such as Slack, Sketch or Chrome for direct sharing from wherever you are working.

JotForm

JotForm is the ultimate tool for creating any type of online form, from simple surveys to signups to payment collection or image uploads. The service has free and paid plans, depending on usage and everything is customizable, so forms can be branded with ease.

Feature you need to be using: PDF Templates are ready-made forms for everything from a simple invoice to contracts or photo waivers. Start with a PDF and tweak as you need. Plus, you can set it up to be filled out digitally and returned to you. This is a huge timesaver, and you can save custom forms in your account to use over and over again.

Featured image via Unsplash.

Source

Categories: Designing, Others Tags:

See what 15 of the Best WordPress Themes in 2020 Have to Offer

January 9th, 2020 No comments

There’s no need to continue to stress yourself out plowing through a host of themes in hopes of finding something that just might suit your immediate needs.

“Just might” is not a very good description to hang your hat on.

If you narrow your search down to 15 or so of the top WordPress themes going into 2020 you should easily find what you need. Better yet, we’ve already narrowed the search for you. Add the fact that WordPress will take care of the administrative features for you, and you should be good to go.

If you won’t settle for anything less than a pixel perfect, 100% responsive, SEO friendly, modern, flexible and WooCommerce ready theme, you’ll still be good to go.

We can prove it; read on to see for yourself.

  1. BeTheme – Responsive Multi-Purpose WordPress Theme

This premium multipurpose WordPress theme, the biggest of them all, is hard to beat in terms of its huge array of tools, features and options, performance, flexibility, and its level of support. Visit BeTheme’s website and you’ll be well into your second cup of coffee by the time you begin to have a good understanding of what this theme can help you accomplish.

  • The highlight is the selection of 500+ customizable, responsive pre-built websites. These professionally crafted design aids cover 30 industry sectors, all the major website types like portfolio, one-pager, etc., and a wide variety of business niches.

They also have functionality and UX features embedded right into them, plus they are customizable and responsive.

  • The popular Muffin Builder 3 page builder, with the WPBakery page builder as an option
  • A Layouts Configurator if you decide to build a page from scratch.
  • A Shortcode Generator and a large selection of shortcodes that, together with BeTheme’s other features, eliminates any need for coding.
  • A powerful Admin Panel that serves to give you all the flexibility you want.

“This theme is the best for WordPress, the layout and flexibility are perfect to develop a site.” – Joso970

Learn more about Be’s 40+ core features by clicking on the banner.

  1. Total Theme

This WordPress theme has been around a while. It has helped more than 41,000 users build premium websites, and it comes with more useful features than you’ll find in most themes of its type and purpose.

Total is and has

  • Drag and drop and extremely easy to use
  • Developer-friendly hooks, filters, and 450+ snippets
  • A Theme Customizer that allows you to quickly change site colors, widths, font characteristics, etc.
  • 100+ page builder elements and extra design modules, along with 500+advanced customizing and styling options

Total’s package includes the popular WPBakery page builder, 40+ pre-built demos, and a quick start demo importer, Revolution Slider and Layer Slider; and Total is WooCommerce ready.

Total is also compatible with most of the popular WordPress plugins. So, you won’t have to be burdened down with an excessive number of third-party plugins.

“I’ve been a loyal customer of Total theme for years. Support is impressively quick, useful and accurate. The theme will allow one to build virtually anything you want. AJ and his team are terrific, and there is no reason to buy any other theme.” – donnieweaver

  1. Avada

Avada has been the #1 selling theme over the past 6 years. There must be a reason – or several. It could be

  • a Dynamic Content System that gives users tremendous flexibility
  • Flawless WooCommerce integration including the capability to drag and drop product designs
  • 55+ pre-built websites to help you build and launch quickly – without coding

You can also import full or partial demos with Avada or use sections from several demos.

“There’s really NOTHING you can’t do with the Avada theme AND they have the best support team of any Theme out there – really!” – MamaSara

Click on the banner to learn more about this best-selling theme.

  1. Houzez – Highly Customizable Real Estate WordPress Theme

Asking a multipurpose theme to provide a solution when a specialty theme is really what is needed is asking too much. Houzez has all the features and functionality a real estate agent or agency is ever likely to need, including

  • property listings formatting options
  • advanced property search capabilities
  • a property management system

Plus, the Houzez theme can be customized to fit an agency’s business model.

“Awesome and very flexible theme and customer support is excellent.” – mardenvato

In need of a specialized theme for realtors? Look no further.

  1. TheGem – Creative Multi-Purpose High-Performance WordPress Theme

Some describe TheGem as having the most beautiful designs for WordPress. Others refer to it as being the ultimate WordPress toolbox for designers. In truth, both descriptions are true.

The package includes

  • 100+ pre-built, one-click installable websites plus 400+ trendy design templates
  • the powerful WPBakery page builder

a ready-to-launch fashion store

I love TheGem Creative Multi-Purpose High Performance Theme. I plan to utilize it for all of my clients. I’m getting some of them to change over as I update their websites.” – acreator7

The ultimate design toolbox is but a click away.

  1. Uncode – Creative Multiuse WordPress Theme

Agencies, bloggers, freelancers, and creatives can all benefit from choosing Uncode, as can businesses or anyone wanting to create a portfolio website, a magazine website, or any type of landing page.

Features include

  • a front-end editor on steroids
  • Adaptive image and grid systems
  • WooCommerce single product features

and more, but the star of the show has to be ThemeForest’s best-sellers showcase of user-created websites which tells a story of what this theme could do for you, why it claims 60K+ sales, and why it is a source of inspiration.

“Easy to use theme and customizable to ones need. I give 5 stars for theme support. Really happy!!” – rchakaipa

Click on the banner to visit the Uncode and its remarkable showcase of websites.

  1. Bridge

Rather than trying to list Bridge’s most likely benefactors, saying that this theme is perfect for just about anyone is more than sufficient. This best-selling creative theme’s features include

  • 420+ premade websites
  • open-ended customizability
  • huge collections of modules, design elements, sliders, and plugins including WooCommerce, as well as both the WPBakery and Elementor page builders
  • 5-star rated support

It should also be noted that Bridge serves a community of 120,000+ happy users.

“Very flexible, the demos are beautiful!” – rebecajobs

Click on the banner for a closer look.

  1. Brook – Multipurpose Creative WordPress Theme

The testimonial is typical and says it all. An abundance of cool features makes Brook a web designer’s dream. In the package, you’ll find a huge collection of premade templates, premium site-building plugins, shortcodes, and design elements. Also, Brook is

  • superfast loading
  • SEO optimized
  • easily customizable

As a bonus, there’s a library of support tutorials you can also view to find out more about Brook.

“COSTUMER SUPPORT 5++++++++++

Feature request 5+++++++++

Everything on highest level

This is first time I get this kind of experience.” – souldisco

Visit the site and check out a video tutorial or two.

  1. XStore | Responsive Multi-Purpose WooCommerce WordPress Theme

Could you use a ready-to-go shop to get an online business started? How about 80 of them? That’s what XStore brings to the table; and there’s more:

  • $300+ worth of premium plugins
  • a single product page builder
  • a powerful header builder
  • demos for a wide variety of products and retail items

In other words, everything you could wish for to get your show on the road.

“As a Graphic Designer, not a web designer, I base my purchases on quality and customer service. I’ve purchased XStore twice and they always have the best customer service if I have a question or problem. Also, the plugins they include for this theme are fantastic value.” – Chelsdevauld

Click on the banner to check out one or more of 80 stores.

  1. Typer – Amazing Theme with Multi Author Publishing Features

Typer may just be the ultimate WordPress theme for publishers in general and bloggers in particular. The 100% Gutenburg optimization provides powerful support for creating blog posts while the Elementor visual page builder enables Typer users to create attractive, professionally-design landing pages.

  • No coding knowledge is needed
  • Typer is optimized for speed + real lazy load images
  • unlimited Header style and unique page and post options

You can also expect to receive premium support should you require it.

“Theme is awesome! Exactly what I needed for my site! Definitely recommend this purchase.” – chriscurran

Click on the banner if a premier publishing theme is on your wish list.

  1. Pofo – Creative Portfolio, Blog and eCommerce WordPress Theme

As its name suggests, Pofo is an excellent choice for anyone in need of building an attention-getting and engaging online portfolio. After all, a good portfolio design is often a key factor contributing to a business’s success.

  • Pofo is blazing fast, fully responsive and Gutenberg compatible
  • This theme offers a wide selection of home and demo pages, design elements, and valuable and useful plugins

Features include the WPBakery page builder, Revolution Slider, and detailed online documentation.

“Pofo is beautiful in design, layout, UX/UI, and color scheme. It’s truly 5 stars. However, with such a great product without a great customer support, it can mean nothing because it won’t allow you to achieve what your needs are. My 5 stars go to customer service!” – KARCIS

Click on the banner to discover more about this multi-purpose theme.

  1. Schema

Schema is not your run-of-the-mill premium multipurpose theme. It has many if not most of the features of other premium themes along with one very significant difference: SEO functionality

  • Schema knows what search engines seek
  • Schema guides search engines through your site – content element by content element
  • Schema checks for clean code and other factors that can affect website rankings

Schema is also fully responsive, ultra-fast, and is compatible with multiple page builders.

“Gorgeous design, super-fast response to my question too. thank you for a wonderful theme :)” simonehow

If SEO is a pain in the neck for you, click on the banner for a solution.

  1. Leadinjection – WordPress Landing Page Theme

With Leadinjection, you can do something well that can be very tricky or even impossible with most WordPress themes. Leadinjection is a landing page theme that is uniquely capable of adding a landing page to an already up-and-running website.

Leadinjection is

  • WordPress Multisite Compatible
  • Conversion Focused
  • WPML and Translation Ready

This is a good tool to have if you have one or more websites to maintain.

This theme has some very cool features, and most importantly it is pretty well-documented and very well supported. The developers have been very helpful every time I’ve had a question. -frankdl98

Add Leadinjection to your web design toolkit.

  1. TheFox | Responsive Multi-Purpose WordPress Theme

It may or may not be a stretch to call TheFox the smartest of ThemeForest’s WordPress themes. But, it certainly has the essential features and elements to back up such a claim.

Maybe it’s because TheFox’s design takes into account the tiniest of details. Whatever the reason, this multi-purpose theme has a solid track record and is a good investment.

“I have been very impressed with TheFox theme. The design and customizability are great and very straight forward. The Customer support is top notch.” – bc hughes

  1. Hongo – Modern & Multipurpose WooCommerce WordPress Theme

Hongo’s new look makes it especially noteworthy, plus the package features plenty of demos, templates, and other creative design elements, WPBakery, one-click demo import, and custom shortcodes.

  • Out of the box premium eCommerce features included
  • Conversion optimised and modern looking product listing and product detail page styles
  • Hongo designs are awarded at many well known awards like awwwards.com, cssdesignawards.com and many others

“Simply the great designs and best theme for WooCommerce, loading fast, customisable and easy to use with the detailed documentation. Their support team is technically sound and very kind to guide wherever needed. We have bought some other themes from ThemeZaa now and they have never lets us down, thanks!” – diyaatps

So don’t wait and start selling your products with Hongo!

*****

The emphasis in this article is on multipurpose themes. It is what many designers, and especially beginners, tend to look for. We’ve included several more specialized themes, one of which serves a particular niche, and others that can be used for a variety of website types.

All 15 themes have many things in common such as excellent flexibility and performance, speed, ease of use, and a large and varied selection of design aids. What this means to you is that you really can’t make a poor choice and should have little difficulty in making the best one.

Please feel free to share this article with a friend or on social media. We’d love to hear about your shopping experience.

Read More at See what 15 of the Best WordPress Themes in 2020 Have to Offer

Categories: Designing, Others Tags:

“All these things are quite easy to do, they just need somebody to sit down and just go through the website”

January 8th, 2020 No comments

I saw a video posted on Twitter from Channel 5 News in the UK (I have no idea what the credibility of them is, it’s an ocean away from me) with anchor Claudia Liza asking Glen Turner and Kristina Barrick questions about website accessibility.

Apparently, they often post videos with captions, but this particular video doesn’t (ironically). So, I’ve transcribed it here as I found them pretty well-spoken.

Some people with disabilities say they are being shut out of online shopping because retailers don’t make allowances for them.@scope says half of people avoid it because a website or app was too hard to use.

Glen Turner gives @ClaudiaLizaTV some ways they could improve. pic.twitter.com/MLim0R4pNf

— Channel 5 News (@5_News) December 2, 2019

[Claudia Liza]: … you do have a visual impairment. How does that make it difficult for you to shop online?

[Glen Turner]: Well, I use various special features on my devices to shop online to make it easier. So, I enlarge the text, I’ll invert the colors to make the background dark so that I don’t have glare. I will zoom in on pictures, I will use speech to read things to me because it’s too difficult sometimes. But sometimes websites and apps aren’t designed in a way that is compatible with that. So sometimes the text will be poorly contrasted so you’ll have things like brown on black, or red on black, or yellow on white, something like that. Or the menu system won’t be very easy to navigate, or images won’t have descriptions for the visually impaired because images can have descriptions embedded that a speech reader will read back to them. So all these various factors make it difficult or impossible to shop on certain websites.

[Claudia Liza]: What do you need retailers to do? How do they need to change their technology on their websites and apps to make it easier?

It’s quite easy to do a lot of these things, really. Check the colors on your website. Make sure you’ve got light against dark and there is a very clear distinctive contrast. Make sure there are descriptions for the visually impaired. Make sure there are captions on videos for the hearing impaired. Make sure your menus are easy to navigate and make it easy to get around. All these things are quite easy to do, they just need somebody to sit down and just go through the website and check that it’s all right and consult disabled people as well. Ideally, you’ve got disabled people in your organization you employ, but consult the wider disabled community as well. There is loads of us online there is loads of us spread all over the country. There is 14 million of us you can talk to, so come and talk to us and say, “You know, is our website accessible for you? What can we do to improve it?” Then act on it when we give you our advice.

[Claudia Liza]: It makes sense doesn’t it, Glen? It sounds so simple. But Christina, it is a bit tricky for retailers. Why is that? What do other people with disabilities tell you?

So, we hear about content on websites being confusing in the way it’s written. There’s lots of information online about how to make an accessible website. There’s a global minimum legal standard called WCAG and there’s lot of resources online. Scope has their own which has loads of information on how to make your website accessible.

I think the problem really is generally lack of awareness. It doesn’t get spoken about a lot. I think that disabled consumers – there’s not a lot of places to complain. Sometimes they’ll go on a website and there isn’t even a way to contact that business to tell them that their website isn’t accessible. So what Scope is trying to do is raise the voices of disabled people. We have crowdsourced a lot of people’s feedback on where they experience inaccessible websites. We’re raising that profile and trying to get businesses to change.

[Claudia Liza]: So is it legal when retails aren’t making their websites accessible?

Yeah, so, under the Equality Act 2010, it’s not legal to create an inaccessible website, but what we’ve found is that government isn’t generally enforcing that as a law.

[Claudia Liza]: Glenn, do you feel confident that one day you’ll be able to buy whatever you want online?

I would certainly like to think that would be the case. As I say, you raise enough awareness and get the message out there and alert business to the fact that there is a huge consumer market among the disabled community, and we’ve got a 274 billion pound expenditure a year that we can give to them. Then if they are aware of that, then yeah, hopefully they will open their doors to us and let us spend our money with them.

The post “All these things are quite easy to do, they just need somebody to sit down and just go through the website” appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Multi-Thumb Sliders: General Case

January 8th, 2020 No comments

The first part of this two-part series detailed how we can get a two-thumb slider. Now we’ll look at a general multi-thumb case, but with a different and better technique for creating the fills in between the thumbs. And finally, we’ll dive into the how behind the styling a realistic 3D-looking slider and a flat one.

Article Series:

  1. Multi-Thumb Sliders: Particular Two-Thumb Case
  2. Multi-Thumb Sliders: General Case (This Post)

A better, more flexible approach

Let’s say that, on a wrapper pseudo-element that covers the same area as the range inputs, we stack left-to–right linear-gradient() layers corresponding to each thumb. Each gradient layer is fully opaque (i.e. the alpha is 1) from the track minimum up to the thumb’s mid-line, after which it’s fully transparent (i.e. the alpha is 0).

Note that the RGB values don’t matter because all we care about are the alpha values. I personally use the red (for the fully opaque part) and transparent keywords in the code because they do the job with the least amount of characters.

How do we compute the gradient stop positions where we go from fully opaque to fully transparent? Well, these positions are always situated between a thumb radius from the left edge and a thumb radius from the right edge, so they are within a range that’s equal to the useful width (the track width, minus the thumb diameter).

This means we first add a thumb radius.Then we compute the progress by dividing the difference between the current thumb’s position and the minimum to the difference (--dif) between the maximum and the minimum. This progress value is a number in the [0, 1] interval — that’s 0 when the current thumb position is at the slider’s minimum, and 1 when the current thumb position is at the slider’s maximum. To get where exactly along that useful width interval we are, we multiply this progress value with the useful width.

The position we’re after is the sum between these two length values: the thumb radius and how far we are across the useful width interval.

The demo below allows us to see how everything looks stacked up in the 2D view and how exactly the range inputs and the gradients on their parent’s pseudo-element get layered in the 3D view. It’s also interactive, so we can drag the slider thumbs and see how the corresponding fill (which is created by a gradient layer on its parent’s pseudo-element) changes.

See the Pen by thebabydino (@thebabydino) on CodePen.

The demo is best viewed in Chrome and Firefox.

Alright, but simply stacking these gradient layers doesn’t give us the result we’re after.

The solution here is to make these gradients mask layers and then XOR them (more precisely, in the case of CSS masks, this means to XOR their alphas).

If you need a refresher on how XOR works, here’s one: given two inputs, the output of this operation is 1 if the input values are different (one of them is 1 and the other one is 0) and 0 if the input values are identical (both of them are 0 or both of them are 1)

The truth table for the XOR operation looks as follows:

Inputs Output
A B
0 0 0
0 1 1
1 0 1
1 1 0

You can also play with it in the following interactive demo, where you can toggle the input values and see how the output changes:

See the Pen by thebabydino (@thebabydino) on CodePen.

In our case, the input values are the alphas of the gradient mask layers along the horizontal axis. XOR-ing multiple layers means doing so for the first two from the bottom, then XOR-ing the third from the bottom with the result of the previous XOR operation and so on. For our particular case of left-to-right gradients with an alpha equal to 1 up to a point (decided by the corresponding thumb value) and then 0, it looks as illustrated below (we start from the bottom and work our way up):

How we XOR the gradient layer alphas (Demo).

Where both layers from the bottom have an alpha of 1, the resulting layer we get after XOR-ing them has an alpha of 0. Where they have different alpha values, the resulting layer has an alpha of 1. Where they both have an alpha of 0, the resulting layer has an alpha of 0.

Moving up, we XOR the third layer with the resulting layer we got at the previous step. Where both these layers have the same alpha, the alpha of the layer that results from this second XOR operation is 0. Where they have different alphas, the resulting alpha is 1.

Similarly, we then XOR the fourth layer from the bottom with the layer resulting from the second stage XOR operation.

In terms of CSS, this means using the exclude value for the standard mask-composite and the xor value for the non-standard -webkit-mask-composite. (For a better understanding of mask compositing, check out the crash course.)

This technique gives us exactly the result we want while also allowing us to use a single pseudo-element for all the fills. It’s also a technique that works for any number of thumbs. Let’s see how we can put it into code!

In order to keep things fully flexible, we start by altering the Pug code such that it allows to add or remove a thumb and update everything else accordingly by simply adding or removing an item from an array of thumb objects, where every object contains a value and a label (which will be only for screen readers):

- let min = -50, max = 50;
- let thumbs = [
-   { val: -15, lbl: 'Value A' }, 
-   { val: 20, lbl: 'Value B' }, 
-   { val: -35, lbl: 'Value C' }, 
-   { val: 45, lbl: 'Value D' }
- ];
- let nv = thumbs.length;

.wrap(role='group' aria-labelledby='multi-lbl' 
      style=`${thumbs.map((c, i) => `--v${i}: ${c.val}`).join('; ')}; 
             --min: ${min}; --max: ${max}`)
  #multi-lbl Multi thumb slider:
    - for(let i = 0; i < nv; i++)
      label.sr-only(for=`v${i}`) #{thumbs[i].lbl}
      input(type='range' id=`v${i}` min=min value=thumbs[i].val max=max)
      output(for=`v${i}` style=`--c: var(--v${i})`)

In the particular case of these exact four values, the generated markup looks as follows:

<div class='wrap' role='group' aria-labelledby='multi-lbl' 
     style='--v0: -15; --v1: 20; --v2: -35; --v3: 45; --min: -50; --max: 50'>
  <div id='multi-lbl'>Multi thumb slider:</div>
  <label class='sr-only' for='v0'>Value A</label>
  <input type='range' id='v0' min='-50' value='-15' max='50'/>
  <output for='v0' style='--c: var(--v0)'></output>
  <label class='sr-only' for='v1'>Value B</label>
  <input type='range' id='v1' min='-50' value='20' max='50'/>
  <output for='v1' style='--c: var(--v1)'></output>
  <label class='sr-only' for='v2'>Value C</label>
  <input type='range' id='v2' min='-50' value='-35' max='50'/>
  <output for='v2' style='--c: var(--v2)'></output>
  <label class='sr-only' for='v3'>Value D</label>
  <input type='range' id='v3' min='-50' value='45' max='50'/>
  <output for='v3' style='--c: var(--v3)'></output>
</div>

We don’t need to add anything to the CSS or the JavaScript for this to give us a functional slider where the values get updated as we drag the sliders. However, having four elements while the wrapper’s grid still has two columns would break the layout. So, for now, we remove the row introduced for the elements, position these elements absolutely and only make them visible when the corresponding is focused. We also remove the remains of the previous solution that uses both pseudo-elements on the wrapper.

.wrap {
  /* same as before */
  grid-template-rows: max-content #{$h}; /* only 2 rows now */

  &::after {
    background: #95a;
    // content: ''; // don't display for now
    grid-column: 1/ span 2;
    grid-row: 3;
  }
}

input[type='range'] {
  /* same as before */
  grid-row: 2; /* last row is second row now */
}

output {
  color: transparent;
  position: absolute;
  right: 0;
	
  &::after {
    content: counter(c);
    counter-reset: c var(--c);
  }
}

We’ll be doing more to prettify the result later, but for now, here’s what we have:

See the Pen by thebabydino (@thebabydino) on CodePen.

Next, we need to get those thumb to thumb fills. We do this by generating the mask layers in the Pug and putting them in a --fill custom property on the wrapper.

//- same as before
- let layers = thumbs.map((c, i) => `linear-gradient(90deg, red calc(var(--r) + (var(--v${i}) - var(--min))/var(--dif)*var(--uw)), transparent 0)`);

.wrap(role='group' aria-labelledby='multi-lbl' 
  style=`${thumbs.map((c, i) => `--v${i}: ${c.val}`).join('; ')}; 
    --min: ${min}; --max: ${max};
    --fill: ${layers.join(', ')}`)
  // - same as before

The generated HTML for the particular case of four thumbs with these values can be seen below. Note that this gets altered automatically if we add or remove items from the initial array:

<div class='wrap' role='group' aria-labelledby='multi-lbl' 
  style='--v0: -15; --v1: 20; --v2: -35; --v3: 45; 
    --min: -50; --max: 50;
    --fill: 
      linear-gradient(90deg, 
        red calc(var(--r) + (var(--v0) - var(--min))/var(--dif)*var(--uw)), 
        transparent 0), 
      linear-gradient(90deg, 
        red calc(var(--r) + (var(--v1) - var(--min))/var(--dif)*var(--uw)), 
        transparent 0), 
      linear-gradient(90deg, 
        red calc(var(--r) + (var(--v2) - var(--min))/var(--dif)*var(--uw)), 
        transparent 0), 
      linear-gradient(90deg, 
        red calc(var(--r) + (var(--v3) - var(--min))/var(--dif)*var(--uw)), 
        transparent 0)'>
  <div id='multi-lbl'>Multi thumb slider:</div>
  <label class='sr-only' for='v0'>Value A</label>
  <input type='range' id='v0' min='-50' value='-15' max='50'/>
  <output for='v0' style='--c: var(--v0)'></output>
  <label class='sr-only' for='v1'>Value B</label>
  <input type='range' id='v1' min='-50' value='20' max='50'/>
  <output for='v1' style='--c: var(--v1)'></output>
  <label class='sr-only' for='v2'>Value C</label>
  <input type='range' id='v2' min='-50' value='-35' max='50'/>
  <output for='v2' style='--c: var(--v2)'></output>
  <label class='sr-only' for='v3'>Value D</label>
  <input type='range' id='v3' min='-50' value='45' max='50'/>
  <output for='v3' style='--c: var(--v3)'></output>
</div>

Note that this means we need to turn the Sass variables relating to dimensions into CSS variables and replace the Sass variables in the properties that use them:

.wrap {
  /* same as before */
  --w: 20em;
  --h: 4em;
  --d: calc(.5*var(--h));
  --r: calc(.5*var(--d));
  --uw: calc(var(--w) - var(--d));
  background: linear-gradient(0deg, #ccc var(--h), transparent 0);
  grid-template: max-content var(--h)/ var(--w);
  width: var(--w);
}

We set our mask Oo the wrapper’s ::after pseudo-element:

.wrap {
  /* same as before */
  
  &::after {
    content: '';
    background: #95a;
    grid-column: 1/ span 2;
    grid-row: 2;

    /* non-standard WebKit version */
    -webkit-mask: var(--fill);
    -webkit-mask-composite: xor;

    /* standard version, supported in Firefox */
    mask: var(--fill);
    mask-composite: exclude;
  }
}

Now we have exactly what we want and the really cool thing about this technique is that all we need to do to change the number of thumbs is add or remove thumb objects (with a value and a label for each) to the thumbs array in the Pug code — absolutely nothing else needs to change!

See the Pen by thebabydino (@thebabydino) on CodePen.

Prettifying tweaks

What we have so far is anything but a pretty sight. So let’s start fixing that!

Option #1: a realistic look

Let’s say we want to achieve the result below:

Screenshot. The track and fill are the same height as the thumbs. The track looks carved into the page, while the fill and the thumb have a convex look inside it.
The realistic look we’re after.

A first step would be to make the track the same height as the thumb and round the track ends. Up to this point, we’ve emulated the track with a background on the .wrap element. While it’s technically possible to emulate a track with rounded ends by using layered linear and radial gradients, it’s really not the best solution, especially when the wrapper still has a free pseudo-element (the ::before).

.wrap {
  /* same as before */
  --h: 2em;
  --d: var(--h);
  
  &::before, &::after {
    border-radius: var(--r);
    background: #ccc;
    content: '';
    grid-column: 1/ span 2;
    grid-row: 2;
  }
  
  &::after {
    background: #95a;

    /* non-standard WebKit version */
    -webkit-mask: var(--fill);
    -webkit-mask-composite: xor;

    /* standard version, supported in Firefox */
    mask: var(--fill);
    mask-composite: exclude;
  }
}

See the Pen by thebabydino (@thebabydino) on CodePen.

Using ::before to emulate the track opens up the possibility of getting a slightly 3D look:

<pre rel="SCSS"><code class="language-scss">.wrap {
  /* same as before */
  
  &::before, &::after {
    /* same as before */
    box-shadow: inset 0 2px 3px rgba(#000, .3);
  }
  
  &::after {
    /* same as before */
    background: 
      linear-gradient(rgba(#fff, .3), rgba(#000, .3))
      #95a;
  }
}

I’m by no means a designer, so those values could probably be tweaked for a better looking result, but we can already see a difference:

See the Pen by thebabydino (@thebabydino) on CodePen.

This leaves us with a really ugly thumb, so let’s fix that part as well!

We make use of the technique of layering multiple backgrounds with different background-clip (and background-origin) values.

@mixin thumb() {
  border: solid calc(.5*var(--r)) transparent;
  border-radius: 50%; /* make circular */
  box-sizing: border-box; /* different between Chrome & Firefox */
  /* box-sizing needed now that we have a non-zero border */
  background: 
    linear-gradient(rgba(#000, .15), rgba(#fff, .2)) content-box, 
    linear-gradient(rgba(#fff, .3), rgba(#000, .3)) border-box, 
    currentcolor;
  pointer-events: auto;
  width: var(--d); height: var(--d);
}

I’ve described this technique in a lot of detail in an older article. Make sure you check it out if you need a refresher!

The above bit of code would do close to nothing, however, if the currentcolor value is black (#000) which it is right now. Let’s fix that and also change the cursor on the thumbs to something more fitting:

input[type='range'] {
  /* same as before */
  color: #eee;
  cursor: grab;
  
  &:active { cursor: grabbing; }
}

The result is certainly more satisfying than before:

See the Pen by thebabydino (@thebabydino) on CodePen.

Something else that really bothers me is how close the label text is to the slider. We can fix this by introducing a grid-gap on the wrapper:

.wrap {
  /* same as before */
  grid-gap: .625em;
}

But the worst problem we still have are those absolutely positioned outputs in the top right corner. The best way to fix this is to introduce a third grid row for them and move them with the thumbs.

The position of the thumbs is computed in a similar manner to that of the sharp stops of the gradient layers we use for the fill mask.

Initially, we place the left edge of the outputs along the vertical line that’s a thumb radius --r away from the left edge of the slider. In order to middle align the outputs with this vertical line, we translate them back (to the left, in the negative direction of the x-axis, so we need a minus sign) by half of their width (50%, as percentage values in translate() functions are relative to the dimensions of the element the transform is applied to).

In order to move them with the thumbs, we subtract the minimum value (--min) from the current value of the corresponding thumb (--c), divide this difference by the difference (--dif) between the maximum value (--max) and the minimum value (--min). This gives us a progress value in the [0, 1] interval. We then multiply this value with the useful width (--uw), which describes the real range of motion.

.wrap {
  /* same as before */
  grid-template-rows: max-content var(--h) max-content;
}

output {
  background: currentcolor;
  border-radius: 5px;
  color: transparent;
  grid-column: 1;
  grid-row: 3;
  margin-left: var(--r);
  padding: 0 .375em;
  transform: translate(calc((var(--c) - var(--min))/var(--dif)*var(--uw) - 50%));
  width: max-content;
  
  &::after {
    color: #fff;
    content: counter(c);
    counter-reset: c var(--c);
  }
}

See the Pen by thebabydino (@thebabydino) on CodePen.

This looks much better at a first glance. However, a closer inspection reveals that we still have a bunch of problems.

The first one is that overflow: hidden cuts out a bit of the elements when we get to the track end.

In order to fix this, we must understand what exactly overflow: hidden does. It cuts out everything outside an element’s padding-box, as illustrated by the interactive demo below, where you can click the code to toggle the CSS declaration.

See the Pen by thebabydino (@thebabydino) on CodePen.

This means a quick fix for this issue is to add a big enough lateral padding on the wrapper .wrap.

padding: 0 2em;

We’re styling our multi-thumb slider in isolation here, but, in reality, it probably won’t be the only thing on a page, so, if spacing is limited, we can invert that lateral padding with a negative lateral margin.

If the nearby elements still have the default have position: static, the fact that we’ve relatively positioned the wrapper should make the outputs go on top of what they overlap, otherwise, tweaking the z-index on the .wrap should do it.

The bigger problem is that this technique we’ve used results in some really weird-looking overlaps when were dragging the thumbs.

Increasing the z-index when the is focused on the corresponding as well solves the particular problem of the overlaps:

input[type='range'] {
  &:focus {
    outline: solid 0 transparent;
		
    &, & + output {
      color: darkorange;
      z-index: 2;
    }
  }
}

However, it does nothing for the underlying issue and this becomes obvious when we change the background on the body, particularly if we change it to an image one, as this doesn’t allow the text to hide in it anymore:

See the Pen by thebabydino (@thebabydino) on CodePen.

This means we need to rethink how we hide the elements in the normal state and how we reveal them in a highlight state, such as :focus. We also want to do this without bloating our CSS.

The solution is to use the technique I described about a year ago in the “DRY Switching with CSS Variables” article: use a highlight --hl custom property where the value is 0 in the normal state and 1 in a highlight state (:focus). We also compute its negation (--nothl).

* {
  --hl: 0;
  --nothl: calc(1 - var(--hl));
  margin: 0;
  font: inherit
}

As it is, this does nothing yet. The trick is to make all properties that we want to change in between the two states depend on --hl and, if necessary, its negation (code>–nothl).

$hlc: #f90;

@mixin thumb() {
  /* same as before */
  background-color: $hlc;
}

input[type='range'] {
  /* same as before */
  filter: grayScale(var(--nothl));
  z-index: calc(1 + var(--hl));
  
  &:focus {
    outline: solid 0 transparent;
    
    &, & + output { --hl: 1; }
  }
}

output {
  /* same grid placement */
  margin-left: var(--r);
  max-width: max-content;
  transform: translate(calc((var(--c) - var(--min))/var(--dif)*var(--uw)));
	
  &::after {
    /* same as before */
    background: 
      linear-gradient(rgba(#fff, .3), rgba(#000, .3))
      $hlc;
    border-radius: 5px;
    display: block;
    padding: 0 .375em;
    transform: translate(-50%) scale(var(--hl));
  }
}

See the Pen by thebabydino (@thebabydino) on CodePen.

We’re almost there! We can also add transitions on state change:

$t: .3s;

input[type='range'] {
  /* same as before */
  transition: filter $t ease-out;
}

output::after {
  /* same as before */
  transition: transform $t ease-out;
}

See the Pen by thebabydino (@thebabydino) on CodePen.

A final improvement would be to grayscale() the fill if none of the thumbs are focused. We can do this by using :focus-within on our wrapper:

.wrap {
  &::after {
    /* same as before */
    filter: Grayscale(var(--nothl));
    transition: filter $t ease-out;
  }
	
  &:focus-within { --hl: 1; }
}

And that’s it!

See the Pen by thebabydino (@thebabydino) on CodePen.

Option #2: A flat look

Let’s see how we can get a flat design. For example:

Screenshot. All slider components are flat, no shadows or gradients. The track and fill are narrower than the thumbs and middle aligned with these. The track has a striped background. The thumbs are scaled down and reveal circular holes in the track around them in their unfocused state.
The flat look we’re after.

The first step is to remove the box shadows and gradients that give our previous demo a 3D look and make the track background a repeating gradient.:

See the Pen by thebabydino (@thebabydino) on CodePen.

The size change of the thumb on :focus can be controlled with a scaling transform with a factor that depends on the highlight switch variable (--hl).

@mixin thumb() {
  /* same as before */
  transform: scale(calc(1 - .5*var(--nothl)));
  transition: transform $t ease-out;
}

See the Pen by thebabydino (@thebabydino) on CodePen.

But what about the holes in the track around the thumbs?

The mask compositing technique is extremely useful here. This involves layering radial gradients to create discs at every thumb position and, after we’re done with them, invert (i.e. compositing with a fully opaque layer) the result to turn those discs into holes.

SVG illustration. Shows that XOR-ing a bunch of radial-gradient() layers gives us a layer with opaque discs and everything else transparent and when, we xor this resulting layer with a fully opaque one, this fully opaque layer acts as an inverter, turning the discs into transparent holes in an otherwise fully opaque layer.
How we XOR the gradient layer alphas (Demo).

This means altering the Pug code a bit so that we’re generating the list of radial gradients that create the discs corresponding to each thumb. In turn, we’ll invert those in the CSS:

//- same as before
- let tpos = thumbs.map((c, i) => `calc(var(--r) + (var(--v${i}) - var(--min))/var(--dif)*var(--uw))`);
- let fill = tpos.map(c => `linear-gradient(90deg, red ${c}, transparent 0)`);
- let hole = tpos.map(c => `radial-gradient(circle at ${c}, red var(--r), transparent 0)`)

.wrap(role='group' aria-labelledby='multi-lbl' 
  style=`${thumbs.map((c, i) => `--v${i}: ${c.val}`).join('; ')}; 
    --min: ${min}; --max: ${max};
    --fill: ${fill.join(', ')}; 
    --hole: ${hole.join(', ')}`)
  // -same wrapper content as before

This generates the following markup:

<div class='wrap' role='group' aria-labelledby='multi-lbl' 
  style='--v0: -15; --v1: 20; --v2: -35; --v3: 45; 
    --min: -50; --max: 50;
    --fill: 
      linear-gradient(90deg, 
        red calc(var(--r) + (var(--v0) - var(--min))/var(--dif)*var(--uw)), 
        transparent 0), 
      linear-gradient(90deg, 
        red calc(var(--r) + (var(--v1) - var(--min))/var(--dif)*var(--uw)), 
        transparent 0), 
       linear-gradient(90deg, 
         red calc(var(--r) + (var(--v2) - var(--min))/var(--dif)*var(--uw)), 
         transparent 0), 
       linear-gradient(90deg, 
         red calc(var(--r) + (var(--v3) - var(--min))/var(--dif)*var(--uw)), 
         transparent 0); 
     --hole: 
       radial-gradient(circle 
         at calc(var(--r) + (var(--v0) - var(--min))/var(--dif)*var(--uw)), 
         red var(--r), transparent 0), 
       radial-gradient(circle 
         at calc(var(--r) + (var(--v1) - var(--min))/var(--dif)*var(--uw)), 
         red var(--r), transparent 0), 
       radial-gradient(circle 
         at calc(var(--r) + (var(--v2) - var(--min))/var(--dif)*var(--uw)), 
         red var(--r), transparent 0), 
       radial-gradient(circle 
         at calc(var(--r) + (var(--v3) - var(--min))/var(--dif)*var(--uw)), 
         red var(--r), transparent 0)'>
  <!-- same content as before -->
</div>

In the CSS, we set a mask on both pseudo-elements and give a different value for each one. We also XOR the mask layers on them.

In the case of ::before, the mask is the list of radial-gradient() discs XOR-ed with a fully opaque layer (which acts as an inverter to turn the discs into circular holes). For ::after, it’s the list of fill linear-gradient() layers.

.wrap {
  /* same as before */
  
  &::before, &::after {
    content: '';
    /* same as before */
    
    --mask: linear-gradient(red, red), var(--hole);

    /* non-standard WebKit version */
    -webkit-mask: var(--mask);
    -webkit-mask-composite: xor;

    /* standard version, supported in Firefox */
    mask: var(--mask);
    mask-composite: exclude;
  }
	
  &::after {
    background: #95a;
    --mask: var(--fill);
  }
}

See the Pen by thebabydino (@thebabydino) on CodePen.

The final step is to adjust the track, fill height, and middle align them vertically within their grid cell (along with the thumbs):

.wrap {
  /* same as before */
  
  &::before, &::after {
    /* same as before */
    align-self: center;
    height: 6px;
  }
}

We now have our desired flat multi-thumb slider!

See the Pen by thebabydino (@thebabydino) on CodePen.

The post Multi-Thumb Sliders: General Case appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

The Auto-Flowing Powers of Grid’s Dense Keyword

January 8th, 2020 No comments

Let’s say we’re working on the homepage of a news website. You’re probably used to seeing some card-based content in a grid layout, right? Here’s a classic example, The New York Times:

Yeah, something like that.

There are going to be some cards/elements/boxes/whatever that need to take up more space than others. A featured article comes to mind.

CSS Grid would be ideal here because we’re working in two directions: rows and columns. Plus, it has this baked-in feature that automatically places items on the grid based on available space. If we were to simply define grid on the parent element, and nothing else, each child would be assigned equal spaces according to how much available space is available on both the columns and rows.

In other words, there’s no need to be strict or explicit in where we tell our grid to place items.

A newspaper site can really benefit from this. Maybe the number of articles on the page will vary. Maybe advertisements will be displayed in some situations but not in others. Even if the content is unpredictable, CSS Grid can make the layout predictable by flowing items automatically into place.

Having nine stories that perfectly fit would be great, but maybe we only have eight one day. Oh well, CSS Grid has us covered to make sure items flow into cells evenly.

Where things might get a little sticky is when we have items that span multiple rows or columns. Let’s go back to that featured article idea and stipulate that it should span the last two columns of a row.

.article--featured {
  grid-column: 2 / span 2;
}

We might have six articles one day because, again, our content is a little unpredictable.

<div class="articles">
  <div class="article">1</div>
  <div class="article">2</div>
  <div class="article">3</div>
  <div class="article--featured">4</div>
  <div class="article">5</div>
  <div class="article">6</div>
</div>

No worries! We expect Grid’s auto-placement feature to work around that featured article for us. But when we drop that featured article in there, here’s what we get:

See the Pen
wvBgGPE
by Geoff Graham (@geoffgraham)
on CodePen.

Hmm, that’s not what we had in mind. It would be so much better if the five articles flowed around the featured article.

What’s actually happening is that Grid takes the explicit placement of the featured article and places it where there is enough available space for it to take up the second and third columns after the articles preceding it in the source. That just so happens to be the second row and there just so happens to be an empty space in front of it because there are no other articles preceding it in the HTML. Grid places the featured article as its told and flows the rest of the items accordingly.

We can force Grid to ignore source order and flow the next available item around it, even if it is after the featured article in the HTML.

What’s the magic nugget with such powers? auto-placement: dense!

.articles {
  display: grid;
  grid-auto-placement: dense;
  grid-gap: 1em;
  grid-template-columns: repeat(3, 100px);
  grid-template-rows: repeat(3, 1fr);
}

See the Pen
grid-auto-flow: dense
by Geoff Graham (@geoffgraham)
on CodePen.

There we go! Now we can rest assured that our layout will stay in tact, regardless of how much content is thrown at the grid.

See the Pen
grid-auto-flow: dense
by Geoff Graham (@geoffgraham)
on CodePen.

The post The Auto-Flowing Powers of Grid’s Dense Keyword appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

4 Ways to Optimize Your Design for Google Images

January 8th, 2020 No comments

Google Image Search has millions of users.

In fact, nearly a quarter of all Google search queries return an image. Visual search on multiple online channels will also continue to grow.

Just look at how social media has shifted from text to images and videos.

Using more images is a very clear call to action for businesses looking to drive more traffic to their websites.

“Images play an important role in your website design,” Garry Grant, CEO of a global SEO services company explained. “They allow your business to capitalize on more keywords while increasing total online visibility.”

However, optimizing images is no simple endeavor. There are a few ins-and-outs you will need to know and leverage.

For instance, those free stock photos you can get from sites like Pexels or Pixabay may not drive the traffic you want from Google Images.

That doesn’t mean that you can’t use them, because they still serve a purpose. But designing your own images may have better Google Images results.

Let’s take a closer look at a few ways to optimize your design for Google Images.

1. Image Filenames Are Important

Image optimization actually begins before you even upload an image to your website during the site design process.

This is where adding a strong filename to your image makes an impact on your Google Images visibility.

The image itself, or text within the image is not read by Google crawlers (as far as we SEO professionals know). This means you want to give Google as much information as possible using the image filename.

To optimize this process, you want to think like a user. What would you type into the Google search bar to find your image.

This includes keywords, action happening in the image itself, and more.

For example, if it is a construction worker at a job site, your image filename could be this: commercial-construction-worker-job-site-inspection.

2. Optimizing Images During Website Design

With a strong filename, you are ready to upload the image to your website during the design process. This is an essential point when it comes to optimizing design for Google Images.

If you are using a CMS like WordPress, you will notice a number of image attributes you can enter once you upload an image. These include title, alt text, and description.

All of these are important to optimizing website design for Google Images, but alt text, also known as alt tag, remains the most valuable for SEO.

The alt text gives you the opportunity to describe the image in more detail. You can put the same text as your image filename, or you can do a bit of variation. It is up to you.

Just be sure to fill in that alt text to get maximum search visibility for your website images.

3. Ensure Website Images Are Compressed

This is a very important way to optimize your design for Google Images. You can have the right filename, perfect alt text, but if your image is slow to load, it can do more damage to your website design than good.

For example, if you upload an original design image that is 4000px, it will surely increase the load time for the page that image is on.

Google will also flag it and not show the image in Google Image Search results.

How do you ensure this doesn’t happen during your site design process? First, you want to upload an image that is the size you need. Not larger. Then you want to compress it.

You can use WordPress plugins like Smush to compress your image and optimize it.

4. Add Top Images To Your Website’s Sitemap

This way to optimize your design for Google Images is a lesser-known tactic. You may have already indexed the pages of your website, but what about the images?

Image sitemaps work the same way as page indexing, only they highlight the images you want Google to focus on.

For instance, a few of your homepage images are probably top on your list, so you will index them along with a few other images from other pages using an image sitemap.

You will only want to index your top images, because doing all is not going to have a major impact on your Google Image Search results.

Wrapping Up . . .

The above ways to optimize your design for Google Images is not the be-all, end-all by any means. However, the above are a quick roadmap to optimizing your site’s images for maximum effect.

Pay close attention to filenames, alt text, and image compression, as these are what many SEOs believe Google looks for. Do you have an image optimization tactic?

Read More at 4 Ways to Optimize Your Design for Google Images

Categories: Designing, Others Tags:

The Split Personality Of Brutalist Web Development

January 8th, 2020 No comments
Desktop homepage of Bloomber.com

The Split Personality Of Brutalist Web Development

The Split Personality Of Brutalist Web Development

Frederick O’Brien

2020-01-08T11:00:00+00:002020-01-09T05:36:13+00:00

Of all the design trends to hit the Internet in recent years, brutalism is surely the most eye-catching, and the most poorly defined. A variety of major brands have embraced ‘brutalist’ aesthetics online. There are even directories for those interested in seeing a selection of them in one place. The style has well and truly entered the mainstream.

Desktop homepage of Bloomber.com

Bloomberg.com‘s stark, no-nonsense design went live in 2016 and was refined in 2018. It is often touted as a leading example of brutalism’s growth online. (Large preview)

Indeed, brutalist web design has grown so quickly that there does not seem to be a clear consensus on what the style actually is. To some it means practicality, to others audacity. Much like the architecture it takes its name from, brutalist web development has become two competing philosophies in one. Neither is necessarily ‘right’, but knowing the difference is important. It may even be sensible to start calling them different things.

A Brief(ish) History Of Brutalism

Before we get ahead of ourselves, let’s recap the term ‘brutalist’ — where it came from and what it means. Brutalism is a style of architecture that took off after World War II, reaching its peak in the ‘50s and ‘60s. Championing simple, geometric designs and bared building materials, the trend was in large part a reaction against the ornate, over-designed structures of preceding decades.

The name comes from béton brut, which is French for raw or rough concrete. Concrete is a common material for brutalist structures, lending itself as it does to the style’s no-frills approach. Other materials can be and are used, but concrete is especially common. Whatever structures are made of, embellishments are deemed unnecessary. The form and the materials are enough.

The United Kingdom, with its fondness for grey, drab things, particularly took to the style. Notable examples of brutalist architecture here include the Royal National Theatre, the Barbican Estate, and Balfron Tower. It has proven especially popular for public buildings — libraries, theatres, universities, housing estates, and so on.

 The Royal National Theatre in London

The National Theatre in London. Designed by Denys Lasdun and opened in 1976, it is a textbook example of brutalist architecture. It is both one of the most hated and most loved buildings in Britain. Photograph by Henry Hemming. (Large preview)

Although there is not a catch-all definition that everyone agrees on, deference is often paid to English architectural critic Rayner Barnam, whose 1955 essay ‘On the New Brutalism’ attempted to outline the core ideas of the style. In anticipation of those of you who would not read the whole thing, Barnham boiled the philosophy down to the following:

In the last resort what characterizes the New Brutalism in architecture as in painting is precisely its brutality, its je-m’ en-foutisme, its bloody-mindedness.

Loosely translated, je-m’ en-foutisme translates as ‘don’t give a damn attitude. To be sure, brutalist buildings are unconcerned about conventional standards of beauty. They are also rather divisive. Where some gush over their firm, utilitarian character, others decry ugliness, impersonality, and, well, brutality.

Love it or hate it, brutalist architecture celebrates rawness. Indeed, Barnam opened his essay with a quote by Swiss-French architect Le Corbusier: “Architecture is the establishing of moving relationships with raw materials.” Le Corbusier’s Unité d’habitation housing designs inspired a generation of brutalist architects.

Balconies at La Maison du Fada in Marseille

Balconies at La Maison du Fada in Marseille, France. Designed by Le Corbusier and completed in 1952, it was a pioneering example of brutalist residential design. Photograph by Jean-Pierre Dalbéra. (Large preview)

So in short, brutalist architecture not only reduces construction to its fundamental materials, it finds beauty in that simplicity. Critics say it’s a bit in your face, a bit impersonal, a bit totalitarian even. The dual meaning of ‘raw’ and ‘brutal’ has clouded the definition, but as a rule, the goal is rawness and the result is perceived by some as brutal.

The style has waned in popularity since its postwar heyday, but it endures as one of the most distinctive around. A good few have attained listed status, and I for one am glad they have. A city of brutalist buildings would be a bit much, but a city without any is poorer for it.

Further Reading

Practicality Or Audacity?

So what’s all this got to do with web development? The philosophy, mainly, and the way it has splintered. Brutalism has found new life online, especially in the last three or four years. A slew of sites have taken on the brutalist moniker, and with the trend’s rise have come accompanying aw(ww)ards, articles, and directories.

Browsing through these things you may well get the impression that not everyone is talking about the same thing. That’s because they aren’t. In the world of web development, ‘brutalist’ has grown to encompass a variety of styles. It’s a disservice to designers to keep lumping together such different approaches. I have separated web brutalism into two types below, but as we shall see even that may not be enough.

Type One: l’Internet Brut

The first type of brutalist web design has much more in common with its architectural forebears. Think of it as l’Internet brut, where the raw materials are HTML and, to a lesser extent, CSS. The backgrounds are light, the text is black, and the hyperlinks are blue. There’s some wriggle room, but that’s the gist of it. No faffing about. Short of displaying actual code you couldn’t get much rougher.

The first ever website

In the beginning was the Style, and the Style was with Brutalism, and the Style was Brutalism. (Large preview)

There are countless examples of this style, big and small. The first ever website is an inadvertent disciple, while more recently Brutalist Web Design by programmer David Bryant Copeland puts forward a lovely little manifesto for the style.

Going up in the world, other websites with strong brutalist streaks include:

Although the raw materials of these sites are very similar, they don’t all look the same. They are shaped around their content and purpose. Like their architectural cousins, there’s actually a huge variety in form.

Craigslist's London homepage as it appears in 2020

A proper l’Internet brut website. It even has grey! (Large preview)

As you can see with the Craigslist homepage above, there is very little in the way of excess, and possibly even less in the way of style. It’s barely changed in 20(!) years, because it hasn’t needed to. Take a look at the code and even a novice like me can follow how the pages are put together. You don’t have to guess how it’s built because it’s all right there in front of you.

With sites like this you’ll often notice an overlap with the ‘publicly minded’ leaning on a lot of these websites — marketplaces, forums, encyclopedias. It’s oddly appropriate to see a site like Wikipedia take on the digital form of, say, Robin Hood Gardens. Bloomberg has plenty of company in the news space as well. Papers like The New York Times and The Washington Post have embraced similarly blunt, functional designs in recent years. News design has always had a strong brutalist streak.

Desktop homepage of The Washington Post website

The Washington Post’s revamped website rolled out in 2015. Newspaper designer Mario Garcia praised it at the time for ‘avoiding clutter and crowdedness.’ (Large preview)

It bears mentioning here that several of the sites used as examples here didn’t set out to be brutalist. Much like Villa Göth, which is widely considered the source of the term brutalism, they set out to be practical and simple. They were adopted, so to speak. Their success is what inspired (and continues to inspire) architects and developers alike. They’re so unconcerned about appearances that they became shining examples of brutalist design without even realizing it!

Sites in this vein don’t always scream beauty, but there is an elegance to their functionality. They are unconcerned and unpretentious, shaped for their purpose using the raw elements of the web. (Pun intended.)

Type Two: l’Internet Fou

This is the split. Right here. Those of you with even a passing interest in web design trends will know what we’ve looked at so far fails to account for a huge number of ‘brutalist’ sites. As Vitaly Friedman noted in Smashing Book 6:

Brutalism in architecture is characterized by unconcerned aesthetics, not intentionally broken aesthetics. When applied to web design, this style often goes along with deliberately broken design conventions and guiding principles.

The rise of ‘brutalist’ design over the last few years has had a lot more to do with brutalness than with rawness. This is the madder world, at times bordering on anarchy. Here design conventions are subverted and usability is an afterthought — and that’s not when it’s being actively sabotaged. These are the sites that prompt articles titled ‘Style Over Substance’, and for The Washington Post to sum up the style as ‘intentionally ugly.’

Desktop homepage of art magazine Toiletpaper

The homepage of artists’ magazine Toiletpaper. (Large preview)

Desktop homepage of self-described brutalist website JI SOO EOM

JI SOO EOM, another site found in the Brutalist Websites directory. (Large preview)

In the suitably migraine-inducing article ‘Brutalism: BrutAl wEbsIteS for mOdern dAy webMAsTeRS’, Awwwards describes this second strain as follows:

Brutalism in web design laughs in the face of rationalism and functionality, in the world of design it can be defined as freestyle, ugly, irreverent, raw, and superficially decorative, etc.

I hope it isn’t controversial to say that this is an altogether different approach to type one. At a stretch, you might argue that this approach is more the domain of artists and graphic designers, and that art is, therefore, the rawest form their websites can take, but that would be a stretch. There’s no question brutalist architecture can drift into ‘statement’ territory, but that’s not its natural realm.

The Brutalist Websites directory suggests, ‘Brutalism [online] can be seen as a reaction by a younger generation to the lightness, optimism, and frivolity of today’s web design.’ There are shades of the founding brutalist ethos in this, but it is more irreverent and subversive. They can be very beautiful in their own way, but also cut from a completely different cloth from the Craigslists of this world.

This Town Ain’t Big Enough For The Two Of Us

So there you have it. When brutalist web design isn’t going all in on rationalism and functionality, it’s laughing in the face of rationalism and functionality. All clear?

The term has grown to encompass approaches that are in many senses at odds with each other. Indeed, Pascal Deville, who founded the Brutalist Websites directory after coining the term in 2014, thinks the style has splintered into three micro-stylistics:

  1. Purists,
  2. UX minimalists,
  3. Anti-ists (or artists).

Having vetted hundreds of submissions over the years, he’d know better than just about anyone else. He says:

The purists reference strongly to the architectural characteristics of Web Brutalism, such as the concept of ‘truth to materials’ and the use of the purest markup elements available. The UX minimalists, in contrast, see efficiency and performance as the main driver of Web Brutalism and even believe that the radical limitation of possibilities can boost conversions. The ‘anti-ists’ or artists see web design as an (still) undervalued form of art and don’t show much respect the status quo and mostly get bad press.

What is a ‘proper’ brutalist website? To an extent, the answer depends on the context. If a website belongs to an artist then something brash may be more appropriate than something unconcerned. Generally speaking, though, it seems to me that the sensibilities of the ‘anti-ist’ type are actually much closer to something like Dadaism, with all its absurdity and mirth and mess, or the avant-garde leanings of Expressionism.

Small Dada Evening by Kurt Schwitters and Theo van Doesburg

Small Dada Evening by Kurt Schwitters and Theo van Doesburg. (Large preview)

Typical Vertical Mess as Depiction of the Dada Baargeld by Johannes Theodor Baargeld

Typical Vertical Mess as Depiction of the Dada Baargeld by Johannes Theodor Baargeld. Which branch of ‘brutalist’ web design do these look more like to you? (Large preview)

I don’t want this to come across as a game of semantics, where different styles are filed away neatly into little boxes. What I am more concerned with is highlighting different approaches so that each may be given the space needed to flourish. As Deville acknowledges, the creative potential of the web is still being explored. ‘It’s a new form of art and I’m very happy to experience first hand,’ he says. ‘It’s happening now.’

This has practical consequences as well. Whether you’re a developer talking to a client or a client talking to a developer, it pays to be clear which version of brutalist web design you’re on about. If you’re a real champ you’ll naturally refer them to this article. Otherwise, visual examples like the one below are likely your best bet for getting to the point.

Example to two different brutalist website styles

They’re both ‘brutalist’ so be sure what you’re asking for. The design on the left is a project by Constantin Grosnov. (Large preview)

Beyond that, maybe we should start giving different styles different names. I appreciate this would be rather inconvenient to a lot of people. Domains have been bought, awards awarded, and articles written, but going forward the label seems too restrictive. It can no longer contain so many approaches. If nothing else, the split personality of brutalist web development shows how much terrain remains to be explored in web design.

There are countless schools of art — Brutalism, Expressionism, Romanticism, Art Deco, Futurism, Dadaism, Impressionism, absurdism, modernism, minimalism, and on and on and on. They find form through paintings, buildings, literature… why not websites? As the links below show, I’m not alone in asking this. With every new development style, ‘anti-mainstream’ becomes less adequate for describing what designers are doing. They are starting to explore the philosophy of web design in ways that haven’t been done before.

The ‘Dadaist’ strain of brutalist web design has one thing absolutely right: the scope for what a website can be is far, far too narrow. The web is an infinite sandbox, and embracing the breadth of possibilities within it can only be a good thing. That starts with expanding our vocabulary.

(ra, yk, il)
Categories: Others Tags:

Take Off With Aviationstack’s Real-Time Flight API

January 8th, 2020 No comments

In our increasingly global world, people travel by airplane…a lot. With rapid turnaround times, unpredictable weather, and unexpected delays, airlines both domestic and international frequently adjust their flight schedules to keep us moving.

If you’re building a website, a progressive web app, or even a native app that involves any kind of travel, the last thing you want to do is give users out-of-date information, and when it comes to air travel, information is out of date almost as soon as its published. Turbulence en route to Bangkok, can have a devastating impact on queues in Denver. A reliable flight tracker should be one of the first must-haves on your feature list.

aviationstack is an incredibly powerful API that delivers comprehensive data about flights worldwide

Of course, any flight tracker is only as useful as the data that powers it. The minimum standard is access to a dataset that covers the information you need, reports data accurately, and boasts a solid uptime.

For those reasons, if you’re looking to introduce flight data to your site, then one of the best ways to go about it, is integrating with aviationstack.

aviationstack is an incredibly powerful API that delivers comprehensive data about flights worldwide, in a simple-to-use format.

Why Track Flights

Let’s say you’re building a ride-booking app, you absolutely want to be able to track flights in order to minimise disruption, coordinate with drivers right across the fleet, and maximise your profits. Or imagine you’re building a website for a train operator, wouldn’t it be nice to let passengers know whether they’re going to make their connecting flight. And of course, if you’re operating an airline it’s common sense that your users will benefit from this kind of rich data.

But companies that service airline customers aren’t the only ones that benefit from tracking airplanes. If you’re running any kind of business that people may travel to, whether that’s a hotel in Madrid, or a tech conference in Las Vegas, showing people their flight options is one way to remove friction when potential attendees are deciding whether to purchase a ticket.

Sometimes, people need to travel at a moment’s notice, and on unfamiliar routes. It may be that there are unexpectedly great waves off the coast of Big Sur; it might be that a bird, previously thought extinct has been spotted in Iceland; it might be that you’ve accidentally left your son Kevin at home in Chicago while you flew to Paris for the holidays. Whatever niche-interest your site or app caters to, if travel’s involved, then a flight tracker is essential.

Why Use aviationstack

If you’re comparing flight data APIs, then here are a few of the reasons we think aviationstack deserves to be at the top of your shortlist:

more than 13,000 airlines are represented across over 10,000 airports

Firstly, aviationstack’s data is amongst the most extensive available, because it’s drawn from high-quality sources. Using aviationstack you can easily look up flights across airports, cities, and countries; you can check historical flight data; you can even check live flights in real-time. The API covers over 9,000 cities in more than 250 countries; over 19,000 airplanes are divided into more than 300 different types; more than 13,000 airlines are represented across over 10,000 airports. For comprehensive data, aviationstack is hard to beat.

Secondly, aviationstack’s data is accurate to the minute. Many of us get a little anxious when we travel, not least when we’re rushing to catch a connecting flight. When your app or site is providing advice and information to potentially fraught customers, accurate information is invaluable, and can often transform a stressful situation into an exceptional user experience that wins you a loyal customer for life.

Thirdly, aviationstack is built on an incredibly reliable infrastructure. It’s owned and operated by apilayer, one of the best-known names in APIs, which means you can be confident that the API won’t buckle under the pressure. The API is incredibly simple to access, with code examples provided in PHP, Python, Go, Ruby, Nodejs, and even jQuery. It’s so simple that even novice front-end coders will get it up and running quickly, without any difficulty.

Last, and by no means least, aviationstack offers an entirely free plan that grants you 500 requests to the API per month, with full aviation, and real-time flight data. Which means you can try it out with zero risk. Once you’re happy, subscriptions start from just $39.99 (billed annually) and you can cancel at any time.

Head over to aviationstack.com today to see the API in action, and claim your free API key.

[– This is a sponsored post on behald of aviationstack –]

Source

Categories: Designing, Others Tags:

The Ultimate Guide to Dark Mode for Email Marketers

January 7th, 2020 No comments

On the regular web (I suppose) we handle “dark mode” with the CSS prefers-color-scheme media query. But, and to nobody’s surprise, it’s way weirder in the land of HTML email. The weirdness is that across different email clients, they handle the dark mode thing differently, starting with the fact that the email client itself might have its own toggle for dark mode.

Say that toggle has dark mode activated. There are three things that might happen:

  1. The UI of the app goes dark mode, but it leaves the email alone (e.g. Apple Mail).
  2. It tries to apply dark mode to your emails as well, but only when it detects areas that are light. Those areas become dark while leaving dark areas alone (e.g. Outlook.com).
  3. It goes full-bore and force-inverts email colors (e.g. Gmail app on iOS 13).

That last one is wacky-town. As Alice Li says:

This is the most invasive color scheme: it not only inverts the areas with light backgrounds but impacts dark backgrounds as well. So if you already designed your emails to have a dark theme, this scheme will ironically force them to become light.
Emphasis hers.

Direct Link to ArticlePermalink

The post The Ultimate Guide to Dark Mode for Email Marketers appeared first on CSS-Tricks.

Categories: Designing, Others Tags:

Multi-Thumb Sliders: Particular Two-Thumb Case

January 7th, 2020 No comments
Animated gif. Chrome only moves the thumb within the left and right limits of the track's content-box.

This is a concept I first came across a few years back when Lea Verou wrote an article on it. Multi-range sliders have sadly been removed from the spec since, but something else that has happened in the meanwhile is that CSS got better — and so have I, so I recently decided to make my own 2019 version.

In this two-part article, we’ll go through the how, step-by-step, first building an example with two thumbs, then identify the issues with it. We’ll solve those issues, first for the two-thumb case then, in part two, come up with a better solution for the multi-thumb case.

Note how the thumbs can pass each other and we can have any possible order, with the fills in between the thumbs adapting accordingly. Surprisingly, the entire thing is going to require extremely little JavaScript.

Article Series:

  1. Multi-Thumb Sliders: Particular Two-Thumb Case (This Post)
  2. Multi-Thumb Sliders: General Case (Coming Tomorrow!)

Basic structure

We need two range inputs inside a wrapper. They both have the same minimum and maximum value (this is very important because nothing is going to work properly otherwise), which we set as custom properties on the wrapper (--min and --max). We also set their values as custom properties (--a and --b).

- let min = -50, max = 50
- let a = -30, b = 20;

.wrap(style=`--a: ${a}; --b: ${b}; --min: ${min}; --max: ${max}`)
  input#a(type='range' min=min value=a max=max)
  input#b(type='range' min=min value=b max=max)

This generates the following markup:

<div class='wrap' style='--a: -30; --b: 20; --min: -50; --max: 50'>
  <input id='a' type='range' min='-50' value='-30' max='50'/>
  <input id='b' type='range' min='-50' value='20' max='50'/>
</div>

Accessibility considerations

We have two range inputs and they should probably each have a , but we want our multi-thumb slider to have a single label. How do we solve this issue? We can make the wrapper a

, use its

to describe the entire multi-thumb slider, and have a that’s only visible to screen readers for each of our range inputs. (Thanks to Zoltan for this great suggestion.)

But what if we want to have a flex or grid layout on our wrapper? That’s something we probably want, as the only other option is absolute positioning and that comes with its own set of issues. Then we run into a Chromium issue where

cannot be a flex or grid container.

To go around this, we use the following ARIA equivalent (which I picked up from this post by Steve Faulkner):

- let min = -50, max = 50
- let a = -30, b = 20;

.wrap(role='group' aria-labelledby='multi-lbl' style=`--a: ${a}; --b: ${b}; --min: ${min}; --max: ${max}`)
  #multi-lbl Multi thumb slider:
  label.sr-only(for='a') Value A:
  input#a(type='range' min=min value=a max=max)
  label.sr-only(for='b') Value B:
  input#b(type='range' min=min value=b max=max)

The generated markup is now:

<div class='wrap' role='group' aria-labelledby='multi-lbl' style='--a: -30; --b: 20; --min: -50; --max: 50'>
  <div id='multi-lbl'>Multi thumb slider:</div>
  <label class='sr-only' for='a'>Value A:</label>
  <input id='a' type='range' min='-50' value='-30' max='50'/>
  <label class='sr-only' for='b'>Value B:</label>
  <input id='b' type='range' min='-50' value='20' max='50'/>
</div>

If we set an aria-label or an aria-labelledby attribute on an element, we also need to give it a role.

Basic styling

We make the wrapper a middle-aligned grid with two rows and one column. The bottom grid cell gets the dimensions we want for the slider, while the top one gets the same width as the slider, but can adjust its height according to the group label’s content.

$w: 20em;
$h: 1em;

.wrap {
  display: grid;
  grid-template-rows: max-content $h;
  margin: 1em auto;
  width: $w;
}

To visually hide the elements, we absolutely position them and clip them to nothing:

.wrap {
  // same as before
  overflow: hidden; // in case <label> elements overflow
  position: relative;
}

.sr-only {
  position: absolute;
  clip-path: inset(50%);
}

Some people might shriek about clip-path support, like how using it cuts out pre-Chromium Edge and Internet Explorer, but it doesn’t matter in this particular case! We’re getting to the why behind that in a short bit.

We place the sliders, one on top of the other, in the bottom grid cell:

input[type='range'] {
  grid-column: 1;
  grid-row: 2;
}

See the Pen by thebabydino (@thebabydino) on CodePen.

We can already notice a problem however: not only does the top slider track show up above the thumb of the bottom one, but the top slider makes it impossible for us to even click and interact with the bottom one using a mouse or touch.

In order to fix this, we remove any track backgrounds and borders and highlight the track area by setting a background on the wrapper instead. We also set pointer-events: none on the actual elements and then revert to auto on their thumbs.

@mixin track() {
  background: none; /* get rid of Firefox track background */
  height: 100%;
  width: 100%;
}

@mixin thumb() {
  background: currentcolor;
  border: none; /* get rid of Firefox thumb border */
  border-radius: 0; /* get rid of Firefox corner rounding */
  pointer-events: auto; /* catch clicks */
  width: $h; height: $h;
}

.wrap {
  /* same as before */
  background: /* emulate track with wrapper background */ 
    linear-gradient(0deg, #ccc $h, transparent 0);
}

input[type='range'] {
  &::-webkit-slider-runnable-track, 
  &::-webkit-slider-thumb, & { -webkit-appearance: none; }
  
  /* same as before */
  background: none; /* get rid of white Chrome background */
  color: #000;
  font: inherit; /* fix too small font-size in both Chrome & Firefox */
  margin: 0;
  pointer-events: none; /* let clicks pass through */
  
  &::-webkit-slider-runnable-track { @include track; }
  &::-moz-range-track { @include track; }
  
  &::-webkit-slider-thumb { @include thumb; }
  &::-moz-range-thumb { @include thumb; }
}

Note that we’ve set a few more styles on the input itself as well as on the track and thumb in order to make the look consistent across the browsers that support letting clicks pass through the actual input elements and their tracks, while allowing them on the thumbs. This excludes pre-Chromium Edge and IE, which is why we haven’t included the -ms- prefix — there’s no point styling something that wouldn’t be functional in these browsers anyway. This is also why we can use clip-path to hide the elements.

If you’d like to know more about default browser styles in order to understand what’s necessary to override here, you can check out this article where I take an in-depth look at range inputs (and where I also detail the reasoning behind using mixins here).

See the Pen by thebabydino (@thebabydino) on CodePen.

Alright, we now have something that looks functional. But in order to really make it functional, we need to move on to the JavaScript!

Functionality

The JavaScript is pretty straightforward. We need to update the custom properties we’ve set on the wrapper. (For an actual use case, they’d be set higher up in the DOM so that they’re also inherited by the elements whose styles that depend on them.)

addEventListener('input', e => {
  let _t = e.target;
  _t.parentNode.style.setProperty(`--${_t.id}`, +_t.value)
}, false);

See the Pen by thebabydino (@thebabydino) on CodePen.

However, unless we bring up DevTools to see that the values of those two custom properties really change in the style attribute of the wrapper .wrap, it’s not really obvious that this does anything. So let’s do something about that!

Showing values

Something we can do to make it obvious that dragging the thumbs actually changes something is to display the current values. In order to do this, we use an output element for each input:

- let min = -50, max = 50
- let a = -30, b = 20;

.wrap(role='group' aria-labelledby='multi-lbl' style=`--a: ${a}; --b: ${b}; --min: ${min}; --max: ${max}`)
  #multi-lbl Multi thumb slider:
  label.sr-only(for='a') Value A:
  input#a(type='range' min=min value=a max=max)
  output(for='a' style='--c: var(--a)')
  label.sr-only(for='b') Value B:
  input#b(type='range' min=min value=b max=max)
  output(for='b' style='--c: var(--b)')

The resulting HTML looks as follows:

<div class='wrap' role='group' aria-labelledby='multi-lbl' style='--a: -30; --b: 20; --min: -50; --max: 50'>
  <div id='multi-lbl'>Multi thumb slider:</div>
  <label class='sr-only' for='a'>Value A:</label>
  <input id='a' type='range' min='-50' value='-30' max='50'/>
  <output for='a' style='--c: var(--a)'></output>
  <label class='sr-only' for='b'>Value B:</label>
  <input id='b' type='range' min='-50' value='20' max='50'/>
  <output for='b' style='--c: var(--b)'></output>
</div>

We display the values in an ::after pseudo-element using a little counter trick:

output {
  &::after {
    counter-reset: c var(--c);
    content: counter(c);
  }
}

See the Pen by thebabydino (@thebabydino) on CodePen.

It’s now obvious these values change as we drag the sliders, but the result is ugly and it has messed up the wrapper background alignment, so let’s add a few tweaks! We could absolutely position the elements, but for now, we simply squeeze them in a row between the group label and the sliders:

.wrap {
  // same as before
  grid-template: repeat(2, max-content) #{$h}/ 1fr 1fr;
}

[id='multi-lbl'] { grid-column: 1/ span 2 }

input[type='range'] {
  // same as before
  grid-column: 1/ span 2;
  grid-row: 3;
}

output {
  grid-row: 2;
  
  &:last-child { text-align: right; }
  
  &::after {
    content: '--' attr(for) ': ' counter(c) ';'
    counter-reset: c var(--c);
  }
}

Much better!

See the Pen by thebabydino (@thebabydino) on CodePen.

Setting separate :focus styles even gives us something that doesn’t look half bad, plus allows us to see which value we’re currently modifying.

input[type='range'] {
  /* same as before */
  z-index: 1;

  &:focus {
    z-index: 2;
    outline: dotted 1px currentcolor;
    
    &, & + output { color: darkorange }
  }
}

See the Pen by thebabydino (@thebabydino) on CodePen.

All we need now is to create the fill between the thumbs.

The tricky part

We can recreate the fill with an ::after pseudo-element on the wrapper, which we place on the bottom grid row where we’ve also placed the range inputs. This pseudo-element comes, as the name suggests, after the inputs, but it will still show up underneath them because we’ve set positive z-index values on them. Note that setting the z-index works on the inputs (without explicitly setting their position to something different from static) because they’re grid children.

The width of this pseudo-element should be proportional to the difference between the higher input value and the lower input value. The big problem here is that they pass each other and we have no way of knowing which has the higher value.

First approach

My first idea on how to solve this was by using width and min-width together. In order to better understand how this works, consider that we have two percentage values, --a and --b, and we want to make an element’s width be the absolute value of the difference between them.

Either one of the two values can be the bigger one, so we pick an example where --b is bigger and an example where --a is bigger:

<div style='--a: 30%; --b: 50%'><!-- first example, --b is bigger --></div>
<div style='--a: 60%; --b: 10%'><!-- second example, --a is bigger --></div>

We set width to the second value (--b) minus the first (--a) and min-width to the first value (--a) minus the second one (--b).

div {
  background: #f90;
  height: 4em;
  min-width: calc(var(--a) - var(--b));
  width: calc(var(--b) - var(--a));
}

If the second value (--b) is bigger, then the width is positive (which makes it valid) and the min-width negative (which makes it invalid). That means the computed value is the one set via the width property. This is the case in the first example, where --b is 70% and --a is 50%. That means the width computes to 70% - 50% = 20%, while the min-width computes to 50% - 70% = -20%.

If the first value is bigger, then the width is negative (which makes it invalid) and the min-width is positive (which makes it valid), meaning the computed value is that set via the min-width property. This is the case in the second example, where --a is 80% and --b is 30%, meaning the width computes to 30% - 80% = -50%, while the min-width computes to 80% - 30% = 50%.

See the Pen by thebabydino (@thebabydino) on CodePen.

Applying this solution for our two thumb slider, we have:

.wrap {
  /* same as before */
  --dif: calc(var(--max) - var(--min));
  
  &::after {
    content: '';
    background: #95a;
    grid-column: 1/ span 2;
    grid-row: 3;
    min-width: calc((var(--a) - var(--b))/var(--dif)*100%);
    width: calc((var(--b) - var(--a))/var(--dif)*100%);
  }
}

In order to represent the width and min-width values as percentages, we need to divide the difference between our two values by the difference (--dif) between the maximum and the minimum of the range inputs and then multiply the result we get by 100%.

See the Pen by thebabydino (@thebabydino) on CodePen.

So far, so good… so what?

The ::after always has the right computed width, but we also need to offset it from the track minimum by the smaller value and we can’t use the same trick for its margin-left property.

My first instinct here was to use left, but actual offsets don’t work on their own. We’d have to also explicitly set position: relative on our ::after pseudo-element in order to make it work. I felt kind of meh about doing that, so I opted for margin-left instead.

The question is what approach can we take for this second property. The one we’ve used for the width doesn’t work because there is no such thing as min-margin-left.

A min() function is now in the CSS spec, but at the time when I coded these multi-thumb sliders, it was only implemented by Safari (it has since landed in Chrome as well). Safari-only support was not going to cut it for me since I don’t own any Apple device or know anyone in real life who does… so I couldn’t play with this function! And not being able to come up with a solution I could actually test meant having to change the approach.

Second approach

This involves using both of our wrapper’s (.wrap) pseudo-elements: one pseudo-element’s margin-left and width being set as if the second value is bigger, and the other’s set as if the first value is bigger.

With this technique, if the second value is bigger, the width we’re setting on ::before is positive and the one we’re setting on ::after is negative (which means it’s invalid and the default of 0 is applied, hiding this pseudo-element). Meanwhile, if the first value is bigger, then the width we’re setting on ::before is negative (so it’s this pseudo-element that has a computed width of 0 and is not being shown in this situation) and the one we’re setting on ::after is positive.

Similarly, we use the first value (--a) to set the margin-left property on the ::before since we assume the second value --b is bigger for this pseudo-element. That means --a is the value of the left end and --b the value of the right end.

For ::after, we use the second value (--b) to set the margin-left property, since we assume the first value --a is bigger this pseudo-element. That means --b is the value of the left end and --a the value of the right end.

Let’s see how we put it into code for the same two examples we previously had, where one has --b bigger and another where --a is bigger:

<div style='--a: 30%; --b: 50%'></div>
<div style='--a: 60%; --b: 10%'></div>
div {
  &::before, &::after {
    content: '';
    height: 5em;
  }
  
  &::before {
    margin-left: var(--a);
    width: calc(var(--b) - var(--a));
  }

  &::after {
    margin-left: var(--b);
    width: calc(var(--a) - var(--b));
  }
}

See the Pen by thebabydino (@thebabydino) on CodePen.

Applying this technique for our two thumb slider, we have:

.wrap {
  /* same as before */
  --dif: calc(var(--max) - var(--min));
  
  &::before, &::after {
    grid-column: 1/ span 2;
    grid-row: 3;
    height: 100%;
    background: #95a;
    content: ''
  }
  
  &::before {
    margin-left: calc((var(--a) - var(--min))/var(--dif)*100%);
    width: calc((var(--b) - var(--a))/var(--dif)*100%)
  }
  
  &::after {
    margin-left: calc((var(--b) - var(--min))/var(--dif)*100%);
    width: calc((var(--a) - var(--b))/var(--dif)*100%)
  }
}

See the Pen by thebabydino (@thebabydino) on CodePen.

We now have a nice functional slider with two thumbs. But this solution is far from perfect.

Issues

The first issue is that we didn’t get those margin-left and width values quite right. It’s just not noticeable in this demo due to the thumb styling (such as its shape, dimensions relative to the track, and being full opaque).

But let’s say our thumb is round and maybe even smaller than the track height:

See the Pen by thebabydino (@thebabydino) on CodePen.

We can now see what the problem is: the endlines of the fill don’t coincide with the vertical midlines of the thumbs.

This is because of the way moving the thumb end-to-end works. In Chrome, the thumb’s border-box moves within the limits of the track’s content-box, while in Firefox, it moves within the limits of the slider’s content-box. This can be seen in the recordings below, where the padding is transparent, while the content-box and the border are semi-transparent. We’ve used orange for the actual slider, red for the track and purple for the thumb.

Recording of the thumb motion in Chrome from one end of the slider to the other.

Note that the track’s width in Chrome is always determined by that of the parent slider – any width value we may set on the track itself gets ignored. This is not the case in Firefox, where the track can also be wider or narrower than its parent . As we can see below, this makes it even more clear that the thumb’s range of motion depends solely on the slider width in this browser.

Animated gif. Firefox moves the thumb within the left and right limits of the actual range input's content-box.
Recording of the thumb motion in Firefox from one end of the slider to the other. The three cases are displayed from top to bottom. The border-box of the track perfectly fits the content-box of the slider horizontally. It’s longer and it’s shorter).

In our particular case (and, to be fair, in a lot of other cases), we can get away with not having any margin, border or padding on the track. That would mean its content-box coincides to that of the actual range input so there are no inconsistencies between browsers.

But what we need to keep in mind is that the vertical midlines of the thumbs (which we need to coincide with the fill endpoints) move between half a thumb width (or a thumb radius if we have a circular thumb) away from the start of the track and half a thumb width away from the end of the track. That’s an interval equal to the track width minus the thumb width (or the thumb diameter in the case of a circular thumb).

This can be seen in the interactive demo below where the thumb can be dragged to better see the interval its vertical midline (which we need to coincide with the fill’s endline) moves within.

See the Pen by thebabydino (@thebabydino) on CodePen.

The demo is best viewed in Chrome and Firefox.

The fill width and margin-left values are not relative to 100% (or the track width), but to the track width minus the thumb width (which is also the diameter in the particular case of a circular thumb). Also, the margin-left values don’t start from 0, but from half a thumb width (which is a thumb radius in our particular case).

$d: .5*$h; // thumb diameter
$r: .5*$d; // thumb radius
$uw: $w - $d; // useful width

.wrap {
  /* same as before */
  --dif: calc(var(--max) - var(--min));
	
  &::before {
    margin-left: calc(#{$r} + (var(--a) - var(--min))/var(--dif)*#{$uw});
    width: calc((var(--b) - var(--a))/var(--dif)*#{$uw});
  }
  
  &::after {
    margin-left: calc(#{$r} + (var(--b) - var(--min))/var(--dif)*#{$uw});
    width: calc((var(--a) - var(--b))/var(--dif)*#{$uw});
  }
}

Now the fill starts and ends exactly where it should, along the midlines of the two thumbs:

See the Pen by thebabydino (@thebabydino) on CodePen.

This one issue has been taken care of, but we still have a way bigger one. Let’s say we want to have more thumbs, say four:

Animated gif. Shows a slider with four thumbs which can pass each other and be in any order, while the fills are always between the two thumbs with the two smallest values and between the two thumbs with the two biggest values, regardless of their order in the DOM.
An example with four thumbs.

We now have four thumbs that can all pass each other and they can be in any order that we have no way of knowing. Moreover, we only have two pseudo-elements, so we cannot apply the same techniques. Can we still find a CSS-only solution?

Well, the answer is yes! But it means scrapping this solution and going for something different and way more clever — in part two of this article!

Article Series:

  1. Multi-Thumb Sliders: Particular Two-Thumb Case (This Post)
  2. Multi-Thumb Sliders: General Case (Coming Tomorrow!)

The post Multi-Thumb Sliders: Particular Two-Thumb Case appeared first on CSS-Tricks.

Categories: Designing, Others Tags: