marcj / css-element-queries

CSS Element-Queries aka Container Queries. High-speed element dimension/media queries in valid css.
http://marcj.github.io/css-element-queries/
MIT License
4.27k stars 487 forks source link

Does it support CSS custom properties/variables? #305

Closed enventa closed 3 years ago

enventa commented 3 years ago

Hi @marcj,

I've tried to define the breakpoint at which a container becomes responsive using a CSS variable. But it seems to be failing. CSS element queires do not work. I can see that the "min-width: XXXpx" tag is not added to the element.

Knowing that your JS parses the CSS files, I'd say that it is not looking whether a CSS variable exists and retrieving its value when it comes across a definition like: .box-container[min-width~="var(--box-bp, '600px')"]. Is this the reason why CSS custom properties are not working? Do you think it is something you can address, so CSS-element-queries supports them?

I think being able to control the breakpoint using CSS variables is something that would make your polyfill even better and super flexible.

Thanks!

enventa commented 3 years ago

No one?

marcj commented 3 years ago

Nope, that is not implemented.

enventa commented 3 years ago

And any plan to add support for it? Thanks!

enventa commented 3 years ago

Hey @marcj,

I've tried to implement it myself. Have to say that I'm not proficient with JS nor Regex, but I would say it is the extractQuery function (from the ElementQueries.js file) the one responsible to parse CSS and retrieve the custom min-width attribute, so I have modified that function like this:

function extractQuery(css) {
            var match, smatch, attrs, attrMatch;

            css = css.replace(/'/g, '"');
            while (null !== (match = regex.exec(css))) {
                smatch = match[1] + match[3];
                attrs = match[2];

                while (null !== (attrMatch = attrRegex.exec(attrs))) {

                    // *** My edit to take into account CSS variables starts here ***
                    var varRegex = /var\([\s\t]*?(\S+),[\s\t]*?(\S+)[\s\t]*?\)/mgi;  // https://regex101.com/r/dPwj5O/2
                    var varMatch = varRegex.exec(attrMatch[3]);
                    if ( null !== varMatch )
                    {
                        var varValue = getComputedStyle(document.documentElement).getPropertyValue(varMatch[1]).trim();
                        if ( "" === varMatch )
                        {
                            varValue = varMatch[2].trim();
                        }

                        // Update value.
                        attrMatch[3] = varValue;

                    }
                    // *** End of edit ***

                    queueQuery(smatch, attrMatch[1], attrMatch[2], attrMatch[3]);
                }
            }
        }

Code above is capable to identify CSS vars (*) and retrieve their value. And attMatch[3] has now the value of the CSS var. However... it is not working, box container is not responsive.

(*) As long as CSS var value is provided as: var(--my-css-var-name, 600px). That is, it has support for default value, as long as it is written without single/double quotes.

Any idea about what I'm doing wrong? Maybe I'm editing the wrong function?

enventa commented 3 years ago

OK, I think I can answer myself. My code above is actually working (so @marcj maybe you could consider adding it to your code eventually?). What fails is my CSS. I was using CSS vars as:

.box-container[min-width~="var(--my-css-var-name, 600px)"] { // Some CSS rules here... }

But that won't work. From W3C:

The var() function can not be used as property names, selectors, or anything else besides property values

Hopefully, CSS Environment Variables will soon be available. More on that here.