-
Notifications
You must be signed in to change notification settings - Fork 689
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] String concatentation #542
Comments
I'm intrigued by the idea of automatic concatenation of consecutive string tokens, but I'm worried that this might derail the general possibility of concatenation. I personally don't think one extra layer of function notation will create an overwhelming number of parentheses. But maybe I've just been programming too long. One thing I've mentioned elsewhere (and Lea seems to be assuming it, as well) is the idea that a concatenation function could do double-duty as a string coercion function, forcing any number or other non-string variables inside it into string version. This is very important for building SVG path data from variables. I'm worried that if you combine this with the default concatenation option you'd really make a mess of parsing. So my vote is for a |
@tabatkins @fantasai Any thoughts? This is standing in the way of many cool CSS variable use cases, and once we agree on a syntax, not particularly hard to implement. |
I'm strongly against the proposal to just make adjacent I'm supportive of (That is, |
@tabatkins Awesome, can we make it happen? Regarding the name, I'd suggest |
+1 to Also +1 to Tab's suggestion that string serialization of numbers and lengths be independent of the formatting of the initial value. If there is demand in future, separate number formatting options could be considered, based on the number formatting options in |
There is Some printing tools have already implemented the behaviour from that working draft. I believe it's not really a good idea to have some new |
The CSS Working Group just discussed
The full IRC log of that discussion<fantasai> Topic: String Concatenation<astearns> github: https://github.com//issues/542 <fantasai> leaverou: There's a bunch of string value accepting proeprties in CSS, and can't use variables in there <fantasai> leaverou: paths <fantasai> leaverou: Lots of places where concatenation would be useful <fantasai> leaverou: and don't have a way to do it <fantasai> leaverou: Didn't recall any objections to the propsoal, just questions about what it's called <fantasai> leaverou: I don't care, we just need a way to do it <AmeliaBR> q+ <fantasai> chris: ppl using preprocessors take string concatenation for granted, it's simple there <fantasai> chris: they're astounded when they find it's not available in raw CSS <fantasai> leaverou: Primarily useful in URLs, but also useful in other places like paths <fantasai> TabAtkins: I agree with the need for a function here, prefer concat() but fine with anything else <chris> q? <fantasai> leaverou: We've also had suggestions for a function that converts things to strings, <xfq> ack AmeliaBR <fantasai> leaverou: text() is generic enough to do both <fantasai> string() sgtm <fantasai> AmeliaBR: Problem with that is that for string coercion you often also want number formatting <fantasai> AmeliaBR: so that might need to be a separate function <fantasai> AmeliaBR: butwould need to be partof the system if you are going to make useful path dat from numeric variables <fantasai> AmeliaBR: need to concatenate not just letters but numbers from variables <fantasai> AmeliaBR: calc expressions <dbaron> q+ to ask what the inputs to this function can be, and where it can be used <fantasai> AmeliaBR: etc. <fantasai> TabAtkins: What are the use cases for coercion? Debugging ovviousl, anything else? <fantasai> leaverou: ... <fantasai> Am Big in dataviz <leaverou> s/.../generated content to display a variable value in the UI/ <leaverou> q+ <fantasai_> AmeliaBR: e.g. bar graphs, want to use value in drawing but also labelling <fantasai_> AmeliaBR: don't want to duplicate content <fantasai_> TabAtkins: I really don't want to get into string formatting <fantasai_> TabAtkins: otherwise do see the value in do see value in displaying 50% on bar chart while 50% also used to size the bar chart <fantasai_> AmeliaBR: So if we want to leave the generic number formatting issue for later, that's fine <fantasai_> AmeliaBR: So long as we still have idea that basic concat function can take non-string values and simply print them out <fantasai_> AmeliaBR: so you can use them for path data <fantasai_> AmeliaBR: In path data you generally want to preserve maximum precision anyway <fantasai_> leaverou: example ... interpolation <fantasai_> leaverou: Don't want to define how concat() interpolates with each other <xfq> ack db <Zakim> dbaron, you wanted to ask what the inputs to this function can be, and where it can be used <fantasai> dbaron: Reading the proposal wasn't clear to me what the inputs of this function is and what the output is in terms of types <fantasai> dbaron: What CSS value types can be used in here? <fantasai> TabAtkins: output tpe is tring <fantasai> TabAtkins: input type is any thing, standard serialization of the token <fantasai> dbaron: There will be a spec defining standard serialization of a token? <leaverou> s/example ... interpolation/yes, that simplifies interpolation as well, if types of arguments were not coerced we'd need to define interpolation between two concat() calls <fantasai> TabAtkins: Need that for variables anyway <fantasai> TabAtkins: If it doesn't exist yet, some othe rspec is implicitly relying on it and it needs to be defined <fantasai> astearns: Wrt used, it's anywhere with a string? <fantasai> fremy: Exception for url? <fantasai> TabAtkins: No, works in url() <xfq> ack lea <fantasai> TabAtkins: url() can take a string <TabAtkins> s/take a string/take only a literal string, there's another issue for generic <string> input/ <fantasai> astearns: I'm hearing lots of nods on having this thing. Any implementer interest? <fremy> (to clarify what tab said, url() can take a string but not a <string>) <fantasai> astearns: From silence sounds like, yes this would be a good thing, no it's not a priority <fantasai> emilio: Expectation is that you can do like sth(var(--whatev))? <fantasai> emilio: Then how can you define it to be any token? <fantasai> TabAtkins: var() is processed at a higher level than any value <fantasai> fremy: If you want a string, you do text("string") <TabAtkins> (It's specific as taking a <string> in the syntax, but in Syntax we handle url() in special ways that prevent it from taking string-producing functions.) <fantasai> emilio: If it takes any token <fantasai> fremy: If it's not a string, then you convert <fantasai> TabAtkins: I think Emilio got it <fantasai> astearns: OK, naming. What do we call the thing? <fantasai> AmeliaBR: Lea suggested text(), but there's already a text() function in paged content <fantasai> fantasai: How about string? was in Lea's original proposal <fantasai> leaverou: sounds fine <fantasai> chris: sounds fine <bkardell_> lol <fantasai> AmeliaBR: Sorry, confused things. It's the string() function that exists, text() does not <fantasai> AmeliaBR: and already implemented <chris> I care more that it exists, than what precisely it is called <xfq> https://drafts.csswg.org/css-gcpm-3/#using-named-strings <tantek> I for one an all for the cat() function, I bet it would poll well on Twitter 😺 <bkardell_> lol <fantasai> astearns: Any objections to text()? <chris> Lets go with text <fantasai> dydz: Prefer concat(), but ... <Rossen> combine() <fantasai> AmeliaBR: Want names that are understandable by non-programmers in CSS <fantasai> AmeliaBR: Also, we tend not to truncate identifiers in CSS <chris> concat is not immediately obvious to non programmers either. both cat and concat are abbreviations <fantasai> TabAtkins: We are not using cat(), tantek! <tantek> 😿 <fantasai> bkardell_: I don't have a better suggestion, but text() is not very clear to me <TabAtkins> text(50%) <Rossen> +1 to bkardell_ <fantasai> bkardell_: There are so many ways that I coudl interpret "text" <tantek> +1 to bkardell_ <fantasai> flatten() :P <fantasai> chris: I think it's pretty clear <fantasai> myles__: We should think about whether concatenation or coercion is more common use case <TabAtkins> url(text("http://example.com", var(--foo))) <florian> echo() ? <tantek> printf() <florian> printf() <fantasai> AmeliaBR: text() is clear for coercion, maybe less clear for concatenation <TabAtkins> No unixisms! <TabAtkins> y'all weirdos! <chris> and text(var(--foo)) with one param is clearer than concat(var(--foo)) <Rossen> stringify() <Rossen> toString() <TabAtkins> to-string() <chris> DOTtoString <dbaron> hopefully everybody has forgotten XPath by now? <tantek> Time for a Twiter survey! <fantasai> iank_: Spreadsheets use concatenate and concat <fantasai> TabAtkins: It's terrible and hard to spell <fantasai> TabAtkins: These are all great names, except for all the ones that are bad. <chris> https://developer.mozilla.org/en-US/docs/Web/XPath/Functions/concat <fantasai> TabAtkins: Let's table this and put together a non-binding Twitter poll <fantasai> florian: Make sure you include an international audience <fantasai> bkardell_: That works best if we all promote it so let us know <fantasai> leaverou: Twitter doesn't have enough space for examples, and based on what examples you use can get different reactions <fantasai> TabAtkins: I'll put together coercion example and concat example, and you can review them <chris> https://stackoverflow.com/questions/9493732/difference-between-text-and-string <fantasai> astearns: Sounds like we'll do this and decide the name later, would be interested in implementer interest <fantasai> astearns: Any objections? <fantasai> RESOLVED: work on astring-coercion-and-concatenation function |
One thing I want to mention: what would be really nice if that future string concatenation could work with anything that accepts strings, especially, grid-template-areas, to allow generating named areas from other variables, for example. Of course, this should work also by allowing converting idents into strings, so those could be reused both inside And this also brings me to another kinda related topic: ident concatenation. Probably also related to converting anything into anything, and related to the |
@kizu Converting a string to a non-string (string to ident, string to parsed number or length) would be a separate issue. But I agree that adding a general parse function for that case is tied in with the unimplemented second parameter to |
Yes, this function's type will be |
Playing devil's advocate for a moment... |
Because Sebastian |
@BigBadaboom And overloading |
I don’t buy the argument that CSS authors don’t know what “string” means. If that was the case, we shouldn’t have used it for GCPM. We have it there now, it exists, and it can be the single tool that authors reach for when they need a string. |
It more CSS-y without the commas anyway. |
Minutes from the meeting where this was discussed suggested this was going to a twitter poll on naming - did that go anywhere? The name summary seems to be We're certainly going to implement this (as |
Iʼm all for a name that is easily understood by non-programmers. Unfortunately, most candidates already have some established meaning (and thus user expectations) in one programming language or the other.
I like A special kind of stringify functions is slugify for generating slugs (short titles, URL-friendly). I think itʼs too narrow-focused. |
|
@noamr |
Hrm you're right. |
So:
So IMO |
Suggesting an alternative approach here. Instead, I'm suggesting to treat every string-requiring CSS property differently.
The reason for this is a sense that strings inside CSS may create a "language within a language" for each property, (which is already my sense with e.g. |
Not sure how Do note that in spreadsheets, it's a I don't think adding string concatenation on a case by case basis is a good idea at all. It makes each individual property more complicated, it makes the language less consistent (which properties support concatenation and which don't?) and adds overhead to learning each property, since each property does concatenation differently (lack of internal consistency). Also it would mean that authors need to wait for the full standards lifecycle (proposal + draft + implementation + test) for every single concatenation use case that we did not foresee early on. Also note that |
Yeah, I'm strongly against special-casing string concatenation per usage site, and I've already given reason why I do not want to go down the "putting them next to each other implies concatenation" route (it ties our hands wrt grammar design later). |
Was the introduction of new syntax already considered for this? Many languages use an operator for string concatination like "string1" + 1.0 + "string2" Note that this is independent of the discussion about automatic type conversion. A function could still be required for converting different types into a string, i.e. "string1" + string(1.0) + "string2" Sebastian |
I don't totally object to
I'm not suggesting to add concatenation on a case by case basis, but rather attempt to solve the problems that require concatenation in a case-by-base basis, without using strings if possible (e.g. what we're doing with paths).
This is where I think this feature might become more powerful than we realize, and can change CSS and the web in unpredictable ways. For example:
I'm not against any of the above, but I think that we should give them a consideration. This feature enables a lot more than meets the eye. |
I believe concatenating data URI SVGs with custom properties is one of the primary use cases, not "more than meets the eye". |
It wasn't an obvious one to me and wasn't in the description of the issue. Dynamically constructing full SVGs from CSS and uglifying are use-cases that can IMO fundamentally change the way CSS is used, reminiscent of |
If we do decide that I think we should name it |
Hi, I'd like to add another use case I haven't seen mentioned here: concatenating units to variables for css functions that require them. For example, for passing hsl components that need to be modified in css:
|
That will not work with the feature we're discussing here; it's for concatenating strings to produce strings, not concatenating raw CSS text to produce more raw CSS text which is then parsed. You'd just get the string What you're asking for is already possible with calc(). |
While experimenting with anchor positioning, I find myself often creating ”namespaced” anchor names, where an ability to use a variable and produce multiple namespaced dashed idents would be very very useful. Basically, currently I have to write something like <span
class="context"
style="
--is: --foo;
--is-content: --foo-content;
--is-extra: --foo-extra;
"
>…</span>
…
<span
class="anchor"
style="
--for: --foo;
--for-content: --foo-content;
--for-extra: --foo-extra;
"
>…</span> Basically, when I want to have two components, and connect multiple parts of one to multiple parts of another, I have to write these verbose definitions. If we would have something like <span class="context" style="--is: foo;">…</span>
…
<span class="anchor" style="--for: foo;">…</span> and define all the things in the CSS: .context {
--is-root: concat(--, var(--is));
--is-content: concat(--, var(--is), -content);
--is-extra: concat(--, var(--is), -extra);
}
.anchor {
--for-root: concat(--, var(--is));
--for-content: concat(--, var(--is), -content);
--for-extra: concat(--, var(--is), -extra);
} Making it possible to use as many different anchors in a certain context, namespaced by just one CSS variable defined on the root element of our component. |
I agree with @LeaVerou. I don't think CSS authors will have a hard time understanding what So I give The user's actual use case
For now, we're stuck with a relatively hacky approach. <div class="box" style="--range: 38;">
<input type="range" value="30" min="20" max="90" id="range">
<output class="tooltip"></output>
</div>
<style>
@property --range {
syntax: "<integer>";
initial-value: 0;
inherits: true;
}
.tooltip::before {
counter-reset: range_integer var(--range);
content: counter(range_integer);
}
<style> Cons: If it's a decimal it can't be displayed, but a lot of times the value of After the improvements, we just need: .tooltip::before {
content: string( var(--range, 0) );
} |
As there's an active discussion about generating idents in #9141 and string concatenation was mentioned there as well, I think it makes sense to align both syntaxes. And it seems most people are leaning towards a So I'd like to concretize the previous resolution and get a resolution to name it Furthermore, I'd like to get a resolution on whether we want to introduce an operator as an alternative to the function. Sebastian |
I think the MVP is definitely a function, an operator comes at a much higher cost and the benefit is questionable. We can always start with a function and if it turns out that authors are concatenating all over the place, we can explore making that easier, but I think a resolution for an operator right now would be premature. |
@SebastianZ I’m not sure we need call time just yet for the name. My interpretation of the previous resolution is that when this gets added to the draft it’s up to the editors to choose a name. Then we can open a new bikeshedding issue if anyone thinks they picked incorrectly. |
Now that #9141 is closed, and we will have I'd vote for |
Would |
I think so: many use cases mentioned in this issue point towards this (like all the usage of the |
I just published an article about my experimental native CSS mixin that allows displaying some of the values as strings: https://kizu.dev/preview-mixin/ How hacky it is? Very hacky. A lot of juggling of registered custom properties, math, and custom counter styles. Having a native |
As discussed with @tabatkins during TPAC last week.
Now with variables (custom properties), string concatenation is coming up in more and more use cases. Constructing URLs from variables for instance (see #541) is useless without concatenation.
Also, building SVG paths from variables.
Tab suggested a
concat()
function. I wonder if we can reuse the syntax fromcontent
which already allows for concatenation in a simple and elegant way, and special case the few cases where existing widely used property values accept<string>+
(e.g.quotes
) if they are sufficiently few and concatenation isn't needed there. Sure, it's weird if concatenation doesn't work in a few places, but I think the usability benefits of doing concatenation in the same simple way that authors are already used to, are worth it. Otherwise, CSS will end up like LISP with all the parentheses (imagine things likeconcat(var(--text), calc(1% * var(--foo)))
, which will be pretty common).Related specs:
The text was updated successfully, but these errors were encountered: