Estilo da Web de última geração

Fique por dentro de alguns recursos interessantes do CSS moderno.

muitas coisas interessantes acontecendo no CSS agora, e muitas delas já têm suporte nos navegadores atuais. Assista a nossa palestra na CDS 2019 abaixo e aborda vários recursos novos e futuros que devem chamar atenção.

Esta postagem se concentra nos recursos que você pode usar hoje. Assista à palestra para uma discussão mais aprofundada sobre os próximos recursos, como o Houdini. Você também pode encontrar demonstrações de todos os recursos discutidos na nossa página CSS@CDS.

Conteúdo

Ajuste de rolagem

O ajuste de rolagem permite definir pontos de ajuste à medida que o usuário rola o conteúdo verticalmente, horizontalmente ou ambos. Ele oferece inércia e desaceleração de rolagem integradas e é compatível com toque.

Este código de exemplo configura a rolagem horizontal em um elemento <section> com pontos de ajuste alinhados aos lados esquerdos dos elementos filhos <picture>:

section {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
}

section > picture {
  scroll-snap-align: start;
}

Veja como funciona:

  • No elemento <section> pai,
    • overflow-x está definido como auto para permitir a rolagem horizontal.
    • A overscroll-behavior-x é definida como contain para impedir que elementos pais rolem quando o usuário atinge os limites da área de rolagem do elemento <section>. Isso não é estritamente necessário para ajustá-las, mas geralmente é uma boa ideia.
    • scroll-snap-type é definido como x para ajustes horizontais e mandatory para garantir que a janela de visualização sempre se ajuste ao ponto de ajuste mais próximo.
  • Nos elementos <picture> filhos, scroll-snap-align é definido como "start", o que define os pontos de ajuste no lado esquerdo de cada imagem (assumindo que direction seja definido como ltr).

Confira uma demonstração ao vivo:

Confira também as demonstrações de snap de rolagem vertical e snap de rolagem de matriz.

:focus-within

:focus-within resolve um problema de acessibilidade antigo: há muitos casos em que o foco em um elemento filho precisa afetar a apresentação de um elemento pai para que a interface seja acessível aos usuários de tecnologias adaptativas.

Por exemplo, se você tiver um menu suspenso com vários itens, ele vai permanecer visível enquanto qualquer um deles estiver em foco. Caso contrário, o menu desaparecerá para os usuários do teclado.

:focus-within informa ao navegador para aplicar um estilo quando o foco está em qualquer elemento filho de um elemento especificado. Voltando ao exemplo de menu, ao definir :focus-within no elemento de menu, você pode garantir que ele permaneça visível quando um item de menu tiver o foco:

.menu:focus-within {
  display: block;
  opacity: 1;
  visibility: visible;
}

Uma ilustração que mostra a diferença de comportamento entre foco e foco interno.

Tente usar as teclas de tabulação nos elementos com foco na demonstração abaixo. Os menus permanecem visíveis quando você foca nos itens do menu:

Consultas de mídia, nível 5

As novas consultas de mídia oferecem formas poderosas de ajustar a experiência do usuário em nossos apps com base nas preferências de dispositivo do usuário. Basicamente, o navegador funciona como um proxy para preferências de nível do sistema que podemos responder no CSS usando o grupo prefers-* de consultas de mídia:

Um diagrama que mostra consultas de mídia interpretando as preferências do usuário no nível do sistema.

Confira as novas consultas que os desenvolvedores vão adorar:

Essas consultas são uma grande vitória para a acessibilidade. Antes, não sabíamos, por exemplo, se um usuário tinha configurado o sistema operacional no modo de alto contraste. Se você quisesse oferecer um modo de alto contraste para um app da Web que permanecesse fiel à sua marca, teria que pedir aos usuários que o escolhessem na interface do app. Agora você pode detectar a configuração de alto contraste no SO usando prefers-contrast.

Uma implicação interessante dessas consultas de mídia é que podemos projetar para várias combinações de preferências do usuário no nível do sistema para acomodar a ampla gama de preferências e necessidades de acessibilidade do usuário. Se um usuário quiser o modo escuro de alto contraste em ambientes com pouca luz, você pode fazer isso.

Para Adam, é importante que a opção "prefere movimento reduzido" não seja implementada como "sem movimento". O usuário está dizendo que prefere menos movimento, não que não quer nenhuma animação. Ele afirma que o movimento reduzido não é o mesmo que nenhum movimento. Confira um exemplo que usa uma animação de crossfade quando o usuário prefere movimento reduzido:

Propriedades lógicas

As propriedades lógicas resolvem um problema que ganhou visibilidade à medida que mais desenvolvedores lidam com a internacionalização. Muitas propriedades de layout, como margin e padding, assumem um idioma que é lido de cima para baixo e da esquerda para a direita.

Um diagrama mostrando as propriedades tradicionais de layout do CSS.

Ao projetar páginas para vários idiomas com modos de escrita diferentes, os desenvolvedores precisavam ajustar todas essas propriedades individualmente em vários elementos, o que rapidamente se torna um pesadelo de manutenção.

As propriedades lógicas permitem manter a integridade do layout em traduções e modos de escrita. Elas são atualizadas dinamicamente com base na ordem semântica do conteúdo, e não na disposição espacial. Com propriedades lógicas, cada elemento tem duas dimensões:

  • A dimensão block é perpendicular ao fluxo de texto em uma linha. Em inglês, block-size é o mesmo que height.
  • A dimensão inline é paralela ao fluxo de texto em uma linha. Em inglês, inline-size é o mesmo que width.

Esses nomes de dimensão se aplicam a todas as propriedades de layout lógico. Por exemplo, em inglês, block-start é o mesmo que top, e inline-end é o mesmo que right.

Um diagrama mostrando as novas propriedades de layout lógico do CSS.

Com as propriedades lógicas, você pode atualizar automaticamente o layout para outros idiomas simplesmente mudando as propriedades writing-mode e direction da página, em vez de atualizar dezenas de propriedades de layout em elementos individuais.

É possível ver como as propriedades lógicas funcionam na demonstração abaixo definindo a propriedade writing-mode no elemento <body> com valores diferentes:

position: sticky

Um elemento com position: sticky permanece no fluxo de bloco até começar a sair da tela, momento em que ele para de rolar com o resto da página e fica na posição especificada pelo valor top do elemento. O espaço alocado para esse elemento permanece no fluxo, e o elemento retorna a ele quando o usuário rola para cima.

A posição fixa permite criar muitos efeitos úteis que antes exigiam JavaScript. Para mostrar algumas das possibilidades, criamos várias demonstrações. Cada demonstração usa basicamente o mesmo CSS e apenas ajusta ligeiramente a marcação HTML para criar cada efeito.

Pilha fixa

Nesta demonstração, todos os elementos fixos compartilham o mesmo contêiner. Isso significa que cada elemento fixo desliza sobre o anterior conforme o usuário rola a página para baixo. Os elementos fixos compartilham a mesma posição.

Slide fixo

Aqui, os elementos fixos são primos. Ou seja, os pais são irmãos. Quando um elemento fixo atinge o limite inferior do contêiner, ele se move para cima com o contêiner, criando a impressão de que os elementos fixos mais baixos estão empurrando os elementos mais altos para cima. Em outras palavras, eles parecem competir pela posição presa.

Sticky Desperado

Assim como o slide fixo, os elementos fixos nesta demonstração são primos. No entanto, elas foram colocadas em contêineres definidos como um layout de grade de duas colunas.

backdrop-filter

A propriedade backdrop-filter permite aplicar efeitos gráficos à área atrás de um elemento, em vez de ao próprio elemento. Isso permite que muitos efeitos legais que antes só eram possíveis com hacks complicados de CSS e JavaScript sejam feitos com uma linha de CSS.

Por exemplo, esta demonstração usa backdrop-filter para conseguir o efeito de desfoque no estilo do SO:

Já temos uma postagem sobre backdrop-filter. Acesse para mais informações.

:is()

Embora a pseudoclasse :is() tenha mais de 10 anos, ela ainda não é usada tanto quanto deveria. Ele usa uma lista separada por vírgulas de seletores como argumento e corresponde a todos os seletores dessa lista. Essa flexibilidade é muito útil e pode reduzir significativamente a quantidade de CSS que você envia.

