How can I detect CSS Variable support with JavaScript?
Asked Answered
S

4

27

The latest version of Firefox has support for CSS Variables, but Chrome, IE and loads of other browsers do not. It should be possible to access a DOM Node or write a little method which returns whether the browser supports this feature, but I haven't been able to find anything which is currently able to do this. What I need is a solution which I can use as condition to run code if the browser does not support the feature, something like:

if (!browserCanUseCssVariables()) {
  // Do stuff...
}
Squamous answered 29/10, 2014 at 14:40 Comment(5)
I can't find any feature detection for this functionality. Personally, I'd recommend not bothering with it, yet. There are no plans to implement this in chrome yet, not to mention IE...Dillion
Here is a list of supported browsers: caniuse.com/#feat=css-variablesBeneficence
Exactly, but im working on a javascript version which should replace that behaivior - which of course should only do its magic if the browser cant. github.com/IceReaper/NextCSSSquamous
Note that Firefox does not support accessing CSS variables via CSSOM, even though it currently supports declaring and using them in CSS. If you're only feature-detecting the CSS side of things without trying to access the values themselves, though, then it shouldn't be too much of a problem.Severus
This no longer the case, check this. IE is the only major browser that doesn't support CSS variables.Dollhouse
Z
56

We can do this with CSS.supports. This is the JavaScript implementation of CSS's @supports rule which is currently available in Firefox, Chrome, Opera and Android Browser (see Can I Use...).

The CSS.supports() static methods returns a Boolean value indicating if the browser supports a given CSS feature, or not.
Mozilla Developer Network

With this, we can simply:

CSS.supports('color', 'var(--fake-var)');

The result of this will be true if the browser supports CSS variables, and false if it doesn't.

(You might think that CSS.supports('--fake-var', 0) would work, but as noted in comments on this answer Safari seems to have a bug there making it fail.)

Pure JavaScript Example

On Firefox this code snippet will produce a green background, as our CSS.supports call above returns true. In browsers which do not support CSS variables the background will be red.

var body = document.getElementsByTagName('body')[0];

if (window.CSS && CSS.supports('color', 'var(--fake-var)')) {
  body.style.background = 'green';
} else {
  body.style.background = 'red';
}

Note that here I've also added checks to see whether window.CSS exists - this will prevent errors being thrown in browsers which do not support this JavaScript implementation and treat that as false as well. (CSS.supports was introduced at the same time CSS global was introduced, so there's no need to check for it as well.)

Creating the browserCanUseCssVariables() function

In your case, we can create the browserCanUseCssVariables() function by simply performing the same logic. This below snippet will alert either true or false depending on the support.

function browserCanUseCssVariables() {
  return window.CSS && CSS.supports('color', 'var(--fake-var)');
}

if (browserCanUseCssVariables()) {
    alert('Your browser supports CSS Variables!');
} else {
    alert('Your browser does not support CSS Variables and/or CSS.supports. :-(');
}

The Results (all tested on Windows only)

Firefox v31

Firefox

Chrome v38

Chrome

Internet Explorer 11

IE11

Zachar answered 29/10, 2014 at 15:4 Comment(5)
Doesn't work with Chrome while CSS experimental features enabled. No matter what it always returns falseProvencher
Work in Chrome Version 60 stable - typed into console: "window.CSS && window.CSS.supports && window.CSS.supports('--fake-var', 0)", returns trueCalamint
@ChrisMorgan When I try window.CSS.supports('--fake-var', 0) on Safari 12.0.2 it returns false but CSS variables are in fact supported. This returns true however (taken from Modernizr): window.CSS.supports('color', 'var(--primary)')Murtha
Thanks for the clarification, good to know. So the two that should be equivalent are in fact not in Safari (presumably a bug), and so checking a var(--x) value should be preferred to a --x property. I’ve updated the answer to work around that bug.Hooligan
The Mozilla documentation uses CSS.supports('(--foo: red)') which seems more straightforward. Nicely written answer though.Damoiselle
B
8

Set a CSS style with CSS variables and proof with Javascript and getComputedStyle() if it is set... getComputedStyle() is supported in many browsers: http://caniuse.com/#feat=getcomputedstyle

HTML

<div class="css-variable-test"></div>

CSS

:root {
  --main-bg-color: rgb(1, 2, 3); /* or something else */
}

.css-variable-test {
    display: none;
    background-color: var(--main-bg-color);
}

JavaScript

var computedStyle = getComputedStyle(document.getElementsByClassName('css-variable-test')[0], null);

if (computedStyle.backgroundColor == "rgb(1, 2, 3)") { // or something else
    alert('CSS variables support');
}

FIDDLE: http://jsfiddle.net/g0naedLh/6/

Beneficence answered 29/10, 2014 at 15:3 Comment(2)
If you have access to modifying the CSS then this solution is probably better than mine, purely because not all browsers currently support JavaScript's implementation of CSS.supports which my answer relies upon. So +1 to this!Zachar
@JamesDonnelly Thx, actually your solution is absolutely correct, because only firefox supports this and also supports CSS.supports... Nice solution.Beneficence
P
8

You don’t need Javascript to detect if a browser supports custom properties, unless the Do stuff... is Javascript itself. Since the thing you’re detecting support for is CSS, I assume that the stuff you’re trying to do is all CSS. Therefore, if there’s a way to remove JS from this specific problem, I would recommend Feature Queries.

@supports (display: var(--prop)) {
  h1 { font-weight: normal; }
  /* all the css, even without var() */
}

Feature queries test support for syntax. You don’t have to query for display; you could use any property you want. Likewise, the value of --prop need not even exist. All you’re doing is checking to see if the browser knows how to read that syntax.

(I just chose display because almost every browser supports it. If you use flex-wrap or something, you won’t catch the browsers that do support custom props but that don’t support flexbox.)

Sidenote: I prefer calling them Custom Properties because that is exactly what they are: properties defined by the author. Yes, you can use them as variables, but there are certain advantages to them as properties, such as DOM inheritance:

body    { --color-heading: green; }
article { --color-heading: blue; }
h1      { color: var(--color-heading); } /* no need for descendant selectors */
Pawsner answered 28/7, 2017 at 16:6 Comment(2)
Why you don't have to use JS detection, the question was for javascript, and it should be assumed there are situations where such detections are absolutely a must to do in JS, and not in CSS. For example, you want to prevent a script from running or even being imported, if no support for its usage is available.Ethology
Or to use feature detection to determine whether the current browser meets your minimum requirements 🙂Tucana
P
1

I had problems getting the window.CSS.supports method to work for testing css variables in chrome 49 (even though it has native support). Ended up doing this:

var supportsCssVars = function() {
    var s = document.createElement('style'),
        support;

    s.innerHTML = ":root { --tmp-var: bold; }";
    document.head.appendChild(s);
    support = !!(window.CSS && window.CSS.supports && window.CSS.supports('font-weight', 'var(--tmp-var)'));
    s.parentNode.removeChild(s);
    return support;
}

console.log("Supports css variables:", supportsCssVars());

Seems to work in all browsers I tested. Probably the code can be optimised though.

Preemie answered 14/3, 2016 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.