- O CSS Grid passou a ser amplamente suportado pelos principais navegadores desde março de 2017, mas
grid-template-areas ainda é menos usado e permite expressar visualmente o layout dentro do CSS sem calcular números de linhas
grid-template-areas funciona posicionando nomes de áreas em strings e vinculando elementos filhos com grid-area; o mesmo nome deve obrigatoriamente formar uma área retangular
- Linhas de grade nomeadas são uma forma de atribuir nomes às linhas, como
content-start / content-end, e os padrões *-start e *-end podem ser usados pelo navegador como áreas implícitas
- Em cards invertidos, headers responsivos, layouts editoriais, posts no estilo Threads, cards sobrepostos e layouts condicionais com
:has(), é possível gerenciar variações de posicionamento alterando apenas a string de áreas no elemento pai
- Chrome, Safari e Firefox oferecem DevTools para áreas de Grid; no Firefox, a exibição dos nomes das áreas e o autocompletar de nomes de linhas possíveis ao editar
grid-area são especialmente úteis
Tornando layouts mais legíveis com grid-template-areas
- Em posicionamentos tradicionais com CSS Grid, é comum especificar diretamente números de linhas, como em
grid-column: 1 / 3
- Números de linhas não ficam visíveis até serem conferidos no DevTools e, em layouts com colunas e linhas, é difícil calcular mentalmente os números corretos
grid-template-areas dá nomes a cada célula para posicionamento, fazendo com que o próprio código CSS pareça um mapa do layout
.page {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas: "item1 item2";
gap: 1rem;
}
.item-1 {
grid-area: item1;
}
.item-2 {
grid-area: item2;
}
- Elementos filhos são mapeados para áreas nomeadas com
grid-area
- Em um exemplo de card, é possível definir algo como
"featured featured article" para fazer a área featured ocupar 2 colunas e a área article ocupar 1 coluna
Sintaxe e regras obrigatórias
grid-template-areas recebe uma ou mais strings de áreas
- Uma única string cria um layout unidimensional apenas com colunas
- Várias strings compõem um layout multidimensional com linhas e colunas
- Ao usar várias strings, quebrar as linhas torna o layout mais fácil de ler
.element {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-areas:
"aside main"
"footer footer";
}
- Cada string representa uma linha da grade e pode ser pensada como uma tabela
- Áreas definidas com o mesmo nome devem formar um retângulo no código
/* invalid */
.layout {
grid-template-areas:
"header header"
"sidebar main"
"header footer";
}
/* valid */
.layout {
grid-template-areas:
"header header"
"sidebar main"
"sidebar footer";
}
- Todas as linhas devem ter o mesmo número de tokens de área e, mesmo que uma área necessária não seja usada, a célula em si deve ser definida
- Células vazias podem ser representadas por um ou mais pontos
.element {
grid-template-areas:
"aside main"
"... footer";
}
- O ponto é o token de célula nula da especificação do CSS Grid e representa uma célula vazia da grade
Relação entre linhas de grade nomeadas e áreas
- No CSS Grid, há uma linha a mais do que o número de colunas
- Com 3 colunas, são criadas 4 linhas de grade
- Linhas de grade nomeadas são uma forma de dar nomes exclusivos às linhas em vez de usar os números padrão
.layout {
grid-template-columns:
[full-start] 1fr
[content-start] 2fr
[content-end] 1fr [full-end];
}
.item {
grid-column: content-start / content-end;
}
- Mesmo dando nomes às linhas, as linhas numéricas continuam disponíveis
- Tamanho de trilha (track size) significa o tamanho de uma coluna ou linha, e valores como
1fr 1fr são tamanhos de trilha
- Em linhas nomeadas, nomeiam-se as linhas ao redor das trilhas
.layout {
display: grid;
grid-template-columns:
[aside-start] 200px [aside-end main-start] 1fr [main-end];
}
- Uma linha pode compartilhar vários nomes; no exemplo acima,
aside-end e main-start são a mesma linha
- Ao definir nomes
*-start / *-end, como aside-start e aside-end, o navegador permite usos como grid-column: aside por meio de nomes de linha implícitos
- Não é necessário nomear todas as linhas; é possível nomear seletivamente apenas as linhas importantes
- No posicionamento, números e nomes podem ser misturados, como em
grid-column: 1 / content-end
Gerenciando variações de posicionamento pela string de áreas do pai
- Com
grid-template-areas, é possível manter os nomes grid-area dos filhos e alterar apenas a string de áreas do elemento pai para mudar o layout inteiro
.aside {
grid-area: aside;
}
.main {
grid-area: main;
}
.footer {
grid-area: footer;
}
- Mantendo os mesmos nomes
aside, main e footer, basta alterar a string de grid-template-areas para que todo o posicionamento seja atualizado automaticamente
- O controle do layout fica centralizado na definição de áreas do pai, facilitando ajustes
Invertendo a direção de cards
- No Flexbox, é fácil inverter a direção de um card com
flex-direction: row-reverse
- No CSS Grid, ao usar números de linhas, mudar a direção exige alterar a definição das colunas e também o valor de
grid-column de cada filho
- Com áreas nomeadas, basta atribuir a imagem e o conteúdo do card a áreas e depois mudar apenas a ordem das áreas no pai
.card {
display: grid;
grid-template-columns: 150px 1fr;
grid-template-areas: "thumb content";
}
.card__thumb {
grid-area: thumb;
}
.card__content {
grid-area: content;
}
.card--flip {
grid-template-columns: 1fr 150px;
grid-template-areas: "content thumb";
}
- O mesmo posicionamento também pode ser expresso com a propriedade abreviada
grid-template
.card--flip {
grid-template: "content image" / 1fr 150px;
}
- A propriedade abreviada é opcional, e também é válido preferir a propriedade longa por considerá-la mais legível
Layout de header responsivo
- Um header com logo, navegação e área de ações pode começar com 3 colunas do mesmo tamanho
- Usando números de linhas, seria necessário especificar
grid-column para .logo, .nav e .actions individualmente
- Com nomes de áreas, cada filho é mapeado para
logo, nav e actions, e por viewport basta mudar grid-template-areas no pai
.header {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "logo nav actions";
}
.logo {
grid-area: logo;
}
.nav {
grid-area: nav;
}
.actions {
grid-area: actions;
}
- Em tamanhos menores, é possível colocar o logo e as ações na primeira linha e a navegação em toda a largura
.header {
grid-template-areas:
"logo logo actions"
"nav nav nav";
}
- A partir de
380px, é possível deixar o logo à esquerda e posicionar a navegação e as ações à direita
@media (min-width: 380px) {
.header {
grid-template-areas:
"logo nav nav"
"logo actions actions";
}
.nav {
justify-self: end;
}
}
- A partir de
900px, é possível voltar para o layout em uma linha
@media (min-width: 900px) {
.header {
grid-template-areas: "logo nav actions";
}
}
- A string de áreas funciona como um mapeamento que mostra diretamente o posicionamento da UI dentro do CSS
Exemplo de layout editorial
- Uma seção com título, texto e imagem pode mudar facilmente o posicionamento por tamanho de viewport usando
grid-template-areas
.section {
display: grid;
grid-template-areas:
". title title"
"thumb content content";
gap: 1rem;
}
- O ponto à esquerda do título é um token de célula nula, indicando espaço vazio
- Em um exemplo de seção no estilo time.com, são usadas as áreas
feature, secondary e most-read junto com colunas vazias dos dois lados
.featured-section {
display: grid;
grid-template-areas:
". feature most-read ."
". secondary most-read .";
grid-template-columns: 1fr minmax(auto, 57.313rem) minmax(12rem, 18.75rem) 1fr;
grid-template-rows: minmax(auto, 25rem) 1fr;
}
- As colunas vazias dos dois lados servem principalmente como espaçamento lateral
- Na versão responsiva, em telas pequenas
feature, secondary e most-read são empilhados verticalmente, e a partir de 500px e 900px as definições de colunas e áreas são alteradas
grid-template-rows pode ser substituído pela definição de áreas, portanto não é indispensável
Componente de post no estilo Threads
- Ao revisar o CSS do Threads app by Meta, é possível observar casos de uso de CSS Grid em componentes de post
- O exemplo original posiciona itens com
grid-template-columns, grid-template-rows e números de linhas
.postBody {
grid-column-start: 2;
grid-row-start: 2;
grid-row-end: span 3;
}
- Várias variações de posts podem ser expressas mais facilmente com
grid-template-areas
.post {
grid-template-areas:
"avatar header"
"avatar body"
". body"
". footer";
}
.post--reply {
grid-template-rows: 40px max-content max-content;
grid-template-areas:
"avatar header"
"body body"
"body body"
"footer footer";
}
.post--nested {
grid-template-areas:
"avatar header"
"avatar body"
"line body"
"footer footer";
}
- É possível distinguir as variações padrão, resposta e post aninhado apenas olhando para as strings de áreas
Itens sobrepostos e nomes de áreas
- Em
grid-template-areas, o mesmo nome deve formar um retângulo; portanto, repetir o mesmo nome em uma forma não retangular é inválido
.layout {
display: grid;
grid-template-columns: 1fr 1fr fr;
grid-template-areas:
"card tag tag"
"title title card";
}
- O exemplo acima é invalid porque
card não forma um retângulo
- Em cards sobrepostos, é possível definir novos nomes de área, como
thumb-1 e thumb-2, e usar esses nomes em grid-column e grid-row
.card {
display: grid;
grid-template-columns: auto auto 1fr;
grid-template-rows: auto auto;
grid-template-areas:
"thumb-1 tag"
"title thumb-2";
}
.thumb {
grid-column: thumb-1 / thumb-2;
grid-row: thumb-1 / thumb-2;
}
- A tag e o título podem ser posicionados em seus respectivos
grid-area e alinhados com align-self e justify-self
- Se necessário, é preciso gerenciar a ordem de empilhamento dos elementos filhos, mas no exemplo a ordem do código-fonte resolve isso
- Este exemplo de sobreposição foi inspirado na página Oddbird’s Cascading Layouts
:has() e layout condicional
- Ao combinar o seletor CSS
:has() com áreas de Grid, é possível mudar o layout conforme a presença de um elemento específico
- É possível aplicar definições de áreas diferentes quando há ou não
figcaption dentro de <figure>
figure {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "img img img";
gap: 0.5rem;
}
img {
grid-area: img;
}
figcaption {
grid-area: caption;
}
.card:has(figcaption) {
grid-template-areas:
"img img caption"
"img img .";
}
Suporte a direções multilíngues LTR/RTL
- O CSS Grid ajusta o layout de acordo com a direção da página, seja LTR ou RTL
- Áreas de grade nomeadas também seguem a direção da página, portanto o layout é invertido em uma configuração RTL
- Como material relacionado à criação de layouts RTL, há o guia RTL Styling 101
Diferenças no suporte das DevTools
- Chrome, Safari e Firefox oferecem DevTools para áreas de Grid
- Chrome
- Posiciona os nomes das áreas no canto superior esquerdo, o que pode fazer as áreas parecerem sobrepostas
- A sobreposição de cores pode alterar a forma como o design é visto
- Safari
- O contorno rosa ajuda a distinguir claramente os itens
- Permite ver os nomes das linhas
- A forma de exibir nomes de linhas ainda pode ser melhorada, por exemplo mostrando-os empilhados
- Firefox
- Os nomes das áreas aparecem com mais clareza do que no Chrome e no Safari
- Oferece uma lista de autocompletar ao inserir nomes personalizados como
*-start e *-end
- Ao editar
grid-area de um item filho, oferece uma lista de todos os nomes de linhas possíveis
Referências
1 comentários
Opiniões no Hacker News
A demo de animação era bem interessante, mas fiquei decepcionado ao descobrir que a animação não foi feita em CSS
Depois de aprender Flexbox, pensei “isso já é suficiente” e não me aprofundei em Grid. Parece haver motivos para preferir Grid [0], mas, no geral, nunca precisei fazer algo que só fosse possível com Grid, e para tabelas de dados uso
<table>de verdade[0] https://css-tricks.com/css-grid-replace-flexbox/
Só usei Grid para coisas como galerias de imagens responsivas, como https://labs.jensimmons.com/2016/examples/image-gallery-grid..., ou cartões responsivos como https://every-layout.dev/demos/grid-cards/. Vale a pena aprender
grid-template-columns, egrid-gapé conveniente. Fora isso, parece que Flexbox resolve quase tudoDito isso,
grid-template-areasainda me parece meio ambíguo. O texto argumenta que é fácil para ajustar layouts por breakpoint ou “quando um colega de equipe precisa mudar o layout”, mas talvez eu simplesmente não seja o público-alvoDá para usar os dois conforme a necessidade e, combinados, eles se tornam uma ferramenta de layout muito poderosa
https://www.youtube.com/watch?v=MWWcZzossc8
Espera,
1/3não é uma fração, mas um intervalo de 1 a 3? Não entendo por que escolheriam essa sintaxe. Em programação há muitas sintaxes razoáveis e bem conhecidas para representar intervalos, como1..3Parece que boa parte dos problemas que programadores têm com CSS vem desse mal-entendido
!importantnão significa “não importante”, mas sim “importante!”Nunca peguei direito nem Grid nem Flexbox. A última estratégia de layout com que eu ainda me virava bem foi float. Este texto me deu confiança para tentar usar CSS Grid quando eu for projetar o próximo layout, e o artigo também é bem feito
Há muitos textos bons, mas, para mim, bastou ler estes dois do CSS-Tricks
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
https://css-tricks.com/snippets/css/complete-guide-grid/
Além dos artigos do CSS-Tricks já citados, recomendo o guia de Flexbox da MDN[1] e a referência “CSS flexible box layout”[2]. Eles me ajudaram a entender mais a fundo os conceitos por trás do Flexbox e como propriedades e propriedades abreviadas realmente funcionam
[1]: https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layou...
[2]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexibl...
Ainda assim, Flexbox é mais parecido com um layout unidimensional com possibilidade de quebra de linha, então o truque é aninhar e empilhar. Grid é mais estático que Flexbox: ele tem templates, e os filhos diretos ocupam áreas predefinidas; há a limitação de não afetar elementos aninhados internamente. Mesmo assim, parece que subgrid deve mudar essa parte
Materiais relacionados:
Grid Garden https://cssgridgarden.com
Flexbox Froggy https://flexboxfroggy.com
Seria bom existir uma versão ainda mais básica que este documento, algo “antes da introdução”. Travei já na parte introdutória e não consegui avançar. Especialmente no trecho “para posicionar itens filhos dentro de um Grid, é preciso especificar o número da linha de cada item com
grid-column”: eu não sabia o que era esse número da linha aquiTentei seguir em frente achando que entenderia pelo contexto, mas logo travei de novo em expressões como
1 / 3e1 / 4|a||b|, as duas linhas do meio contam na prática como uma só, então são 3 no totalPortanto
1/3não é uma fração, mas um intervalo de colunas, e significa “começa na linha 1 e termina na linha 3”O nome “número da linha” não é muito bom, mas na prática são as bordas das colunas. Então
1/3vai da borda 1, ou seja, a mais à esquerda, até a borda 3, ocupando as 2 colunas inteirasPara CSS Grid, recomendo muito Jen Simmons Mondrian with auto flow. Em https://labs.jensimmons.com/2017/01-011.html, pressione
CeDe redimensione a janela. Há também um vídeo no YouTube para assistir junto: https://www.youtube.com/watch?v=qNtJ5p3h2A4É realmente incrível
O que eu ainda quero entender no auto flow é como detectar e preencher espaços vazios. Quando há objetos de tamanhos variados distribuídos aleatoriamente, como fazer o auto flow não deixar lacunas? Ou será que dá para detectar lacunas e adicionar algo nelas?
Espero que não seja uma pergunta idiota, mas por que a sintaxe foi definida com barra, como
1/2,3/4? Algo como1-2, da coluna 1 até a coluna 2, ou1->2, não seria mais natural?1--1,1->-1ou1/-1?Em CSS, valores já são separados por espaços, e considerando também a intuição que normalmente temos quando aparece um hífen, o abaixo é muito melhor
grid-column: 4 somegridarea / 6;grid-column: span 3 / 6;grid-column: span somegridarea / span someothergridarea;Muito mais claro do que escrever assim
grid-column: 4 somegridarea-6;grid-column: span 3-6;grid-column: span 3->6;grid-column: span somegridarea-span someothergridarea;grid-column: span somegridarea->span someothergridarea;Gosto muito desse tipo de post interativo de blog. Para Grid, recomendo muito mexer diretamente em grid areas em ferramentas como https://grid.layoutit.com/
Uso esse site há anos para planejar layouts com Grid, e ficou muito mais fácil ajustar os espaçamentos
Talvez esta seja a primeira vez que realmente entendi CSS Grid. A exibição da numeração ajudou muito, e é um artigo que vou consultar com frequência daqui para frente
Gosto de CSS Grid e do conceito de áreas, mas ainda acho que a parte mais difícil é o gerenciamento responsivo, especialmente entre tamanhos mobile e desktop. Dependendo de qual elemento da UI deve estar aberto ou ocupar a tela inteira, muitas vezes é preciso atualizar
grid-template-areae os tamanhos de linhas/colunas via JavaScriptAinda não encontrei um mundo em que
minmaxoucalcresolvam isso, e gostaria que alguém soubesse a respostavar(--foo), em vez de valores fixosAssim, no JavaScript você só precisa atualizar o valor dessa variável, e o Grid reflete esse valor
display: nonenesse tamanhoUm exemplo bem simples: https://codepen.io/trescenzi/pen/vYqpjvL
:has()ou subgrid, mas não tenho muita experiência prática