Archive

Archive for December, 2020

Optimize Images According to Network and Device Constraints in React

December 10th, 2020 No comments

Connectivity has evolved beyond recognition since the beginning of the internet. We are lightyears past dial up, these days, and can watch a video in high resolution on our smartphone while being connected to a mobile network. But not all mobile connections are created equal – older generation networks (3G, 2G, etc.) are still quite dominant, accounting for almost half of all connections worldwide in 2020.

Unfortunately, the phasing out process is very slow, and many people around the globe are experiencing really dragged out page loads, comparable to the very early days of home internet adoption.

Modern websites became resource-hungry, featuring lots of images and animations. For a visitor on an underpowered device and a fragile network connection, an average webpage might take a good minute to load completely. This is largely due to the fact that developers often make binary decisions when it comes to user’s hardware and network conditions: devices fall either in the desktop or smartphone category, while connectivity is a question of being on- or offline. In reality, user’s circumstances tend to be much more nuanced.

We Can Do Better?

What can be done to bridge the gap for users on modest devices and spotty connections? First, we need to do a quick evaluation of what exactly their conditions are by looking at the following two properties:

Based on that, we can decide, for instance, to adjust the quality of the images we intend to serve. There is a catch, however, with Jamstack websites and apps rendered on the server – `navigator`object, as any other browser API, isn’t available during the rendering stage. A common workaround for this issue is to add a bunch of responsive image markup, but it comes with a significant pain point – inefficient scaling. An image CDN like ImageEngine helps to avoid this and other pitfalls associated with responsive images as it handles all the heavy-lifting behind the scenes by applying automated, smart tweaks to requested resources on-the-fly.

When it comes to adapting to a user’s network constraints, one could detect connection type and instruct an image CDN to vary compression according to connection quality. Here’s how one might go about it in React:

import React, { useState, useEffect } from 'react'

const useConnectionType = (defaultConnectionType) => {

  const isSupported = navigator?.connection?.effectiveType
    ? true
    : false

  const [connectionType, setNetworkStatus] = useState(
    isSupported
      ? navigator.connection.effectiveType
      : defaultConnectionType
  )

  useEffect(() => {
    if (isSupported) {
      const { connection } = navigator
      const updateConnectionType = () => {
        setNetworkStatus(connection.effectiveType)
      }

      connection.addEventListener('change', updateConnectionType)

      return () => {
        connection.removeEventListener('change', updateConnectionType)
      }
    }
  }, [])

  return [ connectionType, setNetworkStatus ]
}

const imageCDNHost = 'images.foo.com

function ConnectionAwareComponent () {

  const [ connectionType ] = useConnectionType()

  let compressionLevel = 0

  switch (connectionType) {
    case 'slow-2g':
      compressionLevel = 65
      break
    case '2g':
      compressionLevel = 50
      break
    case '3g':
      compressionLevel = 30
      break
    case '4g':
      compressionLevel = 0
      break
  }

  return (
    <div>
      {/* Apply variable compression via dedicated directive */}
      <img src={`${imageCDNHost}/?imgeng?=cmpr_${compressionLevel}`} />
    </div>
  )
}

One can take this idea even further to accommodate those on really sluggish and wonky networks by rendering blurred images and offering an option to download a higher resolution version on demand. Or devise a performance score system and adjust what is sent based on that.

On the other hand, the fact that the user is on a “speedy” 4G connection doesn’t necessarily mean they aren’t interested in saving data as they might be accessing a website in roaming. Enabling Client Hints on one’s website will let site owners detect the presence of a data saver flag and take necessary steps to adjust to the user’s preferences.

Reasons for Faster Images

Mediocre CPU, modest amounts of memory and a low-grade connection aren’t imaginary constraints. They pose real user experience challenges potentially affecting hundreds of millions of users worldwide. Some companies began to bake inclusive experiences into their products: streaming services like Netflix and Spotify adjust the streaming quality based on your network conditions, while many others are doing automatic image optimizations behind the scenes for users.

Developing regions, where fast networks aren’t yet accessible to everyone and everywhere, might not be one’s target market. Meanwhile, someone browsing from a rural area in a developed country will likely have a jarring experience if they are served a fully-fledged version of a website. We can be more considerate and intentional by adjusting what we send / display to our users with only a couple of small tweaks.

Using an image CDN like ImageEngine simplifies the image optimization process and automatically responds to the Client Hints for network constraints. The result is a better experience for a network-constrained visitor and an elegant workflow for developers.


The post Optimize Images According to Network and Device Constraints in React appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Categories: Designing, Others Tags:

Pantone Color of the Year 2021

December 10th, 2020 No comments

It’s that time again: the self-fulfilling prophecy that is the Pantone Color of the Year has been announced for 2021.

