-
Notifications
You must be signed in to change notification settings - Fork 682
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-values] A way to dynamically construct custom-ident and dashed-ident values #9141
Comments
yes! i have many use cases for this 🙂 i asked about this at the end of presenting |
While building https://codepen.io/bramus/pen/mdabWzr earlier today I came to the realisation that Instead, something like All this to say that my initial “Ideally, the output of |
I love this! especially for #8320, in conjunction with #8319.
e.g.:
|
Might also consider something like an
|
I split out both because they return a different value. But I think I am misunderstanding what you are saying here.
Good suggestion!
Since #item-x { --id: x; }
#item-y { --id: y; }
#item-z { --id: z; }
.item
view-transition-name: ident("item-" var(--id));
} |
I’m not sure if the best solution is a way to construct dynamic idents, or just better scoping for these features. E.g. what if nesting these inside other rules also scoped their idents? With dynamic idents authors still need to think of a way to ensure uniqueness, which increases cognitive overhead, and is error prone. |
Can you please elaborate? I don't fully understand.
In light of #8319, the ident itself doesn't have to be unique (for view transitions). Right now authors still need to ensure uniqueness but they have to do that with JS or on the server, this allows them to do this in css directly. Happy to discuss alternatives! |
I think @LeaVerou means that if names could be contained/scoped by whatever trigger, that would open up the way to safely allow duplicate names to exist alongside each other. While that would work in some cases – i.e. where children look up the DOM tree to get access to a thing with a certain name – it does not work when all those named items are part of bigger whole. For example: View Transitions with many cards still need a unique name on each card as they all participate in the same VT, or ScrollTimelines that all need to be hoisted up to a shared parent via
They already need to think about uniqueness in many cases (names for view-transition elements, containers, timelines, anchors, custom properties, etc). The solution that is pursued here would allow authors to dedupe a lot of repetitive uniqueness. E.g. things like this: /* This requires uniqueness in HTML and CSS */
#item-1 { --item-id: item-1; }
#item-2 { --item-id: item-2; }
#item-3 { --item-id: item-3; }
#item-4 { --item-id: item-4; }
/* This requires uniqueness only in HTML, as CSS can access those values */
.item { --item-id: ident(attr(id)); } |
@bramus what does the |
Parsing purposes. Think of shorthands, such as With
Without
|
Sure, though perhaps these can work without the scroll-timeline-axis: inline;
scroll-timeline-name: "tl-" var(--id);
/* or */
scroll-timeline: inline ident("tl-" var(--id)); |
So summarizing the discussion here and in #8320 into a proposal:
So this for example would work: section {
--the-id: id();
--the-name: data(name); /* the data-name attribute value */
}
section .thumbnail {
view-transition-name: "thumb-" var(--the-id) "-" var(--the-name);
view-transition-class: any-thumbnail ident("th-" data(some-data-attr));
} This still means that developers would need to figure out how unique IDs are created, but I don't see a way around it yet. |
If
This seems like a huge forwards-compatibility problem. |
What should it be? A string? In what properties would this string be used?
Fair enough. We can decide this on a case-by-case basis or always require |
Yeah. Well in fact I don't see the need for
If
I would prefer some explicit way of concatenating strings into a string, which you may then use inside
Be aware of #1929. And this would be circular: counter-reset: ident("c" counter(c0)) 1; At first there is no instance of |
The point of |
I would assume those declarations to become IACVT. |
String concatenation is discussed in #542 and there was a resolution to add an explicit function for that. Sebastian |
I would be much more in favor of shipping And yes, +1 to being able to create idents (but please, not just strings, let’s not repeat the same mistakes as |
So distilling the proposal based on the above feedback:
How do people feel about |
Yup, some of our internal security folk were finally able to give a "probably okay" to attr() with some restrictions (mainly, not capable of making a url, unless whitelisted). I'll be working on updating the spec for this Soon. No need to make a new attr().
My initial reaction is that we don't need a special function just to save adding an initial |
Oof, generating
Agreed. |
See #5092 for discussion on the security concerns, I just made some edits and posted a comment today. (And no, I doubt data urls would be safe to allow, since you could then just inject the attr() value into a more active URL inside the data url and still exfiltrate the data.) |
Good to hear! My main concern for only allowing I think it would still be ok to disallow certain attributes ( Thinking of This way the more simple cases with almost any attribute in Alternatively (or, in addition?), could limiting the types allowed for constructing That said, given |
This use case is already covered by linked parameters.
An explicit keyword Sebastian |
(replying here to @nt1m’s reply left in #8320 (comment), as it relates more to this issue)
The Tacking onto what @tabatkins mentioned in the call about comma separated values: Something like |
I was originally not in favor of this, but I've been seeing a number of use cases. Even if it's not the optimal solution for all of them, it can serve as a flexible low-level workaround for many, and seems fairly easy to implement. Syntax-wise, I don't think comma-separated is needed, whitespace-separated is what we do in other places where string concatenation happens (e.g. Do we need a separate
|
@LeaVerou Yes, that is the direction this issue headed into: white-space separated parts + only use an Trying to pour the current direction into a CSS syntax, it’s this:
In #10995 (comment) I suggested something like a |
@bramus Nit, but I think this should be sufficient?
The first non-empty stuff seems somewhat orthogonal, and should likely be handled more broadly. |
I see you have a double
That depends on what
I had a good reason but can’t see to recall it right now … hmmm. |
I assume we'd want to allow strings or idents, not specifically the |
Good call. So that makes:
|
Oops, yes!
Do we want to allow
If it produces an |
Looks great, short and sweet. Agenda+ so we can get group consensus. Btw, presumably we want this to work in |
The |
@tabatkins Does that mean |
Yeah, |
I remember trying |
Should it be possible to assign values to custom properties with constructed :root {
ident("--" "my-namespace" "-" "main-color"): pink; /* is this still possible since nesting? */
}
@property ident("--" "my-namespace" "-" "main-color") pink; /* maybe? */ |
This seems tricky because of arbitrary peek-ahead (what makes |
This is food for a follow-up issue, outside of the scope of the original ask. |
To summarize: I am proposing the
That should be it. Everything else mentioned in this issue but not in this comment falls outside of the scope of what is proposed. |
One thing I realized after typing up the above: we should also allow |
Heh, just came here to post exactly this:
Or even things like color tints. And we need to make sure multiple levels of this work. E.g.: --size-1: s
--size-2: m;
--size-3: l;
--size-s: .75em;
--size-m: 1em;
--size-l: 1.25em
font-size: var(ident("--size-" var(ident("--size-" var(--i)))); |
The CSS Working Group just discussed
The full IRC log of that discussion<noamr> bramus: this is about dynamically constructing dynamic idents/dashed-idents. for when authors need to come up for idents in multiple elements in one go<bramus> https://github.com//issues/9141#issuecomment-2536648501 <noamr> bramus: e.g. view-timeline-name. The ident() function together with attr(), can have those created in one go <noamr> bramus: see examples <noamr> bramus: e.g. combining the data-* attribute with other strings <noamr> bramus: another example where view-transition-name is dynamically constructed from the enclosing element <noamr> bramus: proposing an ident() function with space-separated items, can be string/integer/ident <noamr> bramus: can you just use attr? <noamr> bramus: sometimes you need to glue pieces together, some of which are attr and some not, e.g. strings <noamr> bramus: sometimes you need to refer to that name, you can't always put it as an attribute-specific value like "view-transition-name: auto" <kizu> +1, wanted this in 2016 <noamr> astearns: a bit concerned that stitching together ident() really depends on the context in which the function is being used <noamr> astearns: I can see myself being confused about why my ident() is not matching because of not thinking of the context <noamr> bramus: dev tools can definitely help with that, to find the generated values <miriam> q+ <astearns> ack miriam <noamr> bramus: like see a mapping of references to names in view-timeline etc <noamr> miriam: to clarify, when creating idents like this in CSS, it generally means we have to refer to them somewhere else <noamr> miriam: in most of these pieces it makes sense that you've created the name, and then you need to reference them <noamr> q+ <noamr> bramus: in view-timeline, set on non-parent elements, each photo might have its view-timeline, but the dots might not be descendants and still refer to the images by name <noamr> bramus: so e.g. the sibling-index() can be used with ident() to rebuild the ident() <astearns> ack noamr <bramus> noamr: one issue of this is css custom props wher eyou put on an an ancestor and then refer to that var <bramus> … sometimes the attr you want is somewhere above and the participing element is somwheer down below <noamr> bramus: similar to how the attr() behaves, they resolve before inherited <noamr> bramus: one of the examples is where the cart stores an attribute into --id custom property, and down the line an ident() function uses that value <bramus> s/how the attr() behaves/how the attr() behaves when used in a custom prop <noamr> astearns: PROPOSED RESOLUTION that we resolve the feature <noamr> fantasai: proposal should be to adopt to the css-values-5 <noamr> PROPOSED RESOLUTION: work on this issue in css-values-5 draft <fantasai> PROPOSED: Adopt ident() function into css-values-5 <noamr> astearns: objection? <fantasai> RESOLVED: Adopt ident() function into css-values-5 |
(This proposal has some overlap with #542, but that one is specifically about string concatenation. This proposal is about using concatenation to construct custom-idents and dashed-idents)
In many CSS features, authors need to give elements a certain name so that they can later refer to those targeted elements. Think of
container-name
,view-transition-name
,view-timeline-name
,scroll-timeline-name
, etc. Depending on the property these names are of the type<custom-ident>
or<dashed-ident>
. These names need to be unique (within the feature that’s being used). In case of View Transitions and Scroll-Driven Animations this uniqueness can become burden for authors.Take this Scroll-Driven Animations example, where the author is setting a unique timeline name per element, using
:nth-child()
:Same with View Transitions, where I’ve seen this code in the wild
To make things easier for authors, it would be nice if they could dynamically construct
<custom-ident>
or<dashed-ident>
values. I am thinking of two functions:ident(…)
to generate a<custom-ident>
valuedashed-ident(…)
to generate a<dashed-ident>
valueThe functions can accept an arbitrary number of arguments, but need at least 1. The arguments are of the type
<string>
or a function that generates string-like values (*).With
sibling-index()
being accepted, the first example could be simplified as follows:Ideally, the output of
calc()
andattr()
would also be allowed as arguments into the proposed functions.(*) Maybe this last part needs an explicit cast to string, which is covered in #542. Or ff the casting of the arguments would be too difficult to do, maybe some value interpolation could be used? In that case the functions would accept only 1 argument, e.g.
dashed-ident("tl-{sibling-index()}")
.The text was updated successfully, but these errors were encountered: