Frontend Masters Boost RSS Feed https://frontendmasters.com/blog Helping Your Journey to Senior Developer Thu, 18 Apr 2024 23:43:31 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.2 225069128 What’s Going On in Dark Theme / Light Theme Land https://frontendmasters.com/blog/dark-and-light/ https://frontendmasters.com/blog/dark-and-light/#comments Thu, 18 Apr 2024 23:43:30 +0000 https://frontendmasters.com/blog/?p=1716 There has been a fresh round of enthusiasm and writing around light mode / dark mode support for the web lately. I think it’s driven partially by the new light-dark() function in CSS (CSS Color Module Level 5 spec) that makes it easier to declare values that change depending on the mode. Here’s the basic usage:

html {
  color-scheme: light dark;

  background: light-dark(white, black);
  color: light-dark(black, white);
}

In real life, you’d probably be using custom properties with your colors. So you’d set up your colors for light mode, then when the special dark mode media query matches, you’d re-declare all those variables, and then you’d use them. Paweł Grzybek has a nice basic explanation. Here’s a comparison.

You used to have to do this:

:root {
  color-scheme: light dark;

  --dark-color: #292524;
  --light-color: #f5f5f4;

  --text-color: var(--dark-color);
  --bg-color: var(--light-color);
}

@media (prefers-color-scheme: dark) {
  :root {
    --text-color: var(--light-color);
    --bg-color: var(--dark-color);
  }
}

body {
  color: var(--text-color);
  background-color: var(--bg-color);
}

And now you can do this:

:root {
  color-scheme: light dark;

  --light: #292524;
  --dark: #f5f5f4;
}

body {
  color: light-dark(var(--light), var(--dark));
  background-color: light-dark(var(--dark), var(--light));
}

Essentially, it prevents you from having to use the @media query and re-declare variables. I like it. I think it makes code like this more readable and succinct — pending variable naming and usage of course.

Here’s what it’s good for: designing a site that responds to the operating system level setting for light mode / dark mode. And you have to be good with the level of browser support (no Safari just yet, as I write, but it’s in preview). If you are wondering what the fallback is, it’s doing things the old way (see above), and if you’re going to write that you might as well leave it at that.

If you’re going to want to offer more themes than just light and dark, well, you’re out of luck here, you’ll need to implement something else, likely based on changing classes on the <html> element and updating variables when the class matches.

html.nickleoden-theme {
  --bg-color: purple;
  --text-color: green;
}

I could imagine a more composable toggle method in the future, but this is what we have for now.


When I first saw light-dark(), I liked the basic idea, but I figured as soon as you offer your own user toggle for mode, you’d be out of luck. After all, you can’t change what the prefers-color-scheme media query returns, and thus which of the two values light-dark() will pick. But it turns out you can! The trick lies in that color-scheme property. You’ll see recommendations that you use color-scheme: light dark;. If you only set one or the other, you’re forcing light-dark() to pick the relevant side.

So then your user toggle could force one or the other values on the document if it’s set. (If it’s not set, leave it alone!). Here’s that working:

I like that this is based on a CSS property, as it means that you can use the cascade if you need to, setting the color-scheme on a per-element basis.

That’s just cool I think.


Anne Sturdivant blogged some recent learnings about all this color theme stuff and I learned a few things. For one, color-scheme also has normal which is “no color schemes defined, default to the browser or OS setting”, which I would assume means works the same as light dark, but in my testing did not switch over to dark when I switched my OS 🤷. Then there is only as a keyword to, uhm, I guess even more forcibly set the theme? It’s not clear to me, and also not really supported yet anyway.

Annie also clearly points out that when you change the color-theme away from the default light mode, all sorts of stuff changes. It’s certainly not just the results of light-dark(). If you set dark, the UI scrollbars go dark, and all the different form controls go dark. In fact, that might be the number one use-case for color-scheme really, even if we do have accent-color now.


There is also this whole idea of System Colors that tends to come up in writing about this, so I’m going to do the same. These are “named” colors, like rebeccapurple, but they have a fancy baked in ability in that they can change when the color-scheme changes. So if you want to flip out basically white and black, but not bother with variables and fancy functions and whatnot, you’ve got:

body {
  background-color: Canvas;
  color: CanvasText;
  color-scheme: light dark;
}

Note the Canvas and CanvasText, those are the System Colors. Allow me to snipe the images of the available colors and what they look like in the different modes from a great article by Mads Stoumann.

Mads made a cool demo of a theme toggler that uses newfangled style queries that is worth checking out. Remember, though, that these client-side-only theme switchers are really just demos. It’s likely on a real-world site, if you’re offering a switcher, you should try to persist that information. A cookie, sessionStorage, localStorage, to a database… something. Then when you do that, there is the risk that the page renders before you can access and set that information, leading to FART, my most successful coining of an acronym ever. It’s a tricky thing, as delaying rendering just for something like this doesn’t feel right.


Another thing percolating in the industry is, as Bramus puts it: What if you had real control over Light Mode / Dark Mode on a per-site basis? I always say that web standards bodies, and even browsers themselves to some degree, are at their best when they see developers toiling and doing the same sort of things, and then introduce better and standardized methods. Properly implementing color themes and the toggling methods with persistence is real work! It doesn’t look like color themes are just a fad, so I think this is a clear opportunity for help.

I think a bit of browser UI would be perfectly welcome:

