DEV Community

Cover image for CSS Style Queries
Lazar Nikolov for creatures.dev

Posted on • Originally published at creatures.dev

CSS Style Queries

Style Queries is a very cool feature in CSS, and they’re defined by the containment spec. Aside from being able to query a parent’s inline size (that’s container queries), the containment spec also includes the ability to query a parent’s style values (that’s style queries). Even though the container queries are available in all modern browsers, the style queries aren’t. Chrome and Edge have it. Opera’s working on it. Firefox and Safari, not so much. If you haven’t learned about container queries so far, check out our Container Queries article. Style queries are just slightly different than container queries, so I’d suggest to learn about container queries first. Alright, let’s play with some style queries!

Syntax

Here’s our first example:

The markup is simple. We have a list of collection of cards who have an image, a title and some text. We can see that the images have an overlay with different colors. We can call them different variants of the card, and it’s a really good example for demonstrating style queries. Let’s break down the example. In the markup, we can see that we’re defining a CSS variable on every <li> element: style='--variant: teal', and that’s all we need to do in our markup. Then in our CSS we define a container query, but instead of querying on its size, we’re querying on its specific style value, which is the variable we defined earlier: @container style(--variant: teal). This creates a containment context on the element that has the --variant: teal variable, and that’s the first <li> element. Just like the container queries, everything we put inside has to target a descendant of that <li> element. In our case we’re targeting the .poster element, which is the image, and we’re setting its ::after element’s content to a specific SVG image:

@container style(--variant: teal) {
    .poster::after {
        content: url("data:image/svg+xml;base64,PHN2Zy.........)
    }
}
Enter fullscreen mode Exit fullscreen mode

We can now repeat the same for the other variants cream, mint, pink, yellow and sky, and our card variants will be done!

You might’ve also noticed that even though the style queries are built on top of container queries, we didn’t define the container or container-name anywhere. CSS is smart enough to figure it out for you. But what if you have multiple components that use the --variant variable? In that case, you can explicitly define the container name, so your style queries don’t mix:

li {
   container-name: daily-mix-card;
    /* ... */
}

@container daily-mix-card style(--variant: teal) {
    /* ... */
}
Enter fullscreen mode Exit fullscreen mode

Combining multiple styles

Let’s see another example:

In this example we’re using the variables to indicate whether certain things should be visible in the card. There are three variables: ---star-seller, ---order-soon, and ---free-delivery. All of them when set to true will make the “✪ Star Seller”, “Only X left - order soon” and “FREE delivery” (respectfully) elements visible. If you look at line 29 in the HTML you’ll see that we have two variables defined: --star-seller and --order-soon. And if you look at the “EWB Bench” item, you’ll see that both the purple “Star Seller” and the red “Only 1 left - order soon” labels are displayed. Or check out the vintage lamp item with the red border around its image. It has all three styles set to true. To define a style query that queries on multiple styles, use and to combine the style(...) functions like this:

@container style(--star-seller: true) and style(--free-delivery: true) and style(--order-soon: true) {
  img {
    border: 3px solid red;
  }
}
Enter fullscreen mode Exit fullscreen mode

With this approach, we can create and combine as many styles as we like. The best thing about it is that everything is controlled just by the style attribute of the <li> element. If we want to dynamically control that using JavaScript, all we need to do is invoke the setProperty method of the element’s style property:

product.style.setProperty('--star-seller', true);
Enter fullscreen mode Exit fullscreen mode

Conclusion

Just imagine what you can do with style queries. All that with just pure CSS! No JavaScript logic to show/hide or conditionally render certain elements. Style queries allow us to define variants of our components, or toggle the visibility of certain elements, all just by setting a single CSS variable at the root element. We can also dynamically add/remove/change the variables with JavaScript by using the style.setProperty() method.

Another benefit of this feature is the separation of data from design. The HTML and CSS define all the possible varieties, while the JavaScript only toggles them. And since we’re talking about plain JavaScript, we can use style queries to define our variants and togglable elements without being constrained to a specific UI framework! That’s why this CSS feature is a game changer, and I can’t wait for it to be supported by all modern browsers.

Top comments (1)

Collapse
 
jd2r profile image
DR

Exciting stuff! Thanks for sharing :)