DEV Community

Cover image for Using CSS prefers-reduced-transparency and light-dark()
Matt Angelosanto for LogRocket

Posted on • Originally published at blog.logrocket.com

Using CSS prefers-reduced-transparency and light-dark()

Written by Elijah Agbonze✏️

As users, we all have different preferences for the applications we use. Usually, these preferences are set on our device to be applied to all applications. In the past, websites would have little to no idea about the preferences set by users. Developers would set features and themes based on what they believed were the most popular, inadvertently causing accessibility conflicts.

For example, many developers and gamers prefer dark themes. But assuming that all developers and gamers prefer a dark theme and setting your website to a dark theme would be unpleasant for developers and gamers who prefer a light theme.

Ideally, you would design your application so that features align with whatever preferences each user has set. New CSS features are allowing developers to optimize their websites to fit user preferences.

In this article, we will talk about two new CSS features for optimizing according to users' preferences. The first is prefers-reduced-transparency, which reduces translucency, and the second is light-dark(), which sets a light or dark theme. We will also look at live demos of these features.

The prefers-reduced-transparency media query

The CSS prefers-reduced-transparency media query allows you to optimize your elements to use less or no transparency by detecting whether a user has set a reduced transparency preference on their device settings:

/* syntax */
.transparent-element {
  opacity: 0.6;
}
@media (prefers-reduced-transparency) {
  /* reduce elements transparency */
  .transparent-element {
    opacity: 1;
  }
}
Enter fullscreen mode Exit fullscreen mode

transparent-element only becomes opaque when the user has the reduced transparency feature turned on. You can turn yours on if you’re using the following operating symptoms:

  • Windows 10/11: Settings > Personalization > Colors > Transparency effects
  • macOS: System Preferences > Accessibility > Display > Reduce transparency
  • iOS: Settings > Accessibility > Display & Text Size > Reduce Transparency
  • Android: Setting > Accessibility > Visibility enhancements > Reduce transparency and blur

Before we jump into more examples of using the prefers-reduced-transparency feature, let’s look at why people use it and why you (as a developer) should care about it.

Why use prefers-reduced-transparency?

As a web developer, your goal is usually to make a UI consistent for all users and to make your website fully accessible.

If your website’s UI is made up of transparent text or images but there are users who do not prefer transparent objects, there is a possibility that those users may struggle with your website and exit it entirely. This can be due to several reasons:

  1. Visual impairments or sensitivities: Some users may have visual impairments. Reducing transparency can improve the contrast between texts and background elements, making it easier for them to read and interact with the content
  2. Performance: On older and less powerful devices, transparent elements such as overlays and blurred backgrounds can require additional processing power and memory
  3. Battery life: Devices with AMOLED or OLED displays may use less power when displaying solid colors compared to transparent elements

Additionally, there are some users who simply prefer a solid, straightforward UI.

Demo: Hands-on with prefers-reduced-transparency

At the time of writing, prefers-reduced-transparency is still experimental and not supported in most modern browsers. So you want to make sure it works as expected in your support browser before moving to production.

You can test the example below using Chrome 118 and above. You can also use Firefox, but you will need to set layout.css.prefers-reduced-transparency.enabled to true. To do that, open a new tab and type in about:config. Then, search for layout.css.prefers-reduced-transparency.enabled and toggle the Boolean to true.

In our earlier example, we basically made a transparent element non-transparent by simply adding a media rule. Now, we will take it a step further and use a day-to-day example:

See the CodeCodePen.

Now, if you head to your device preferences and turn on the reduced transparency, you’ll notice that the card elements become fully opaque.

When you hover over each card, the element only scales up and down. In other use cases, you may need to specify a completely different hover declaration to differentiate between the hovered element and the others. This is an example in a header nav:

.nav li {
  opacity: 0.7;
}

.nav li:hover {
  opacity: 1;
}

