Skip to content

[css-cascade] Idea: Multiple Values for a Property #9490

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

Open
AdamSobieski opened this issue Oct 18, 2023 · 6 comments
Open

[css-cascade] Idea: Multiple Values for a Property #9490

AdamSobieski opened this issue Oct 18, 2023 · 6 comments

Comments

@AdamSobieski
Copy link

AdamSobieski commented Oct 18, 2023

Introduction

What if a property could have multiple values?

What if a property could have multiple values which were aggregated or pooled from multiple declarations?

Syntax

Generators-based Option

Let us consider the following generators-based syntax idea:

div { *prop: yield(x); }
#el { *prop: yield(y); }
.cls { *prop: yield(z) yield(w) !important; }

which intends to communicate that the element:

<div id="el" class="cls" />

would have multiple values, {z, w}, for its property prop.

Aggregation from Multiple Declarations

Let us add a prefixed symbol, ^, to be able to express that the resultant iterable value is desired to aggregate or to pool values from multiple declarations. The following syntax:

div { ^*prop: yield(x); }
#el { ^*prop: yield(y); }
.cls { ^*prop: yield(z) yield(w); }

intends to communicate that the element:

<div id="el" class="cls" />

would have multiple values, {x, y, z, w}, for its property prop.

Single-valued and Multiple-valued Semantics

Traditional single-valued and new multiple-valued semantics could co-exist in a system. This co-existence would be enhanced if multiple-value declarations would be processed in an algorithmic ordering (see: cascade and specificity). This would provide an interesting default sorting on sequences of values with respect to iteration.

Object Model

With respect to adding this functionality to CSS, we might want to consider CSSStyleDeclaration which provides the getPropertyValue() method which is specified as returning a CSSOMString value rather than an object value. An object value could indicate that a return value could be a string or an iterable of strings, e.g., an array or list. For a string-based output for multiple values, perhaps a delimited string could be utilized? Perhaps there could also be a getPropertyValues() (plural) function on CSSStyleDeclaration which would return an iterable of strings, e.g., an array or list, this having one element for single-value scenarios.

Perhaps something like the following might work:

var element = document.getElementById('el');

for (const value of element.style.getPropertyValue('prop'))
{
  console.log(value);
}

this outputting something like

x
y
z
w

Conclusion

I hope that these ideas are of some interest to the group. What do you think of the capability for properties to have multiple values? Do any other syntax possibilities come to mind with which to express these ideas?

@Loirooriol
Copy link
Contributor

See prior discussion in #1594

@AdamSobieski
Copy link
Author

AdamSobieski commented Oct 19, 2023

Thank you @Loirooriol.

An important keyword with respect to that prior discussion from 2017 is "additive".

Also, as @dbaron pointed out, @Hixie and others were discussing these topics, supplementing, prepending, and appending multiple values for CSS properties, back in 1999: https://lists.w3.org/Archives/Public/www-style/1999Oct/0025.html .

@fantasai fantasai changed the title Idea: Multiple Values for a Property [css-cascade] Idea: Multiple Values for a Property Jan 9, 2024
@mirisuzanne
Copy link
Contributor

You show some syntax ideas, but not really a use-case. In practice, what would an author use this to achieve? What's the purpose of the feature?

@AdamSobieski
Copy link
Author

AdamSobieski commented Feb 19, 2025

Yes, concrete use-cases are needed for iterable and concatenable style properties.

Brainstorming, in CSS, there are different kinds of space-delimited values. Some are shorthand syntax conventions for other properties, e.g.:

margin: 10px 20px 30px 40px;

others are more set-like or list-like, e.g.:

transform: rotate(45deg) scale(1.5) translateX(10px);

One of the abstract uses of the syntax brainstorming and ideas, above, would be to enable new functionalities with respect to set-like and list-like style properties.

Interestingly, if they could be interpreted as space-delimited strings, iterable style property values could be backwards compatible. That is, {x, y, z, w} could also be interpreted as: "x y z w".

Set-like or list-like property values, some of these presently space-delimited, could be considered for iteration and concatenation scenarios, if these capabilities were possible in CSS.

@Crissov
Copy link
Contributor

Crissov commented Feb 20, 2025

In short: there is no use case!?

@AdamSobieski
Copy link
Author

AdamSobieski commented Feb 20, 2025

In short: I don't yet have a concrete use case example, on hand, for the expressiveness. However, someone else might!

Here are three topics from the initial post:

  1. concatenating properties' values,
  2. iterable properties,
  3. combining these ideas, concatenating iterable properties' values.

While any possible eventual syntax might vary, here are an example for each of these three topics:

Concatenating Properties' Values

.cls1 { ^prop: x }
.cls2 { ^prop: y }
<div id="el" class="cls1 cls2" />
let element = document.getElementById('el');
let value = element.style.getPropertyValue('prop'); // == "x y"

Iterable Properties

.cls3 { *prop: yield(x) yield(y) }
<div id="el" class="cls3" />
let element = document.getElementById('el');
let value = element.style.getPropertyValue('prop'); // == "x y"
for (const i of element.style.getPropertyValues('prop'))
{
  // x, y
}

Concatenating Iterable Properties' Values

.cls4 { ^*prop: yield(x) yield(y) }
.cls5 { ^*prop: yield(z) yield(w) }
<div id="el" class="cls4 cls5" />
let element = document.getElementById('el');
let value = element.style.getPropertyValue('prop'); // == "x y z w"
for (const i of element.style.getPropertyValues('prop'))
{
  // x, y, z, w
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants