Я пытаюсь использовать переменные CSS в медиа-запросе, и это не работает.
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
Я пытаюсь использовать переменные CSS в медиа-запросе, и это не работает.
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
Ответы:
Из спецификации ,
var()
Функция может быть использована вместо любой части значения в любой собственности на элементе.var()
Функция не может быть использована в качестве имен свойств, селекторов, или что - нибудь еще , кроме значений свойств. (Обычно это приводит к неверному синтаксису или значению, значение которого не связано с переменной.)
Так что нет, вы не можете использовать его в медиа-запросах.
И в этом есть смысл. Потому что вы можете установить, --mobile-breakpoint
например :root
, на <html>
элемент, а оттуда унаследовать его другим элементам. Но медиа-запрос не является элементом, он не наследуется <html>
, поэтому не может работать.
Это не то, чего пытаются добиться переменные CSS. Вместо этого вы можете использовать препроцессор CSS.
Как ответил Ориол , в настоящее время CSS-переменные уровня 1 var()
не могут использоваться в медиа-запросах . Однако в последнее время появились разработки, которые позволят решить эту проблему. Через несколько лет, когда уровень 1 модуля переменных среды CSS будет стандартизирован и реализован, мы сможем использовать env()
переменные в медиа-запросах во всех современных браузерах.
Если вы прочитали спецификацию и у вас возникли сомнения, или если вы хотите выразить свою поддержку варианта использования медиа-запроса, вы все равно можете сделать это в GitHub w3c / csswg-drafts # 1693 или в любой проблеме CSS GitHub с префиксом «[ css-env-1] » .
Исходный ответ 09.11.2017 : Недавно рабочая группа CSS решила, что переменные CSS уровня 2 будут поддерживать использование переменных среды, определяемых пользователем env()
, и попытаются сделать их действительными в медиа-запросах . Группа решила эту проблему после того, как Apple впервые предложила стандартные свойства пользовательского агента , незадолго до официального анонса iPhone X в сентябре 2017 года (см. Также WebKit: «Разработка веб-сайтов для iPhone X» Тимоти Хортона ). Затем другие представители браузеров согласились, что они будут в целом полезны на многих устройствах, например на телевизионных дисплеях и при печати чернилами с размытыми краями. ( env()
раньше называлсяconstant()
, но теперь это устарело. Вы все еще можете увидеть статьи, в которых упоминается старое название, например, эта статья Питера-Пола Коха .) Через несколько недель Кэмерон МакКормак из Mozilla понял, что эти переменные среды можно использовать в медиа-запросах, а Таб Аткинс младший затем компания Google поняла, что определяемые пользователем переменные среды будут особенно полезны в качестве глобальных непереопределяемых корневых переменных, используемых в медиа-запросах. Теперь декан «Дино» Джексон из Apple присоединится к Аткинсу для редактирования Уровня 2.
Вы можете подписаться на обновления по этому поводу в w3c/csswg-drafts
выпуске GitHub # 1693 . (Чтобы получить особенно важные исторические сведения, разверните журналы встреч, встроенные в решения CSSWG Meeting Bot, и выполните поиск по запросу «MQ», что означает «медиа-запросы».)
Я планирую обновить этот вопрос в будущем, когда появятся новые разработки. Будущее захватывающее.
Обновление 2018-02-08 :
Safari Technology Preview 49 добавила поддержку синтаксического анализа calc()
в медиа-запросах, что также может быть прелюдией к их поддержке env()
.
Обновление 2018-04-27 : команда Chromium в Google решила начать работу env()
. В ответ Аткинс начал указывать env()
в отдельном неофициальном проекте стандарта: модуль переменных среды CSS уровня 1 . (См. Его комментарий на GitHub в w3c / csswg-drafts # 1693 и его комментарий в w3c / csswg-drafts # 1817. ) Черновик вызывает переменные в медиа-запросах в качестве явного варианта использования:
Поскольку переменные среды не зависят от значения чего-либо, взятого из определенного элемента, их можно использовать в местах, где нет очевидного элемента для извлечения, например, в
@media
правилах, гдеvar()
функция не будет действительной.
Если вы прочитали спецификацию и у вас возникли опасения, или если вы хотите выразить свою поддержку варианта использования медиа-запроса, вы все равно можете сделать это в GitHub w3c / csswg-drafts # 1693 или в любой проблеме CSS GitHub с префиксом «[ css-env-1] » .
Обновление 2019-07-06 : Работа над спецификациями продолжается. GitHub выпуск № 2627 и GitHub вопрос # 3578 посвящены пользовательские переменные окружения в запросах медиа.
Однако вы МОЖЕТЕ сделать @media запросить ваш оператор: root!
:root {
/* desktop vars */
}
@media screen and (max-width: 479px) {
:root {
/* mobile vars */
}
}
Полностью работает в Chrome, Firefox и Edge, по крайней мере, в последних производственных версиях на момент публикации.
var
, чтобы его можно было использовать в вычислениях где-то в другом месте css
, для этого все равно потребуется поместить «магическое значение» (здесь 479 пикселей) в два места: медиа-запрос и объявление var.
По-видимому, просто невозможно использовать такие собственные переменные CSS. Это одно из ограничений .
Умный способ использовать это - изменить ваши переменные в медиа-запросе, чтобы повлиять на весь ваш стиль. Я рекомендую эту статью .
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
Один из способов добиться желаемого - использовать пакет npm postcss-media-variables
.
Если вас устраивает использование пакетов npm, вы можете посмотреть документацию здесь
пример
/* 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) {}
Как вы можете прочитать другие ответы, это все еще невозможно .
Кто-то упомянул пользовательские переменные окружения ( env()
вместо них похожие на пользовательские переменные css var()
), и принцип верен, хотя есть еще две основные проблемы:
Вы можете использовать JavaScript, чтобы изменить значение медиа-запросов и установить для него значение переменной 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 = '..'
Я написал небольшой скрипт, который вы можете разместить на своей странице. Он заменяет все правила СМИ со значением 1px
со значением переменной Css --replace-media-1px
, правила со значением 2px
с --replace-media-2px
и так далее. Это работает для запросов СМИ with
, min-width
, max-width
, height
, min-height
и max-height
даже тогда , когда они связаны с использованием 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) {
...
}