Skip to content

[css-variables-2] Custom units as simple variable desugaring #7379

Open
@tabatkins

Description

@tabatkins

I've had "custom units" on the back burner of my mind for years now, and never got around to working on them - they had enough question to answer that it seemed exhausting. This morning, tho, I saw a tweet by @jonathantneal exploring the idea of making them just be sugar over normal custom property usage, and... I think I love it?

The example they had:

:root { --rs: calc(1rem * .25); }
.usage { padding-inline: 4--rs; }

/* desugars to */

.usage { padding-inline: calc(4 * (var(--rs))); }

That is, if we see a "custom unit" (aka a dimension whose unit is a dashed-ident), we just treat it as a variable reference (triggering the normal behavior of using a variable - the property is assumed valid, etc), and expand it at variable-resolution time into exactly that calc - given N--foo, produce calc(N * (var(--foo))).

I think this was problematic in the past because there were questions of initial value, resolution-time behavior, etc., but afaict those are all answered now by just using a registered custom property. That is, if you've registered your property/"unit" as a <length>, then you can set it like --unit:1.2em; and it'll resolve that into an absolute length immediately, inheriting as a px length. (Or, if you do want the unit to resolve at point of use instead of point of definition, just leave it unregistered, or registered with a * grammar.)

Plus, a property registration suffices to fully define the "unit" immediately, since you can just set its size in the initial descriptor. But it also leaves open the possibility of redefining it on the fly like any other custom property, if needed.

So the above example could instead be set up as:

@property --rs {
  syntax: "<length>";
  initial: .25rem;
  inherits: true;
}

.usage { padding-inline: 4--rs; }

This still leaves the door open to do a more full-featured custom unit thing later if we want; full-featured "registered custom units" would just override the variable-based behavior instead. But for now I think this does 95% or more of what we want custom units to do, in a flexible and readable manner.

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions