Я пытаюсь использовать переменные 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.
max-width
! Он должен полностью работать!
- person user9645; 09.12.2020
max-width
, потому что вы пишете тот же текст, но оно выполняет нечто совершенно иное. Объявление свойства CSS действует как установщик, он устанавливает значение для элемента, а max-width
в медиа-запросе является геттером: он запрашивает текущую ширину чего-либо (а затем сравнивает ее с предоставленным значением). Текст max-width: 1000px
в качестве медиа-запроса (в форме НЕДЕЙСТВИТЕЛЬНОГО псевдокода) похож на viewport.getWidth() <= 1000px
, а в качестве объявления свойства это будет element.setMaxWidth(1000px)
.
- person Taederias; 29.05.2021
Как Ориоль ответил, в настоящее время var()
Переменные CSS уровня 1 нельзя использовать в медиа-запросах. Однако в последнее время появились разработки, которые позволят решить эту проблему. Через несколько лет, когда уровень 1 модуля переменных среды CSS будет стандартизирован и реализовано, мы сможем использовать env()
переменные в медиа-запросах во всех современных браузерах.
Если вы прочитали спецификацию и у вас возникли сомнения, или если вы хотите выразить свою поддержку в случае использования медиа-запроса это можно сделать в GitHub w3c / csswg-drafts # 1693 или в любая проблема CSS GitHub с префиксом «[css-env-1]».
Исходный ответ 2017-11-09: недавно Рабочая группа 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's разрешения и выполните поиск по запросу «MQ», что означает «медиа-запросы».)
Я планирую обновить этот вопрос в будущем, когда появятся новые разработки. Будущее захватывающее.
Обновление 2018-02-08: Safari Technology Preview 49 добавил поддержку синтаксического анализа calc()
в медиа-запросах, что может быть прелюдией к поддержке env()
и в них.
Обновление 2018-04-27: команда Chromium в Google решила начать работу над env()
. В ответ Аткинс начал указывать env()
в отдельном неофициальном проекте стандарта: CSS Модуль переменных среды, уровень 1. (См. его комментарий GitHub в w3c / csswg-draft # 1693. и его комментарий в w3c / csswg-draft # 1817.) Черновик вызывает переменные в медиа-запросах в качестве явного варианта использования:
Поскольку переменные среды не зависят от значения чего-либо, извлеченного из определенного элемента, их можно использовать в местах, где нет очевидного элемента для извлечения, например, в правилах
@media
, где функцияvar()
не действует.
Если вы прочитали спецификацию и у вас возникли сомнения, или если вы хотите выразить свою поддержку варианта использования медиа-запроса, вы все равно можете сделать это в GitHub w3c / csswg-drafts # 1693 или в любая проблема CSS GitHub с префиксом« [css-env-1] ».
Обновление 2019-07-06: работа над спецификациями продолжается. проблема GitHub № 2627 и GitHub issue # 3578 посвящены настраиваемым переменным среды в медиа-запросах.
Однако вы МОЖЕТЕ сделать @media запросить ваш оператор: root!
:root {
/* desktop vars */
}
@media screen and (max-width: 479px) {
:root {
/* mobile vars */
}
}
Полностью работает в Chrome, Firefox и Edge, по крайней мере, в последних производственных версиях на момент публикации.
Одно ограничение: если вам нужно получить доступ к значению как к переменной - например, для использования в вычислениях в другом месте - вам понадобится переменная, и для этого потребуется определить переменную в двух местах: медиа-запрос и объявление переменной.
По-видимому, просто невозможно использовать такие собственные переменные 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) {}
Вы можете использовать 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) {
...
}
Как вы можете прочитать в других ответах, это все еще невозможно.
Кто-то упомянул пользовательские переменные среды (похожие на пользовательские переменные css env()
вместо var()
), и принцип верен, хотя есть еще две основные проблемы: