This content originally appeared on Bram.us and was authored by Bramus!
Yesterday I took some time to rework my Houdini-powered CSS Gradient Border Animation Demo to include a fallback for non-Houdini browsers.
The plan of attack was pretty straightforward:
- Manual frame-by-frame animations for non-Houdini browsers
- Automagic Houdini-powered animations for browser with
@property
support
Only problem with that approach is that there’s currently no way to use @supports
to detect whether a browser supports Houdini’s @property
or not, so I needed to get creative with @supports
…
~
? Houdini, ain't that a magician?
Houdini is a set of low-level APIs that exposes parts of the CSS engine, giving developers the power to extend CSS by hooking into the styling and layout process of a browser’s rendering engine. Houdini is a group of APIs that give developers direct access to the CSS Object Model (CSSOM), enabling developers to write code the browser can parse as CSS, thereby creating new CSS features without waiting for them to be implemented natively in browsers.
It really is magic, hence it's name Houdini. I'd recommend this slidedeck and this video to get you started
~
Table of Contents
~
# What I want
Ideally I want to check for support for @property
using something like this:
/* Syntax Proposal */
@supports (@property) {
…
}
/* Syntax Proposal, Expanded to check for certain descriptor support */
@supports (@property { syntax: "<angle>" }) {
…
}
/* Alternative Syntax Proposal */
@supports descriptor(@property, syntax: "<angle>") {
…
}
Unfortunately this is currently not possible and considered a shortcoming of CSS @supports
. The issue is being discussed in CSSWG Issue 2463.
~
# Getting creative with @supports
?♂️ Note that I’ll be using browser names here (e.g. Firefox), even though the statements apply to their underlying rendering engines (e.g. Gecko). And when talking about “Chromium” I mean all browsers that are based on it (e.g. Google Chrome, Microsoft Edge, Brave, etc.)
As Chromium (Blink) currently is the only browser that supports @property
, we need to create a @supports
rule that targets Chromium only. While at it let’s also create @supports
rules to target only Safari (WebKit), Firefox (Gecko), or a combination thereof.
Looking at what each browser uniquely supports, these three rules can be used as a starting point:
- Only Firefox supports
-moz-appearance: none
- Only Safari supports the
:nth-child(An+B [of S]?)
selector - Both Chromium and Firefox support
contain: paint
? By combining/excluding these rules you can target a set of browsers, or only one specific one.
? Note that the following @supports
rules are a hacky workaround which reeks a lot like browser sniffing. They’re very fragile as rendering engines may add support for those properties/selectors over time. Things can — and will — break in the future. Be ye warned.
~
# The @supports
rules
# Targeting Firefox Only
Firefox is the only browser that supports -moz-appearance: none
/* Firefox Only */
@supports (-moz-appearance: none) {
…
}
# Targeting Not-Firefox (e.g. Chromium + Safari)
By negating the selector only Firefox supports you can target Chromium + Safari:
/* Chromium + Safari */
@supports (not (-moz-appearance: none)) {
…
}
# Targeting Safari Only
Safari is the only browser that supports the complex :nth-child(An+B [of S]?)
selector — which itself allows you to create a :nth-of-class
-like selector — so you can rely on that:
/* Safari Only */
@supports selector(:nth-child(1 of x)) {
…
}
# Targeting Not-Safari (e.g. Chromium + Firefox)
You could negate the selector above to target Chromium and Firefox, but instead I chose to check for support for contain: paint
which both browsers support:
/* Chromium + Firefox */
@supports (contain: paint) {
…
}
The reason why I choose this selector becomes clear in the next part ?
# Targeting Chromium Only
To target Chromium only you can select both Chromium and Firefox (using @supports (contain: paint)
), and then exclude Firefox from there (using @supports (not (-moz-appearance: none))
).
Combined you get this @supports
rule:
/* Chromium Only */
@supports (contain: paint) and (not (-moz-appearance: none)) {
…
}
# Targeting Not-Chromium (e.g. Safari + Firefox)
As @supports
understands OR-logic, you can combine the rules for Safari and Firefox into one:
@supports (-moz-appearance: none) or selector(:nth-child(1 of x)) {
…
}
~
# Combined Demo
Below is a combined demo. The background-color
of the body should be:
- Chromium:
blue
- Firefox:
lime
- Safari:
red
See the Pen CSS @support rules to target only Firefox / Safari / Chromium by Bramus (@bramus) on CodePen.
Additionally you can also check this combined image (“cheat sheet”):
~
# In Closing
I’m glad I could flesh things out and create @supports
rules to target the three major rendering engines. Let’s hope we can drop these workarounds soon, when CSSWG Issue 2463 gets resolved (and implemented) ?
~
To help spread the contents of this post, feel free to retweet its announcement tweet:
CSS `@supports` rules to target only Firefox / Safari / Chromium
— Bram.us (@bramusblog) June 23, 2021
? https://t.co/lV2Ubz6cVm
? #CSS #atSupports #FeatureQueries #ProgressiveEnhancement pic.twitter.com/84GtuC0OCc
Follow @bramus (= me, the author) and/or @bramusblog (= the feed of this blog) on Twitter to stay-up-to date with future posts. RSS also available.
~
Thank me with a coffee.
I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!
To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.
This content originally appeared on Bram.us and was authored by Bramus!
Bramus! | Sciencx (2021-06-23T14:32:11+00:00) CSS @supports rules to target only Firefox / Safari / Chromium. Retrieved from https://www.scien.cx/2021/06/23/css-%e2%80%8bsupports-rules-to-target-only-firefox-safari-chromium/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.