Estoy tratando de usar variables CSS en la consulta de medios y no funciona.
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
Estoy tratando de usar variables CSS en la consulta de medios y no funciona.
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
Respuestas:
De la especificación ,
La
var()
función se puede usar en lugar de cualquier parte de un valor en cualquier propiedad de un elemento. Lavar()
función no se puede usar como nombres de propiedad, selectores o cualquier otra cosa además de los valores de propiedad. (Hacerlo generalmente produce una sintaxis no válida, o bien un valor cuyo significado no tiene conexión con la variable).
Entonces no, no puede usarlo en una consulta de medios.
Y eso tiene sentido. Debido a que puede establecer, --mobile-breakpoint
por ejemplo :root
, en , es decir, el <html>
elemento, y desde allí ser heredado a otros elementos. Pero una consulta de medios no es un elemento, no hereda <html>
, por lo que no puede funcionar.
Esto no es lo que las variables CSS intentan lograr. Puede usar un preprocesador CSS en su lugar.
Como Oriol ha respondido , actualmente, las Variables CSS Nivel 1 var()
no se pueden usar en consultas de medios . Sin embargo, ha habido desarrollos recientes que abordarán este problema. En unos pocos años, una vez que el Módulo de Variables de Entorno CSS Nivel 1 esté estandarizado e implementado, podremos usar env()
variables en consultas de medios en todos los navegadores modernos.
Si lee la especificación y tiene alguna inquietud, o si desea expresar su apoyo al caso de uso de consultas de medios, aún puede hacerlo en GitHub w3c / csswg-drafts # 1693 o en cualquier problema de CSS GitHub con el prefijo "[ css-env-1] " .
Respuesta original 09-11-2017 : Recientemente, el Grupo de trabajo CSS decidió que las Variables CSS Nivel 2 admitirán el uso de variables de entorno definidas por el usuario env()
y tratarán de que sean válidas en las consultas de los medios . El Grupo resolvió esto después de que Apple propuso por primera vez las propiedades estándar de agente de usuario , poco antes del anuncio oficial del iPhone X en septiembre de 2017 (ver también WebKit: "Diseño de sitios web para iPhone X" por Timothy Horton ). Otros representantes del navegador acordaron que serían generalmente útiles en muchos dispositivos, como pantallas de televisión e impresión de tinta con bordes de sangrado. ( env()
solía llamarseconstant()
, pero eso ahora ha quedado en desuso. Es posible que aún vea artículos que se refieren al nombre anterior, como este artículo de Peter-Paul Koch .) Después de algunas semanas, Cameron McCormack de Mozilla se dio cuenta de que estas variables de entorno serían utilizables en consultas de medios, y Tab Atkins, Jr. Luego, Google se dio cuenta de que las variables de entorno definidas por el usuario serían especialmente útiles como variables raíz globales, no reemplazables y utilizables en consultas de medios. Ahora, Dean "Dino" Jackson de Apple se unirá a Atkins en la edición del Nivel 2.
Puede suscribirse a las actualizaciones sobre este asunto en la w3c/csswg-drafts
edición # 1693 de GitHub . (Para obtener detalles históricos especialmente relevantes, expanda los registros de la reunión integrados en las resoluciones del CSSWG Meeting Bot y busque "MQ", que significa "consultas de medios".)
Planeo actualizar esta pregunta en el futuro cuando ocurran más desarrollos. El futuro es emocionante.
Actualización 08/02/2018 :
Safari Technology Preview 49 ha agregado soporte para analizar calc()
las consultas de medios, lo que también puede ser un preludio de soporte env()
en ellas.
Actualización 27/04/2018 : el equipo de Chromium en Google ha decidido comenzar a trabajar env()
. En respuesta, Atkins comenzó a especificar env()
en un borrador de estándar no oficial separado: el Módulo de Variables de Entorno CSS Nivel 1 . (Consulte su comentario de GitHub en w3c / csswg-drafts # 1693 y su comentario en w3c / csswg-drafts # 1817. ) El borrador menciona las variables en las consultas de los medios como un caso de uso explícito:
Debido a que las variables de entorno no dependen del valor de nada extraído de un elemento en particular, se pueden usar en lugares donde no hay un elemento obvio del cual extraer, como en las
@media
reglas, donde lavar()
función no sería válida.
Si lee la especificación y tiene alguna inquietud, o si desea expresar su apoyo al caso de uso de consultas de medios, aún puede hacerlo en GitHub w3c / csswg-drafts # 1693 o en cualquier problema de CSS GitHub con el prefijo "[ css-env-1] " .
Actualización 2019-07-06 : el trabajo continúa en las especificaciones. El número 2627 de GitHub y el número 3578 de GitHub están dedicados a variables de entorno personalizadas en consultas de medios.
Sin embargo, lo que PUEDE hacer es consultar a @media su: declaración raíz.
:root {
/* desktop vars */
}
@media screen and (max-width: 479px) {
:root {
/* mobile vars */
}
}
Totalmente funciona en Chrome, Firefox y Edge al menos las últimas versiones de producción a partir de esta publicación.
var
, por lo que puede usarlo en cálculos en otra parte del css
, esto todavía requiere poner el "valor mágico" (aquí, 479 px) en dos lugares: la consulta de medios y una declaración var.
Aparentemente, simplemente no es posible usar variables CSS nativas como esa. Es una de las limitaciones .
Una forma inteligente de usarlo es cambiar sus variables en la consulta de medios, para impactar todo su estilo. Recomiendo este artículo .
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
Una forma de lograr lo que desea es usar el paquete npm postcss-media-variables
.
Si está de acuerdo con el uso de paquetes npm, puede consultar la documentación aquí.
Ejemplo
/* 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) {}
Como puede leer otras respuestas, aún no es posible hacerlo.
Alguien mencionó variables ambientales personalizadas (similares a las variables CSS personalizadas en env()
lugar de var()
), y el principio es sólido, aunque todavía hay 2 problemas principales:
Puede usar JavaScript para cambiar el valor de las consultas de medios y establecerlo en el valor de una variable 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 = '..'
Escribí un pequeño script que puedes incluir en tu página. Reemplaza cada regla de medios con un valor de 1px
con el valor de la variable css --replace-media-1px
, reglas con valor 2px
con --replace-media-2px
y así sucesivamente. Esto funciona para las preguntas de los medios with
, min-width
, max-width
, height
, min-height
y max-height
aun cuando se conectan utilizando 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) {
...
}