Od razu napiszę, że niestety nie znam odpowiedzi na pytanie tytułowe. Podobnie nie wiem co by było z podróżnikiem w czasie, który unicestwiłby własnego dziadka przed poczęciem swojego ojca. Ale opowiem trochę o paradoksie przyczynowo-skutkowym w CSS.
Co by było gdyby?
To, że zmienne CSS bardzo ułatwiają pracę, to rzecz oczywista. Mały czy duży, każdy o tym wie. Bo przecież zamiast duplikować selektory i zmieniać wartości właściwości w różnych media queries, można oprzeć wartości o zmienne CSS, a tychże wartości zmieniać w media queries.
Czyli zamiast tak:
p {
font-size: 20px;
margin: 10px 0;
}
@media screen and (min-width:720px) {
p {
font-size: 25px;
margin: 15px 0;
}
}
@media screen and (min-width:1140px) {
p {
font-size: 30px;
margin: 20px 0;
}
}
Możemy zrobić tak:
:root {
--fontSize: 20px;
--margin: 10px 0;
}
p {
font-size: var(--fontSize);
margin: var(--margin);
}
@media screen and (min-width:720px) {
:root {
--fontSize: 25px;
--margin: 15px 0;
}
}
@media screen and (min-width:1140px) {
:root {
--fontSize: 30px;
--margin: 20px 0;
}
}
Na pierwszy rzut oka wydaje się to bezsensowne - więcej kodu, ale będzie o wiele łatwiej nam ogarniać taki arkusz.
I właśnie pewnego dnia, aby ułatwić sobie pracę jeszcze bardziej zadałem sobie w głowie pytanie: co by było gdyby? A dokładnie, co by było gdyby zmiennych używać jako parametry dla media queries. Czyli tak:
:root {
--tablet: 720px;
--desktop: 1140px;
}
@media screen and (min-width:var(--tablet)) {
/* tu selektory */
}
@media screen and (min-width:var(--desktop)) {
/* tu selektory */
}
Stwierdziłem, że to rzecz jeszcze bardziej ekstra niż standardowe przeznaczenie zmiennych. Mało, to lepsze niż kierowanie latającym spodkiem. A po krótkiej chwili euforii postanowiałem sprawdzić przykładowy kod w działaniu. I co się okazało? Nic. Literalnie nic. Selektory w media queries nie działały. Zacząłem szukać w czeluściach internetu informacji na ten temat i trafiłem nawet na wzmiankę w dokumentacji Bootstrap.
You can also use our breakpoint variables in your media queries:
.content-secondary {
display: none;
}@media (min-width(var(--breakpoint-sm))) {
.content-secondary {
display: block;
}
}
Wracam więc do kodu, zerkam czy gdzieś nie zapomniałem o postfiksie "px", liczę nawiasy, minusy, sprawdzam nazwy zmiennych. I d...
alej nic! Jeszcze raz internet i trafiam na cytat z w3.org:
The var() function can be used in place of any part of a value in any property on an element. The var() function can not be used as property names, selectors, or anything else besides property values. (Doing so usually produces invalid syntax, or else a value whose meaning has no connection to the variable.)
Czyli, że niby ok, tzn. nie powinno działać. Pocieszające...
W sumie ma to sens, bo gdyby zrobić tak:
:root {
--tablet: 720px;
}
@media screen and (min-width:var(--tablet)) {
:root {
--tablet: 920px;
}
}
to, czy media query powinno być oparte o warunek min-width:720px czy też min-width:960px? Bo skoro hipotetycznie wpadliśmy w środek media query dla min-width:720px (załóżmy, że ekran ma szerokość 800px), ale w środku zmieniamy wartość zmiennej na 960px, to warunek przestaje działać?
Skąd więc ten dziwny zapis w dokumentacji Bootstrap? Czyżby było jednak jakieś wyjście, hack, trick?
Oczywiście, że nie, bo jak się okazuje nie ma ludzi nieomylnych:
https://github.com/twbs/bootstrap/issues/25703
https://github.com/twbs/bootstrap/issues/29012
https://github.com/twbs/bootstrap/pull/29020
ale i leniwych, bo to już 2 lata:)
Niezmiennie zapraszam na kolejny wpis. Do przeczytania!
Przydatne linki:
w3.org a zmienne CSS.