Explorando a propriedade de exibição: geração de caixa

Publicados: 2022-03-10
Resumo rápido ↬ Continuando uma série sobre a propriedade display em CSS, desta vez Rachel Andrew dá uma olhada nos valores que controlam a geração de caixas, para aqueles momentos em que você não quer gerar nenhuma caixa.

Este é o segundo de uma pequena série de artigos sobre a propriedade display em CSS. Você pode ler o artigo inicial da série em “The Two Values ​​Of Display”. A especificação de display é uma especificação muito útil para entender, pois sustenta todos os diferentes métodos de layout que temos.

Embora muitos dos valores de display tenham suas próprias especificações, muitos termos e ideias são detalhados em display . Isso significa que entender esta especificação ajuda você a entender as especificações que essencialmente detalham os valores de display . Neste artigo, vou dar uma olhada nos valores de geração de caixa de displaynone e contents .

Tudo é uma caixa

Em CSS tudo gera caixas. Uma página da web é essencialmente um conjunto de blocos e caixas embutidas, algo que você entende muito bem se abrir o DevTools em seu navegador favorito e começar a selecionar elementos na página. Você pode ver as caixas que compõem o layout e como suas margens, preenchimento e bordas são aplicadas.

Uma imagem de um layout simples com uma lista não ordenada destacada no navegador DevTools
Eu destaquei o elemento ul usando o Firefox DevTools para que eu possa inspecionar as diferentes partes da caixa. (Visualização grande)

Geração de Caixa de Controle

Os valores none e contents de display lidam com se as caixas devem aparecer. Se você tem elementos em sua marcação e não quer que eles gerem uma caixa em CSS, então você precisa suprimir de alguma forma a geração da caixa. Há duas coisas possíveis que você pode querer fazer. Que são:

  • Impedir a geração de uma caixa e todos os seus filhos.
  • Impedir a geração de uma caixa, mas ainda exibir os filhos.

Podemos dar uma olhada em cada um desses cenários, por sua vez.

Mais depois do salto! Continue lendo abaixo ↓

Mostrar nenhum

O valor none de display é como impedimos a geração de uma caixa e todos os filhos dessa caixa. Ele age como se o elemento não estivesse lá. Portanto, é útil em situações em que você pretende ocultar completamente esse conteúdo, talvez porque ele será revelado posteriormente após a ativação de um link.

Se eu tiver um exemplo com um parágrafo, uma lista não ordenada e outro parágrafo, você poderá ver que os itens estão sendo exibidos no fluxo normal. A ul tem um fundo e uma borda aplicados, além de algum preenchimento.

Veja o exemplo de geração de caixa de canetas por Rachel Andrew.

Veja o exemplo de geração de caixa de canetas por Rachel Andrew.

Se eu adicionar display: none ao ul , ele desaparece da exibição visual, levando consigo os filhos do ul mais o plano de fundo e a borda.

Veja o exemplo de exibição de Pen Box Generation: none por Rachel Andrew.

Veja o exemplo de exibição de Pen Box Generation: none por Rachel Andrew.

Se você usar display: none , ele ocultará o conteúdo de todos os usuários do site. Isso inclui usuários de leitores de tela. Portanto, você só deve usar isso se sua intenção for que a caixa e tudo dentro dela estejam completamente ocultos para todos.

Há situações em que você pode querer adicionar informações adicionais para usuários de tecnologia assistiva, como leitores de tela, mas ocultá-las para outros usuários; nesses casos, você precisa usar uma técnica diferente. Algumas sugestões excelentes são feitas por Scott O'Hara em seu artigo “Inclusively Hidden”.

Usando display: none é, portanto, bastante simples. Use-o em uma situação em que você deseja que uma caixa e o conteúdo desapareçam da exibição, da árvore de caixas e da árvore de acessibilidade (como se nunca estivessem lá em primeiro lugar).

exibição: conteúdo

Para o segundo cenário, precisamos olhar para um valor muito mais recente de display. O valor display: contents removerá a caixa à qual é aplicado da árvore de caixas da mesma forma que display: none remove, mas deixa os filhos no lugar. Isso causa algum comportamento útil em termos de coisas que podemos fazer em nossos layouts. Vamos ver um exemplo simples e depois explorar mais.

