The new CSS :is()
pseudo-class is shaping up to become a great way to target elements, saving on lines and lines of code, and keeping CSS as readable as possible. It is the next stage of the evolution of :matches()
and :any()
, adding a little extra functionality and increasing how semantic and intuitive the language behind selectors is.
In this quick tip we’ll make acquaintance with it. Let’s start by seeing how this pseudo-class, officially referred to in the spec as “matches-any”, is used in application. Then we’ll talk about how it’s replacing both :matches()
and :any()
, and why it makes more sense to use the word “is” instead.
#CSS
— Λdam Λrgyle (@argyleink) November 7, 2019
:is() selector 🎉
the successor to :any() and :matches()
sneak peak into our talk, here's a neat gif I made with XD showing what the :is() selector syntax can do. be excited for Chrome Dev Summit y'all!https://t.co/0r2CcUx9Hv pic.twitter.com/wSuGOsDLvZ
Example Uses of :is()
You can probably intuit the functionality of :is()
just by looking at it: it’s a means to test if an element is a certain thing, working essentially as a boolean like the if
you’ll find in many programming languages. For example, in its simplest form these two selectors are functionally the same:
article {...}
:is(article) {...}
In both cases the styling will activate if an element is an article
.
It can also be used to detect multiple types of elements in a single declaration via a comma separated list. For example, again, these two selectors are functionally the same:
article, section, aside {...}
:is(article, section, aside) {...}
By itself this might not seem very interesting–an added complexity if anything–but it becomes especially helpful when used to target child elements. For example, let’s say you wanted to target h1
elements, but only when they are a child of an article
, section
or aside
element. Usually you would need to write:
article h1, section h1, aside h1 { font-weight: 900; }
However by instead using is:()
this can be compressed to:
:is(article, section, aside) h1 { font-weight: 900; }
It really starts to ramp up in efficiency when you have multiple parent and child elements you want to test for. What if, instead of just targeting child h1
elements, as in the above example, you want to target all child heading elements? Without :is()
, (and not using classes for the sake of illustration), you would need to write:
article h1, article h2, article h3, article h4, article h5, article h6, section h1, section h2, section h3, section h4, section h5, section h6, aside h1, aside h2, aside h3, aside h4, aside h5, aside h6, { font-weight: 900; }
But with :is()
instead you only need:
:is(article, section, aside) :is(h1, h2, h3, h4, h5, h6) { font-weight: 900; }
Why :is() Replaces :any() and :matches()
In previous drafts of the “matches-any” spec this pseudo-class used the name :matches()
before subsequently being renamed to :is(). An older selector again is :any()
, however unlike :is()
or :matches()
it doesn’t support complex selectors.
The primary reason it makes sense to instead use :is()
comes from another boolean style pseudo-class that functions in the inverse way, that being :not()
. With this “matches-none” pseudo-class you can apply styling to everything but a collection of selectors.
For example, earlier we targeted all the headings that are children of article
, section
and aside
elements. With :not()
we can target all the headings that are not children of these elements:
:not(article, section, aside) :is(h1, h2, h3, h4, h5, h6) { font-weight: 400; }
It makes good grammatical sense to pair :is()
with :not()
, hence making the combination logical and intuitive, and this is the primary reason it’s replacing :any()
and :matches()
. That said, the fact that it's shorter to type has also been cited as one of the reasons it is an improvement.
Current Status and Support
The :is()
“matches-any” pseudo-class is currently at working draft status.
You can mostly try it out now in Firefox, Chrome and Safari, however all three browsers are still using the old :any()
name, which must be used with vendor prefixes. For Firefox use :-moz-any()
and for Chrome and Safari use :-webkit-any()
. Chrome and Safari also support :matches()
.
Fallbacks
You can also use :any()
and :matches()
to create fallbacks for :is()
. For example, a cross browser set of fallbacks might look like this:
:-webkit-any(article, section, aside) h1 { font-weight: 900; } :-moz-any(article, section, aside) h1 { font-weight: 900; } :matches(article, section, aside) h1 { font-weight: 900; } :is(article, section, aside) h1 { font-weight: 900; }
The devs behind PostCSS are also looking at adding the ability to automate the addition of these fallbacks into your code.
Wrapping Up
The :is()
pseudo-class is going to make it feasible to handle much more complex element targeting than before, using vanilla CSS where previously we would have most likely needed a pre-processor to handle the task. We can all look forward to it coming out of draft status and reaching full browser support.
For more information check out the links listed below:
Related Links
- :is() W3C spec draft
- :is() at CanIUse.com
- MDN Web Docs - :is() (:matches(), :any())
- MDN Web Docs - :not()
Learn More About CSS Selectors
-
CSSDemystifying CSS Pseudo-Classes (:nth-child vs. :nth-of-type)
-
CSSWhat is CSS Specificity and How Does it Work?
-
Web DevelopmentThe 30 CSS Selectors You Must Memorize
No comments:
Post a Comment