Próbuję użyć zmiennych CSS w zapytaniu o media i to nie działa.
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
Próbuję użyć zmiennych CSS w zapytaniu o media i to nie działa.
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
Odpowiedzi:
Ze specyfikacją ,
var()
Funkcja może być używana zamiast dowolnej części wartości w każdej nieruchomości na elemencie.var()
Funkcja nie może być używana jako nazwy własności, selektorów, czy cokolwiek innego oprócz wartości nieruchomości. (Takie postępowanie zwykle powoduje powstanie nieprawidłowej składni lub wartości, której znaczenie nie ma związku ze zmienną).
Więc nie, nie możesz go użyć w zapytaniu o media.
I to ma sens. Bo możesz ustawić --mobile-breakpoint
np. Na :root
, czyli <html>
element, i stamtąd być dziedziczony do innych elementów. Ale zapytanie o media nie jest elementem, nie dziedziczy po nim <html>
, więc nie może działać.
To nie jest to, co próbują osiągnąć zmienne CSS. Zamiast tego możesz użyć preprocesora CSS.
Jak odpowiedział Oriol , obecnie w zapytaniach o media nie można używać zmiennych CSS poziomu 1var()
. Jednak ostatnio nastąpiły zmiany, które pozwolą rozwiązać ten problem. Za kilka lat, po ustandaryzowaniu i wdrożeniu modułu zmiennych środowiskowych CSS na poziomie 1 , będziemy mogli używać env()
zmiennych w zapytaniach o media we wszystkich nowoczesnych przeglądarkach.
Jeśli przeczytałeś specyfikację i masz obawy lub jeśli chcesz wyrazić swoje poparcie dla przypadku użycia zapytania o media, nadal możesz to zrobić w GitHub w3c / csswg-drafts # 1693 lub w jakimkolwiek numerze CSS GitHub poprzedzonym prefiksem „[ css-env-1] ” .
Oryginalna odpowiedź 09.11.2017 : Niedawno grupa robocza CSS zdecydowała, że zmienne CSS poziomu 2 będą obsługiwać zmienne środowiskowe zdefiniowane przez użytkownika przy użyciu env()
i będą starać się, aby były one prawidłowe w zapytaniach o media . Grupa rozwiązała ten problem po tym, jak Apple po raz pierwszy zaproponował standardowe właściwości agenta użytkownika , na krótko przed oficjalnym ogłoszeniem iPhone'a X we wrześniu 2017 r. (Patrz także WebKit: „Projektowanie stron internetowych dla iPhone'a X” autorstwa Timothy'ego Hortona ). Inni przedstawiciele przeglądarek zgodzili się wtedy, że będą one ogólnie przydatne na wielu urządzeniach, takich jak wyświetlacze telewizyjne i druk atramentowy z krawędziami spadającymi. ( env()
kiedyś nazywanoconstant()
, ale teraz jest to przestarzałe. Nadal możesz zobaczyć artykuły, które odwołują się do starej nazwy, na przykład ten artykuł Petera-Paula Kocha .) Po kilku tygodniach Cameron McCormack z Mozilli zdał sobie sprawę, że te zmienne środowiskowe będą użyteczne w zapytaniach o media, a Tab Atkins, Jr. firmy Google zdał sobie wtedy sprawę, że zmienne środowiskowe zdefiniowane przez użytkownika byłyby szczególnie przydatne jako globalne, niepodlegające zastąpieniu zmienne główne, których można używać w zapytaniach o media. Teraz Dean „Dino” Jackson z Apple dołączy do Atkinsa w edycji poziomu 2.
Możesz zasubskrybować aktualizacje w tej sprawie w w3c/csswg-drafts
numerze 1693 na GitHubie . (Aby uzyskać szczególnie istotne szczegóły historyczne, rozwiń dzienniki spotkań osadzone w rozwiązaniach CSSWG Meeting Bot i wyszukaj „MQ”, co oznacza „zapytania o media”).
Planuję zaktualizować to pytanie w przyszłości, gdy nastąpi więcej zmian. Przyszłość jest ekscytująca.
Aktualizacja 2018-02-08 :
Safari Technology Preview 49 dodała obsługę parsowania calc()
w zapytaniach o media, co może być wstępem do env()
ich obsługi.
Aktualizacja 2018-04-27 : Zespół Chromium w Google zdecydował się rozpocząć pracę env()
. W odpowiedzi Atkins zaczął określać env()
w oddzielnym, nieoficjalnym projekcie standardu: moduł zmiennych środowiskowych CSS Poziom 1 . (Zobacz jego komentarz GitHub w w3c / csswg-drafts # 1693 i jego komentarz w w3c / csswg-drafts # 1817 ). Wersja robocza przywołuje zmienne w zapytaniach o media jako jawny przypadek użycia:
Ponieważ zmienne środowiskowe nie zależą od wartości czegokolwiek narysowanego z określonego elementu, mogą być używane w miejscach, w których nie ma oczywistego elementu do narysowania, na przykład w
@media
regułach, w którychvar()
funkcja byłaby nieprawidłowa.
Jeśli przeczytałeś specyfikację i masz obawy lub jeśli chcesz wyrazić swoje poparcie dla przypadku użycia zapytania o media, nadal możesz to zrobić w GitHub w3c / csswg-drafts # 1693 lub w dowolnym numerze CSS GitHub poprzedzonym prefiksem „[ css-env-1] ” .
Aktualizacja 06.07.2019 : Trwają prace nad specyfikacjami. GitHub numer 2627 i GitHub numer 3578 są poświęcone niestandardowym zmiennym środowiskowym w zapytaniach o media.
MOŻESZ jednak zrobić zapytanie @media do instrukcji: root!
:root {
/* desktop vars */
}
@media screen and (max-width: 479px) {
:root {
/* mobile vars */
}
}
Całkowicie działa w Chrome, Firefox i Edge przynajmniej w najnowszych wersjach produkcyjnych na ten post.
var
, więc można jej użyć w obliczeniach w innym miejscu w css
, nadal wymaga to umieszczenia „magicznej wartości” (tutaj 479px) w dwóch miejscach: zapytanie o media i deklaracja var.
Najwyraźniej po prostu nie jest możliwe użycie takich natywnych zmiennych CSS. To jedno z ograniczeń .
Sprytnym sposobem użycia tego jest zmiana zmiennych w zapytaniu o media, aby wpłynąć na cały Twój styl. Polecam ten artykuł .
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
Jednym ze sposobów osiągnięcia tego, co chcesz, jest użycie pakietu npm postcss-media-variables
.
Jeśli nie masz nic przeciwko korzystaniu z pakietów npm, możesz zapoznać się z dokumentacją tego samego tutaj
Przykład
/* input */
:root {
--min-width: 1000px;
--smallscreen: 480px;
}
@media (min-width: var(--min-width)) {}
@media (max-width: calc(var(--min-width) - 1px)) {}
@custom-media --small-device (max-width: var(--smallscreen));
@media (--small-device) {}
Jak możesz przeczytać inne odpowiedzi, nadal nie możesz tego zrobić.
Ktoś wspomniał o niestandardowych zmiennych środowiskowych (podobnych do niestandardowych zmiennych css env()
zamiast var()
) i zasada jest słuszna, chociaż nadal występują 2 główne problemy:
Możesz użyć JavaScript, aby zmienić wartość zapytań o media i ustawić ją na wartość zmiennej css.
// get value of css variable
getComputedStyle(document.documentElement).getPropertyValue('--mobile-breakpoint'); // '642px'
// search for media rule
var mediaRule = document.styleSheets[i].cssRules[j];
// update media rule
mediaRule.media.mediaText = '..'
Napisałem mały skrypt, który możesz umieścić na swojej stronie. Zastępuje każdą regułę multimedialny o wartości 1px
o wartości zmiennej css --replace-media-1px
, przepisy o wartości 2px
ze --replace-media-2px
i tak dalej. Działa to dla zapytań medialnych with
, min-width
, max-width
, height
, min-height
i max-height
nawet wtedy, gdy są one połączone za pomocą and
.
JavaScript:
function* visitCssRule(cssRule) {
// visit imported stylesheet
if (cssRule.type == cssRule.IMPORT_RULE)
yield* visitStyleSheet(cssRule.styleSheet);
// yield media rule
if (cssRule.type == cssRule.MEDIA_RULE)
yield cssRule;
}
function* visitStyleSheet(styleSheet) {
try {
// visit every rule in the stylesheet
var cssRules = styleSheet.cssRules;
for (var i = 0, cssRule; cssRule = cssRules[i]; i++)
yield* visitCssRule(cssRule);
} catch (ignored) {}
}
function* findAllMediaRules() {
// visit all stylesheets
var styleSheets = document.styleSheets;
for (var i = 0, styleSheet; styleSheet = styleSheets[i]; i++)
yield* visitStyleSheet(styleSheet);
}
// collect all media rules
const mediaRules = Array.from(findAllMediaRules());
// read replacement values
var style = getComputedStyle(document.documentElement);
var replacements = [];
for (var k = 1, value; value = style.getPropertyValue('--replace-media-' + k + 'px'); k++)
replacements.push(value);
// update media rules
for (var i = 0, mediaRule; mediaRule = mediaRules[i]; i++) {
for (var k = 0; k < replacements.length; k++) {
var regex = RegExp('\\((width|min-width|max-width|height|min-height|max-height): ' + (k+1) + 'px\\)', 'g');
var replacement = '($1: ' + replacements[k] + ')';
mediaRule.media.mediaText = mediaRule.media.mediaText.replace(regex, replacement);
}
}
CSS:
:root {
--mobile-breakpoint: 642px;
--replace-media-1px: var(--mobile-breakpoint);
--replace-media-2px: ...;
}
@media (max-width: 1px) { /* replaced by 642px */
...
}
@media (max-width: 2px) {
...
}