A lot of developers desire things which are currently problematic for CSS and many of these would appear to be somewhat hard to explain why. Two common kinds of problems are circularity and performance. The magic that CSS is able to do is both a blessing a a curse here. From a developer's perspective, CSS seems to resolve things that are in conflict with one another all the time or which would 'appear' to be the same kind of problem. However, it accomplishes this through carefully designing based on constraints of precisely what can happen, and when. A good example of the kinds of asks that have these challenges are those described commonly as 'container queries' problems.
The idea here is force us to focus on 'where things fit' within the architecture of CSS pretty naturally and how we might build a new pattern within CSS implementations to solve the sort of variable answers required. It allows the development of internal pathways toward solving certain classes of such problems (a new opportunity for variable answers/expression) and does so in a way that this progress can be exposed to developers in native and performant ways, in comparatively short order. They might pair this additional tools, like preprocessors or other CSS properties to help us explore the larger space. It is a step geared toward solving this initial problem - additional sugars and higher level integrations then have an underlying plausible path laid.
In several ways, the existing toggle()
proposal is related and its use cases could even potentially be solved with this patten as well, so tt seems generally potentially useful and interesting regardless of whether this is the route toward ultimately solving the entire container queries problem or not:
The switch function allows elements make values dependent on a list of possible conditional values with relevant context instead of inheriting the same value. When processing the value of switch()
, properties may provide relevant contextual values which are substituted at the appropriate time.
/* example 1 /
.foo {
display: grid;
grid-template-columns: switch(
(available-inline-size > 1024px) 1fr 4fr 1fr;
(available-inline-size > 400px) 2fr 1fr;
(available-inline-size > 100px) 1fr;
default 1fr;
);
}
The syntax of the switch()
function is:
switch( <switch-value>)
where <switch-value>
is a vector of <switch-condition> <css-value> pairs separated by
;`..
(Something like (TODO write this up it's handwavey/incorrect/incomplete) (<IDENT> ?(<|> <length>)) <CSSVal>;
)
They are evaluated in order until one is true, and its value is used.
The switch() notation is not allowed to be nested;it may not contain attr() or calc() notations. Declarations containing such constructs are invalid. Properties may specify relevant context variables that make sense within their context. inline-available-size
, for example can be made available to various properties that are computed at layout time. Expressions containing context-variables not provided by the property are invalid.
/* Example 2: invalid examples /
/*
This example would be invalid because
the display property would not provide
an available-inline-size context as
it cannot be known at this time.
*/
.bar {
display: switch(
(available-inline-size>1024px) block;
default: inline;
);
}
/* Invalid because this contains calc() or attr() /
.bat {
grid-template-columns: switch(
(available-inline-size > 1024px) calc(100vh/2);
(available-inline-size > 400px) 3fr;
(available-inline-size > 100px) 2fr;
default 1fr;
);
}
As suggested earlier, the intent is that properties could definte potential values for these and there is spirtitual similarity to toggle here... For example, that might be written as something like
em {
font-style: switch(
(parent-font-style == em), normal;
default: italic;
}
Similarly, while you could do this mostly with available-inline-size
, it might be interesting in the future to be able to express something like 'if I am wrapped' for something like text-alignment:
.block {
text-alignment: switch(
(is-wrapping) center;
default left;
);
}
* See also David Baron's ideas here https://github.com/dbaron/container-queries-implementability for addressing some of the same use cases.
- There is overlap - but they are mutually interesting and overlap is not complete.
- Both contain low level next steps and these steps are both potentially valuable regardless of which way we go
- We favor some time exploring both as possibilities - there is certainly useful information and potential in both of them
* The specific proposal is to start with inline-available-size
(could bikeshed) being made available by some properties to explore this, but to lay down a pattern that could be more widely used for things that are this class of problem. Igalia is exploring this space with grid-template-columns as a small investment to further inform, no specific timeline.
* The constraints need to be clarified here, I am basing these mainly on Tab's work on toggle()
. It may also be necessary for it to be the sole value, but Oriol thinks perhaps not so I'm leaving this one out for now.
determined-inline-size
? it's not necessarily what's available right? it's what's calculated?