My favorite use case for Style Queries is the ability to change a bunch of styles based on the value of a so called “higher-order variable”. You use that variable as a switch to change a bunch of properties.
@container style(--theme: dark) {
.card {
background: royalblue;
border-color: navy;
color: white;
}
.card button {
border-color: navy;
background-color: dodgerblue;
color: white;
}
}
Current issue with Style Queries though is that:
- You need browser support (which is Chrome Canary only at the time of writing)
- Only parent elements can be containers that children can query. There is no way to have an element be both the container and the querying child targeting self (because: cycles)
While the first issue should get fixed over time, the second one never will …
~
Last week, Jane Ori surprised me a wonderful post that tackled the latter issue. Leveraging @property
, they were able to implement Higher-Order Variables that work on the element itself! The technique is called Type Grinding:
Type Grinding allows your design tokens (keywords, or “<custom-ident>” values) written in your CSS to be transformed into any other values – like
width
,padding
,color
, etc – without relying on anything outside of CSS.
For example, you could have a --size
Custom Property that accepts the values sm
, md
, or lg
. Changing its value will act as a switch to change many other CSS properties, similar to Style Queries but without the need for Style Queries support!
The full code to achieve it is detailed in the post by Jane. It starts of with registering the --size
with only its allowed values:
@property --size {
syntax: "sm|md|lg";
initial-value: md;
inherits: true;
}
Based on the value of --size
, it’s possible to have more properties that output a 1
or a 0
:
@property --_sm-else-0 {
syntax: "sm|<integer>";
initial-value: 0;
inherits: true;
}
@property --_if-sm-then-1-else-0 {
syntax: "<integer>";
initial-value: 1;
inherits: true;
}
.type-grinding {
--size: md;
--_sm-else-0: var(--size);
--_if-sm-then-1-else-0: var(--_sm-else-0);
}
With that at the base, Jane builds things up further, finally achieving the Type Grinding. Apart from being somewhat complicated, the only downside of the whole approach is that it needs @property
support – a feature that’s only available in Chromium-based browsers at the time of writing.
If you happen to be visiting this site using Chrome, you can try it out yourself in the demo embedded below:
See the Pen CSS-Only Badge Component via the "Type Grinding" Trick! by Jane Ori 💜 (@propjockey) on CodePen.
CSS-Only Type Grinding: Casting Tokens (sm|md|etc
) into Useful Values →