What is the most practical way to check for @supports support using only CSS?
@supports
currently only tests property/value combinations, and nothing else. Your other options don't work because none of them are valid (including the last one with just the at-keyword followed by the opening brace!). The property/value pair requirement is dictated by the grammar for @supports
, which you can find in the spec.
Simply test for a property/value pair that you know is guaranteed to work across all user agents whether or not @supports
is implemented. This (sort of) eliminates the possibility that you'll run into a user agent that implements @supports
but not that property/value combination, focusing on its support for @supports
instead.
Your given example of display: block
will suffice. Your use of the cascade to check if a browser does not implement @supports
by overriding declarations within a @supports
rule for browsers that do support it is also acceptable (being the only obvious way to do it anyway).
Feature detection for @supports?
Using pure CSS, you can sort of rely on the cascade to determine whether a browser understands @supports
by making a @supports
rule with a universally-supported declaration, such as a color
declaration, and overriding another such rule that is declared globally:
#test {
color: red;
}
@supports (color: green) {
#test {
color: green;
}
}
In any browser that implements @supports
correctly, #test
should have green text. Otherwise, it'll have red text.
See my answer to this question for a detailed explanation of the pure CSS method.
If you're looking to detect it using JavaScript, you can use the Modernizr feature detection library as mentioned in the comments (be sure to include css-supports in your download config):
if (Modernizr.supports) {
console.log('Your browser supports @supports.');
} else {
console.log('Your browser does not support @supports.');
}
CSS @supports vs Checking Support via JS
What is the best approach to checking CSS property support with
@supports
in older browsers not supporting this CSS syntax?This depends entirely on what you're trying to do. If you're checking support for a specific value of a property (such as
flex
for thedisplay
property), it is sufficient to provide a fallback value and let the cascade handle it for you in most cases.Using your example, it's as simple as:
div {
display: none;
display: flex;
}If you're dealing with an entire property that may not be supported in older browsers, then it depends entirely on what you're trying to accomplish with or without that property. For example,
border-radius
usually doesn't have any adverse effects on layout, so older browsers that don't support it will degrade gracefully without you having to do anything else. But other properties may have adverse effects on layout, and you will need to account for different properties and layout configurations differently.Would it make sense or be practical to utilize both CSS and JS for this?
If you're using JS to cover as many bases as possible, using CSS may either be redundant, or serve as a modern, non-JS alternative that will account for users who have disabled JS. This may also vary depending on what sort of feature you're detecting.
Since this is about
@supports
, it's worth noting that there is a JavaScript API calledCSS.supports
which functions identically except you call it from within JavaScript. If you're not worried about users with scripting disabled, you can check if it is implemented and use it if it is, or your existing feature detection code otherwise:var supported = false;
if (window.CSS) {
supported = window.CSS.supports('display', 'flex');
} else {
// Your existing feature detection code here
}Is there some sort of
if/else
syntax for CSS@supports
?There is no if/else syntax for CSS conditional at-rules such as
@supports
and@media
, and even if there were, browsers that don't support@supports
will likely ignore the else portion. If you need to account for older browsers, your only option is to use the cascade as shown above (and even if browser support isn't an issue, it's much simpler and covers most use cases).The other way is to duplicate the condition and prepend
not
to negate it, and the CSS rules in each@supports
rule will be mutually exclusive (which is helpful if you want to include other properties that should be applied only when the property is not supported, and cannot be emulated using legacy syntax for older browsers):@supports (display: flex) {
div { display: flex; }
}
@supports not (display: flex) {
div { display: none; }
}
How to check if css value is supported by the browser?
I assume you meant to check whether the vh
value is supported, not whether specifically DIV#id
bears it?
function cssPropertyValueSupported(prop, value) {
var d = document.createElement('div');
d.style[prop] = value;
return d.style[prop] === value;
}
cssPropertyValueSupported('width', '1px');
// => true
cssPropertyValueSupported('width', '1vh');
// => maybe true, maybe false (true for me)
cssPropertyValueSupported('width', '1foobar');
// => false
Use CSS.supports() with media queries?
No.
CSS Conditional Rules Module Level 3 only provides for testing support for property: value
.
CSS Conditional Rules Module Level 4 adds the ability to test for selectors.
There's no provision for testing for support for hover.
Note that even in browsers which do support it, it might not be accessible to the user (e.g. if they use a traditional desktop browser without a mouse/trackpad/etc).
I need an easy way to detect CSS3 media query support using jquery
You can create a stylesheet with a media query and see if it works.
In your HTML:
<style>@media all and (min-width:1px) {
.mediatest {position:absolute}
}</style>
(Or you could dynamically create the stylesheet, but that's harder)
Then in your script:
var d = document.createElement('div');
d.className = "mediatest";
document.body.appendChild(d);
if( window.getComputedStyle && window.getComputedStyle(d).position == "absolute") {
// supports media queries!
}
document.body.removeChild(d);
Media query for devices supporting hover
Thanks to Dekel's comments I solved this by running the logic in JS and applying a class instead:
e.g.
const canHover = !(matchMedia('(hover: none)').matches);
if(canHover) {
document.body.classList.add('can-hover');
}
Then in the stylesheet:
.myElement {
background: blue;
}
.can-hover .myElement:hover {
background: red;
}
I've tested this on desktop Chrome, Safari and Firefox, and iOS Safari and it works as expected.
Related Topics
CSS Transition Between Left -> Right and Top -> Bottom Positions
For What Reason Margin Collapse Rules Were Introduced in CSS
Is a <Button> Allowed to Have Display:Grid
Disable CSS Animation on Pseudo Element Inherited from Parent
Why Don't CSS Filters Work on Svg Elements in Chrome
Google Webfonts Render Choppy in Chrome on Windows
The 'Justify-Content' Property Isn't Working
How to Fade In/Out Multiple Texts Using CSS/Jquery Like on Droplr
How Does Hexadecimal Color Work
What's the Difference Between Visibility: Hidden and Visibility: Collapse in Flexbox
Row Wrap in Flex-Box Not Wrapping in Safari
Delay Mouseout/Hover with CSS3 Transitions
CSS Reset That Sets Everything to Default Values
CSS Variables Defaults: Set If Not Already Set
Chrome Device Mode Emulation Media Queries Not Working
How to Emulate Prefers-Color-Scheme Media Query in Chrome
CSS Spec: Block-Level Box, Block Container Box and Block Box