Range Syntax Comes to Container Style Queries and if()

The range syntax isn’t new. We’ve been able to use it with media queries to query viewport dimensions and resolutions, as well as container size queries to query container dimensions. With Chrome 142, we can use it with container style queries to compare literal numeric values and numeric values tokenized by custom properties or the `attr()` function.

This feature also applies to the `if()` function.

Here’s a quick demo showing the range syntax used to compare a custom property (`–lightness`) to a literal value (`50%`):

“`css
#container {
–lightness: 10%;
background: hsl(270 100% var(–lightness));
color: if(
style(–lightness < 50%): white; style(--lightness >= 50%): black
);

* {
@container style(–lightness < 50%) { color: white; } @container style(--lightness >= 50%) {
color: black;
}
}
}
“`

You’ll need Chrome 142 or higher to see this work.

Both methods achieve the same thing differently.

Let’s delve deeper.

### Range syntax with custom properties

In the next demo, I’ve removed the `if()` logic, leaving only the container style queries. We’ve created a custom property `–lightness` on `#container`. We save it as a custom property and use it to form the HSL-formatted background value.

“`css
#container {
–lightness: 10%;
background: hsl(270 100% var(–lightness));
}
“`

We then select the container’s children and conditionally declare their `color` using container style queries. If `–lightness` is less than `50%`, the `color` is `white`. If it’s `50%` or more, the `color` is `black`.

“`css
#container {
* {
@container style(–lightness < 50%) { color: white; } @container style(--lightness >= 50%) {
color: black;
}
}
}
“`

Note that the `@container` at-rules cannot be moved to the `#container` block as it would query `–lightness` on the container of `#container`, where it doesn’t exist.

Before the range syntax, we could only query specific values, making it much more useful now.

The `if()`-based declaration would work in either block:

“`css
#container {
–lightness: 10%;
background: hsl(270 100% var(–lightness));

color: if(
style(–lightness < 50%): white; style(--lightness >= 50%): black
);

* {
color: if(
style(–lightness < 50%): white; style(--lightness >= 50%): black
);
}
}
“`

Container style queries only look up the cascade, while `if()` also looks for custom properties within the same CSS rule. Container queries allow defining a specific containment context using the `container-name` CSS property:

“`css
#container {
–lightness: 10%;
background: hsl(270 100% var(–lightness));
container-name: myContainer;

* {
@container myContainer style(–lightness < 50%) { color: white; } @container myContainer style(--lightness >= 50%) {
color: black;
}
}
}
“`

If the `@container` at-rule can’t find `–lightness` on `myContainer`, the block doesn’t run. To look further up the cascade, declare `container-name: myContainer` higher up. The `if()` function doesn’t allow this, but container queries offer scope control.

### Range syntax with the `attr()` CSS function

We can also pull values from HTML attributes using the `attr()` CSS function.

In the HTML below, an element has a data attribute `data-notifs` representing the number of unread notifications:

We select `[data-notifs]::after` to place the number inside `[data-notifs]` using the `content` CSS property. This is where we put the `@container` at-rules, with `[data-notifs]` serving as the container. A `height` and matching `border-radius` are included for styling:

“`css
[data-notifs]::after {
height: 1.25rem;
border-radius: 1.25rem;
}
“`

The container style query logic: if the notification count is 1-2 digits (less than or equal to 99), `content: attr(data-notifs

Similar Posts