Current support only shows in Safari and Firefox and Chrome maintain an older syntax. I think it's safe to assume :matches() will eventually be adopted widely by browser vendors.
// Firefox Stable
:-moz-any(a) {
color: blue;
}
// Chrome Stable
:-webkit-any(a) {
color: blue;
}
// Safari Stable
:matches(a) {
color: blue;
}
Thanks for issue.
We need to add data to Can I Use. Can you help me a find what versions exactly need it?
Does latest versions need prefixes?
What I listed is the current state for "stable" browser releases at the present time
These two aren't exactly equal, so there's a lot of risk for Autoprefixer.
These two aren't exactly equal, so there's a lot of risk for Autoprefixer.
Thanks! Any link with differences?
@ai As far as stable browsers are concerned the only differences is the vendor prefixes I posted above.
Yeap, there is some (still unknown) difference between :matches() and -webkit-any()
Make sure to carefully test your pages when replacing :-webkit-any() by :matches() as they are not strictly equivalent. In particular, :-webkit-any() does not handle the specificity correctly.
ā https://webkit.org/blog/3615/css-selectors-inside-selectors-discover-matches-not-and-nth-child/
Same with -moz-any(), it changes specificity of the selector:
Shortly I'm going to land bug 544834, which implements the :-moz-any() selector. This patch, however, doesn't handle specificity properly; it just treats :-moz-any() as having the specificity of a pseudo-class.
Since :matches() !== -webkit-any()/-moz-any() and we could not fix changes in Autoprefixer, we canāt add this feature.
@grayghostvisuals but with the power of PostCSS you can do it in PostCSS plugins. It will be something like:
module.exports = postcss.plugin('postcss-matches', () => {
return root => {
root.walkRules(rule => {
if (rule.selector.indexOf(':matches(') !== -1) {
rule.selectors = rule.selectors.reduce((all, i) => {
if (i.indexOf(':matches(') !== -1) {
return all.concat([
i,
i.replace(/:matches\(/gi, '-webkit-any('),
i.replace(/:matches\(/gi, '-moz-any(')
])
} else {
return all.concat([i])
}
}, [])
}
})
}
})
Ping me when you implement it, I will add link to Autoprefixer README.md.
@ai Sorry to reply you so late.
For example, ':any' does not support nesting.
:matches(:matches(h1, h2), h3) š :-webkit-any(:-webkit-any(h1, h2), h3) š @yisibl ouh, so there are even 2 differences: wrong selector specificity and nesting :(
Just for completenessā sake, there is another difference: :-webkit-any doesnāt support complex selectors.
:-webkit-any(p span) ā:is(p span) ā
(:is is the new name of :matches.)
So I suppose using a Sass/Less/PostCSS mixin is the best way to go until all browsers support :is(), since thereās no way for Autoprefixer to safely convert it?
@tedw If a CSS preprocessor is already used, then nesting may be preferable. It seems to me that :is() is mainly useful in standard, unprocessed CSS code.
@simevidas Thanks for the quick reply! Hereās my use case for reference:
:is(h1, h2, h3, h4, h5, h6) + :is(h1, h2, h3, h4, h5, h6) {
margin-top: 0;
}
I was hoping to avoid generating every heading combination, especially since this code is nested in another selector in my project, so was going to do this:
:-webkit-any(h1, h2, h3, h4, h5, h6) + :-webkit-any(h1, h2, h3, h4, h5, h6) {
margin-top: 0;
}
:-moz-any(h1, h2, h3, h4, h5, h6) + :-moz-any(h1, h2, h3, h4, h5, h6) {
margin-top: 0;
}
:is(h1, h2, h3, h4, h5, h6) + :is(h1, h2, h3, h4, h5, h6) {
margin-top: 0;
}
However, youāre probably right that nesting is the best solution for now:
h1, h2, h3, h4, h5, h6 {
& + h1,
& + h2,
& + h3,
& + h4,
& + h5,
& + h6 {
margin-top: 0;
}
}
Although it makes me feel good to reduce the amount of generated CSS, I realize the extra bytes are negligible after gzipping š.
P.S. Thanks for all the work you do for the web dev community! Been following you on Twitter and reading your blog posts for a long time.
Btw, I just noticed that this selector generates some invalid combinations, such as h3 + h1 and h2 + h2, where the first heading isnāt a higher level than the second heading. In fact, only 15 out of 36 combinations are valid in that sense. But I guess CSS performance is no longer a big issue, so itās probably fine.
@simevidas Oh, good call! In my case, H1s are automatically stepped down to H2, so I think this would be the shortest selector for all accessible heading combinations:
h2 + h2,
h2 + h3,
h3 + h3,
h3 + h4,
h4 + h4,
h4 + h5,
h5 + h5,
h5 + h6,
h6 + h6 {
margin-top: 0;
}
Consecutive headings are already a bit of an edge case, and Iām fine with invalid combinations not getting the correct styling, so this is perfect.
Sorry for getting off topic here, but thanks for the reply!