Frontend Masters Boost RSS Feed https://frontendmasters.com/blog Helping Your Journey to Senior Developer Wed, 14 Aug 2024 17:25:38 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.1 225069128 Relative Color Syntax — Basic Use Cases https://frontendmasters.com/blog/relative-color-syntax-basic-use-cases/ https://frontendmasters.com/blog/relative-color-syntax-basic-use-cases/#comments Mon, 12 Aug 2024 18:38:35 +0000 https://frontendmasters.com/blog/?p=3448 As of last month, Firefox 128’s support of the relative color syntax means we’ve now got support across the board. I’m excited about that as it’s an extremely powerful way to manipulate colors in CSS. Plus it was part of Interop this year so that is further proof that is trucking along nicely.

The syntax with generic names looks like this:

color-function(from origin-color channel1 channel2 channel3 / alpha)

Here’s how it works in my head:

Add Opacity to a Color you Already Have

It’s common to have CSS custom properties set up for colors on a project.

html {
  --color-yellow: oklch(80% 0.15 94);
  --color-green:  oklch(70% 0.25 140);

  ...
}

Now you want to use that yellow, but at about 50% opacity. How do you do that? There are actually a couple of ways to add transparency to an existing color, but in my opinion the relative color syntax is the nicest.

In the past, I’ve split out the color values like this:

html {
  --color-yellow-lch: 80% 0.15 94;
  --color-yellow: oklch(var(--color-yellow-lch);

  ...
}

That way I could either use the color all together, or use the split out values to apply opacity:

.box {
  background: var(--color-yellow);
  border-color: oklch(var(--color-yellow-lch) / 50%);
}

But that can get out of hand! You could also split each color into L, C, and H, the combine those, giving you five variables for every color. Too much.

With the relative color syntax, breaking down colors isn’t necessary. You apply alpha (and other transformations) on demand, leaving the original single color as the only variable (token) you need.

.box {
  background: var(--color-yellow);
  border-color: oklch(from var(--color-yellow) l c h / 50%); 
}

I much prefer the idea of keeping the main colors tokenized as custom properties, then tweaking them as needed on demand.

Darken a Color you Already Have

In the above example, we had --color-yellow and I ended by saying I prefer doing one-off tweaks on demand rather than making a whole new variable. If you have a ton of usage of a slightly-darker version of a color, then sure, make a new variable and stay consistent. But if it’s more of a one-off, relative color syntax is awesome:

.box {
  background: var(--gray-5);

  h2 {
    color: var(--color-yellow);
    /* Darkened version of yellow */
    border-bottom: 2px solid oklch(from var(--color-yellow) calc(l - 0.4) c h);
  }
}

Lighten a Color you Already Have

Same deal here. I’m using OKLCH because I like it, particularly the “uniform brightness” characteristic. Meaning when doing this darkening and lightening across different colors, it feels like it lightens/darkens the same amount. Which feels weird to write, but it’s true. Other color spaces do not lighten and darken consistently.

.box {
  background: var(--gray-5);

  h2 {
    color: var(--color-orange);
    /* Darkened version of orange */
    border-bottom: 2px solid oklch(from var(--color-orange) calc(l + 0.4) c h);
  }
}

Easy Variations

Avoiding making too many variables is a nice consequence of the relative color syntax, but you can still use the relative color syntax to make variables if it’s useful to have them.

I like the idea of starting with a base color, perhaps a slightly tinted gray, and then making the official variations with the relative color syntax.

html {
  --base-gray: oklch(12.94% 0.02 159);
  
  --gray-1: var(--base-gray);
  --gray-2: oklch(from var(--base-gray) calc(l + 0.1) c h);
  --gray-3: oklch(from var(--base-gray) calc(l + 0.2) c h);
  --gray-4: oklch(from var(--base-gray) calc(l + 0.3) c h);
  --gray-5: oklch(from var(--base-gray) calc(l + 0.4) c h);
  --gray-6: oklch(from var(--base-gray) calc(l + 0.5) c h);
  --gray-7: oklch(from var(--base-gray) calc(l + 0.6) c h);
  --gray-8: oklch(from var(--base-gray) calc(l + 0.7) c h);
}

The fact that you can start with any color, use any color function, and manipulate any part of the color is incredibly powerful. The above use cases are pretty basic. I’m sure more talented designers or developers who deeply know color will be able to do much more interesting things!

]]>
https://frontendmasters.com/blog/relative-color-syntax-basic-use-cases/feed/ 1 3448
Figma Typography Variables https://frontendmasters.com/blog/figma-typography-variables/ https://frontendmasters.com/blog/figma-typography-variables/#respond Mon, 05 Aug 2024 14:07:03 +0000 https://frontendmasters.com/blog/?p=3203 When we were recording the “Figma for Developers, v2” workshop, I mentioned that Variables were in beta and that they couldn’t be used with typography yet. Coincidentally, typography support was added the next day after the recording. Figma variables are also no longer in beta.

Let the record show, I was correct during the recording—and that’s the important part, right? Let’s review what Figma Variables are, then explore how to use them with your typography system.

A Brief Review of Variables in Figma

In Figma, Variables are placeholders for reusable values—just like JavaScript. These values include colors, numeric values, and more.

Variable dropdown includes Color, Number, String, and Boolean
The variable types in Figma

Once set, you can use them across different design elements in your Figma designs. Variables can also be shared with your team and used across multiple Figma files. This makes it easy to make sweeping changes to your design system with a few button clicks.

Using Variables to Control Typography in Figma

Previously, Figma’s variables were great for colors and spacing, ensuring consistency. However, we lacked the same flexibility with fonts. We had to use various styles and components for different themes or brands. Styles are still incredibly useful, but they lack the ability to change a single value used by multiple styles. This makes a task like switching a font incredibly tedious as you’d have to update every single style. In the course, we explored some approaches using various plugins in an attempt to automate this process, but the constraint was still there. This was a significant limitation and meant that we had to combine multiple approaches in order to maintain consistency throughout our design system.

Now that variables can be used with typography, you can now define variables for font settings. Figma now supports using variables for the following properties: 

  • font family
  • font weight & style
  • font size
  • line height
  • letter spacing
  • paragraph spacing & indentation

Each of these properties can be controlled using the same variable types that we saw when we walked through variables during the course, with numbers and strings being the most pertinent for defining typography properties. For example, you can use a string variable to define the font family.

With the values set, you can select a variable when selecting the font family in the left-side panel in the Figma canvas. Changing the variable will now change all text in your designs that reference this variable, allowing you to quickly make changes across your entire design by updating a single value.

Here’s a quick video demonstrating setting a block of text to a variable, then changing that variable:

There are still a few limitations. For example, variables don’t support percentages for line heights. Variables also don’t autocomplete for spacing or line height. Hopefully, Figma will address these soon.

Using Variables with Modes

In the course, we used Variable Modes to switch between light and dark themes as well as different responsive breakpoints. This approach also works with our new typography variables allowing your variables to point to different variables depending on what mode you’re in.

Imagine managing font sizes for different viewports. Create a “Typography” collection in the variables editor. We’ll create two modes: Desktop and Mobile. Depending on which mode we’re using the variables will have one of two values as seen in the screenshot below.

With these changes, we can switch to a smaller set of font sizes when designing for mobile. If we need to change the font size across all of our mobile views, we can simply update the appropriate variable. 

One thing that  makes variable modes powerful is that any layer set to Auto will inherit the any mode set on the parent. This means that if you switch the mode of the frame containing multiple text elements from Desktop to Mobile, all of your typography will automatically update to the values defined in the Mobile mode.

Being able to support different font sizes and spacing across viewports is the most compelling application of typography variables for me, personally. But, they could also be useful if you had to support multiple brands or themes in your design system. 

