-
Notifications
You must be signed in to change notification settings - Fork 668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-variables-2] Custom shorthands with @property
#7879
Comments
Nested shorthands could work with something similar as the grid syntax : https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas @property --some-shorthand {
syntax: "<color>"
"<text-decoration-line> <text-decoration-style> <text-decoration-color>"
"<ident>";
constituent-properties: color text-decoration display;
values: ...;
} |
vs.
The only purpose of the Maybe better to omit this and have more flexibility. |
I very like that idea 😍 But there is one thing I don't like.
... looks like definition, not like applying. I like the way how it's made in Less. With an I don't know if CSS let property be named from the symbol |
I remember seeing in multiple places that @tabatkins mentioned that mixins, I however could not find the original reasoning behind it.
You are declaring values for properties. The single keyword shortcuts are more unlike css I think. |
I really like the idea of emulating mixins by being able to define custom shorthands. I also really like being able to define values for these shorthands that expand to completely separate values in the longhands, though maybe that can be left to conditionals? However, defining the syntax of the shorthand like this could be problematic as it can create disambiguation issues that are not present in the individual shorthands. E.g. consider property @property --some-shorthand {
syntax: "<length>{0,4}" "<length>{0,4}";
constituent-properties: a, b;
} Then what is It is also quite a burden on authors to have to match CSS property syntax. What if they don't need the entire possible range of syntaxes? It is also an impossible feat: even if they matched it when they wrote the rule, what happens when the syntax changes? Additionally, most CSS properties have much more complex syntaxes that what can be defined with the I think instead we should have syntax that somehow destructures the shorthand value into constituent custom properties that we then feed into CSS properties in the definition, without the author having the burden of duplicating existing CSS property syntax. Something like (super handwavy sketch): @shorthand --some-shorthand {
/* Read <length> into --some-shorthand-padding
and <color> into --some-shorthand-color */
syntax: padding "<length>", color "<color>";
@expands-to {
padding: calc(10px + var(--some-shorthand-padding, 0);
color: var(--some-shorthand-color, black);
border: 1px solid var(--some-shorthand-color, transparent);
}
} or even, with Nesting (of course then it's no longer a shorthand, but more of a mixin): @mixin --some-shorthand {
/* Read <length> into --some-shorthand-padding
and <color> into --some-shorthand-color */
syntax: padding "<length>", color "<color>";
@expands-to {
padding: calc(10px + var(--some-shorthand-padding, 0);
color: var(--some-shorthand-color, black);
border: 1px solid var(--some-shorthand-color, transparent);
&:hover {
color: lighter(var(--some-shorthand-color, black));
}
}
} |
What I remember was that |
Agreed. The only way to make it not ambiguous is by not allowing multipliers in the syntax definitions. This creates a fixed number of values that can be declared. (ignoring multi-token values like We trade in some flexibility and gain some composability. This is typical for such patterns also in other languages and contexts.
Being able to reference properties might help, but this again opens up the door to ambiguous value lists when a shorthand property is referenced.
Aside from that I think this is mostly fine. Being able to pass individual values to the shorthand is mostly an escape hatch. But I do think it enables some nice patterns.
That is actually exactly what this proposal does, minus that last bit. This also has the benefit of making these fully self documenting allowing editors and other tools to provide auto complete, linting, hover text, ... The main feature I think is the I expect most users of a defined custom shorthand to just use one of the "preset" value lists. |
This might be problematic given that It is confusing that different syntax definitions would be allowed between longhand and shorthand. |
I have several doubts about this, shorthands are not as simple as they may seem at first glance. From my experience of implementing properties, shorthands need 3 parts:
It's not clear to me that these are all covered in a non-ambiguous way. Taking Lea's example: @shorthand --some-shorthand {
/* Read <length> into --some-shorthand-padding
and <color> into --some-shorthand-color */
syntax: padding "<length>", color "<color>";
@expands-to {
padding: calc(10px + var(--some-shorthand-padding, 0);
color: var(--some-shorthand-color, black);
border: 1px solid var(--some-shorthand-color, transparent);
}
} Does this define If the shorthand defines the longhands, then what defines the Also, I fail to see how the @shorthand --some-shorthand {
/* Read <length> into --some-shorthand-padding
and <color> into --some-shorthand-color */
syntax: padding "<length>", color "<color>";
}
*, * :>> * {
padding: calc(10px + var(--some-shorthand-padding, 0);
color: var(--some-shorthand-color, black);
border: 1px solid var(--some-shorthand-color, transparent);
}
And |
But not all longhands can be serialized as shorthands anyway.
Both, plus
padding: 1px;
--some-shorthand: 10px black; would give you a different result. |
OK, then And creating shorthands of standard properties seems problematic, because they can have a complex grammar. |
The core of this proposal is a simple system of "slots".
Equivalent to :
If this system is in any way ambiguous it can not be implemented.
Avoiding the syntax definitions entirely and using This does not actually remove any type information because the properties and order are known. @property --some-shorthand {
syntax: "a"
"b b b"
"c";
constituent-properties: color text-decoration display;
values: ...;
}
Padding itself has this value definition @property --some-shorthand {
syntax: "a"
"b b"
constituent-properties: margin padding;
values: ...;
}
Both Users can not deviate from the template defined with |
@LeaVerou said :
I agree with this more now. What happens when they make a mistake? A more simple "passthrough" system as I laid out above is better I think. |
@LeaVerou I didn't fully grasp this example before. @mixin --some-shorthand {
/* Read <length> into --some-shorthand-padding
and <color> into --some-shorthand-color */
syntax: padding "<length>", color "<color>";
@expands-to {
padding: calc(10px + var(--some-shorthand-padding, 0);
color: var(--some-shorthand-color, black);
border: 1px solid var(--some-shorthand-color, transparent);
&:hover {
color: lighter(var(--some-shorthand-color, black));
}
}
} I think you can achieve the same result with this : @property --some-shorthand-padding {
syntax: "<length>";
inherits: false;
initial-value: 0;
}
@property --some-shorthand-color {
syntax: "<color>";
inherits: false;
initial-value: black;
}
@property --some-shorthand {
syntax: "a"
"b";
constituent-properties: --some-shorthand-padding --some-shorthand-color;
values: purple-version / 20px purple,
yellow-version / 30px yellow;
}
/* internal "API" */
.some-element {
padding: calc(10px + var(--some-shorthand-padding, 0));
color: var(--some-shorthand-color, black);
border: 1px solid var(--some-shorthand-color, transparent);
}
/* user writes */
.some-element {
--some-shorthand: yellow-version;
} Equivalent to: .some-element {
padding: calc(10px + var(--some-shorthand-padding, 0));
color: var(--some-shorthand-color, black);
border: 1px solid var(--some-shorthand-color, transparent);
}
/* user writes */
.some-element {
--some-shorthand-padding: 30px;
--some-shorthand-color: yellow;
} I have no idea how handy this is in practice and I would need to cook up some more realistic examples to be able to judge this. But I think it is really nice that creators of components can have complex internals and expose something as simple as : .some-element {
--some-shorthand: yellow-version;
} |
As I replied to @Loirooriol earlier, this: sufficiently general selector {
padding: var(--foo);
}
.foo {
--foo: 10px;
} Is not equivalent to: .foo {
--shorthand-with-padding: 10px;
} In the former, if anything, even with the tiniest specificity overrides |
I fail to see the issue with that. But as I understand it we have sufficient tools with specificity, cascade layers and |
I think this can be considered as 2 different proposals:
And then you could use them together. |
Just realized there is a big problem with shorthands: they must expand into longhands at parse time. But |
@Loirooriol Do you see another way this feature is implementable? I don't think it solves enough author cases to warrant entirely new grammar/syntax that enables expanding at parse time. Especially since it is just syntactic sugar and it can be a preprocessor only thing. |
Maybe the expansion could be deferred until computed value time, though then there can be a conflict if there are declarations for the longhands |
I don't think that is worth it. I think that rules out using |
My argument was specifically against @apply. Things like mixin/include, or this custom shorthand idea, are fine, or at least will be bad for different reasons. ^_^ |
Thank you for that @tabatkins, interesting read! Also thank you for the feedback and insights @Loirooriol @LeaVerou 🎉 |
Was there some kind of discussion outside the repo about implementation hurdles? This does not seem to follow from the last couple of comments. |
@Loirooriol said :
But maybe I misunderstood this or the impact of these hurdles. I am obviously in favour of re-opening to explore this further but I also don't want to take up everyones valuable time with an idea that isn't practical :) |
That just means we can't use |
Context :
Currently there is no way to reuse small groups of declarations (keys and values) in multiple styles without creating a style rule for them.
To apply this to multiple components you need to alter your markup.
Or you need to copy/paste the declarations to each style rule.
Mixins are often used to work around this.
I know mixins will never be a thing in native CSS and maybe the same reasons behind that apply to this proposal.
Custom properties also help to some extend because they allow values to be re-used.
Naming conventions help to group sets of values.
Proposal :
Can custom shorthands be defined through
@property
?syntax
must match the declared constituent propertiesinitial
work exactly like they work for native shorthandsI included
padding
in the example but maybe shorthand in shorthands have issues?Is equivalent to :
Set values of constituent properties :
This is somewhat related to #7273 as it allows similar patterns when styling elements.
The text was updated successfully, but these errors were encountered: