Variáveis ​​nativas de CSS que não funcionam em consultas de mídia


140

Eu estou tentando usar variáveis ​​CSS na consulta de mídia e ele não funciona.

:root {
  --mobile-breakpoint: 642px;
}

@media (max-width: var(--mobile-breakpoint)) {

}

Você tentou em vários navegadores? (Como Chrome e Firefox)
Cohars 21/11

1
Sem pré-processador @SandrinaPereira
Cohars

1
@SandrinaPereira Então você pode no Firefox e Chrome 👍
Cohars


3
Apenas para esclarecer as pessoas que encontram isso no Google: você pode usar propriedades personalizadas CSS dentro do escopo de uma consulta de mídia, simplesmente não pode usá-las em uma declaração de consulta de mídia.
David Deprost 10/06/19

Respostas:


112

Das especificações ,

A var()função pode ser usada no lugar de qualquer parte de um valor em qualquer propriedade em um elemento. ovar() função não pode ser usada como nomes de propriedades, seletores ou qualquer outra coisa além de valores de propriedades. (Isso geralmente produz uma sintaxe inválida ou um valor cujo significado não tem conexão com a variável.)

Portanto, não, você não pode usá-lo em uma consulta de mídia.

E isso faz sentido. Porque você pode definir, --mobile-breakpointpor exemplo :root, para , ou seja, o <html>elemento e, a partir daí, ser herdado para outros elementos. Mas uma consulta de mídia não é um elemento, ela não herda de<html> , portanto, não pode funcionar.

Não é isso que as variáveis ​​CSS estão tentando realizar. Você pode usar um pré-processador CSS.


77
A resposta está correta, pois atualmente a especificação não lida com variáveis ​​CSS em consultas de mídia, mas incorreta, não é isso que as variáveis ​​CSS estão tentando realizar. Reduzindo o número de repetição e mágicas é exatamente por isso variáveis CSS foram criados - veja w3.org/TR/css-variables-1/#intro
mikemaccana

69

Como a Oriol respondeu , atualmente, o nível 1 das variáveis ​​CSS var()não pode ser usado em consultas de mídia . No entanto, houve desenvolvimentos recentes que abordarão esse problema. Dentro de alguns anos, quando o Módulo 1 de variáveis ​​de ambiente CSS for padronizado e implementado, poderemos usarenv() variáveis ​​em consultas de mídia em todos os navegadores modernos.

Se você ler a especificação e tiver alguma preocupação, ou se desejar expressar seu suporte ao caso de uso de consulta de mídia, ainda poderá fazê-lo no GitHub w3c / csswg-draft # 1693 ou em qualquer problema de CSS GitHub prefixado com "[ css-env-1] " .


Resposta original 09/11/2017 : Recentemente, o Grupo de Trabalho CSS decidiu que o nível de variáveis ​​2 do CSS oferecerá suporte ao uso de variáveis ​​de ambiente definidas pelo usuário env()e tentará torná-las válidas em consultas de mídia . O Grupo resolveu isso depois que a Apple propôs propriedades padrão de agente de usuário pela primeira vez , pouco antes do anúncio oficial do iPhone X em setembro de 2017 (consulte também o WebKit: “Criando sites para o iPhone X” de Timothy Horton ). Outros representantes do navegador concordaram que seriam geralmente úteis em muitos dispositivos, como telas de televisão e impressão a tinta com bordas de sangria. ( env()costumava ser chamadoconstant(), mas que agora foi descontinuado. Você ainda pode ver artigos que se referem ao nome antigo, como este artigo de Peter-Paul Koch .) Depois de algumas semanas, Cameron McCormack, da Mozilla, percebeu que essas variáveis ​​de ambiente seriam utilizáveis ​​em consultas de mídia e Tab Atkins, Jr. o Google então percebeu que variáveis ​​de ambiente definidas pelo usuário seriam especialmente úteis como variáveis ​​raiz globais e não substituíveis, utilizáveis ​​em consultas de mídia. Agora, Dean "Dino" Jackson, da Apple, se juntará a Atkins na edição do Nível 2.

Você pode se inscrever para receber atualizações sobre esse assunto na w3c/csswg-draftsedição 1693 do GitHub . (Para detalhes históricos especialmente relevantes, expanda os logs de reunião incorporados nas resoluções do CSSWG Meeting Bot e procure por "MQ", que significa "consultas de mídia".)

Pretendo atualizar esta questão no futuro, quando ocorrerem mais desenvolvimentos. O futuro é emocionante.


