1

I am rendering the following style very early in the <head> :

<style>
:root {
    --enhanced: false;
}
@supports (selector(:not(.foo))) and
    (aspect-ratio: 1 / 1) and
    (margin-block-start: 1rem) and
    (gap: 1rem) and
    (display: grid) and
    (--css: variables) and
    (object-fit: cover) and
    (display: flex) {

    :root {
        --enhanced: true;
    }
}
</style>

Then, later, after Google Tag Manager has loaded on the page, I am then running some JavaScript to get the value of the CSS custom property that was declared:

var enhancedExperience = getComputedStyle(document.querySelector('html')).getPropertyValue('--enhanced');

return enhancedExperience;

I have deployed this code to a website with a very high amount of traffic to run an experiment. And I have found that roughly 16% of the time getComputedStyle(document.querySelector('html')).getPropertyValue('--enhanced') returns an empty string. And it is happening on a diverse range of browsers including the latest versions of all major browsers.

I was expecting the empty string for browsers that do not support CSS custom properties. But I can see from the analytics data that most of the 16% of users are on browser versions that do have support for CSS custom properties.

Why might this be? I thought perhaps race condition but considering the CSS custom property is declared so early on in the <head> and the JavaScript doesn't run until GTM is loaded, is that possible?

1 Answer 1

1

Try:

var enhancedExperience = window.getComputedStyle(document.body).getPropertyValue('--enhanced');
return enhancedExperience;

EDIT: Update (based on comment from @JamesCat):

CSS custom properties store literal strings. So if you define something like:

--enhanced: calc(100px - 20px);

Then

getComputedStyle(elem).getPropertyValue('--enhanced');

returns the string 'calc(100px - 20px)', not the evaluated result. JavaScript doesn't compute calc() expressions from CSS variables directly.

If you want to get the resolved value, you can use this workaround:

const enhancedExperience = getComputedStyle(document.body).getPropertyValue('--enhanced');
const el = document.createElement('div');
el.style.setProperty('--enhanced', enhancedExperience);
el.style.width = 'var(--enhanced)';
el.style.position = 'absolute';
el.style.visibility = 'hidden';
document.body.appendChild(el);
const resolved = getComputedStyle(el).getPropertyValue('width');
el.remove();
return resolved;

(Credit to my model GPT for helping me discover this hack.)

Sign up to request clarification or add additional context in comments.

2 Comments

for css variables that are calcs this is just returning the string 'calc(foo - ba)' rather than the result of the calc :-(
@JamesCat Thanks for the note – you're right that getPropertyValue('--foo') returns the raw string like 'calc(...)'. I’ve updated my answer with a workaround that lets you get the computed result using a hidden element.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.