Explorando a propriedade de exibição: geração de caixa
Publicados: 2022-03-10display
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 display
— none
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.
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.
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.
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.
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.
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
.
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.
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 propriedadedisplay
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 propriedadedisplay
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.
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.