Estou usando o mesmo exemplo de antes, mas desta vez usei display: contents no ul . Os itens da lista agora estão visíveis, no entanto, eles não têm plano de fundo e bordas e estão agindo como se você tivesse adicionado elementos li à página sem nenhum ul delimitador.

Veja o exemplo de exibição de Pen Box Generation: conteúdo de Rachel Andrew.

Veja o exemplo de exibição de Pen Box Generation: conteúdo de Rachel Andrew.

A razão pela qual remover uma caixa e manter os filhos é útil é devido ao modo como outros valores de display se comportam. Quando alteramos o valor de display , fazemos isso em uma caixa e nos filhos diretos dessa caixa, conforme descrevi no último artigo. Se eu adicionar display: flex às regras CSS de um elemento, esse elemento se tornará uma caixa de nível de bloco e os filhos diretos se tornarão itens flexíveis. Os filhos desses itens flexíveis retornam ao fluxo normal (eles não fazem parte do layout flexível).

Você pode ver esse comportamento no próximo exemplo. Aqui eu tenho um elemento de contenção definido para exibir flex, ele tem quatro filhos diretos, três elementos div e um ul . O ul tem dois itens de lista. Todos os filhos diretos participam do layout flexível e são dispostos como itens flexíveis. Os itens de lista não são filhos diretos e, portanto, são exibidos como itens de lista dentro da caixa do ul .

Veja o flexbox Pen Box Generation e exiba: contents 1 por Rachel Andrew.

Veja o flexbox Pen Box Generation e exiba: contents 1 por Rachel Andrew.

Se pegarmos este exemplo e adicionarmos display: contents ao ul , a caixa será removida da exibição visual e agora os filhos participarão do layout flex. Você pode ver que eles não se tornam filhos diretos. Eles não são selecionados pelo seletor universal filho direto ( .wrapper > * ) da maneira que os elementos div e ul são, e eles mantêm o plano de fundo dado a eles. Tudo o que aconteceu é que a caixa do ul que o contém foi removida, todo o resto continua normalmente.

Veja o flexbox Pen Box Generation e exiba: contents 2 por Rachel Andrew.

Veja o flexbox Pen Box Generation e exiba: contents 2 por Rachel Andrew.

Isso tem implicações potencialmente muito úteis se considerarmos elementos em HTML que são importantes para acessibilidade e dados semânticos, mas que geram uma caixa adicional que pode nos impedir de dispor o conteúdo com layout flexível ou de grade.

Este não é um "Reset" CSS

Você deve ter notado como um efeito colateral de usar display: contents é que a margem e o preenchimento do elemento são removidos. Isso porque eles estão relacionados à caixa, parte do CSS Box Model. Isso pode levar você a pensar que display: contents é uma boa maneira de se livrar rapidamente do preenchimento e da margem em um elemento.

Este é um uso que Adrian Roselli viu na natureza; ele estava preocupado o suficiente para escrever um post detalhado explicando os problemas de fazê-lo - “ display: contents não é uma redefinição de CSS”. Alguns dos problemas que ele levanta se devem a um infeliz problema de acessibilidade em navegadores atualmente com exibição: conteúdos que discutiremos abaixo. No entanto, mesmo depois que esses problemas forem resolvidos, remover um elemento da árvore de caixa simplesmente para se livrar da margem e do preenchimento é um tanto extremo.

Se nada mais, seria problemático para a futura manutenção do site, um futuro desenvolvedor pode se perguntar por que eles não parecem ser capazes de aplicar nada a essa caixa misteriosa - perdendo o fato de que ela foi removida! Se você precisar que a margem e o preenchimento sejam 0 , faça um favor ao seu futuro eu e defina-os como 0 de uma maneira consagrada pelo tempo. Reserve o uso de display: contents para aqueles casos especiais em que você realmente deseja remover a caixa.

Também vale a pena notar a diferença entre display: contents e subgrid CSS Grid Layout. Where display: contents remove completamente a caixa, o plano de fundo e a borda da exibição, tornando um item de grade uma subgrade manteria qualquer estilo de caixa nesse item e apenas passaria pelo dimensionamento da faixa para que os itens aninhados pudessem usar a mesma grade. Saiba mais em meu artigo, “CSS Grid Level 2: Here Comes Subgrid”.

Problemas de acessibilidade e exibição: conteúdo