For example, you could have a different mode for each brand theme you support. You could also define different font families for your Android application as opposed to your iOS application. You could even define different font sizes for your marketing website as opposed to your application’s user interface.

What About Styles?

Prior to supporting variables within typography in Figma, we used Styles—and these are still useful. A variable can represent one value. Styles, however, can store a composite of values (e.g. font family, size, and line height). This gives us the ability to use variables as primitives, define the font, size, and spacing for our typography and then save that combination as a style.

It’s less about whether to use styles or variables and more about how to use styles and variables. What’s really cool about this is that you can use a single variable as part of a number of different types. Updating that variable will then immediately update every style that relies on that variable.

In Conclusion

Introducing variable support for typography in Figma is definitely a welcome change that we’re already beginning to leverage in our internal design system at Temporal. Variables now unifies colors, spacing, and typography using a single approach. Combining variables with styles is powerful, as well. Variables allow for individual changes, while styles provide preset options. This mix helps us build and update design systems with a lot less hassle.

That said, some features are missing, such as percentage line heights and spacing suggestions. But, I suspect those features will be coming soon and I’ll have to update this yet again.

In the meantime, I encourage you to take the typography in one of your existing designs and update using typography variables. I suspect you’ll be pleasantly surprised with how easy they are to work with.

]]>
https://frontendmasters.com/blog/figma-typography-variables/feed/ 0 3203
Why is this thing in Dark Mode? https://frontendmasters.com/blog/why-is-this-thing-in-dark-mode/ https://frontendmasters.com/blog/why-is-this-thing-in-dark-mode/#respond Wed, 03 Jul 2024 16:09:48 +0000 https://frontendmasters.com/blog/?p=2907 I was looking at an email in a web app the other day, and it was showing it to me in “Dark Mode”. The email itself (of my own creation) purposely doesn’t bother to set a background or color for the most part, as then the defaults kick in which help naturally support both dark and light modes. So I was pleased! It worked!

Email in “Dark Mode” in Front
Email in “Light Mode” in Front

But then I was like… why am I looking at this email in Dark Mode? While I was working on the email, it was in Light Mode. I made it using MJML and the VS Code Extension which gave me a preview of the email, it was was in Light Mode there, so it looked surprising to me in Dark Mode that first time.

First I checked my System Settings on macOS to see what was going on there:

Light Mode there, so it wasn’t my system that was forcing Dark Mode.

Then I checked my browser. I happened to be using Arc, which has Themes.

That selected option on the left is “Automatic Appearance” which is what some things call “System” meaning match what the OS is doing.

Since that was set to “Automatic Appearance” it was following the OS’ Light Mode so that wasn’t doing it (probably). There is also Command Bar shortcuts in Arc. Try typing “Switch” in there to see actions to change it:

Other browsers do it differently, but can do it. For example you can “Customize Chrome” from a button on the Start Page in which you can force a theme or set to “Device”.

But this wasn’t explaining it for me either, as I was Light Mode through both of those layers.

What it turned out to be was a website-level setting. I was using the email app Front. Front has it’s own settings for themes, and in there indeed it was forcing a Dark Mode.

Changing that would change the colors of my email, which is exactly what I was trying to figure out.

So in terms of power, It’s like:

  1. Website setting
  2. Browser setting
  3. OS/Device setting

And those top two typically have an option to allow the setting to fall through to the next level.

That’s a lot of stuff to check when you’re trying to figure out what is controlling a color theme! I’m tempted to say too many, but when it comes to user control over websites, I tend to be in the camp of giving as much control to the user as possible. That leaves me extra conflicted about adding browser level color mode switches on a per-side basis, as it will likely lead to a 4-level system of diagnosing what mode is active.

]]>
https://frontendmasters.com/blog/why-is-this-thing-in-dark-mode/feed/ 0 2907
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