Explorando a propriedade de exibição: grades até o fim

Publicados: 2022-03-10
Resumo rápido ↬ Continuando uma série sobre a propriedade display em CSS, desta vez Rachel Andrew dá uma olhada no que acontece quando você usa grid como um valor de display, com informações adicionais sobre como a subgrade muda esse comportamento.

Hoje, vamos dar uma olhada no que acontece quando usamos display: grid e como podemos usar o novo valor de subgrade de grid-template-columns e grid-template-rows para permitir grades até a nossa marcação , que se relacionam entre si.

Este artigo faz parte de uma série que analisa vários aspectos da propriedade de display CSS e é uma continuação dos dois primeiros artigos:

  1. Os dois valores de display
  2. Geração de Caixa
  3. Grades até o fim

O que acontece quando criamos um contêiner de grade?

CSS Grid Layout é ativado usando display: grid . Se você leu o primeiro artigo desta série, saberá que o que essa propriedade de valor único realmente significa é display: block grid . Obtemos uma caixa de nível de bloco que é definida como um contêiner de grade , com filhos diretos que são itens de grade e participam do layout da grade.

Se você der uma olhada na especificação de exibição, verá isso na tabela que define todos os diferentes valores para display . As palavras grid container estão vinculadas à definição de grid container na Grid Specification. Portanto, para descobrir o que isso realmente significa, precisamos ir procurar lá. Quando o fazemos, obtemos alguns esclarecimentos úteis sobre o comportamento de um contêiner de grade.

Mais depois do salto! Continue lendo abaixo ↓

Diz-se que um contêiner de grade estabelece um Contexto de Formatação de Grade que é semelhante a um Contexto de Formatação de Bloco (BFC). Eu escrevi um extenso guia para o Contexto de Formatação de Blocos. Nesse artigo você descobrirá duas coisas sobre um BFC que são as mesmas para um contexto de formatação de grade. Os flutuadores não invadem o contêiner de grade e as margens do contêiner não são recolhidas com as do conteúdo.

Existem diferenças, no entanto, apenas quando entramos no contêiner da grade. Os filhos de um contêiner de grade e não participam do layout de bloco e inline, são itens de grade e, portanto, participam do layout de grade. Isso significa que algumas coisas com as quais estamos acostumados no layout em bloco e em linha não são verdadeiras.

Se qualquer item no layout for flutuado ou limpo, as propriedades float e clear não terão efeito quando o item se tornar um item de grade. A propriedade vertical-align não tem efeito e os pseudoelementos ::first-letter e ::first-line não podem ser usados.

O fato de que um item não pode ser flutuante e um item de grade é útil em termos de criação de fallbacks. Ao criar um fallback para navegadores que não suportam grid usando floats (quando grid é suportado), você não precisa fazer nada de especial: o float é sobrescrito.

Eu descrevo essa abordagem em meu artigo sobre suporte a navegadores sem grade. Existem situações em que o comportamento se tornou problemático, embora esses problemas possam ser resolvidos usando outra parte do CSS, conforme descrito neste post, descompactando um problema com grade e flutuadores, “Layouts editoriais, exclusões e grade CSS”.

Com tudo isso dito, se não fizermos nada além de alterar o valor de display para grid , não veremos muita diferença em nosso layout. Os filhos diretos são itens de grade, no entanto, por padrão, acabamos com uma grade de uma coluna. Uma grade sempre tem uma coluna e uma linha. O resto das linhas que podemos ver depois de fazer isso são linhas implícitas, ou seja, linhas criadas para conter o conteúdo.

Um conjunto de cartas dispostas uma abaixo da outra em uma única coluna.
Quando criamos um contêiner de grade sem colunas, obtemos uma grade de uma coluna. (Visualização grande)

Podemos começar a formar algo que se pareça mais com uma grade para nós, dando um valor à propriedade grid-template-columns . A propriedade aceita uma lista de faixas como valor; se eu der três faixas 1fr, agora nos encontramos com uma grade de três colunas, e usar a propriedade gap me dá espaçamento entre essas cartas.

Agora temos algo que nos parece uma grade:

Cartões dispostos em três colunas e duas linhas
Definimos algumas faixas de coluna e uma lacuna para obter um layout de grade óbvio (visualização grande)

