Search code examples
cssgoogle-chromevendor-prefix

Bug? Nested CSS vendor prefix breaks Chrome CSS parsing


CSS nesting is a relatively new feature that is now natively supported in all major browsers. Please refer to https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting for more information on CSS nesting.

In the following example, the "This Button Should Be Red" button should be red. It's red in FireFox, but in Chrome it is not. My Chrome version is 119.0.6045.106 (Official Build) (64-bit).

Only if I remove the &::-moz-focus-inner { ... } rule will Chrome display it correctly as red.

Is this a bug in Chrome?

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>CSS Nesting Test</title>
    <style>
        button {
            &::-moz-focus-inner {
                border-width: 0;
            }

            &:not(:disabled) {
                background-color: red;
            }
        }
    </style>
</head>
<body style="margin:0;padding:50px;">
<button>This Button Should Be Red</button>
</body>
</html>


Solution

  • As per nesting specification,

    If a nested CSS rule is invalid then all of the enclosed styles will be ignored. This does not affect the parent or preceding rules.

    ::-moz-focus-inner is not listed as a valid pseudo element, hence Chrome treats it as invalid selector.

    If you need rules for only one vendor, you can just put them last. If several vendors are necessary, I don't see any obvious workaround except for defining every vendor in separate parent rule (one group per vendor).

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8"/>
        <title>CSS Nesting Test</title>
        <style>
            button {
                &:not(:disabled) {
                    background-color: red;
                }
    
                &::-moz-focus-inner {
                    border-width: 0;
                }
            }
        </style>
    </head>
    <body style="margin:0;padding:50px;">
    <button>This Button Should Be Red</button>
    </body>
    </html>