Dynamic Contrast Layers with CSS Style Queries
Cory Rylan
- 2 minutes
Creating complex nested UIs often involves balancing the fine line between aesthetics and usability. An important part of this balance is controlling the contrast in layered elements. Components nested often can blend into their parent components, making it difficult to distinguish between them.
Components typically don't have a way to know their nesting level, so they can't adjust their contrast accordingly. Traditional approaches involve using CSS variables with naming conventions such as *-on-value
to represent a manual color change when on a certain layer. This approach is not only complex but also difficult to maintain.
However, with the latest CSS features, namely CSS Style Queries, you can make your UI adapt in real-time, with a dynamic layering system. Let's dive in to understand how we can build dynamic contrast layers using CSS Style Queries.
Setting Up Base Styles
We start by defining base styles using CSS custom properties. These variables set up different shades for our backgrounds:
:root {
--layer-background: #2d2d2d;
--layer-background-100: #2d2d2d;
--layer-background-200: #4b4b4b;
--layer-background-300: #757575;
--layer: 200;
}
The --layer
variable is important here as it will control which contrast layer we are currently in.
Using @container Queries
Next, we set up @container
style queries to alter these styles based on the value of --layer
:
@container style(--layer: 200) {
[layer] {
--layer-background: var(--layer-background-200);
--layer: 300;
}
}
@container style(--layer: 300) {
[layer] {
--layer-background: var(--layer-background-300);
--layer: 200;
}
}
[layer] {
background: var(--layer-background);
}
The @container style(--layer: 200)
and @container style(--layer: 300)
queries allow you to dynamically adjust the style based on the current value of the --layer
variable. It's like media queries but on a DOM Element/Component level.
Implementing Layers
Finally, we utilize these styles in our HTML elements:
<div layer>
<input value="input" layer />
<button layer>button</button>
<div layer>
<input value="input" layer />
<button layer>button</button>
</div>
</div>
Here, the [layer]
attribute acts as a flag for elements that need dynamic contrast. The CSS rules we defined earlier will automatically update these elements based on the current --layer
value.
No matter what the nesting level is, the contrast will always be consistent. This is because the --layer
variable is updated based on the current nesting level. This ensures that the contrast is always consistent, no matter how deep the nesting is.
Conclusion
With CSS Style Queries, dynamic layering has become much more flexible and maintainable. You no longer have to write bulky CSS code or rely on JavaScript to make real-time UI adaptations. This opens up a new opportunities for building more accessible, and visually consistent web UI.