Um problema sério atualmente faz com que o display: contents não seja útil para a coisa para a qual seria mais útil. Os casos óbvios para display: contents são aqueles casos em que caixas adicionais são necessárias para adicionar marcação que torna seu conteúdo mais facilmente compreendido por aqueles que usam leitores de tela ou outros dispositivos de assistência.

O elemento ul da nossa lista na primeira display: contents CodePen é um exemplo perfeito. Você pode obter o mesmo resultado visual achatando a marcação e não usando uma lista. No entanto, se o conteúdo for semanticamente uma lista, for melhor compreendido e lido por um leitor de tela como uma lista, deve ser marcado como uma.

Se você quiser que os elementos filho façam parte de um layout flexível ou de grade, como se a caixa do ul não estivesse lá, você deve poder usar display: contents para afastar a caixa e torná-la assim - mas deixe a semântica em vigor. A especificação diz que este deve ser o caso,

“A propriedade display não afeta a semântica de um elemento: ela é definida pela linguagem do documento e não é afetada pelo CSS. Além do valor none, que também afeta a saída aural/fala e a interatividade de um elemento e seus descendentes, a propriedade display afeta apenas o layout visual: sua finalidade é permitir que os designers alterem o comportamento do layout de um elemento sem afetar o layout subjacente. semântica do documento”.

Como já discutimos, o valor none oculta o elemento dos leitores de tela, no entanto, outros valores de display estão puramente lá para nos permitir alterar a forma como as coisas são exibidas visualmente . Eles não devem tocar a semântica do documento.

Por isso, muitos de nós pegamos de surpresa ao perceber que display: contents estava, de fato, removendo o elemento da árvore de acessibilidade nos dois navegadores (Chrome e Firefox) que o haviam implementado. Portanto, alterando a semântica do documento, fazendo com que um leitor de tela não saiba que uma lista é uma lista uma vez que a ul foi removida usando display: contents . Este é um bug do navegador - e sério.

No ano passado, Hidde de Vries escreveu esse problema em seu post “Marcação mais acessível com display:contents ” e levantou problemas contra os vários navegadores para aumentar a conscientização e fazê-los trabalhar em uma correção. O Firefox corrigiu parcialmente o problema, embora ainda existam problemas com certos elementos, como o botão. O problema está sendo trabalhado ativamente no Chrome. Há também um problema para o WebKit. Incentivo você a marcar com estrela esses bugs se tiver casos de uso para exibição: conteúdo que seria afetado pelos problemas.

Até que esses problemas sejam corrigidos e as versões do navegador que exibiam o problema caiam em desuso, você precisa ter muito cuidado ao usar display: contents em qualquer coisa que transmita informações semânticas e precise ser exposta a tecnologia assistiva. Como afirma Adrian Roselli,

“Por enquanto, use apenas display: contents se você for testar com tecnologia assistiva e puder confirmar que os resultados funcionam para os usuários.”

Há lugares onde você pode usar display: contents com segurança sem essa preocupação. Uma seria se você precisasse adicionar marcação adicional para criar fallbacks para sua grade de layouts flexíveis em navegadores mais antigos. Navegadores que suportam display: contents também suportam grid e flexbox, portanto você pode display: contents longe dos elementos div redundantes adicionados. No exemplo abaixo, criei uma grade baseada em float, completa com wrappers de linha.

Em seguida, uso display: contents para remover os wrappers de linha para permitir que todos os itens se tornem itens de grade e, portanto, possam fazer parte do layout de grade. Isso pode fornecer uma ferramenta adicional ao criar fallbacks para layouts avançados, pois, se você precisar adicionar marcação extra, poderá removê-la com display: contents ao fazer seu layout de grade ou flexível. Não acredito que esse uso deva causar problemas - embora, se alguém tiver informações de acessibilidade melhores do que eu e puder apontar um problema, faça isso nos comentários.

Veja os wrappers de linha de remoção de canetas com display: conteúdos de Rachel Andrew.

Veja os wrappers de linha de remoção de canetas com display: conteúdos de Rachel Andrew.

Empacotando

Este artigo examinou os valores de geração de caixa da propriedade de display . Espero que agora você entenda o comportamento diferente de display: none — que remove completamente uma caixa e todos os filhos, e display: contents que remove apenas a própria caixa. Você também deve entender os possíveis problemas de usar esses métodos no que diz respeito à acessibilidade.