Cada um dos itens de grade em nosso exemplo tem seus próprios filhos. Os cartões possuem cabeçalhos e rodapés e uma área para o conteúdo principal do cartão. Esses filhos são itens de grade, mas seus filhos retornaram ao layout de bloco e embutido. O cabeçalho, a área de conteúdo e o rodapé não fazem nenhuma grade como coisas. Isso ocorre porque quando alteramos o valor de display para grid , ele não herda, mas apenas os filhos se tornam itens de grade; seus filhos retornam ao layout de bloco.

Aninhamento de grades

Se um cartão tiver mais conteúdo do que os outros cartões, os cartões dessa linha ficarão mais altos. O valor inicial de align-items para itens de grade é stretch . Nossos cartões se estendem até a altura total. Os itens dentro, no entanto, estão no fluxo normal de bloco e em linha e, portanto, não se estendem magicamente para preencher o cartão. (É por isso que na imagem acima você pode ver que os cartões com menos conteúdo têm uma lacuna na parte inferior.)

Se quiséssemos que eles (para fazer com que o rodapé sempre ficasse na parte inferior), poderíamos tornar nosso item de grade uma grade também. Nesse caso, uma grade de coluna única é tudo o que precisamos. Podemos então definir trilhas de linha, fornecendo a área na qual o div com uma classe de conteúdo fica, um tamanho de trilha de 1fr . Isso faz com que ele ocupe todo o espaço disponível no contêiner e empurrará o rodapé para a parte inferior do cartão.

