Skip to content

[css-cascade][cssom] Define what happens when legacy shorthand has grammar broader than longhand #7195

@Loirooriol

Description

@Loirooriol

https://drafts.csswg.org/css-cascade-4/#legacy-shorthand

When the old property has a distinct syntax from the new property, the two names are aliased using the shorthand mechanism. These shorthands are defined to be legacy shorthands, and their use is deprecated. They otherwise behave exactly as regular shorthands, except that the CSSOM will not use them when serializing declarations.

The problem is that some of these legacy shorthands can accept some values which have no equivalent in the standard property. For example, https://drafts.csswg.org/css-backgrounds-3/#propdef-background-clip

<'background-clip'> = <box>#
<box> = border-box | padding-box | content-box

But then https://compat.spec.whatwg.org/#the-webkit-background-clip-property defines this legacy shorthand:

<'-webkit-background-clip'> = border-box | padding-box | content-box | text

So it's not clear what happens if you set -webkit-background-clip: text. I would expect something like:

CSS.supports("-webkit-background-clip: text"); // true
CSS.supports("background-clip: text"); // false
element.style.cssText = "-webkit-background-clip: text";
element.style.length; // 1
element.style[0]; // "background-clip"
element.style.webkitBackgroundClip; // "text"
element.style.backgroundClip; // ""
getComputedStyle(element).webkitBackgroundClip; // "text"
getComputedStyle(element).backgroundClip; // ""

i.e. the shorthand sets the longhand to a special value that cannot be represented by its grammar, so the longhand serializes as empty string, but the shorthand can serialize the value. Somewhat analogous to when setting a shorthand to a variable.

This is what browsers do:

  • Firefox ignores the spec and accepts background-clip: text as valid. This avoids serialization problems:

    CSS.supports("-webkit-background-clip: text"); // true
    CSS.supports("background-clip: text"); // true
    element.style.cssText = "-webkit-background-clip: text";
    element.style.length; // 1
    element.style[0]; // "background-clip"
    element.style.webkitBackgroundClip; // "text"
    element.style.backgroundClip; // "text"
    getComputedStyle(element).webkitBackgroundClip; // "text"
    getComputedStyle(element).backgroundClip; // "text"
  • Blink serializes background-clip as "text", but this seems very wrong because background-clip: text is considered invalid!

    CSS.supports("-webkit-background-clip: text"); // true
    CSS.supports("background-clip: text"); // false
    element.style.cssText = "-webkit-background-clip: text";
    element.style.length; // 1
    element.style[0]; // "background-clip"
    element.style.webkitBackgroundClip; // "text"
    element.style.backgroundClip; // "text"
    getComputedStyle(element).webkitBackgroundClip; // "text"
    getComputedStyle(element).backgroundClip; // "text"
  • WebKit doesn't implement -webkit-background-clip as a shorthand. Instead, it's implemented as an independent longhand that shares a computed style with background-clip (somewhat like physical and logical properties also share a computed value). Additionally, it accepts background-clip: text as valid:

    CSS.supports("-webkit-background-clip: text"); // true
    CSS.supports("background-clip: text"); // true
    element.style.cssText = "-webkit-background-clip: text";
    element.style.length; // 1
    element.style[0]; // "-webkit-background-clip"
    element.style.webkitBackgroundClip; // "text"
    element.style.backgroundClip; // ""
    getComputedStyle(element).webkitBackgroundClip; // "text"
    getComputedStyle(element).backgroundClip; // "text"

Other properties may have other behaviors.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions