Consultas de elementos e como você pode usá-las hoje

Publicados: 2022-03-10
Resumo rápido ↬ Por algum tempo, nos deparamos com os limites do que o CSS pode fazer . Aqueles que constroem layouts responsivos admitirão livremente as frustrações e deficiências do CSS que nos forçam a buscar pré-processadores CSS, plugins e outras ferramentas para nos ajudar a escrever os estilos que não conseguimos escrever apenas com CSS. Mesmo assim, encontramos limitações com o que as ferramentas atuais nos ajudam a realizar.

Pense por um momento em uma estrutura física. Se você está construindo um edifício grande com material fraco, é necessário muito suporte externo para mantê-lo unido, e as coisas precisam ser superconstruídas para permanecerem resistentes. Quando você está construindo um site a partir de HTML, CSS e JavaScript, esse suporte externo pode se parecer com frameworks, plugins, pré-processadores, transpiladores, ferramentas de edição, gerenciadores de pacotes e processos de construção.

Mais depois do salto! Continue lendo abaixo ↓

Em vez de adicionar mais um plugin ao topo da pilha, eu me perguntei se, estendendo uma das principais linguagens, CSS , poderíamos fortalecer o material a partir do qual os sites são construídos, desenvolvendo sites melhores e mais fortes que exigem menos suporte e ferramentas externas construir.

O estado atual das consultas de elemento

Com ferramentas como pré-processadores de CSS, escrevemos CSS abreviado, para ser expandido posteriormente em sua forma completa (antes de ser visualizado em um navegador). Os plug-ins podem operar na página junto com os elementos que afetam, mas para aplicar estilos, eles escrevem estilos CSS diretamente no HTML ou alternam nomes de classes que aplicam diferentes regras CSS. Em ambos os casos, precisamos escrever ou gerar o CSS que precisaremos antes que a página seja carregada.

O problema

O problema com esse método é que mesmo os melhores plugins geralmente exigem personalização e configuração em cada layout que você usa. Além disso, quando o JavaScript está escrevendo estilos para você, pode ser difícil manter sua lógica baseada em plug-ins e seus estilos CSS juntos ao refatorar ou reutilizar o código.

Outro problema com os pré-processadores é que quaisquer erros escritos em taquigrafia rapidamente se transformam em uma bagunça muito maior quando o CSS é expandido em sua forma completa. Ao usar plugins, adicionamos muitos pontos potenciais de falha. Podemos estar usando vários plugins para realizar um punhado de coisas diferentes que poderiam ser desnecessárias se o CSS fosse um pouco mais poderoso. Isso cria uma carga extra para os desenvolvedores manterem, para os navegadores renderizarem e para os usuários fazerem download.

Existe alguma esperança para o futuro do desenvolvimento web?

Em 2013, Tyson Matanich escreveu um artigo intitulado “Media Queries Are Not the Answer: Element Query Polyfill”, que introduziu o conceito de consultas de elemento para um grande público. Isso deu início a uma discussão sobre como plugins e polyfills podem ser construídos para navegar pelas deficiências do CSS.

Desde então, enquanto esperamos que os recursos CSS avancem, vários plugins foram lançados que permitem que os desenvolvedores usem consultas de elementos de algumas maneiras diferentes.

O que são consultas de elemento?

As consultas de elemento são como consultas de mídia, exceto que suas regras se aplicam às propriedades dos elementos reais, em vez das da janela de visualização do navegador.

Como surgiu o EQCSS

No final de 2013, encontrei-me trabalhando no front-end de um aplicativo web Ruby on Rails. O aplicativo precisava exibir informações detalhadas para os usuários, e o objetivo era criar uma interface responsiva que funcionasse igualmente bem em telefones, tablets e navegadores de desktop. Isso apresentou alguns desafios, um dos quais foi que grande parte do conteúdo importante a ser exibido era melhor exibido em tabelas - sim, elementos reais da table (para mostrar transações financeiras, registros esportivos etc.).

O projeto EQCSS surgiu como resultado de uma pesquisa sobre media queries de elementos. Agora, finalmente foi lançado, e você pode usá-lo hoje. Confira as demonstrações.

Criei estilos responsivos usando media queries que exibiam o elemento table corretamente para navegadores de diferentes tamanhos. Mas assim que uma dessas tabelas responsivas foi exibida em um modelo que continha uma barra lateral, de repente todos os meus pontos de interrupção responsivos se transformaram em pontos de interrupção responsivos. Eles simplesmente não levaram em conta a barra lateral de 200 pixels, fazendo com que as coisas se sobrepusessem e parecessem quebradas.

Outro obstáculo: os nomes de usuário variavam em comprimento de 3 a 20 caracteres, e eu me peguei desejando poder ajustar automaticamente o tamanho da fonte de cada nome de usuário com base no número de caracteres que ele continha. Eu precisava colocar cada nome de usuário na barra lateral, e era complicado escolher um tamanho de fonte pequeno o suficiente para caber em um nome de usuário de 20 caracteres, mas grande o suficiente para o visualizador ver um nome de usuário de 3 caracteres.

Para contornar problemas como esses, muitas vezes eu me pegava copiando consultas de mídia inteiras, duplicando grandes seções de minha base de código, simplesmente porque precisava de uma maneira mais inteligente de aplicar os estilos responsivos em cada layout. Eu confiei no JavaScript como outra solução improvisada, escrevendo muitas funções quase idênticas que observariam uma página e aplicariam estilos em lugares onde o CSS não poderia alcançar. Depois de um tempo, o fardo adicional de todo esse código duplicado começou a sobrecarregar a base de código e tornou as alterações difíceis de fazer.

Eu sabia que tinha que haver uma solução melhor e, depois de um tempo, comecei a pensar: não preciso de consultas de mídia — o que preciso são consultas de elemento!

Pesquisa e desenvolvimento

Em 2014, comecei a experimentar diferentes maneiras de informar CSS sobre as propriedades dos elementos conforme eles apareciam na página, para que eu pudesse aplicar estilos melhores. Eu esperava descobrir uma abordagem que me permitisse escrever estilos que combinassem a beleza do CSS com o poder do JavaScript.

Algumas abordagens abandonadas que desisti incluem adicionar atributos a tags HTML para adicionar suporte responsivo e tentar encontrar maneiras de incorporar blocos inteiros de código CSS dentro de instruções if baseadas em JavaScript para produzir algum tipo de monstro Frankenstein remendado de JavaScript e CSS.

Mas, em vez de facilitar as coisas, todas as minhas abordagens fracassadas tinham uma coisa em comum: elas adicionavam mais trabalho! Eu sabia que a solução certa simplificaria e reduziria o trabalho que precisava ser feito, então continuei procurando. Por meio desses experimentos, acabei com uma ideia refinada do tipo de sintaxe que seria necessária para que as consultas de elementos funcionassem bem.

Como mencionado, para um site construído a partir de HTML, CSS e JavaScript, o suporte externo vem na forma de frameworks, plugins, pré-processadores, transpiladores, ferramentas de edição, gerenciadores de pacotes e processos de construção. Em vez de adicionar mais um plugin ao topo da pilha, eu me perguntei se, estendendo uma das principais linguagens, CSS, poderíamos fortalecer o material do qual os sites são construídos, construindo sites melhores e mais fortes que exigem menos suporte externo e ferramentas para construir.

O nascimento de uma sintaxe

No final de 2014, munido de uma melhor visão da sintaxe necessária, entrei em contato com Maxime Euziere, um fenomenal golfista de código JavaScript e pedi sua opinião sobre a possibilidade de estender CSS usando JavaScript no navegador em tempo de execução. Ele não apenas me informou que é possível, mas se ofereceu para me ajudar a fazê-lo! Chamamos a sintaxe de EQCSS, abreviação de “element query CSS”. O nome também é um aceno para a palavra “excesso”, porque tudo o que ele faz excede o que o CSS pode fazer.

A necessidade

Meu requisito para a sintaxe era que fosse o mais próximo possível do CSS - tão próximo que os marcadores de sintaxe seriam enganados ao pensar que era CSS padrão. Então, mapeei a sintaxe CSS para consultas de elementos que faziam sentido - o tipo de sintaxe que as pessoas ficam surpresas ainda não existe.

Eu sabia que se estivéssemos estendendo o suporte do navegador para CSS usando JavaScript, o plug-in precisaria ser o mais leve e direto possível para fazer o trabalho, o que descartava o uso de bibliotecas como jQuery para construir o plug-in. Eu precisava de uma biblioteca JavaScript pura que adicionasse os recursos que eu quero no futuro aos navegadores que eu tenho que oferecer suporte hoje.

Neste momento, a discussão na comunidade CSS está focada em regras @ personalizadas, e falar sobre consultas de elementos ainda é preliminar. Provavelmente ainda estamos a anos de qualquer especificação oficial de CSS para recursos como esse e, mesmo após uma especificação, ainda precisaremos esperar por suporte suficiente ao navegador antes de podermos usar esses recursos em sites.

Esperar que esses recursos sejam adicionados ao CSS não faz sentido quando precisamos dessa funcionalidade para criar e corrigir sites hoje.

O resultado

O resultado desta pesquisa foi a criação de uma sintaxe que inclui um novo conjunto de condições responsivas avançadas, estilos de escopo e novos seletores para elementos de direcionamento, bem como uma biblioteca JavaScript pura chamada EQCSS.js. Além disso, o suporte para Internet Explorer (IE) 8 foi fornecido em um polyfill externo opcional. Tanto o plugin quanto o polyfill foram lançados sob a licença do MIT e são gratuitos para todos usarem.

Casos de uso para consultas de elementos

Desenvolvedores de plug-ins

Ao criar componentes e widgets de interface do usuário, os desenvolvedores geralmente ficam limitados por consultas de mídia. Muitas vezes temos que escolher entre construir muitos layouts diferentes que podem ser configurados pela pessoa que usa o plug-in e simplificar a interface até o ponto em que você possa criar uma solução de tamanho único.

Mas ao projetar plugins e interfaces com consultas de elementos, podemos facilmente escrever estilos responsivos que cobrem todas as situações que antecipamos, tornando-os realmente à prova de balas, não importa qual conteúdo o usuário coloque ou onde o plugin apareça. Suponha que pudéssemos estilizar um widget com layouts que variam de 150 a 2.000 pixels de largura. Então, não importa onde esse widget seja exibido em um site, ele sempre ficará ótimo.

Construtores de modelos

Quando você está prototipando um site, é comum reorganizar os elementos de design na página e pensar no design como uma coleção de componentes modulares. Se você escreveu consultas de mídia CSS, às vezes isso pode ser um caso de otimização prematura . Ao projetar com consultas de elemento, você mantém as condições responsivas independentes do layout, oferecendo muito mais flexibilidade para mover as coisas sem precisar retrabalhar os estilos.

Coisas que achei especialmente úteis para projetar ou simular usando consultas de elemento incluem:

  • barras de navegação,
  • modais,
  • formulários de inscrição e login,
  • rodapés,
  • tabelas de preços,
  • páginas de destino,
  • mesas,
  • caixas de guias,
  • acordeões,
  • widgets da barra lateral,
  • reprodutores de mídia,
  • seções de depoimentos.

Qualquer elemento de design pode ser “definido” e portado em qualquer lugar – página para página ou site para site.

Suporte a dispositivos

Um dos problemas que você enfrenta ao oferecer suporte à Web em dispositivos móveis é a abundância de hardware. O mercado de dispositivos está mais fragmentado do que nunca, e novos dispositivos estão surgindo todos os dias. Não podemos mais manter uma lista dos navegadores e dispositivos que suportamos, por isso é crucial saber que um design funciona em qualquer lugar, mesmo em dispositivos que ainda não foram lançados.

Ao usar consultas de elementos, você pode projetar sites de uma maneira melhor e eliminar algumas dessas diferenças entre navegadores.

Muitos artigos escritos recentemente sobre a necessidade de consultas de elementos ilustram muitos dos casos de uso em detalhes. Então, vamos ver como usá-los!

Como escrever consultas de elementos

Começar com o EQCSS é fácil. Tudo o que você precisa para começar a usar a sintaxe EQCSS é incluir o JavaScript em algum lugar do seu HTML.

Baixando EQCSS.js

Se você quiser clonar o projeto EQCSS do GitHub, digite:

 git clone https://github.com/eqcss/eqcss.git

Se você usa npm, pode adicionar EQCSS ao seu projeto com o seguinte comando:

 npm install eqcss

Adicionando EQCSS.js ao seu HTML

Depois de baixar o EQCSS, você pode adicioná-lo ao seu HTML com uma tag de script :

 <script src="EQCSS.js"></script>

Este arquivo ( EQCSS.js ) inclui suporte para todos os navegadores atuais, incluindo IE 9 e superior. Para suportar o IE 8, teríamos que usar muitos outros polyfills. Tenha em mente que o IE 8 nem mesmo suporta consultas de mídia CSS sem um polyfill, então é incrível que conseguimos fazer consultas de elemento funcionarem lá também. Para incluir suporte do IE 8 para um site usando EQCSS, adicione o seguinte link antes do link para o plugin principal:

 <!‐‐[if lt IE 9]><script src="EQCSS‐polyfills.js"></script><![endif]‐‐>

Executando EQCSS

Por padrão, o plug-in EQCSS calculará todos os estilos que encontrar assim que a página for carregada e também sempre que detectar que o navegador está sendo redimensionado, semelhante às consultas de mídia. Você também pode chamar EQCSS.apply() manualmente com JavaScript para recalcular estilos a qualquer momento, o que pode ser útil quando o conteúdo for atualizado na página.

Escrevendo CSS de consulta de elemento

O plug-in EQCSS.js pode ler estilos de duas maneiras diferentes. Você pode incluir EQCSS em qualquer marca de style em uma página HTML. Você também pode escrever EQCSS em uma folha de estilo CSS externa.

Se você quiser manter seu código baseado em EQCSS separado de seu CSS, você pode carregar a sintaxe EQCSS usando a tag de script com o tipo definido como text/eqcss . Você pode adicionar estilos inline em uma tag como esta ou vincular a uma folha de estilo .eqcss externa com <script type=“text/eqcss” src=styles.eqcss></script> , que carregaria um arquivo chamado styles.eqcss .

Anatomia de uma consulta de elemento

Escopo de estilo

A sintaxe no EQCSS para escrever consultas de elemento é muito semelhante à formatação de consultas de mídia CSS, mas em vez de @media , começamos a consulta com @element . A única outra informação que precisamos fornecer é pelo menos um seletor ao qual esses estilos devem se aplicar. Veja como você criaria um novo escopo para um elemento chamado <div class=“widget”> :

 @element '.widget' { }

O elemento entre aspas (neste caso, .widget ) pode ser qualquer seletor CSS válido. Com esta consulta, criamos um novo escopo no elemento .widget . Ainda não incluímos nenhuma condição responsiva para o escopo, portanto, qualquer estilo em uma consulta como essa se aplicaria ao elemento com escopo sempre.

Sem a capacidade de definir estilos para um ou mais elementos (em vez de toda a página de uma vez), não poderíamos aplicar consultas responsivas apenas a esses elementos. Uma vez que criamos esse escopo em nível de elemento, usar os recursos mais avançados da sintaxe EQCSS se torna fácil — como o meta seletor $parent , por exemplo — porque o JavaScript agora tem um ponto de referência para calcular coisas como o parentNode do escopo elemento. Isso é enorme!

É verdade que o CSS já inclui um seletor descendente direto, com o > , que nos permite selecionar elementos que são filhos diretos do elemento especificado. Mas o CSS atualmente não oferece nenhuma maneira de viajar na outra direção na árvore genealógica, para selecionar um elemento que contém outro elemento, que se chamaria de seu elemento pai. A especificação “CSS Selectors Level 4” agora inclui um seletor :has() , que funciona de maneira semelhante ao seletor :has() do jQuery, mas atualmente o suporte do navegador é nulo. O CSS com escopo possibilita um tipo diferente de seletor pai.

Agora que abrimos um escopo no contexto do elemento .widget , podemos escrever estilos de sua perspectiva para direcionar seu próprio elemento pai:

 @element '.widget' { $parent { /* These styles apply to the parent of .widget */ } }

Outro exemplo de seletores especiais que podem ser usados ​​em qualquer consulta de elemento são os seletores $prev e $next , que representam os elementos irmãos anteriores e próximos. Mesmo que o CSS possa alcançar o próximo irmão do nosso widget com um seletor como .widget + * , não há como o CSS voltar para trás e selecionar o elemento que vem diretamente antes de outro elemento.

 <section> <div>This will be the previous item</div> <div class="widget">This is the scoped element</div> <div>This will be the next item</div> </section> <style> @element '.widget' { $prev { /* These styles apply to the element before .widget */ } $next { /* These styles apply to the element after .widget */ } } </style>

Consultas de elemento

Os desenvolvedores usam consultas de mídia CSS com mais frequência para design responsivo, aplicando estilos com base na altura ou largura da janela de visualização do navegador. A sintaxe EQCSS suporta muitos novos tipos de condições responsivas. Em vez de trabalhar apenas com a largura e a altura do navegador, você pode escrever estilos que se aplicam aos elementos com base em suas próprias propriedades, como quantos elementos filho ele contém ou quantos caracteres ou linhas de texto estão no elemento no momento .

Adicionar essas condições responsivas aos seus estilos com escopo é semelhante à forma como você formataria consultas de mídia: você adicionaria and (condition: value) para cada condição que deseja verificar. Neste exemplo, verificaremos se algum elemento .widget está exibindo pelo menos 500 pixels de largura na página.

 @element '.widget' and (min‐width: 500px) { /* CSS rules here */ }

A sintaxe de uma consulta de elemento se divide da seguinte forma:

  • consulta de elemento @element selector_list [ condition_list ] { css_code }
  • lista de seletores " css selector [ "," css selector ]* "
  • lista de condições and ( query_condition : value ) [ "and (" query condition ":" value ")" ]*
  • valor number [ css unit ]
  • condição de consulta min-height | max-height | min-width | max-width | min-characters | max-characters | min-lines | max-lines | min-children | max-children | min-scroll-y | max-scroll-y | min-scroll-x | max-scroll-x min-height | max-height | min-width | max-width | min-characters | max-characters | min-lines | max-lines | min-children | max-children | min-scroll-y | max-scroll-y | min-scroll-x | max-scroll-x
  • unidade css % | px | pt | em | cm | mm | rem | ex | ch | pc | vw | vh | vmin | vmax % | px | pt | em | cm | mm | rem | ex | ch | pc | vw | vh | vmin | vmax

Como outro exemplo, veja como escrever uma consulta que torna o elemento body vermelho quando o elemento .widget atinge 500 pixels de largura:

 @element '.widget' and (min‐width: 500px) { body { background: red; } }

Observe que o elemento body muda quando o .widget atinge uma certa largura, não o próprio elemento .widget !

Condições de consulta do elemento

Abaixo está a lista completa de condições responsivas que o EQCSS suporta.

Condições com base na largura

  • demonstração min-width para pixels, demonstração para porcentagens
  • demonstração max-width para pixels, demonstração para porcentagens

Condições baseadas em altura

  • demonstração min-height para pixels, demonstração para porcentagens
  • demonstração max-height para pixels, demonstração para porcentagens

Condições Baseadas em Contagem

  • demonstração min-characters para elementos de bloco, demonstração para entradas de formulário
  • demonstração de max-characters para elementos de bloco, demonstração para entradas de formulário
  • demonstração min-lines
  • demonstração max-lines
  • demonstração min-children
  • demonstração max-children

Condições baseadas em rolagem

  • demonstração min-scroll-y
  • demonstração max-scroll-y
  • demonstração min-scroll-x
  • demonstração max-scroll-x

Você pode combinar qualquer número dessas condições em suas consultas de elemento para estilos responsivos verdadeiramente multidimensionais. Isso lhe dá muito mais flexibilidade e controle sobre como os elementos são renderizados. Por exemplo, para reduzir o tamanho da fonte de um cabeçalho com mais de 15 caracteres quando menos de 600 pixels de espaço estão disponíveis para exibição, você pode combinar as condições para max‐characters: 15 e max‐width: 600px :

 h1 { font‐size: 24pt; } @element 'h1' and (min‐characters: 16) and (max‐width: 600px) { h1 { font‐size: 20pt; } }

Meta-seletores

Um dos problemas que você pode encontrar quando começar a escrever estilos de escopo com condições responsivas é que, quando várias instâncias do mesmo seletor estão em uma página, usar esse seletor em sua consulta de elemento aplicará estilos a todas as instâncias desse seletor no página quando qualquer um deles corresponder às condições. Tomando nossos exemplos de .widget anteriores, suponha que tivéssemos dois widgets na página (talvez um na barra lateral e outro exibido na largura total) e escrevemos nossa consulta de elemento assim:

 @element '.widget' and (min‐width: 500px) { .widget h2 { font‐size: 14pt; } }

Isso significaria que, quando um elemento .widget na página tiver pelo menos 500 pixels de largura, o estilo se aplicará a ambos os elementos .widget . Isso provavelmente não é o que queremos que aconteça na maioria dos casos. É aqui que entram os meta-seletores!

As duas partes que compõem nossa consulta de elemento são o seletor e a condição responsiva. Portanto, se quisermos segmentar apenas os elementos da página que correspondem ao seletor e às condições responsivas ao mesmo tempo, podemos usar o meta seletor $this . Podemos reescrever nosso último exemplo para que o estilo se aplique apenas a elementos .widget que correspondam à condição min‐width: 500px :

 @element '.widget' and (min‐width: 500px) { $this h2 { font‐size: 14pt; } }

Vários novos seletores são suportados pela sintaxe EQCSS que não estão em CSS regular. Aqui está a lista completa:

  • $this demonstração
  • demonstração $parent
  • demonstração $root
  • $prev
  • $next demonstração

Esses seletores funcionarão apenas em uma consulta de elemento.

Abrindo o Portal entre JavaScript e CSS

  • eval(') demonstração

O último e último recurso do EQCSS é o mais selvagem de todos: eval(') . Através desta porta reside todo o poder do JavaScript, acessível a partir do CSS. Embora JavaScript possa aplicar estilos a elementos, atualmente tem dificuldade em alcançar algumas coisas, como os pseudo-elementos :before e :after . Mas e se o CSS pudesse alcançar o JavaScript de outra direção? Em vez de JavaScript configurar propriedades CSS, e se CSS pudesse estar ciente de JavaScript?

É aqui que entra eval(') . Você pode acessar e avaliar qualquer JavaScript, seja para usar o valor de uma variável JavaScript em seu CSS, para executar um JavaScript one-liner (como eval('new Date().getFullYear()') ), para verificar valores sobre o navegador e outros elementos que o JavaScript pode medir (como eval('innerHeight') ) ou para executar uma função JavaScript e usar o valor que ela retorna em seus estilos CSS. Aqui está um exemplo que gera 2016 em um elemento <footer> :

 @element 'footer' { $this:after { content: " eval('new Date().getFullYear()')"; } }

Usando $it dentro de eval(')

Ao avaliar JavaScript, eval(') também funciona a partir do contexto do elemento com escopo ativo, o mesmo elemento ao qual os estilos de $this se aplicam. Você pode usar $it em JavaScript escrito em eval(') como um espaço reservado para o elemento com escopo se isso ajudar você a estruturar o código, mas se omitido, funcionará da mesma maneira. Por exemplo, digamos que temos uma div com a palavra “hello” nela. O código a seguir produziria “hello hello”:

 <div>hello</div> <style> @element 'div' { div:before { content: "eval('$it.textContent') "; } } </style>

Aqui, $it se refere ao div porque é o seletor com escopo definido no momento. Você também pode omitir o $it e escrever o seguinte código para exibir a mesma coisa:

 @element 'div' { div:before { content: "eval('textContent') "; } }

eval(') pode ser útil em situações em que o CSS não está ciente das medidas ou eventos que acontecem na página após o carregamento. Por exemplo, os elementos iframe usados ​​para incorporar vídeos do YouTube vêm com largura e altura especificadas. Embora você possa definir a largura como auto em CSS, não há uma maneira fácil de manter a proporção correta de largura para altura quando o vídeo se expande para preencher o espaço disponível.

Uma solução comum para manter as proporções responsivas durante o dimensionamento é colocar o conteúdo que precisa manter sua proporção em um wrapper e, em seguida, adicionar preenchimento ao wrapper com um valor baseado na proporção entre largura e altura que você deseja manter. Isso funciona, mas exige que você conheça a proporção de todos os vídeos com antecedência, além de exigir mais marcação HTML (um elemento wrapper) para cada vídeo que você deseja incorporar de forma responsiva. Multiplique isso em todos os sites que tenham vídeos responsivos, e isso é muita sujeira que não precisaria estar lá se o CSS fosse um pouco mais inteligente.

Talvez uma abordagem melhor para proporções responsivas envolva colocar cada vídeo em um wrapper sem preenchimento e, em seguida, escrever uma biblioteca JavaScript que calcule a proporção de cada vídeo encontrado e aplique a quantidade correta de preenchimento a cada wrapper.

Mas e se o CSS pudesse acessar essas medidas diretamente? Não apenas poderíamos consolidar o CSS para todas as diferentes proporções em uma regra, mas se pudéssemos avaliá-lo assim que a página carregasse, poderíamos escrever uma regra que redimensionasse de forma responsiva qualquer vídeo que dermos no futuro. E poderíamos fazer tudo sem nenhum invólucro!

Se isso parece bom demais para ser verdade, confira. Veja como é simples escrever elementos de iframe de redimensionamento responsivo sem wrapper no EQCSS:

 @element 'iframe' { $this { margin: 0 auto; width: 100%; height: eval('clientWidth/(width/height)'); } }

Aqui, width e height referem-se aos atributos width=“” e height=“” no iframe em HTML. JavaScript pode realizar o cálculo de (width/height) , o que nos dá a proporção; e para aplicá-lo em qualquer largura, basta dividir a largura atual do elemento iframe pela proporção.

Isso tem a concisão e legibilidade do CSS e todo o poder do JavaScript. Sem necessidade de wrappers extras, sem classes extras e sem CSS extra.

Tenha cuidado com eval(') , no entanto. Há uma razão pela qual as expressões CSS eram consideradas perigosas no passado, e também há uma razão pela qual experimentamos a ideia. Se você não for cuidadoso com quantos elementos você os está aplicando na página ou com a frequência com que está recalculando estilos, o JavaScript pode acabar executando as coisas centenas de vezes mais do que o necessário. Felizmente, EQCSS nos permite invocar EQCSS.apply() ou EQCSS.throttle() para recalcular os estilos manualmente, para que tenhamos mais controle sobre quando os estilos são atualizados.

A Zona de Perigo!

Outros problemas podem ocorrer se você criar consultas com condições ou estilos conflitantes. EQCSS, como CSS, é lido de cima para baixo usando uma hierarquia de especificidade. Embora CSS seja uma linguagem declarativa, ela contém alguns recursos avançados. Está a apenas alguns passos de ser Turing-completo como linguagem de programação. Até agora, depurar CSS tem sido um assunto bastante simples, mas o EQCSS muda o CSS de ser simplesmente uma linguagem declarativa interpretada para uma linguagem de folha de estilo dinâmica com uma camada adicional de interpretação entre CSS e o navegador. Com este novo território vem uma variedade de novas armadilhas potenciais.

Aqui está um exemplo de um loop recíproco no EQCSS, algo que as consultas de mídia CSS normais são imunes por design:

 @element '.widget' and (min‐width: 300px) { $this { width: 200px; } }

Eu chamo isso de jekyll: hide; CSS. Mas, além de um estilo continuamente acionado, há também a possibilidade de escrever várias consultas que acionam umas às outras, no que chamamos de “loop recíproco invertido duplo”, o mais desagradável de todos:

 @element '.widget' and (min‐width: 400px) { $this { width: 200px; } } @element '.widget' and (max‐width: 300px) { $this { width: 500px; } }

Em teoria, aquele widget infeliz ficaria preso em um loop, redimensionando entre 200 e 500 pixels até o fim dos tempos, incapaz de se fixar em uma largura. Para casos como este, o EQCSS simplesmente calcula as regras na ordem em que são avaliadas, premia o vencedor e segue em frente. Se você reorganizar a ordem em que essas regras aparecem, o último estilo sempre vencerá se forem de igual especificidade.

Algumas pessoas dizem que a capacidade de criar loops (ou mesmo loops recíprocos duplos invertidos) é uma falha de projeto, mas para evitar que loops sejam possíveis, você precisaria limitar o poder do EQCSS de uma forma que removeria a maior parte o valor que a sintaxe fornece. Por outro lado, criar loops infinitos em JavaScript é muito fácil, mas isso não é visto como uma falha da linguagem — é visto como uma evidência de seu poder! É o mesmo com consultas de elementos.

Depurando consultas de elementos

Atualmente, depurar consultas de elementos pode parecer um pouco como depurar consultas de mídia antes de termos ferramentas como o inspetor da Web para nos mostrar os estilos conforme eram calculados na página. Por enquanto, depurar e desenvolver consultas de elementos exigem que o desenvolvedor mantenha um modelo mental de qual comportamento responsivo deve estar acontecendo. No futuro, a construção de ferramentas de desenvolvedor com reconhecimento de EQCSS pode ser possível, mas a partir de agora, as ferramentas de desenvolvedor em todos os principais navegadores estão cientes apenas dos estilos que o EQCSS já aplicou aos elementos na página e não estão cientes dos as condições de resposta que o EQCSS está observando.

Como projetar com consultas de elementos

A maneira mais simples de usar consultas de elemento é converter designs existentes usando consultas de mídia em consultas de elemento, “liberando” elementos e seus estilos responsivos de um layout e facilitando a reutilização desse código em outras páginas e projetos. A consulta de mídia e a consulta de elemento a seguir podem significar a mesma coisa:

 footer a { display: inline-block; } @media (max‐width: 500px) { footer a { display: block; } }
 footer a { display: inline-block; } @element 'footer' and (max‐width: 500px) { $this a { display: block; } }

A diferença é que, no exemplo original, os links de rodapé permanecem como display: block até que o navegador tenha pelo menos 500 pixels de largura. O segundo exemplo, usando consultas de elemento, teria a mesma aparência, mas apenas se o elemento de footer tivesse largura total.

Depois de liberar esse estilo de sua media query original, podemos agora colocar o rodapé em um contêiner de qualquer largura e ter certeza de que quando o rodapé precisar que o estilo responsivo seja aplicado (ou seja, quando for mais estreito que 500 pixels), ele será aplicado.

  1. Certifique-se de que EQCSS.js esteja presente no HTML do documento de destino.
  2. Substitua @media por @element no CSS.
  3. Adicione um seletor CSS ao escopo de cada consulta @element .
  4. Opcional: Substitua as ocorrências do elemento com escopo definido por $this nas consultas de elemento.

A menos que o componente de design que você está convertendo tenha sido originalmente projetado para ser exibido usando toda a largura da janela de visualização do navegador, você provavelmente terá que ajustar os pontos de interrupção após a conversão em consultas de elemento.

Evitando o Bloqueio

A experiência de criar estilos EQCSS é semelhante à experiência de escrever CSS regular: todas as suas propriedades e técnicas CSS favoritas ainda estão lá, apenas com alguns recursos adicionais que os ajudam a trabalhar juntos de novas maneiras. Como o EQCSS emite CSS padrão para o navegador, qualquer recurso CSS para o qual seu navegador tenha suporte integrado funcionará quando usado com o EQCSS. Se algum dia recursos como consultas de elementos e estilos com escopo forem especificados em CSS e suportados em navegadores, você poderá começar a usá-los em seu código EQCSS imediatamente, enquanto ainda depende do EQCSS para os outros recursos que o navegador não ainda suporte nativo.

Como você pode usar a sintaxe EQCSS tanto diretamente no CSS quanto em seu próprio script, com o tipo text/eqcss , se o CSS desenvolver uma sintaxe para consultas de elementos nativos, você ainda poderá carregar o EQCSS como um script e evitar conflitos .

Olhando para o futuro, uma solução que os desenvolvedores de navegadores estão experimentando agora é o Houdini, que abriria o acesso para desenvolvedores de plugins estenderem o CSS de novas maneiras, como adicionar suporte ao próprio navegador. Algum dia, pode ser possível escrever plugins mais eficientes que interpretem a sintaxe EQCSS e tragam esses recursos para os navegadores de uma maneira mais direta e performática do que a atual biblioteca JavaScript permite.

Então, ainda devemos usar consultas de mídia?

Sim, embora as consultas de elemento forneçam muitas maneiras novas e interessantes de direcionar elementos com estilos, as consultas de mídia (embora limitadas) sempre serão executadas mais rapidamente no navegador do que um estilo que depende de JavaScript para calcular. No entanto, as consultas de mídia CSS são mais do que apenas estilizar HTML para telas. As consultas de mídia CSS também oferecem suporte a consultas baseadas em impressão e outras maneiras pelas quais os sites exibem informações. O EQCSS pode ser usado em conjunto com consultas de mídia para coisas como estilos de impressão, portanto, não há necessidade de retirar a consulta de mídia apenas porque as consultas de elemento agora também podem ser usadas!

Projetando com 2020 Visão

A melhor coisa que podemos fazer para o futuro do CSS é experimentar essas ideias o máximo possível hoje. Nenhuma quantidade de brainstorming e teorização sobre esses recursos será tão útil quanto tentar implementá-los e colocá-los em uso, descobrindo as técnicas que os tornam úteis e poderosos.

Além de fornecer uma solução para consultas de elementos, espera-se que o EQCSS.js também sirva como plataforma para outros experimentos de extensão de CSS. If you have an idea for a new responsive condition, a new CSS property or a new selector to use in your code, forking EQCSS.js and modifying it to include your idea can get you most of the way there with little effort.

Modular Design

In designing layouts using element queries, the biggest shift is learning how to stop viewing the DOM from the top down and from the perspective of only the root HTML element, and to start thinking about individual elements on the page from their own perspectives within the document.

The old paradigms of “desktop-first” and “mobile-first” responsive design aren't relevant any longer — the new way of building layouts approaches design “element-first.” Using element queries enables you to work on the individual parts that make up a layout, in isolation from one another, styling them to a greater level of detail. If you are using a modular approach for your back-end code already but have so far been unable to package your CSS with your modules because of the difficulties of styling with media queries alone, then element queries will finally allow you to modularize your styles in the same way.

Thinking Element-First

Element-first design is in the same spirit as the atomic design principle but looks different in practice from how most people have implemented atomic design in the past.

For example, let's say you have some HTML like the following, and the desired responsive behavior can be explained as, “The search input and button are displayed side by side until the form gets too narrow. Then, both the input and the button should be stacked on top of each other and displayed full width.”

 <form> <input type=search> <input type=button value=Search> </form>

Desktop-First Approach

In a desktop-first mindset, you would write styles for the desktop layout first and then add responsive support for smaller screens.

 input { width: 50%; float: left; } @media (max‐width: 600px) { input { width: 100%; float: none; } }

Mobile-First Approach

In a mobile-first mindset, you would design the mobile view first and add support for the side-by-side view only when the screen is wide enough.

 input { width: 100%; } @media (min‐width: 600px) { input { width: 50%; float: left; } }

Element-First Approach

In the first two examples, the media breakpoint was set to 600 pixels, and not because that's how wide the inputs will be when they switch. Chances are, the search input is probably inside at least one parent element that would have margins or padding. So, when the browser is 600 pixels wide, those inputs might be somewhere around 550 or 525 pixels wide on the page. In a desktop-first or mobile-first approach, you're always setting breakpoints based on the layout and how elements show up within it. With an element-first layout, you're saying, “I don't care how wide the browser is. I know that the sweet spot for where I want the inputs to stack is somewhere around 530 pixels wide.” Instead of using a media query to swap that CSS based on the browser's dimensions, with element-first design, we would scope our responsive style to the form element itself, writing a style like this:

 input { width: 100% } @element 'form' and (min‐width: 530px) { $this input { width: 50%; float: left; } }

The code is similar to that of the two previous methods, but now we are free to display this search input anywhere — in a sidebar or full width. We can use it in any layout on any website, and no matter how wide the browser is, when the form itself doesn't have enough room to display the inputs side by side, it will adapt to look its best.

Resources For Getting Started

EQCSS-Enabled Template

 <!DOCTYPE html> <html> <head> <meta charset="utf‐8"> <title></title> <style></style> </head> <body> <!‐‐[if lt IE 9]><script src="https://elementqueries.com/EQCSS‐polyfills.min.js"></script><![endif]‐‐> <script src="https://elementqueries.com/EQCSS.min.js"></script> </body> </html>

Demonstrações

  • Responsive Aspect Ratio
  • Sticky Scroll Header
  • Blockquote Style
  • Calendário
  • Content Demo
  • Counting Children Demo
  • Date Demo
  • Zastrow-style Element Query Demo Demo
  • Flyout Demo
  • Headline Demo
  • Media Player Demo
  • Message Style Demo
  • Modal Demo
  • Nav Demo
  • Parent Selector Demo
  • Pricing Chart Demo
  • Responsive Tables Demo
  • Scroll-triggered Blocker Demo
  • Signup Form Demo
  • Testimonials Block Demo
  • Tweet-Counter Demo
  • JS Variables Demo
  • Responsive Scaling Demo
  • Geometric Design Demo
  • Responsive Order Form
  • Element Query Grid
  • JS Functions in CSS
  • Responsive Content Waterfall

Leitura adicional

You can find the EQCSS project on GitHub, demos, documentation and articles on the EQCSS website. An ever-growing number of Codepens use EQCSS, and you can create your own pen by forking the batteries-included template that comes hooked up with EQCSS. You can also play with the EQCSS tool that I built to preview if your EQCSS code is working as expected.

Happy hacking!