Perhaps you know this one: if any part of a selector is invalid, it invalidates the whole selector. For example:
div, span::butt {
background: red;
}
Even though div
is a perfectly valid selector, span:butt
is not, thus the entire selector is invalidated — neither divs nor span::butt
elements on the page will have a red background.
Normally that’s not a terribly huge problem. It may even be even useful, depending on the situation. But there are plenty of situations where it has kind of been a pain in the, uh, :butt
.
Here’s a classic:
::selection {
background: lightblue;
}
For a long time, Firefox didn’t understand that selector, and required a vendor prefix (::-moz-selection
) to get the same effect. (This is no longer the case in Firefox 62+, but you take the point.)
In other words, this wasn’t possible:
/* would break for everyone */
::selection, ::-moz-selection {
background: lightblue;
}
That would break for browsers that understood ::selection
and break for Firefox that only understood ::-moz-selection
. It made it ripe territory for a preprocessor @mixin
, that’s for sure.
Here’s another zinger.
/* For navigation with submenus */
ul.submenu {
display: none;
}
ul.menu li:hover ul.submenu,
ul.menu li:focus ul.submenu,
ul.menu li:focus-within ul.submenu {
display: block;
}
/* Oh no! We've broken all menu functionality in IE 11,
because it doesn't know what `:focus-within` is so it
throws out the entire selector */
This behavior is annoying enough that browsers have apparently fixed it going forward. In a conversation with Estelle Weyl, I learned that this is being changed. She wrote in the MDN docs:
Generally, if there is an invalid pseudo-element or pseudo-class within in a chain or group of selectors, the whole selector list is invalid. If a pseudo-element (but not pseudo-class) has a
-webkit-
prefix, As of Firefox 63, Blink, Webkit and Gecko browsers assume it is valid, not invalidating the selector list.
This isn’t for any selector; it’s specifically for pseudo-elements. That is, double colons (::
).
Here’s a test:
I’d call that a positive change.
I was listening to Shoptalk with Google Podcasts and you talk about this exact subject; a short time later, Google Assistant recommends this article. So useful, and yet so terrifying.
Good news!
I’ve ran into this while using :focus-within a few times lately. Works fine in modern browsers since it’s supported, but breaks in older browsers (IE strikes again!). Not hard to fix, but definitely annoying. Wish they’d change it so that browsers would just ignore invalid selectors instead of breaking. :/
I hit a similar issue with Firefox a few months ago. It used to consider ::webkit- prefixed selector as invalid, thus ignoring the whole selector and rules it contained. It was especially annoying when using tools such as Autoprefixer which would apply prefixes for you and break your styles on Firefox.
(Btw they did a great job at addressing the issue since I reported it on their Bugzilla and I guess it’s been fixed in version 63 of the browser)
Probably it’s worth noting that it isn’t for any pseudo-element (yet), it’s only for
-webkit
-prefixed pseudo-elements. This is done for compatibility reasons because WebKit- and Blink-based browsers have treated these such pseudo-elements this way and many websites rely on this behavior.There is a proposal to invert this rule and treat all pseudo-elements (and probably even pseudo-classes) as potentially valid selectors, except those that were often used for browser selection hacks. But this proposal didn’t seem to get enough traction…