Veja um exemplo rápido:

button.focus,
button:focus {
  
}

article > h1,
article > h2,
article > h3,
article > h4,
article > h5,
article > h6 {
  
}

/* selects the same elements as the code above */
button:is(.focus, :focus) {
  
}

article > :is(h1,h2,h3,h4,h5,h6) {
  
}

gap

O layout de grade do CSS já tem gap (anteriormente grid-gap) há algum tempo. Ao especificar o espaçamento interno de um elemento de contêiner em vez do espaçamento em torno de elementos filhos, gap resolve muitos problemas comuns de layout. Por exemplo, com o espaço, você não precisa se preocupar com as margens em elementos filhos que causam espaços em branco indesejados ao redor das bordas de um elemento que contém:

Ilustração mostrando como a propriedade de intervalo evita espaços indesejados ao redor das bordas de um elemento de contêiner.

E tem mais: gap está chegando ao flexbox, trazendo todos os mesmos benefícios de espaçamento que a grade tem:

  • Há uma declaração de espaçamento em vez de várias.
  • Não é necessário estabelecer convenções para o projeto sobre quais elementos filhos devem ter o espaçamento. O elemento que contém é o proprietário do espaçamento.
  • O código é mais fácil de entender do que estratégias mais antigas, como a coruja lobotomizada.

O vídeo a seguir mostra os benefícios de usar uma única propriedade gap para dois elementos, um com layout de grade e outro com layout flexível:

No momento, apenas o FireFox oferece suporte a gap em layouts flexíveis, mas confira esta demonstração para ver como ele funciona:

CSS Houdini

O Houdini é um conjunto de APIs de baixo nível para o mecanismo de renderização do navegador que permite informar ao navegador como interpretar o CSS personalizado. Em outras palavras, você tem acesso ao modelo de objetos CSS, o que permite extend o CSS via JavaScript. Essa mudança gera vários benefícios:

  • Com ela, você tem muito mais poder para criar recursos CSS personalizados.
  • É mais fácil separar as preocupações de renderização da lógica do aplicativo.
  • Ele tem melhor desempenho do que o polyfilling do CSS que fazemos atualmente com JavaScript, porque o navegador não precisa mais analisar scripts e fazer um segundo ciclo de renderização. O código Houdini é analisado no primeiro ciclo de renderização.

Ilustração mostrando como o Houdini funciona em comparação com polyfills JavaScript tradicionais.

O Houdini é um nome abrangente para várias APIs. Para mais informações sobre o status atual, consulte Houdini está pronto? Na nossa palestra, abordamos a API Properties and Values, a API Paint e o worklet de animação porque elas têm o maior suporte no momento. Poderíamos facilmente dedicar uma postagem completa a cada uma dessas APIs incríveis, mas, por enquanto, confira nossa palestra para ter uma visão geral e algumas demonstrações interessantes que começam a dar uma noção do que você pode fazer com as APIs.

Menu flutuante

Há mais algumas coisas que gostaríamos de discutir, mas não tivemos tempo para abordar em detalhes. Por isso, fizemos uma rodada rápida. ⚡ Se você ainda não conhece alguns desses recursos, assista a última parte da palestra.

  • size: uma propriedade que permite definir altura e largura ao mesmo tempo
  • aspect-ratio: uma propriedade que define uma proporção para elementos que não têm uma.
  • min(), max() e clamp(): funções que permitem definir restrições numéricas em qualquer propriedade CSS, não apenas largura e altura
  • list-style-type uma propriedade existente, mas em breve vai oferecer suporte a uma gama mais ampla de valores, incluindo emojis e SVGs
  • display: outer inner: em breve, a propriedade display vai aceitar dois parâmetros, o que vai permitir especificar explicitamente os layouts externo e interno em vez de usar palavras-chave compostas, como inline-flex.
  • Regiões CSS: permitem preencher uma área não retangular especificada para onde o conteúdo pode fluir
  • Módulos CSS: o JavaScript poderá solicitar um módulo CSS e receber um objeto rico que facilita a realização de operações