@media (prefers-reduced-transparency) {
  .nav li {
    opacity: 1;
  }

  .nav li:hover {
    text-decoration: underline;    
  }
}
Enter fullscreen mode Exit fullscreen mode

Addressing each transparent element in the media rule and reducing the transparency for each element can be a pain. So a clean and simple way to adjust the transparency of each applicable element would be to use CSS variables wherever possible. For example:

/* using CSS variables */
:root {
  --primary-color: #3caf507d;
  --opacity: 0.7;
}

.transparent-element {
  opacity: var(--opacity);
}

.transparent-background {
  background-color: var(--primary-color);
}

@media (prefers-reduced-transparency) {
  :root {
    --primary-color: #3caf50;
    --opacity: 1;
  }
}
Enter fullscreen mode Exit fullscreen mode

So far, the examples we’ve seen have to deal with reducing the transparency for users who prefer that. But it is also possible to build your website so that it supports opaque elements by default, while providing users the option to have transparent elements.

To do that, we would need to assign a value to prefers-reduced-transparency. There are two values that can be assigned to prefers-reduced-transparency:

  1. no-preference, which indicates that the reduced transparency is not turned on on the user’s device
  2. reduce, which indicates that the reduced transparency preference is turned on by the user
/* syntax */
    .opaque-element {
      opacity: 1;
    }

    @media (prefers-reduced-transparency:no-preference) {
      /* add transparency to elements */
      .opaque-element {
        opacity: 0.6;
      }
    }
Enter fullscreen mode Exit fullscreen mode

Here is a demo of our testimonial example:

See the CodePen.

Now you have to be careful how you set the transparency of your app. From all the examples you’ve seen, you’ll notice that the default behavior needed for the app is always set before optimizing to fit users' preference.

If your app favors transparent elements by default, you should set that first and then use the prefers-reduced-transparency to adjust to less transparency.

This is important because not maintaining this consistency could cause your app to have an inconsistent UI where elements that were intended to be transparent wind up being opaque for browsers that don’t yet support prefers-reduced-transparency:

.transparent-element {
  opacity: 1;
}

@media (prefers-reduced-transparency:no-preference) {
  .transparent-element {
    opacity: 0.6;
  }
}
Enter fullscreen mode Exit fullscreen mode

The default should always be set first before any optimizations.

CSS light-dark() function

light-dark() is a CSS function that enables setting two colors for a property in which one of the colors will be used depending on the theme set by the user on their device.

I mentioned at the beginning of this article that most developers prefer a dark theme compared to a light theme. In the past, optimizing your app to fit the user’s theme preference was done globally using prefers-color-scheme, but with the light-dark() function, you can address each theme from a CSS property:

:root {
  color-scheme: light dark;
}

body {
  background: light-dark(#f4f4f4, #0b1121);
}
Enter fullscreen mode Exit fullscreen mode

Here if our testimonial example from before with the light-dark() function implemented:

See the CodePen.

To use the light-dark() function, color-scheme must be set to light dark. Being at the :root would make it globally accessible.

N.B., make sure you’re using Firefox because, at the time of this writing, the light-dark() function is only supported in Firefox.

The name of this function indicates that the first color passed into the function is when the device is on a light theme, and the second is when it’s on a dark theme. For example, I could set my website’s header to be dark blue when on a dark theme and light blue when on a light theme, so I’d have this:

header {
  background: light-dark(lightblue, darkblue);
}
Enter fullscreen mode Exit fullscreen mode

light-dark() makes it easier to handle each property without having to make a declaration over again. With this function, you can build support for light and dark themes at the same time rather than consecutively.

Conclusion

In this article, we first looked at the prefers-reduced-transparency media feature, which is a useful feature for improving your website’s accessibility to users who prefer less transparency.

We also explored the light-dark() function, which improves your website’s versatility by providing theme options for all users. It is a great feature that you can start exploring, but it isn’t recommended you start relying on it now, because it’s still new and has little browser support.

Thanks for reading!


Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.

LogRocket Signup

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — Start monitoring for free.

Top comments (0)