For 2021, we’re getting two colors of the year. The colors selected to grace museum gift shops, and end-of-year blog posts are Ultimate Gray (a mid-range gray somewhere around #939597) and Illuminating (a citrus yellow that’s approximately #F5DF4D).

A marriage of color conveying a message of strength and hopefulness that is both enduring and uplifting.

The last time Pantone selected two colors was Rose Quartz & Serenity in 2016, and we all know what a tranquil, serene year that was; so 2021 will presumably unleash the curse of an ancient mummy on the world, or see us collide with the Sun.

2020’s color, “Classic Blue”, probably wasn’t much of a color of the year unless it happens to be the color you painted your home office. If the company had genuine foresight, it might have opted for the blandest beige it could find — in fact in the Summer paint brand Dulux almost opted for that for 2021, naming “Brave Ground” its color for next year, but for beige’s “resilient” qualities rather than any lockdown boredom.

Perhaps that’s why Pantone’s PR department opted for two colors in 2021: a nondescript grey to keep us going until we’re all vaccinated, and a wildly luminous yellow for the latter part of the year.

In fairness to Pantone, its color choices aren’t predictions as is often reported, rather aspirations. Pantone believes the pairing “expresses a message of positivity supported by fortitude” which may be just what the world needs right now.

A combination of colors is much more sensible than a single color, with so much about color dependent on context. But the actual color treatment of 2021 is much more likely to be multi-color gradients.

You can try out Pantone’s colors for 2021 on Instagram, or on Pantone Connect.

Source

Categories: Designing, Others Tags:

Using CSS Custom Properties to Adjust Variable Font Weights in Dark Mode

December 10th, 2020 No comments

Black isn’t always slimming.

When recently testing a dark mode option for one of my sites, I experienced first-hand the issue that Robin Rendle addresses in this article. All of my page text — headings and body copy — appeared to bulk up when I switched to dark mode. And it didn’t matter what fonts I used or which browsers I tried. The same thing happened with all of them.

For example, here’s what happens with Adobe’s Source Sans Pro in Chrome for Windows:

See those blurry edges when we switch to dark mode?

It’s not an illusion. The light characters really are heavier against dark backgrounds. We can zoom in to see better:

The characters really are thicker in dark mode!

And it becomes really obvious when we invert the dark mode portions of those images:

We can really see the difference when putting the characters side-by-side on the same white background.
We can really see the difference when putting the characters side-by-side on the same white background.

One solution

Since variable fonts enjoy wide browser support, we can use them to help us address this issue. The three panels below demonstrate a solution we’ll be working toward:

The top shows us some light text on a dark background. The middle panel shows what happens in dark mode without changing any font weight settings. And the bottom panel demonstrates dark mode text that we’ve thinned out a bit. That third panel is adjusted to match the weight of its light counterpart, which is what we’re trying to accomplish here.

Here’s how we can get this improved effect:

  1. Reduce font-weight properties in dark mode via one of the following methods:
    1. Manually changing each font-weight assignment directly in a dark mode media query.
    2. Creating a single --font-weight-multiplier custom property that changes its value in dark mode, and by which we can then multiply by each element’s default font-weight value.
    3. Same thing, but instead of calculating each element’s font-weight property individually, we take advantage of CSS variable scoping and the universal selector (*) to apply our multiplier calculation everywhere at once.
  2. Adjust a variable font’s grade (“GRAD”) axis. Not all variable fonts support this specific feature, but Roboto Flex, does. Altering this axis value changes the font’s apparent weight, without affecting the width of the letters.
  3. Adjust a variable font’s darkmode ("DRKM") axis. Dalton Maag’s aptly-named Darkmode, with its eponymous darkmode axis, is uniquely suited for this. As with the Roboto Flex’s grade axis, adjusting Darkmode’s darkmode axis changes the font’s apparent weight. But while the grade axis requires some fine-tuning of values, the darkmode axis is simply switched on (thinner) or off (regular).

The techniques in the first group work for most variable fonts. The solution Robin uses in his article is actually the very first item in the group. I’ll expand on the second and third items in the group by introducing custom properties that help us automatically adjust font weights in dark mode.

The second and third groups involve less common font-variation-settings axes. Though these strategies apply to fewer typefaces, they may be preferable when available. The trick is knowing what a variable font supports before choosing it.

I’ve made a demonstration page including all the strategies covered in this article. You can see what some different variable fonts look like in light mode, in dark mode with no adjustment, and in dark mode with our solutions for thinning out characters.

In addition to the strategies listed above, there’s always one more option: don’t do anything! If you think your fonts look good enough in light and dark mode, or you don’t have the bandwidth right now to wrestle with reflow, element resizing, browser/display inconsistencies, and extra CSS to maintain, then you may not have to change a thing. Focus on the rest of your site and leave yourself open to the possibility of revisiting this topic later.

Strategy 1: Reducing the font-weight value

Most variable text fonts have a weight axis, which lets us assign any specific font-weight value within the weight range available to that font (e.g. 0-1000, 300-800, etc.). Each technique in this strategy takes advantage of this fine control over the weight axis to reduce font-weight values in dark mode. (The need for such font-weight precision is also what renders most non-variable fonts unsuitable for this solution.)

If you’re using variable fonts you have locally, you can check their axes and value ranges at Wakamai Fondue:

At Wakamai Fondue, you can view any local font’s variable axes and ranges.

Keep in mind that, if you’re using the @font-face rule to load fonts, you should set a font-weight range for each of them at the same time:

@font-face {
  src: url('Highgate.woff2') format('woff2-variations');
  font-family: 'Highgate';
  font-weight: 100 900;
}

If you neglect this step, some variable fonts may not properly reflect specific font-weight values in current Chromium browsers.

Dalton Maag Highgate’s font-weight set to 800 in Chrome without (left) and with (right) a font-weight range specified in the @font-face rule.

The basic solution: Manually entering each weight

Here’s the technique most of us may reach for. We create a dark mode media query in which we enter some font-weight values that are a bit lower than their defaults.

/* Default (light mode) CSS */ 
body {
  font-weight: 400;
}

strong, b, th, h1, h2, h3, h4, h5, h6 {
  font-weight: 700;
}

/* Dark mode CSS */
@media (prefers-color-scheme: dark) {
  body {
    font-weight: 350;
  }

  strong, b, th, h1, h2, h3, h4, h5, h6 {
    font-weight: 600;
  }
}
CodePen Embed Fallback

It works, and it’s no problem to maintain — so long as we’re not planning on adding or editing any other weights at our site! But if we do start incorporating more weights, it can get unwieldy fast. Remember to enter each selector/property combo both outside and inside the prefers-color-scheme media query. We’ll have to do some manual calculations (or guesswork) to determine the dark mode property values for each element.

Creating a weight multiplier custom property and using it in a calculation when setting an element’s weight

I generally try to adhere to Mike Riethmuller’s credo that “media queries are only used to change the value of custom properties.” And that’s the improvement we make in this solution. Instead of having to enter font weights for all our elements in and out of dark mode, the only thing we’re putting in our media query is a --font-weight-multiplier custom property:

@media (prefers-color-scheme: dark) {
  :root {
    --font-weight-multiplier: .85;
  }
}

Then, for all our font-weight properties throughout the stylesheet, we’ll multiply the variable’s value by our preferred default weight value for each element — thus lowering the font weight by 15% in dark mode. If we’re not in dark mode, we’ll multiply the default weight by 1, meaning it doesn’t change at all.

Here’s what I mean. Normally, we’d use this to set a body font weight of 400:

body {
  font-weight: 400;
}

For this solution, we use this:

body {
  font-weight: calc(400 * var(--font-weight-multiplier, 1));
}

In the var() function, notice that our variable has a fallback value of 1. Because --font-weight-multiplier is only set in dark mode, this fallback value will be used the rest of the time. So, by default, our font weight for body text stays at 400 (400*1). But in dark mode, the weight decreases to 340 (400*.85).

We’ll also do this with bold elements:

strong, b, th, h1, h2, h3, h4, h5, h6 {
  font-weight: calc(700 * var(--font-weight-multiplier, 1));
}

These weights will decrease from 700 to 595 (700*.85) in dark mode.

And we can use the same technique for any other elements where we want to set the font-weight to something other than 400 by default.

I’m using a value of .85 for --font-weight-multiplier, because I’ve found that to be a good general value for most fonts (like Adobe Source Sans Pro, the free typeface I use in most of this article’s demos). But feel free to play around with that number.

Here’s how this looks put together:

/* DARK-MODE-SPECIFIC CUSTOM PROPERTIES */
@media (prefers-color-scheme: dark) {
  :root {
    --font-weight-multiplier: .85;
  }
}

/* DEFAULT CSS STYLES... */
body {
  font-weight: calc(400 * var(--font-weight-multiplier, 1));
}

strong, b, th, h1, h2, h3, h4, h5, h6 {
  font-weight: calc(700 * var(--font-weight-multiplier, 1));
}
CodePen Embed Fallback

Creating a weight multiplier variable and automatically calculating and applying it to all elements at once.

When using many CSS custom properties, I think many of us stick to a “set as needed and manually apply everywhere” approach. That’s what the previous solution does. We set our custom property value in the :root (and/or use a fallback value), set it again in a media query, then apply it with calc() and var() functions throughout our stylesheet each time we assign a font-weight value.

The code might look something like this:

h1 {
  font-weight: calc(800 * var(--font-weight-multiplier, 1);
}

summary {
  font-weight: calc(600 * var(--font-weight-multiplier, 1);
}

But when we use this technique for various elements, you can see we have to do these three things every time we assign font-weight values:

  • Include the calc() function
  • Include the var() function
  • Remember the --font-weight-multiplier custom property’s name and default value

Instead, I’ve recently started inverting this approach for certain tasks, taking advantage of CSS variable scope with a “set everywhere and apply once” method. For this technique, I replace every font-weight property in the stylesheet with a --font-weight variable, keeping the name the same except for the dashes, for simplicity’s sake. I then set this value to the default weight for that particular selector (e.g. 400 for body text). Neither calc() nor var() is needed — yet. This is how we set everywhere.

Then we apply once, with a lone font-weight property in our stylesheet that sets every text element’s weight via the universal selector. Modifying our snippet above, we’d now have this:

h1 {
  --font-weight: 800;
}

summary {
  --font-weight: 600;
}

* {
  font-weight: calc(var(--font-weight, 400) * var(--font-weight-multiplier, 1);
}

The calc() function multiplies each of our --font-weight custom properties by our multiplier variable, and the font-weight property then applies the value to its appropriate element.

It’s unnecessary to use only a single var() for each custom property in the stylesheet. But I often like doing so when performing calculations and/or using a helper variable, as we do here. That said, while this is certainly the cleverest technique for adjusting font weights, that doesn’t mean it’s the best technique for all projects. There is at least one serious caveat.

The primary advantage of using the universal selector technique — that it applies to everything — also introduces its chief risk. There may be some elements that we don’t want thinned out! For example, if our form elements retain dark text on light backgrounds in dark mode, they may still get steamrolled by the universal selector.

There are ways to mitigate this risk. We could replace * with a long selector string containing a list of only elements to thin out (having them opt-in to the calculation). Or we could hard-code font weights for the elements that we don’t want affected (opt-out):

* {
  font-weight: calc(var(--font-weight, 400) * var(--font-weight-multiplier, 1));
}

button, input, select, textarea {
  font-weight: 400;
}

Such fixes may ultimately make code just as complicated as the previous technique. So, you’ll have to gauge which is appropriate for your project. If you still have concerns over performance, code complexity, or think this technique might introduce undesired (even unpredictable) results, the previous technique might be safest.

The final code:

/* DEFAULT CUSTOM PROPERTIES */
:root {
  --font-weight: 400;
  --font-weight-multiplier: 1;
}
strong, b, th, h1, h2, h3, h4, h5, h6 {
  --font-weight: 700;
}

/* DARK-MODE-SPECIFIC CUSTOM PROPERTIES */
@media (prefers-color-scheme: dark) {
  :root {
    --font-weight-multiplier: .85;
  }
}

/* APPLYING THE CUSTOM PROPERTIES... */
* {
  font-weight: calc(var(--font-weight, 400) * var(--font-weight-multiplier, 1));
}
CodePen Embed Fallback

We’re not required to set the default --font-weight: 400 and --font-weight-multiplier: 1 custom properties in the above code, because we’ve included the fallback values in the var() functions. But as code gets more complicated, I often like assigning them in a logical place, just in case I want to find and alter them later.

A final note on this strategy: we can also apply weights with the font-variation-settings property and a "wght" axis value, instead of font-weight. If you’re using a typeface with several axes, maybe you find it more manageable to do all your font tweaking that way. I know of at least one font (Type Network’s Roboto Flex, which we’ll be using later in this article) that has 13 axes!

Here’s how to apply our solution via a font-variation-settings property:

* {
  --wght: calc(var(--font-weight, 400) * var(--font-weight-multiplier, 1));
  font-variation-settings: "wght" var(--wght);
}

Strategy 1 Addendum: Handling letter-spacing

One side effect of lowering our type weight is that, for most non-monspaced fonts, it also narrows the characters.

Here again is what happens when we lighten Source Sans Pro with our multiplier. The top two panels below show Source Sans Pro in light and dark mode by default. And the lower panel shows the lighter version.

Adobe’s Source Sans Pro in light mode, dark mode by default, and dark mode thinned out.

With no adjustments, the characters in light mode and dark mode are the same width. But when we lower the font weight, those characters now take up less space. You may not like how this change affects your flow or element sizes (e.g. narrower buttons). And some designers think it’s a good idea to add letter spacing in dark mode, anyway. So, if you want, you can create another custom property to add some space.

Implementing a custom property for letter spacing

Just like we did with our font-weight multiplier variable, we’re going to create a letter spacing variable with a default value that gets overridden in dark mode. In our default (light mode) :root, we set our new --letter-spacing custom property to 0 for now:

:root {
  /* ...other custom variables... */
  --letter-spacing: 0;
}

Then, in our dark mode query, we raise the value to something greater than 0. I’ve entered it as .02ch here (which combines pretty well with a --font-weight-multiplier value of .85). You could even get clever and fine-tune it with some calculations based on your font weights and/or sizes, if you like. But I’ll use this hard-coded value for now:

@media (prefers-color-scheme: dark) {
  :root {
    /* ...other custom variables... */
    --letter-spacing: .02ch;
  }
}

Finally, we apply it via our universal selector (with a fallback value of 0):

* {
  /* ...other property settings... */
  letter-spacing: var(--letter-spacing, 0);
}

Note: Though I use the ch unit in this example, using em also works, if you prefer. For Source Sans Pro, a value of .009em is about equal to .02ch.

Here’s the full code for a font weight multiplier with letter spacing:

/* DEFAULT CSS CUSTOM PROPERTIES */
:root {
  --font-weight: 400;
  --font-weight-multiplier: 1;
  --letter-spacing: 0;
}

strong, b, th, h1, h2, h3, h4, h5, h6 {
  --font-weight: 700;
}

/* DARK MODE CSS CUSTOM PROPERTIES */
@media (prefers-color-scheme: dark) {
  :root {
    /* Variables to set the dark mode bg and text colors for our demo. */
    --background: #222;
    --color: #fff;

    /* Variables that affect font appearance in dark mode. */
    --font-weight-multiplier: .85;
    --letter-spacing: .02ch;
  }
}

/* APPLYING CSS STYLES... */
* {
  font-weight: calc(var(--font-weight, 400) * var(--font-weight-multiplier, 1));
  letter-spacing: var(--letter-spacing, 0);
}

body {
  background: var(--background, #fff);
  color: var(--color, #222);
}
CodePen Embed Fallback

Fonts with constant-width characters (aka multi-plexed fonts)

In addition to monospaced fonts, there are some other typefaces specifically designed so that their individual characters take up the same amount of horizontal space, regardless of weight. For example, if an “i” occupies five horizontal pixels of space at a weight of 400, and a “w” occupies thirteen pixels at the same weight, they will still occupy five and thirteen pixels, respectively, when their weights are increased to 700.

Arrow Type’s Recursive Sans is one such typeface. The following image shows how Recursive’s characters maintain the same widths in light mode, default dark mode, and dark mode with our font weight multiplier, respectively:

The characters in Arrow Type’s Recursive maintain their widths regardless of font weight.

Multi-plexed typefaces, like Recursive, are designed so you won’t need to adjust letter spacing when changing their font weights in dark mode. Your element sizes and page flow will remain intact.

Strategy 2: Adjust a variable font’s grade axis

The grade axis ("GRAD") changes a font’s apparent weight without changing its actual font-weight value or the widths of its characters. When using fonts with this axis, you may not need our font weight multiplier variable at all.

For Type Network’s free Roboto Flex font, a grade of -1 is thinnest, 0 (default) is normal, and 1 is thickest. With this font, I start by assigning its grade axis a value of around -.75 for dark mode.

Roboto Flex in light mode, dark mode default, and dark mode with “GRAD” set to -.75
:root {
  --GRAD: 0;
}

@media (prefers-color-scheme: dark) {
  :root {
    --GRAD: -.75;
  }
}

body {
  font-variation-settings: "GRAD" var(--GRAD, 0);
}
CodePen Embed Fallback

So, adjusting the grade axis seems like the perfect solution if it’s available to you, right? Well, maybe. There are a few things to keep in mind when considering it.

First, the scale for all fonts doesn’t always go from -1 to 1. Some range from 0 to 1. At least one typeface uses percents, making 100 the default. And other fonts align the grade scale with font weights, so the range may be something like 100-900. If you want to use the grade axis in the latter case, you may have to set all your font weights everywhere to a default of 400, and then use the grade axis for all weight changes. For dark mode, you’ll then want to treat grade essentially like we do in our font weight multiplier solution — applying the multiplier to the "GRAD" axis in font-variation settings.

The second caveat is that some typefaces don’t let you grade a font to a value below its default weight. So, grade can’t lighten it at all. Apple’s San Francisco typeface (which can be tested via font-family: system-ui; on Apple devices) has both of these issues. As of macOS Catalina, San Francisco has a grade axis. It’s scaled to line up with font weights, and its minimum value is 400.

San Francisco’s grade and weight axes use the same scale, but have different ranges.

Because we can’t set the grade to a value lower than 400, we can’t lighten fonts from a default of 400 in dark mode. If we want to go lower, we’ll need to lower the weight axis value, instead.

Strategy 3: Adjusting a variable font’s darkmode axis

There’s currently only one typeface with a darkmode ("DRKM") axis at the time of this writing: Dalton Maag’s Darkmode.

The darkmode axis is essentially a grade axis without any fine-tuning. Just turn it on (1) for a thinner appearance in dark mode, and leave it off (0, the default) for normal display.

Darkmode in light mode, in dark mode with “DRKM” unset, and in dark mode with “DRKM” set to 1.
:root {
  --DRKM: 0;
}

@media (prefers-color-scheme: dark) {
  :root {
    --DRKM: 1;
  }
}

body {
  font-variation-settings: "DRKM" var(--DRKM, 0);
}
CodePen Embed Fallback

I like the Darkmode font a lot. But beware that it is a commercial license that’s required for professional use. Dalton Maag offers a trial version that can be used for “academic, speculative, or pitching purposes only.” I’m hoping this typeface is a pilot for more Dalton Maag families to get a darkmode axis, and that other font foundries will then follow suit!

Other factors to consider

We’ve covered a few big strategies for working with variable fonts in a dark mode context. But, as with most things, there are other things to consider that might sway you toward one solution or another.

Dark mode on high-resolution (“retina”) screens

On screens with higher pixel densities (e.g. most modern phones, MacBooks, iMacs, etc.), the thickening effect of dark mode is often less pronounced. Therefore, you may not want to thin the fonts on these screens out as much — if at all!

If you still want to lighten fonts a bit, you can add another media query to make the effect less severe. Depending which solution you’re using, you can raise the --font-weight-multiplier value closer to 1, raise the --GRAD value closer to 0, or disable --DRKM altogether (since it’s either on or off, with no in-between).

If you add this query, remember to place it below the original prefers-color-scheme query, or it may have no effect. Media queries don’t add CSS specificity, so their order matters!

@media (prefers-color-scheme: dark) and (-webkit-min-device-pixel-ratio: 2), 
       (prefers-color-scheme: dark) and (min-resolution: 192dpi) { 
  :root {
    --font-weight-multiplier: .92;
    /* Or, if you're using grade or darkmode axis instead: */
    /* --GRAD: -.3; */
    /* --DRKM: 0; */
  }
}

If you don’t want to lighten fonts at all on high density screens in dark mode, you can update your original dark mode prefers-color-scheme query to the following, to omit these screens:

@media (prefers-color-scheme: dark) and (-webkit-max-device-pixel-ratio: 1.9), 
       (prefers-color-scheme: dark) and (max-resolution: 191dpi) { 

  /* Custom properties for dark mode go here. */

}

Mixing fonts with different axes (and mixing variable fonts with non-variable fonts)

If you’re using more than one typeface on your site, you’ll need to consider what effects these adjustments may have on all of them. For example, if you’re using multiple fonts with intersecting axes, you could wind up accidentally combining the effects of multiple strategies (e.g. reducing both grade and weight simultaneously):

If your stylesheet includes solutions for several typefaces/axes, then the effect on fonts that have multiple axes (like this example’s Roboto Flex, which has both grade and weight axes) may be cumulative.
CodePen Embed Fallback

If all the fonts on your site are variable and have a grade axis with a matching scale and range (e.g. if they all range from -1 to 1), that’s the solution I’d recommend. However, you’ll have to revisit this if you plan to add other fonts later that don’t meet those criteria. Same goes for the darkmode axis, too, if it becomes more widespread.

If all your fonts are variable, but they don’t all share the same axes (e.g. grade and darkmode), then using only the --font-weight-multiplier custom property may be your safest bet.

Finally, if you’re mixing variable and non-variable fonts, know that the non-variable fonts will not change appearance with any of these solutions — with some exceptions. For example, if you’re using the font weight multiplier with the font-weight property, it is possible that some — but maybe not all — of your font weights will change enough to move to the next lower weight name.

Say your site includes a font with three weights: regular (400), semi-bold (600), and bold (700). In dark mode, your bold text may lighten up enough to display as semi-bold. But your regular font will still stay regular (as that’s the lowest weight included on the site). If you want to avoid that inconsistency, you could apply your variable font weights via font-variation-settings, and not font-weight, so your non-variable fonts aren’t affected at all. They’ll just always maintain their default weight in dark mode.

In closing

It’s always a happy coincidence when complementary technologies attain common usage near the same time. With the rise in popularity of both dark mode and variable fonts, we have the luxury of using the latter to mitigate one of the challenges of the former. Using CSS custom properties in conjunction with weight, grade, and darkmode axes, we can bring some consistency to the look of our text in both light and dark modes.

You can visit my interactive demo with the fonts and axes from this article.


The post Using CSS Custom Properties to Adjust Variable Font Weights in Dark Mode appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Categories: Designing, Others Tags:

2020 was not a good year for learning

December 9th, 2020 No comments

There, I said it.

What did I learn about building websites in 2020? A lot. But what I learned is not nearly as important as how I learned it. So instead, I want to share a couple of strategies I used to unblock learning in less-than-ideal times.

I spent almost a decade teaching design and, let me tell you, the conditions for curiosity were all wrong this year. You are not alone if you’ve found yourself battling brain fog, deep existential crisis, and long spans of nothingness instead of basking in a creative renaissance. I spent most of this year in a tiny apartment under a terrifying lockdown in epicenter-of-the-pandemic New York with my husband, two cats, and a very energetic toddler. I’ll save the details for a therapist, but let’s just say this year did not go as planned.

But then again, whose year did? The entire world plunged into crisis. I only feel deep gratitude for having weathered this storm and for having cultivated the skills I needed for my little family to thrive despite the chaos.

I spent years speaking at conferences about mental models and growing creativity. This year, I’ve had to focus on the other side of that coin: helping people recover their creativity when it feels out of reach. The first thing I usually recommend to anyone feeling creatively blocked is that they start actively wasting their time.

Waste your time

I had ambitious plans for 2020, having plotted out a rigorous study plan for myself. That plan is now in the garbage next to my travel plans and willingness to wear anything but yoga pants.

What I am capable of after a good night’s sleep, coffee in hand, is one thing. What I can manage after a sleepless night followed by a full day of Zoom meetings while simultaneously trying to wrangle a toddler is another thing entirely.

The loss of childcare meant that the only time to indulge in learning was after a long day of work after my daughter was tucked into bed, and I was completely exhausted. The last thing I wanted was disciplined study in pursuit of a goal, so I changed my approach: focus on breadth, widen the scope of topics, let my mind wander, and feed my curiosity. As a bonus, this shift often kept me from losing the evening to bingeing Netflix or doom-scrolling the news late into the night.

When you’re low on motivation or approaching burnout, create the opportunity to “waste time” and play. Follow what interests you, not just the things you “should” be interested in. Do not let your velocity or productivity enter the equation – respect that a life of learning is much more complex than that. Practice curiosity and protect your ability to play, it is critical to learning and creating. If you’re curious about why that is, look up inquiry-based or constructivist learning. What you’ll learn will have nothing to do with building websites, and that’s the point.

Nostalgia

Many talented people felt their ability to create disappear this year, for a variety of reasons. I want to be clear — that’s a normal human reaction to all of this. There is no “one weird trick” for unblocking productivity when the world is on fire. But, if building websites brings you the joy and/or money you need, and you want some advice from someone trained in jump-starting learning, I’ll say this: revisit your foundations. Not the foundations, but your foundations.

When things are this uncertain for this long, we reach for coping mechanisms. Why not use one to unblock learning? In a recent New York Times article, psychologists said that ‘conjuring nostalgia during stressful times is a healthy coping mechanism,” and I totally agree. Between re-watching 90’s movies and cooking comfort foods, I dove back into what brought me to tech: design, CSS, color functions, typography, design patterns. I played around in Illustrator, dusted off old repos, looked at happy projects, and remembered old trends. I avoided burning energy on the hot new thing. Instead, I revisited the foundations of my understanding through the lens of experience.

I’m not suggesting you stay in your comfort zone, but I am saying it’s okay to start there. The important thing is starting.

Routines and Structures

There is disruption on every level: global, national, and personal. I don’t know anyone who hasn’t experienced a disruption to their lives. When our routines are disrupted and our basic needs (including health and psychological) are threatened, we are unable to learn well. One of the most effective things a teacher can do in the classroom is to make sure their students eat breakfast, so focus on your needs. Getting a good night’s sleep contributes to learning. Caring for your mental health contributes to learning. Punishing yourself for struggling does not.

This year, as all of my support structures disappeared, there was not enough Natalya to do everything and be there for everyone. Accepting that was difficult. I spent a lot of energy shifting my focus from “the year I wished for” to the one I was experiencing. I used every trick in the teacher’s handbook on myself to keep my love of learning intact, feel some progress, and keep up. No matter how much I did, I still felt like I didn’t do enough. It was just the kind of year when everything felt like it took more energy (because it did). Setting up new routines and structures is work. Factor that into your equation when evaluating your progress.

This is where I would usually rant about how teaching and childcare are real skills and difficult jobs, dedicating several paragraphs on how important and valuable the work of teachers and caregivers is. But anyone who has been homeschooling or caring for someone this year is already well aware.

Creating the right conditions for effective learning is a lot of work, so give yourself credit if you’ve been taking it on.

This has been a deeply unsustainable year for so many. Showing up and making it through each day and making any progress is enough. Not giving up and trying again, day after day, is success.

What I learned…

Ah, the reason you’re reading this. I would love to talk about the cool design and tech stuff I learned this year, but I won’t. What I learned as an individual in 2020 is not nearly as important as what I hope we learned as an industry.

I hope we learned that the most important thing to know about building websites is that there are real people building them, and we need to make sure they can thrive.

Lunch perks and swag are cool, but what about childcare, accessibility, and support structures? What about flexible hours and remote-first practices? We should notice that the companies which supported people before the pandemic are doing better than the ones struggling to pivot to do the work they should have been doing all along.

I wish it didn’t take a global pandemic, but we need change. Let’s use this knowledge to build a better society with stronger principles and more thoughtful structures—not just better websites.


The post 2020 was not a good year for learning appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Categories: Designing, Others Tags:

npm ruin dev

December 9th, 2020 No comments

In 2020, I rediscovered the enjoyment of building a website with plain ol’ HTML, CSS, and JavaScript — no transpilin’, no compilin’, no build tools other than my hands on the keyboard.

Seeing as my personal brand could be summed up “so late to the game that the stadium has been demolished,” I decided to start a podcast in 2020. It’s the podcast of my agency, Clearleft, and it has been given the soaringly imaginative title of The Clearleft Podcast. I’m really pleased with how the first season turned out. I’m also really pleased with the website I put together for it.

The website isn’t very big, though it will grow with time. I had a think about what the build process for the site should be and after literally seconds of debate, I settled on a build process of none. Zero. Nada.

This turned out to be enormously liberating. It felt very hands-on to write the actual HTML and CSS that will be delivered to end users, without any mediation. I felt like I was getting my hands into the soil of the site.

CSS has evolved so much in recent years—with features like calc() and custom properties—that you don’t have to use preprocessors like Sass. And vanilla JavaScript is powerful, fully-featured, and works across browsers without any compiling.

Don’t get me wrong—I totally understand why complicated pipelines are necessary for complicated websites. If you’re part of a large team, you probably need to have processes in place so that everyone can contribute to the codebase in a consistent way. The more complex that codebase is, the more technology you need to help you automate your work and catch errors before they go live.

But that setup isn’t appropriate for every website. And all those tools and processes that are supposed to save time sometimes end up wasting time further down the road. Ever had to revisit a project after, say, six or twelve months? Maybe you just want to make one little change to the CSS. But you can’t because a dependency is broken. So you try to update it. But it relies on a different version of Node. Before you know it, you’re Bryan Cranston changing a light bulb. You should be tweaking one line of CSS but instead, you’re battling entropy.

Whenever I’m tackling a problem in front-end development, I like to apply the principle of least power: choose the least powerful language suitable for a given purpose. A classic example would be using a simple HTML button element instead of trying to recreate all the native functionality of a button using a div with lashings of ARIA and JavaScript. This year, I realized that this same principle applies to build tools too.

Instead of reaching for all-singing all-dancing toolchain by default, I’m going to start with a boring baseline. If and when that becomes too painful or unwieldy, then I’ll throw in a task manager. But every time I add a dependency, I’ll be limiting the lifespan of the project.

My new year’s resolution for 2021 will be to go on a diet. No more weighty node_modules folders; just crispy and delicious HTML, CSS, and JavaScript.


The post npm ruin dev appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Categories: Designing, Others Tags:

How to Create a Favicon That Changes Automatically

December 9th, 2020 No comments

I found this Free Favicon Maker the other day. It’s a nice tool to make a favicon (true to its name), but unlike other favicon generators, this one lets you create one from scratch starting with a character or an emoji. Naturally, I was curious to look at the code to see how it works and, while I did, it got me thinking in different directions. I was reminded of something I read that says it is possible to dynamically change the favicon of a website. That’s actually what some websites use as a sort of notification for users: change the favicon to a red dot or some other indicator that communicates something is happening or has changed on the page.

I started browsing the emojis via emojipedia.org for inspiration and that’s when it struck: why not show the time with a clock emoji (?) and other related favicons? The idea is to check the time every minute and set the favicon with the corresponding clock emoji indicating the current time.

We’re going to do exactly that in this article, and it will work with plain JavaScript. Since I often use Gatsby for static sites though, we will also show how to do it in React. From there, the ideas should be usable regardless of what you want to do with your favicon and how.

Here’s a function that take an emoji as a parameter and returns a valid data URL that can be used as an image (or favicon!) source:

// Thanks to https://formito.com/tools/favicon
const faviconHref = emoji =>
  `data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%22256%22 height=%22256%22 viewBox=%220 0 100 100%22><text x=%2250%%22 y=%2250%%22 dominant-baseline=%22central%22 text-anchor=%22middle%22 font-size=%2280%22>${emoji}</text></svg>`

And here’s a function that targets the favicon in the and changes it to that emoji:

const changeFavicon = emoji => {
  // Ensure we have access to the document, i.e. we are in the browser.
  if (typeof window === 'undefined') return

  const link =
    window.document.querySelector("link[rel*='icon']") ||
    window.document.createElement("link")
  link.type = "image/svg+xml"
  link.rel = "shortcut icon"
  link.href = faviconHref(emoji)

  window.document.getElementsByTagName("head")[0].appendChild(link)
}

(Shout out to this StackOverflow answer for that nice little trick on creating the link if it doesn’t exist.)

Feel free to give those a try! Open up the DevTools JavaScript console, copy and paste the two functions above, and call changeFavicon("?"). You can do that right on this website and you’ll see the favicon change to that awesome dancing emoji.

Back to our clock/time project… If we want to show the emoji with the right emoji clock showing the correct time, we need to determine it from the current time. For example, if it’s 10:00 we want to show ?. If it’s 4.30 we want to show ?. There aren’t emojis for every single time, so we’ll show the best one we have. For example, between 9:45 to 10:14 we want to show the clock that shows 10:00; from 10:15 to 10:44 we want to show the clock that marks 10.30, etc.

We can do it with this function:

const currentEmoji = () => {
  // Add 15 minutes and round down to closest half hour
  const time = new Date(Date.now() + 15 * 60 * 1000)

  const hours = time.getHours() % 12
  const minutes = time.getMinutes() < 30 ? 0 : 30

  return {
    "0.0": "🕛",
    "0.30": "🕧",
    "1.0": "🕐",
    "1.30": "🕜",
    "2.0": "🕑",
    "2.30": "🕝",
    "3.0": "🕒",
    "3.30": "🕞",
    "4.0": "🕓",
    "4.30": "🕟",
    "5.0": "🕔",
    "5.30": "🕠",
    "6.0": "🕕",
    "6.30": "🕡",
    "7.0": "🕖",
    "7.30": "🕢",
    "8.0": "🕗",
    "8.30": "🕣",
    "9.0": "🕘",
    "9.30": "🕤",
    "10.0": "🕙",
    "10.30": "🕥",
    "11.0": "🕚",
    "11.30": "🕦",
  }[`${hours}.${minutes}`]
}

Now we just have to call changeFavicon(currentEmoji()) every minute or so. If we had to do it with plain JavaScript, a simple setInterval would make the trick:

// One minute
const delay = 60 * 1000

// Change the favicon when the page gets loaded...
const emoji = currentEmoji()
changeFavicon(emoji)

// ... and update it every minute
setInterval(() => {
  const emoji = currentEmoji()
  changeFavicon(emoji)
}, delay)

The React part

Since my blog is powered by Gatsby, I want to be able to use this code inside a React component, changing as little as possible. It is inherently imperative, as opposed to the declarative nature of React, and moreover has to be called every minute. How can we do that?

Enter Dan Abramov and his amazing blog post. Dan is a great writer who can explain complex things in a clear way, and I strongly suggest checking out this article, especially if you want a better understanding of React Hooks. You don’t necessarily need to understand everything in it — one of the strengths of hooks is that they can be used even without fully grasping the internal implementation. The important thing is to know how to use it. Here’s how that looks:

import { useEffect } from "react"
import useInterval from "./useInterval"

const delay = 60 * 1000

const useTimeFavicon = () => {
  // Change the favicon when the component gets mounted...
  useEffect(() => {
    const emoji = currentEmoji()
    changeFavicon(emoji)
  }, [])

  // ... and update it every minute
  useInterval(() => {
    const emoji = currentEmoji()
    changeFavicon(emoji)
  }, delay)
}

Finally, just call useTimeFavicon() in your root component, and you are good to go! Wanna see it work? Here’s a deployed CodePen Project where you can see it and here’s the project code itself.

Wrapping up

What we did here was cobble together three pieces of code together from three different sources to get the result we want. Ancient Romans would say Divide et Impera. (I’m Italian, so please indulge me a little bit of Latin!). That means “divide and conquer.” If you look at the task as a single entity, you may be a little anxious about it: “How can I show a favicon with the current time, always up to date, on my React website?” Getting all the details right is not trivial.

The good news is, you don’t always have to personally tackle all the details at the same moment: it is much more effective to divide the problem into sub-problems, and if any of these have already been solved by others, so much the better!

Sounds like web development, eh? There’s nothing wrong with using code written by others, as long as it’s done wisely. As they say, there is no need to reinvent the wheel and what we got here is a nice enhancement for any website — whether it’s displaying notifications, time updates, or whatever you can think of.


The post How to Create a Favicon That Changes Automatically appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Categories: Designing, Others Tags:

How to Prioritize Speed with a Mobile-First Design

December 9th, 2020 No comments

By the end of the year, the number of global smartphone users is expected to reach 3.5 billion. That’s a significant 9.3% increase over the last 12 months.

In a world where everyone is constantly connected to their mobile devices, it makes sense that web developers and designers would need to consider new rules for how they create engaging experiences. After all, most of us find browsing from our smartphones to be much more convenient than sitting down at a laptop each day.

With a little luck, you’re already taking steps to mobile optimize your website but standards are changing all the time. To make sure your website is up to scratch, here’s your guide to prioritizing your site for mobile, ready for the new year.

Understanding Mobile-First Design

The first step in updating your web design and development principles, is understanding the concept of mobile first design, and how it’s changed.

With a responsive website, you create something that adjusts to the screen size of any device; with a mobile-first site, you’re focusing first-and-foremost on the user experience that people get when they’re on mobile, taking that as your starting point, and building from there. Instead of building your website for the desktop and using mobile as an afterthought, you start with a consideration of mobile.

Even Google is highlighting the demand for this process lately, with the mobile-first indexing algorithm. If you can’t design for mobile-first, then you could risk your clients being unable to rise up the search engine ranks.

So, how do you get started?

1. Start With the Right Tools

Web developers and designers are nothing without a great toolkit.

The good news is that there are solutions out there that can help you to master the right skills for a mobile-focused user experience. For instance, Skeleton is excellent for small-scale projects that require fluid grids and minimal compiling.

Alternatively, Bootstrap can offer a one-size-fits-all solution for the front-end development for mobile devices. There’s a default grid system available, plenty of components, and JavaScript plugins to work with.

With the right tools, you can minimize and prioritize the content that’s most valuable for your website projects. This is crucial for maximizing website speed and creating clarity when it comes to content and imagery.

For instance, check out the ESPN website; it’s split into very easy-to-follow categories of content that are perfect for scrolling on a smartphone. The grid of videos makes it feel like you’re using a tool like YouTube.

2. Prioritize Mobile-First Elements

Once you have the right tools to assist you, it’s time to begin building your mobile-first website from the ground up. Rather than jumping straight into considerations of the latest design trends, it’s important to start with the foundations.

For instance, navigation within a mobile page is usually hidden under a hamburger button. However, you can take this concept to the next level too. For example, the Shojin mobile website only demonstrates the most important website options within the navigation bar to avoid overwhelming users.

The key here is to keep things as simple as possible, without restricting what your audience can do when they visit your website. Although you want to keep the number of interactive elements on your site small, you also need to ensure that those elements are easy to find and use.

All buttons and CTAs should be clear and tappable. Fonts need to be large enough to read from any screen, and your navigation system needs to be 100% simple, without slowing anything down.

On average, we recommend making all clickable elements at least 48 pixels in height.

3. Use Responsive Imagery and SVGs

Images are a crucial part of any website. They add context and appeal to your design. However, they can also seriously slow down your website if you’re not careful.

Remember, different devices have different demands when it comes to imagery. A desktop page may need a 1200px wide image, while a mobile-only needs the image to be 400px wide at most. The old way of making your images work was to load a large resolution image and use the same file on every platform. Unfortunately, this slows downloading time significantly.

Instead, it’s better to have at least two different versions of the same image for your mobile and desktop solutions. You can also consider SVG.

SVGs are incredibly scalable – more so than bitmaps. With SVG, you can ensure any icon or graphic continues to look sharp and clickable across all devices. Because these files are often smaller, your site loads quicker too! Hubspot is great at using SVGs.

Intricate illustrations are a massive component of HubSpot’s brand. If those images were saved as PNGs or other alternative files, then they would take forever to load. Because they’re all SVGs, you can enjoy the same consistent experience across desktop and mobile.

4. Get the Typography Right

It’s not just the big graphics and images that make a huge difference to your website when it comes to mobile-first design. You also need to think about the legibility and clarity of your website across all devices and platforms. If people can’t read the value proposition of the company that you’re designing for, you’re going to have a major problem.

Focus on making your content as easy to read as possible. Look into the typefaces that seem most appealing on a range of devices.

Remember to balance the body and heading font sizes for the device size too. You’ll need to ensure that the experience feels consistent and smooth as your users scroll through each page. Just take a look at the mobile version of the IMPACT website, for instance.

The headings aren’t as huge as they are on the desktop version of the website, and they’re displayed below, rather than above the featured image. However, this helps to give a more immediately eye-catching and structured experience to mobile users.

There’s even a handy “Search Engine Optimization” tag included, that users can click on if they want to find more related articles.

When it comes to typography, remember that it’s not just size and clarity that matter, but how things are structured throughout your website too. Your type should naturally guide your visitors along the page.

5. Master Available Device Features

Finally, on smartphones, you can accomplish a range of amazing things that you might not be able to do when using a desktop device. Your users can make calls, open apps, send messages, and more, all from within their mobile browser. They can also move their smartphone around a room, taking advantage of concepts like AR and VR.

Taking advantage of the unique capabilities that smartphone design can offer gives you a chance to get unique with your user experience.

Making the most of the mobile experience can be much simpler than you’d think. For instance, on a desktop site, you could list your phone number on a contact page. On a mobile site, the number can begin a call when clicked. You can also take the same approach with email addresses, and social media icons too.

Depending on how experimental you feel, there’s also plenty of opportunities to go above and beyond with your mobile features. You may decide to create a mobile app version of a website that your customers can download onto their phones.

Alternatively, you can look into things like AR technology. This could allow your users to practice placing items of furniture that they may be thinking of buying from an online retailer into their house, so they can see how well they work with their other interior design choices.

Making the Most of Mobile-First Design

Ultimately, having a responsive website that works on both mobile and desktop devices is mandatory in the modern world. However, going above and beyond with mobile-first design is a great way to get ahead of the game.

If you can focus on building a website that puts the experiences of mobile users first, then you can create something that’s much more likely to grab audience attention and deliver amazing experiences.

If nothing else, showing your clients that you have what it takes to design for mobile is an excellent way to ensure that you can gain as many new project opportunities as possible.

Source

Categories: Designing, Others Tags:

Black And White Is the New Black: 25 Eye-Catching Examples of Black and White Design

December 9th, 2020 No comments
abstract black and white flower design

Does #000000 and #FFFFFF mean anything to you? If you’re a designer, a programmer, or just someone who works in web design they probably do. When beautifully united, a black and white design can turn your artwork into a sophisticated and classy masterpiece.

Before we jump into our top black and white design picks, let’s take a moment to carefully dig out the symbolism behind this timeless color duo.

Black and White Design

black and white design illustration
by Karolin Schnoor

Black and white are the opposite shades that embody many connotations that we all get accustomed to over the years. Black is often associated with darkness, night, and seriousness while the color white represents light, purity, and innocence.

beautiful black and white illustration artwork
by Dániel Taylor

Speaking of light and dark, here’s a random fun fact: ever heard of the term “eigengrau”? Eigengrau can be translated as “intrinsic gray” or “almost black” but not quite. Even though black represents the absence of light, the human eye can not perceive true blackness. Instead, we see eigengrau whether our eyes are closed or open in the perfect darkness.

eigengrau and black colors comparison

In color psychology, black and white colors have many different associations. Black often refers to aggression, fear, and sorrow, whereas white usually symbolizes cleanliness, safety, and even new beginnings. But this doesn’t mean that the elegant color black always evokes something negative and depressing and white holds quite the opposite. It’s just the way they are used in our everyday lives and the way that they are embraced by different cultures.

For example, in many cultures, people tend to wear black at funerals. But this longstanding tradition does not apply to every culture in the world. Contrary to popular belief this historic tradition is mainly peculiar to Western cultures and dates back to the Roman Empire. It is believed that Romans were the trendsetters of wearing black garments when they lose a loved one.

However, in Asian and Middle Eastern cultures the official color of mourning isn’t black at all. White is worn at funerals because it symbolizes rebirth in Asian culture. In South Africa, red isn’t the color of passion but sorrow. In Egypt, as one might easily guess gold and yellow are quite common even in funerals. In Thailand, people wear purple, and in Iran, blue is the go-to color if you’re heading to a funeral.

Ghanaians attired in traditional funeral colors
Ghanaians attired in traditional funeral colors

While these color connations vary and can go on forever, the one thing that is acceptable in every culture is that black and white is a killer duo. Black and white contrast so well with each other that this combination is embraced by almost every branch of art. From filmmakers and fashion designers to graphic designers and photographers, the black and white design remains to be the number one choice when it comes to keeping things minimalistic yet charming.

woman raising both arms in a black and white photo
Credit: @lilianpereir

Whether you’re looking for an effect to create an enchanting dichotomy or just had enough of radiant colors, using black and white design can create a striking impact of boldness. You may think the absence of color results in unremarkable outcomes in a graphic design world ablaze with color, but polar opposites hold a vast potential if balanced right.

In graphic design, the black and white color combination is especially used if there is a text or image that needs to be the center of attention. The intensity and depth of these hues give designers the ability to focus on the message without having too many colors involved while creating maximum contrast.

Without further ado, let’s leave the color aside and take a look at the stunning examples of black and white designs that never goes out of fashion.

25 Powerful Black and White Design Examples

Photography - concept art layout artist ui design portal nature black and white 2 colors graphic design hero image logo brand identity photography ui web design web website minimal typography concept design
by Ania Cywinska
- art direction symbol mood minimalism texture band merch band logo caspian t-shirt design t-shrt minimal black and white typography type photography design
by Sam Kaufman
black and white website design
by
black and white pillar illustration
by Dániel Taylor
Double Barrel Website Design
by Double Barrel
black and white abstract website design
by Skuares | Creative and Digtial Studio
black and white design sculpture
by Stuurmen In SOTD
by Gizem Vural
Daft Punk Website concept visual design black and white modern layout bold music dark ui futuristic homepage fashion landing page creative typography web design interface minimal clean ui design ux
by Achraf Elkaami
?Mood lights man nature black and white landscape art geometry design character vector concept flat texture illustration
by Alina Starovoitova
by Gergely:K
Into Infinity texture photography black and white painting design illustration
by Sam Kaufman
black white website design
by Soyour Style
Cabaret poster black and white illustration
by Agata Ledzwa
BASIC Culture Manual
by BASIC Culture Manual In SOTD
black and white illustration
by Jono Garrett
Melanie DaVeid Website
by Melanie DaVeid
Genesis black and white design
by Genesis In Nominees
black white website design
by Urban Edge Design
Yule grunge style black and white illustration
by Nicolas Vittori
black and white website design
by ChintanNed.
black white website design
by Marcin Kaniewski
girl with a tattoo pencil cute product design web design ui ux doodle cigarette tattoo simple design cartoon girl character design character black and white monochrome minimal line illustration comic
by tatooine girl
Stonelime Website
by Stonelime
Posters X Skillrep graphic black and white pattern printing prints print poster design poster art posters poster branding and identity branding agency branding design brand identity brandidentity brand design brand branding sports branding sport
by Antonio Calvino

Wrapping Up

We can’t argue that different vibrant colors enhance the design. But this doesn’t mean that you can’t create a powerful impression by using only black and white. With the right application, the duality of black and white design is more than enough to leave a strong impression.

Not a fan of color? Share your thoughts in the comments below and tell us about your favorite examples of black-and-white design.

Do you like traditional and vintage-inspired designs but had enough of monochrome style? For our readers seeking to see captivating vintage colors rather than black and white, we compiled some great examples of vintage color palettes to inspire you.

Categories: Others Tags:

Very Extremely Practical CSS Art

December 9th, 2020 No comments
Examples of Lynn Fischer's single div projects: repeated polar bears, plants on a shelf, a blinking light, and a tiny electronic piano.

I’ve always enjoyed the CSS art people create, but I’ve never ventured into it much myself. I’m familiar with many of the tricks involved, but still find it surprising every time: the way people are able to make such fluid and beautiful images out of little boxes. I always end up digging around in dev tools to see how things are done, but I had never seen the process unfold.

Any time CSS art starts getting attention, there is always someone around to say “that’s not practical” or “just use SVG” or something similarly dismissive and boring. It’s a terrible argument, even if it was true — no one is required to be Practical At All Times. What a terrible world that would be.

In October, I took the time to watch Lynn Fisher (Twitter, CodePen), one of my favorite CSS artists, live-stream her single-div process. Somewhere in the back of my mind, I assumed single-div artwork relied on highly complicated box-shadows—almost a pixel-art approach. I’m not sure where that idea came from, I probably saw someone do it years ago. But her process is much more “normal” and “practical” than I even realized: a number of reasonably layered, sized, and positioned background gradients.

Wait. I know how to do that. It’s not the technique that’s magical—it’s the audacity of turning a few gradients into a block of cheese with cake inside!

I’ve used all these properties before on client projects. I’ve created gradients, layered images, sized them, and positioned them for various effects. None of that is new, or complicated, or radical. I really didn’t learn anything at all about the CSS itself. But it had a huge impact on my perception of what I could accomplish with those simple tools.

Within a few weeks, I was using that in production. Again, it’s nothing fancy or complicated—the perfect low-hanging fruit where a custom SVG feels just slightly too bulky. Here’s the effect I created, for a personal project, with a few custom properties to make adjustment easier:

CodePen Embed Fallback

Last week we used a similar trick as part of a Very Practical & Official client component library. It was Stacy Kvernmo’s idea, and it worked great.

Thanks Lynn, and all you other fabulous CSS Artists! Thanks for showing us all how much farther we can push this language that we love so much, and the Very Serious tools we use every day.


The post Very Extremely Practical CSS Art appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Categories: Designing, Others Tags:

TypeScript & Relevance

December 8th, 2020 No comments

In our wide world of building for the web, we have every opportunity to talk about tools. We lunge to fill every gap we find in our projects with a definitive technological approach. Some of us are given “a seat at the table” feasting on even the most minuscule of technological debates. This marketplace of opinion is founded upon a desire to arrive, at least for the moment, at an optimum. We postulate about tooling so that we might achieve efficiency, extend our exploratory reach, or pave the quickest path to viability.

If you have read anything on this website, you are likely more than aware of the notion of Imposter Syndrome—the debilitating reflection that you do not deserve to be in the position you hold or know what you think you should know. Those of us that have learned to deal with Imposter Syndrome are at risk of slipping into (what I recognize in myself as) Relevance Syndrome—a mid-career complication of Imposter Syndrome. It is what happens when you spend years repeating the mantra, “I deserve to be here,” but have never truly accepted its premise. It happens when you attempt to counteract the softening of your hard skills and end up hardening your soft ones. Maintaining relevance sure is a great reason to opine about tooling.


With that, I will casually lean against this brick wall, slide my shades to the tip of my oh-so-relevant nose, and dismissively mention that yes, I too, have learned TypeScript. One year into the experience, and I can say that I have grown quite fond of it.

I’d like to use TypeScript’s purpose to make a separate point, so if you will, please bear with me through this quick example.

TypeScript, among other things, enforces the types of things you send around. Take this JavaScript function that multiplies two numbers:

const product = (x, y) => x * y;

Imagine you broke your rules by calling this function without numeric arguments like, product('A', 'B'). There are many ways you could validate this function to catch this scenario, but your validation would only occur at the time of execution—while the script is running, often in a browser. You can’t really debug this until those events occur. What TypeScript can do is tell you that you are breaking the rules before execution — as you are writing your code. To do this, you state which types of things you are using.

const product = (x: number, y: number) => x * y;

Here, we specify types for the two arguments, saying that variable x and y are both a number. Now, if you were to use this function with the wrong types of arguments, your application script would loudly fail to build. Because your script must work before it can be built, you never need to worry about these sorts of errors ever occurring in the wild. It takes a lot of effort to achieve this, however. You must define your types, everywhere.

You may find writing TypeScript types to be like organizing a bookshelf. You set some rules that, when followed, achieve an optimal organization that is easily-referenced.

Or, you may find writing TypeScript types to be like forcing your child into extracurricular activities against their will. It is rigidly unforgiving and doesn’t let your code figure out who it is and where it is going! You’re stunting its development by imposing your will upon it!

I’d like to think there is as much capacity for value in a well-organized bookshelf as there is for ingenuity in an independent spirit, and there is so much to learn from both.


Let’s end with considering relevance again.

You may feel pressure to know what you are doing before you do it—to type yourself before your code executes. You may feel pressure to account for all your failures and learnings before you give it a go in public. That, my friends, is an immense effort you have taken on to maintain your type. It is a pressure and rigidity that, at times, is great to put upon our software, but is unfair to apply to yourself or others.

We all have our "1" + "1" = "11" moments. They are relevant and entirely human, if not a form of genius. Embrace them. To strictly prevent them is unscalable.

I feel in this moment that I may have learned how to learn TypeScript this year, and hope to hold on loosely to whatever type that makes me.


The post TypeScript & Relevance appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Categories: Designing, Others Tags: