現時点でもEvery Layoutは充分に機能するが、値の型を変換する機能があれば、より柔軟に扱うことができるのになと思うレイアウトに遭遇した。
たとえばこんな感じ。
最小限のCSSにしたので、訳わからない意図ではあるが、liが20emより小さくなったときに2カラムから1カラムになるレイアウトにおいて、2カラムのときにliの順番が偶数のものが順番的に早く現れるといった具体である。
ul {
display: flex;
flex-wrap: wrap;
width: 100%;
}
li {
flex-grow: 1;
width: 50%;
min-width: 20em;
}
@media ( min-width: ( 20em * 2 ) ) {
li:nth-child(even) {
order: 1;
}
}
まずこのCSSには問題があり、メディアクエリの 20em * 2 の結果は2カラムから1カラムになる瞬間と同時ではない。
メディアクエリのスコープはブラウザ単位(だから:rootに記載する変数がメディアクエリ内では使用できない)であるから、1emはデフォルトだと16pxだが、liのemはそうだとは限らないからである。
これを解決するためにはliのmin-widthとメディアクエリをpxで書き換えるしかない。
あるいはenv関数を用いて、以下のようにかければ解決できるようになる(現状ではそのような環境変数は用意されていないし、メディアクエリにcalc関数は使えない。しかも本来はliが20文字以下になるときに1カラムにしたいという意図が含まれているから、ちょっと計算が複雑になってしまう)。
li {
min-width: calc( env(--default-font-size) * 20 );
}
@media ( min-width: calc( env(--default-font-size) * 40 ) ) {
li:nth-child(even) {
order: 1;
}
}
※ちなみに昨今注目されているコンテナクエリの指定値には、emは使用できず、pxのみ指定可能であるため、以下のように書き換えることはできない(コンテナクエリのスコープの問題もあるし、たとえemのスコープがulだとしたら、emは可変のため何度もクエリが発行する可能性があるから)。
li {
min-width: 20em;
}
@container ( min-width: ( 20em * 2 ) ) {
li:nth-child(even) {
order: 1;
}
}
だから、こんな感じの関数があればいいなあと思ったというポエム回。
li {
min-width: 20em;
}
// ulのサイズが100vwだと仮定する
li:nth-child(odd) {
order: number(50vw - 20em); // 計算結果が整数の数字になる
// コンテナクエリの中であれば、このようにもできる
order: number(50cqw - 20em);
}
li:nth-child(even) {
order: number(20em - 50vw); // 計算結果が整数の数字になる
// コンテナクエリの中であれば、このようにもできる
order: number(20em - 50cqw);
}
// display: noneを適用する場合は、このような感じにしたい
li:nth-child(even) {
display: bool(calc(20em - 50vw), block, none);
}
2022/09/13現在、ドラフト段階のCSSのsign()関数が実現にもっとも近いが、動作するはずのSafariでもうまく動かなかった。
ちなみに以下でも動かない。
li:nth-child(even) {
--order: max(0, calc(50vw - 20em));
order: 1;
order: var(--order);
}
orderに認識不明な値(1pxなど)を入力すると、order: 1が適用されるものの、var(–order)の場合は、order: 1さえも適用されない。