Atualização 2018-02-08 : O Safari Technology Preview 49 adicionou suporte para análise calc()em consultas de mídia, o que pode ser um prelúdio para o suporte a env()elas também.


Atualização 2018-04-27 : a equipe do Chromium no Google decidiu começar a trabalhar env(). Em resposta, a Atkins começou a especificar env()em um rascunho padrão não oficial: o Módulo de Variáveis ​​de Ambiente CSS Nível 1 . (Veja seu comentário no GitHub em w3c / csswg-drafts # 1693 e seu comentário em w3c / csswg-drafts # 1817. ) O rascunho chama variáveis ​​nas consultas de mídia como um caso de uso explícito:

Como as variáveis ​​de ambiente não dependem do valor de algo extraído de um elemento específico, elas podem ser usadas em locais onde não há elemento óbvio para extrair, como em @mediaregras, nas quais a var()função não seria válida.

Se você ler a especificação e tiver alguma preocupação, ou se desejar expressar seu suporte ao caso de uso de consulta de mídia, ainda poderá fazê-lo no GitHub w3c / csswg-draft # 1693 ou em qualquer problema de CSS GitHub prefixado com "[ css-env-1] " .


Atualização 2019-07-06 : O trabalho continua com as especificações. O problema do GitHub nº 2627 e o do GitHub nº 3578 são dedicados a variáveis ​​ambientais personalizadas em consultas de mídia.


31

No entanto, o que você PODE fazer é @media consultar sua instrução: root!

:root {
     /* desktop vars */
}
@media screen and (max-width: 479px) {
    :root {
        /* mobile vars */
    }
}

Funciona totalmente no Chrome, Firefox e Edge pelo menos nas versões de produção mais recentes a partir desta publicação.


Uau, obrigado! Definitivamente, essa deve ser a resposta correta.
SimplyComplexable

1
Bom saber. Uma limitação: se também for necessário acessar esse valor como a var, também pode ser usado em cálculos em outros locais css, isso ainda exige colocar o "valor mágico" (aqui, 479px) em dois lugares: a consulta de mídia e uma declaração var.
Home

8

Aparentemente, não é possível usar variáveis ​​CSS nativas como essa. É uma das limitações .

Uma maneira inteligente de usá-lo é alterar suas variáveis ​​na consulta de mídia, impactando todo o seu estilo. Eu recomendo este artigo .

:root {
  --gutter: 4px;
}

section {
  margin: var(--gutter);
}

@media (min-width: 600px) {
  :root {
    --gutter: 16px;
  }
}

Eu não entendo o significado de "alterar suas variáveis ​​na consulta de mídia", você pode mostrar um exemplo?

1
Não foi isso que eu quis dizer. Eu perguntei sobre o valor da consulta de mídia.

4
Sim, acabei de fazer, está no artigo que vinculei. Eu sei que não é o que você esperava, mas variáveis CSS simplesmente não pode ser usado para definir as consultas de mídia
Cohars

8

Uma maneira de conseguir o que você deseja é usar o pacote npm postcss-media-variables.

Se você está bem com o uso de pacotes npm, pode dar uma olhada no documentatoin para o mesmo aqui

Exemplo

/* 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) {}

4
Obrigado, mas estava tentando não usar nenhum pré-processador.

et. al: Com postcss você também pode usar cssnext cssnext.io/features/#custom-media-queries
sebilasse

1
@sebilasse: personalizados-media-consultas não aborda o principal problema de não ser capaz de usar variáveis CSS como pontos de interrupção para consultas de mídia
zhirzh

1
O postcss não é um pré

1

Como você pode ler outras respostas, ainda não é possível fazer isso.

Alguém mencionou variáveis ​​de ambiente personalizadas (semelhantes às variáveis ​​de CSS personalizadas em env()vez de var()), e o princípio é sólido, embora ainda existam 2 problemas principais:

  • suporte fraco ao navegador
  • até o momento, não há como defini-los (mas provavelmente o será no futuro, pois esse é apenas um rascunho não oficial)

1

Resposta curta

Você pode usar o JavaScript para alterar o valor das consultas de mídia e configurá-lo para o valor de uma variável 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 = '..'


Resposta longa

Escrevi um pequeno script que você pode incluir em sua página. Ele substitui todas as regras de mídia por um valor de 1pxcom o valor da variável css --replace-media-1px, regras por valor 2pxcom --replace-media-2pxe assim por diante. Isso funciona para as consultas de mídia with, min-width, max-width, height, min-heighte max-heightmesmo quando eles estão conectados usando 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) {
  ...
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.