Veja a caneta [display: subgrid is not what we want](https://codepen.io/rachelandrew/pen/PvQzeG) por Rachel Andrew.

Veja a tela da caneta: subgrade não é o que queremos por Rachel Andrew.

Você pode fazer esse aninhamento de grades o quanto precisar. Eu realmente não penso nisso como aninhamento, já que não estamos criando tabelas aninhadas aqui e geralmente estamos usando os elementos HTML estruturais já instalados. Estamos apenas alterando o valor de display um nível de cada vez para o que for mais apropriado para os filhos desse elemento. Isso pode ser layout flexível ou layout de grade, mas na maioria das vezes será layout de bloco e em linha. Nesse caso, não precisamos fazer nada porque é isso que acontece por padrão.

Alinhando os cabeçalhos e rodapés

Como vimos agora, se queremos um conjunto de cartões dispostos em uma grade, e queremos que eles sejam exibidos tão altos quanto o cartão mais alto, e queremos que os rodapés sejam empurrados para a parte inferior do cartão, precisamos de muito pouco CSS . O layout CSS para o exemplo acima é o seguinte:

 .cards { display: grid; gap: 20px; grid-template-columns: 1fr 1fr 1fr; } article { display: grid; grid-template-rows: auto 1fr auto; row-gap: 20px; }

E se quisermos que a cor de fundo nos cabeçalhos e rodapés se alinhem? Cada cartão é um item de grade, mas os cabeçalhos e rodapés estão na grade do item. Eles não têm relação entre si e por isso não podemos alinhá-los. Aqui seria bom se pudéssemos de alguma forma herdar a grade através dos filhos.

Se pudéssemos definir uma grade no pai que tivesse três linhas, coloque os cartões nessas três linhas e faça com que o cabeçalho, o conteúdo e o rodapé fiquem em uma das linhas. Dessa forma, cada cabeçalho estaria na mesma linha e, portanto, se um cabeçalho ficasse mais alto, toda a linha ficaria mais alta.

Não temos uma boa solução para isso nos navegadores hoje, mas está a caminho. O recurso de subgrade do CSS Grid Layout Level 2 habilitará esse padrão exato. Você poderá criar uma grade no pai e, em seguida, optar seletivamente pelas linhas e/ou colunas para usar essa grade, em vez de definir uma nova grade no elemento child que seja completamente independente dessa grade.

Observe que os exemplos a seguir funcionam apenas no momento da escrita no Firefox Nightly. O valor de subgrade de grid-template-columns e grid-template-rows é um novo recurso e parte do Nível 2 da CSS Grid Specification. Para experimentar esse recurso, baixe uma cópia do Firefox Nightly.

Você pode ver como isso funciona nas imagens abaixo. Na primeira imagem, criei três faixas de linha no pai e espalhei o cartão entre elas. Com o Firefox Grid Inspector destacando a grade, você pode ver que as linhas do pai não se relacionam com as linhas usadas pelos filhos.

Uma imagem de uma grade de três colunas com as faixas do Firefox Grid Inspector sobrepostas.
Inspecionar a grade com o Firefox Grid Inspector mostra que os elementos não estão sendo exibidos nas trilhas do pai. (Visualização grande)

Se, em vez de definir três linhas no filho, eu usar o valor subgrid para grid-template-rows , o cartão agora usará essas linhas no pai. Você pode ver como os dois agora estão alinhados e, portanto, os cabeçalhos e rodapés também se alinham:

Uma imagem de uma grade de três colunas, todos os elementos dentro dos cartões alinhados.
Usando a subgrade, cada parte do cartão entra em sua própria faixa (visualização grande)

O que estamos fazendo aqui com subgrid não é um novo valor de display . O item que é uma subgrade é um contêiner de grade em si, pois definimos display: grid nele. Os itens de grade estão se comportando como os itens de grade normalmente. Este é o layout de grade regular - não é diferente da grade aninhada original, exceto que (em vez de o item ter seu próprio dimensionamento de trilha de linha) está usando as trilhas do pai.

 .cards { display: grid; gap: 20px; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: repeat(2,auto 1fr auto); } article { grid-row-end: span 3; display: grid; grid-template-rows: subgrid; }

Essa é a vantagem do subgrid; não há muito o que aprender se você já sabe como usar o layout de grade. Você pode ler sobre o resto dos detalhes no meu post anterior aqui na Smashing Magazine, “CSS Grid Level 2: Here Comes Subgrid”.

Ontem (23 de maio de 2019 ), a subgrade chegou ao Firefox Nightly, então temos uma implementação testável do valor da subgrade de grid-template-columns e grid-template-rows . Por favor, pegue uma cópia do Nightly e experimente isso. Com uma cópia do Nightly, você pode ver o exemplo final funcionando neste CodePen:

Veja a tela da caneta: subgrade não é o que queremos por Rachel Andrew.

Veja a tela da caneta: subgrade não é o que queremos por Rachel Andrew.

Veja se você pode pensar em outros casos de uso que são resolvidos com o recurso de subgrade, ou talvez coisas que você acha que estão faltando. Embora um recurso esteja disponível apenas em um navegador noturno, esse é o momento em que é possível fazer alterações nas especificações se algum problema for descoberto. Então, faça um favor ao seu futuro desenvolvimento web e experimente recursos como este para que você possa ajudar a contribuir para a plataforma web e melhorar as coisas.

Se você acha que encontrou um bug na implementação do Firefox, você pode dar uma olhada no bug de implementação principal no Bugzilla que tem links para problemas relacionados na seção Depende . Se você não conseguir ver seu problema, crie um caso de teste reduzido o mais simples possível e levante o bug. Se você acha que a subgrade deve fazer algo para resolver um caso de uso, e isso é algo não detalhado na especificação, você pode levantar um problema no CSS Working Group GitHub para um potencial aprimoramento.

E quanto display: contents ?

Se você está acompanhando, pode pensar que display: contents (conforme descrito no artigo anterior sobre display ) pode resolver os problemas que o subgrid procura resolver — o de permitir que crianças indiretas participem de um layout de grade. Esse não é o caso, e nosso exemplo de cartas é uma maneira perfeita de demonstrar a diferença.

Se, ao invés de fazer do nosso cartão um layout de grade com display: grid , removêssemos a caixa usando display: contents , obteríamos este resultado neste próximo CodePen. (Tente remover a linha display: contents das regras para .card para ver a diferença.)

Veja a tela da caneta: subgrade não é o que queremos por Rachel Andrew.

Veja a tela da caneta: subgrade não é o que queremos por Rachel Andrew.

Neste exemplo, a caixa do cartão foi removida e, portanto, o cabeçalho, o conteúdo e o rodapé participam diretamente do layout da grade e são colocados automaticamente na grade. Não era isso que queríamos de jeito nenhum! O valor de contents de display será muito útil uma vez que os problemas de acessibilidade em navegadores mencionados no meu último artigo sejam resolvidos, porém, resolve problemas diferentes do que estamos explorando.

Mais leituras e exemplos

Eu tenho criado vários exemplos e demos para ajudar todos a entender o subgrid. Você pode experimentá-los nos links abaixo:

  • Exemplos de Grade CSS Nível 2
  • Grade CSS Nível 2: Aí vem a subgrade
  • Grids All The Way Down (Apresentação)
  • Documentação MDN para Subgrade