A perfect implementation would be that the browser itself remembers what choice you’ve made (light, dark, or default to system preference), and that is applied during rendering, avoiding FART. Sounds like it is going to require a new API and then potentially browsers actually using it themselves, which is kinda funny to think about. I normally think about web APIs as being for developers, not browsers.

]]>
https://frontendmasters.com/blog/dark-and-light/feed/ 2 1716
Color Picker with Display P3 https://frontendmasters.com/blog/color-picker-with-display-p3/ https://frontendmasters.com/blog/color-picker-with-display-p3/#respond Fri, 12 Apr 2024 22:46:41 +0000 https://frontendmasters.com/blog/?p=1688 One of my recent moanings-and-groanings is the fact that seemingly no color-picker supports Display P3 colors. Display P3 allows you to use far more vivid colors then we’ve historically had access to in CSS, but now are totally supported in CSS through newer color functions like oklch(). Not even the built-in color picker to macOS.

Well it’s time for me to quit my bitchin’ because I’ve just seen two. I only looked at Mac stuff because that’s what I use. Feel free to chime in with options on other operating systems.

XScope can do it — but XScope is $50 and I find it heavy handed for the work I do. System Color Picker is free and I find very nice in it’s simplicity (it’s just a UX improvement over the default). The workflow I want, and it delivers, is: pick color from screen, have color on clipboard in OKLCH (that’s it).

]]>
https://frontendmasters.com/blog/color-picker-with-display-p3/feed/ 0 1688
Okay, Color Spaces https://frontendmasters.com/blog/okay-color-spaces/ https://frontendmasters.com/blog/okay-color-spaces/#respond Fri, 01 Mar 2024 16:56:39 +0000 https://frontendmasters.com/blog/?p=1069 Eric Portis did a bang up job explaining color spaces on the web. sRGB is, as Eric puts it “the web’s dominant, default color space”, but he doesn’t spend much time on that. Thanks to recent evolutions in web tech, we have access to a wider gamut of colors (P3) and more color spaces than we’ve had before.

What is a color space? It is a way of modeling colors on a 3D graph this is… made up. They aren’t scientific truths or anything. They are just ideas from smart people that help us do useful things with colors, like interpolate between them for gradients. A color space might take on this responsibility: be able to change one of the values and have the result be predictable and and consistent. That’s what OKLCH does, why I’m hot on it, and I think you should at least know about it.

]]>
https://frontendmasters.com/blog/okay-color-spaces/feed/ 0 1069
The Color Input & The Color Picker https://frontendmasters.com/blog/the-color-input-the-color-picker/ https://frontendmasters.com/blog/the-color-input-the-color-picker/#comments Thu, 18 Jan 2024 16:25:43 +0000 https://frontendmasters.com/blog/?p=503 HTML has a color input that is pretty decent:

<input type="color">

That’s it. Support across the board. However, browsers can and do have different approaches to what happens when the input is used.

macOS Chrome (has it’s own UI)
macOS Firefox (uses the macOS system color picker)
macOS Safari (has it’s own UI, allows you to open macOS system color picker)
Windows Chrome (has it’s own UI) (Edge looks the same)

Window Firefox (uses the Windows system color picker)
Chrome on Android (Pixel 8)
Safari on iOS 17

Ultimately: the user activates the input, may choose a color using the provided UI, and the color becomes the inputs value.

It’s not my favorite that you can only get 6-digit HEX colors in and out of it, like #F06D06 and the like. No transparency, no other formats. I have a feeling display-p3 color formats like OKLCH will have a real popularity boom in coming years (because they are sweet: more colors, more logical) and we’ll start wanting better integration, like with color inputs.

The Eyedropper

Note that some of those color panels have an eyedropper function. Those are awfully handy. Sometimes the color I’m shooting for is right on my screen somewhere, and a color eyedropper is the fastest and easiest way to grab it.

Turns out there is a native API for an eyedropper! You don’t have to use a color input to access an eyedropper.

You can test for support like:

if ("EyeDropper" in window) {
  
}

And use it like:

// used in case you need to cancel the experience
const abortController = new AbortController();

const eyeDropper = new EyeDropper();

try {
  const result = await eyeDropper.open({ signal: abortController.signal });
  console.log(result.sRGBHex);
} catch (e) {
  console.error(e);
}

Demo

Anywhere you use a color input, you might as well offer an eyedropper, too.

Test for support first, of course, but I think that statement above largely holds true. Offering a dedicated eyedropper button means saving users a step in case that’s what they are trying to do anyway.

And using the native one is nice, as I find it’s generally a nicer color picker than anything integrated into app itself. Eyedroppers built into very major design tools like Adobe Photoshop and Figma largely only let you pick colors from inside the documents themselves, not from anywhere on the screen. Boooo.

The demo above shows how a color input and eyedropper button can work together right next to each other.

Support

Support for color inputs is good across the board, but support for the EyeDropper API, at the time of this writing, is just Chrome’n’friends. No Safari or Firefox.

But the real UX story isn’t quite that clear.

In Firefox, the color input opens the native color picker (both macOS and Windows) and that native picker has an eyedropper. So Firefox users have decently quick access if they need it.

In Safari, the native color picker is an extra click away, but it’s still gettable.

Chrome on Android has no support.

I would have assumed iOS didn’t either, and it’s true that it doesn’t support the EyeDropper API, but in a quick play of iOS 17 on an iPhone 15, the native UI for a color picker has an eye dropper (!!). That’s pretty cool. I would think that brings Safari generally a lot closer to offering the API directly.

]]>
https://frontendmasters.com/blog/the-color-input-the-color-picker/feed/ 2 503