[css-values] Add a way to set longhands to the corresponding expansion of a shorthand value
Nobody has claimed this yet.
- Dominant language
- Bikeshed
- Stars
- 4.9k
- Forks
- 816
- PR merge metrics
- PR metrics pending
Description
Rationale
There are some ways to set longhands to values that can't be represented at specified-value time, so they just serialize as empty string. In particular:
- Pending-substitution values:
document.body.style.margin = "var(--m)"; document.body.style.marginTop; // "" per spec - Expanded
toggle()values (see #6764)document.body.style.margin = "toggle(1px, 2px)"; document.body.style.marginTop; // "" per #6764 - Expanded system fonts
document.body.style.font = "small-caption"; document.body.style.fontFamily; // "" in Gecko, Blink, WebKit - Values set by a legacy shorthand with broader grammar (see #7195)
document.body.style.webkitBackgroundClip = "text"; document.body.style.backgroundClip; // "" in Backgrounds L3 (presumably, see #7195)document.body.style.webkitBorderImage = "100% / 1px"; document.body.style.borderImageWidth; // "" in WebKit, since 1px forces border-width when set via -webkit-border-image
This doesn't seem ideal, since we lose round-tripping (assigning empty string in CSSOM will just remove the declaration) and it's hard to tell what the value is. All these cases have in common that the value is set from some shorthand, so cssText can help serializing such shorthand, but this produces poor results when some longhand has been modified afterwards (see #2515):
document.body.style.cssText = "margin: var(--m); margin-top: 1px";
document.body.style.marginLeft; // "" :( and the following don't help:
document.body.style.cssText; // "margin-right: ; margin-bottom: ; margin-left: ; margin-top: 1px;"
document.body.style.margin; // ""
Proposal
So I had an idea to address all of this: introduce from-shorthand( <custom-ident> ':' <whole-value>):
from-shorthand()is a<whole-value>.- It's invalid if the
<custom-ident>doesn't match the name of some shorthand ASCII case-insensitively. - When used on a longhand, it's invalid if the referred shorthand is not a shorthand of the longhand.
When used on a shorthand, it's invalid if the referred shorthand is not a "super-shorthand" (i.e. it's invalid if there is a property which is a longhand of the current shorthand but is not a longhand of the referred shorthand). - It's invalid if the
<whole-value>is an invalid value for the referred shorthand. - Custom properties don't have shorthands, so when used on an unregistered prop it should just be tokenized instead of resolving there.
- At computed-value time, it basically resolves to the value that the current property would get if the referred shorthand had been set to the
<whole-value>. - I'm using a
:since it looks clearer, like a declaration. Function arguments typically use,but that could get confusing in case the<whole-value>has commas. (Edited: initially suggested;)
Then:
document.body.style.margin = "var(--m)";
document.body.style.marginTop; // "from-shorthand(margin: var(--m))"
document.body.style.margin = "toggle(1px, 2px)";
document.body.style.marginTop; // "from-shorthand(margin: toggle(1px, 2px))"
document.body.style.font = "small-caption";
document.body.style.fontFamily; // "from-shorthand(font: small-caption)"
document.body.style.webkitBackgroundClip = "text";
document.body.style.backgroundClip; // "from-shorthand(-webkit-background-clip: text)" in L3
document.body.style.webkitBorderImage = "100% / 1px";
document.body.style.borderImageWidth; // "from-shorthand(-webkit-border-image: 100% / 1px)" in WebKit
// (the 100% is discarded and may be something else)
document.body.style.cssText = "margin: var(--m); margin-top: 1px";
document.body.style.marginLeft; // "from-shorthand(margin: var(--m))"
document.body.style.cssText; // "margin-right: from-shorthand(margin: var(--m)); margin-bottom: from-shorthand(margin: var(--m)); margin-left: from-shorthand(margin: var(--m)); margin-top: 1px;"
document.body.style.margin; // ""
I guess there may be compat issues in the var() case, but hopefully people are not relying on getting an empty string.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the proposal and its examples, then compare the related discussions in #6764, #7195, and #2515. Work is done when the CSS Values behavior and serialization rules for from-shorthand() are resolved and specified, including shorthand/longhand validity cases and custom properties.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100