Not Ready for Prime Time
Like any other living programming language, CSS includes features and functionality that are actively being worked on.
These functions can sometimes be previewed using browsers that have access to the bleeding edge. Firefox Nightly and Chrome Canary are two such browsers. Other features and functionality are so new that they only exist in what is being actively discussed by the W3C.
This function enables Alternate Annotation Forms, characters reserved for marking up things like notation and annotation. These characters typically will be outlined with a circle, square, or diamond shape.
Not many typefaces contain Alternate Annotation Forms, so it’s good to check to see if the typeface you’re using includes them before trying to get
annotation() to work. Tools such as Wakamai Fondue can help with that.
counter() and counters()
When you create an ordered list in HTML, the browser will automatically generate numbers for you and place them before your list item content. These pieces of browser-generated list content are called counters.
By using a combination of the
::marker pseudo-element selector, the content property, and the
counter() function, we can control the content and presentation of the counters on an ordered list. For browsers that don’t support
counters() yet, you still get a decent experience due to the browser automatically falling back to its generated content:
For situations where you have nested ordered lists, the
counters() function allows a child ordered list to access its parent. This allows us to control their content and presentation. If you want to learn more about the power of
counter(), and counters(), you can read “CSS Lists, Markers, And Counters” by Rachel Andrew.
This function will allow you to blend one background image into one or more other background images. Its proposed syntax is similar to gradient functions, where you can specify the stops where images start and end.
This function allows you to flip the orientation of a language’s reading order. For English, that means a left-to-right (
ltr) reading order gets turned into right-to-left (
rtl). Only Firefox currently has support for
dir(), but you can achieve the same effect in Chromium-based browsers by using an attribute selector such as
That being said, device sniffing is a fallacious affair — you shouldn’t consider
env() a way to cheat it. Instead, use it as intended: to make sure your design works for devices that impose unique hardware constraints on the viewport.
has() is a relational pseudo-class that will target an element that contains another element, provided there is at least one match in the HTML source. An example of this is be
a:has(> img), which tells the browser to target any link that contains an image.
has() is triggered only after the browser has been told to process conditional logic, and therefore query the state of things.
This function will let you insert either a static image (referenced with
url(), or draw one dynamically via gradients and
These functions will allow us to perform more advanced mathematical operations:
- Square root:
The square root of the sum of squares of its arguments: hypot()
I’m especially excited to see what people who are more clever than I am will do with these functions, especially for things like animation!
When providing minimum, maximum, and preferred values as arguments,
clamp() will honor the preferred value so long as it does not exceed the minimum and maximum boundaries.
clamp() will allow us to author things like components whose size will scale along with the size of the viewport, but won’t shrink or grow past a specific size. This will be especially useful for creating CSS locks, where you can ensure a responsive type size will not get so small that it can’t be read.
:host() and :host-context()
To be honest, I’m a little hazy on the specifics of the jargon and mechanics that power the Shadow DOM. Here’s how the MDN describes
:host()CSS pseudo-class function selects the shadow host of the shadow DOM containing the CSS it is used inside (so you can select a custom element from inside its shadow DOM) — but only if the selector given as the function’s parameter matches the shadow host.
And here’s what they have to say about
:host-context()CSS pseudo-class function selects the shadow host of the shadow DOM containing the CSS it is used inside (so you can select a custom element from inside its shadow DOM) — but only if the selector given as the function’s parameter matches the shadow host’s ancestor(s) in the place it sits inside the DOM hierarchy.
:is() and :where()
:is() has had a bit of an identity crisis. Previously referred to as both
matches() and vendor prefixed as
:-moz-any, it now enjoys a standardized, agreed-upon name. It is a pseudo class selector that accepts a range of selectors as its argument.
This allows an author to group and target a wide range of selectors in an efficient way.
:where() is much like
:is(), only it has a specificity of zero, while the specificity of
:is() is set to the highest specificity in the provided selector list.
:where() will allow us a good deal of flexibility about how we select things to style, especially for situations where you may not have as much control over the web site or web app’s stylesheet (e.g. third-party integrations, ads, etc.).
max() and min()
These functions allow you to select either the maximum or minimum value from a range of values you provide. Much like
clamp(), these functions allow us to make things responsive up until a certain point.
:nth-col() and :nth-last-col()
These pseudo-classes will allow you to select one or a specified series columns in a CSS grid to apply styling to them. A good mental model for how these functions will work is how CSS pseudo class selectors operate. Unlike pseudo class selectors,
:nth-last-col() should be able to target implicit grid columns.
This function allows you to specify a list of different kinds of characters to use for list bullets. Much like
annotation(), you’ll want to make sure the typeface you use contains a glyph you want to use as a symbol before trying to get
symbols() to work.