Using CSS prefers-reduced-transparency and light-dark()
Tags: css, webdev
Published: 2023-12-21 18:54:13

**Written by [Elijah Agbonze](https://blog.logrocket.com/author/elijahtrillionz/)✏️**

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:

```css
/* syntax */
.transparent-element {
  opacity: 0.6;
}
@media (prefers-reduced-transparency) {
  /* reduce elements transparency */
  .transparent-element {
    opacity: 1;
  }
}
```

`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](https://caniuse.com/?search=prefers-reduced-transparency). 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](https://codepen.io/Elijah-Trillionz-the-sans/pen/oNmyGWB).

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:

```css
.nav li {
  opacity: 0.7;
}

.nav li:hover {
  opacity: 1;
}

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

  .nav li:hover {
    text-decoration: underline;    
  }
}
```

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](https://blog.logrocket.com/create-better-themes-with-css-variables/) wherever possible. For example:

```css
/* 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;
  }
}
```

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

```css
/* syntax */
    .opaque-element {
      opacity: 1;
    }

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

Here is a demo of our testimonial example:

[See the CodePen](https://codepen.io/Elijah-Trillionz-the-sans/pen/poGZQQb).

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`:

```css
.transparent-element {
  opacity: 1;
}

@media (prefers-reduced-transparency:no-preference) {
  .transparent-element {
    opacity: 0.6;
  }
}
```

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`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme), but with the `light-dark()` function, you can address each theme from a CSS property:

```css
:root {
  color-scheme: light dark;
}

body {
  background: light-dark(#f4f4f4, #0b1121);
}
```

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

[See the CodePen](https://codepen.io/Elijah-Trillionz-the-sans/pen/qBgyLaJ).

To use the `light-dark()` function, [`color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/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](https://caniuse.com/?search=light-dark).

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:

```css
header {
  background: light-dark(lightblue, darkblue);
}
```

`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](https://lp.logrocket.com/blg/css-signup).

[![LogRocket Signup](https://blog.logrocket.com/wp-content/uploads/2019/12/cpu-memory-usage.png)](https://lp.logrocket.com/blg/css-signup)

[LogRocket](https://lp.logrocket.com/blg/css-signup) 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](https://lp.logrocket.com/blg/css-signup).