Feedback necessário: como definir alvenaria CSS?

Ian Kilpatrick
Ian Kilpatrick
Tab Atkins-Bittner
Tab Atkins-Bittner

Publicado em 19 de setembro de 2024

O Grupo de trabalho do CSS combinou as duas propostas de disposição em bloco do CSS em um rascunho de especificação. O grupo espera que isso facilite a comparação entre os dois e a tomada de uma decisão final. A equipe do Chrome ainda acredita que uma sintaxe de montagem separada seria a melhor maneira de prosseguir. Embora o maior problema de desempenho mencionado na nossa postagem anterior tenha sido resolvido, ainda há preocupações em relação à sintaxe, aos valores iniciais e à facilidade de aprendizado de uma versão combinada com a grade.

No entanto, para testar nossas suposições, trabalhamos com alguns exemplos para mostrar como a alvenaria funcionaria com cada versão. Confira os exemplos desta postagem e envie seu feedback para que possamos tomar uma decisão e continuar com esse recurso.

Esta postagem não aborda todos os casos de uso possíveis, mas é claro que separar a disposição de alvenaria do layout de grade não vai resultar na falta de funcionalidade do recurso. Na verdade, o oposto pode ser verdadeiro. Como você vai conferir nesta postagem, a versão display: masonry cria novas oportunidades e uma sintaxe mais simples. Além disso, muitos desenvolvedores expressaram preocupações sobre a possibilidade de reordenar itens com o efeito de alvenaria causando problemas de acessibilidade. Isso também está sendo resolvido para as duas versões da sintaxe, usando a propriedade reading-flow proposta.

Um layout de alvenaria básico

Esse é o layout que a maioria das pessoas imagina quando pensa em alvenaria. Os itens são mostrados em linhas, e depois que a primeira linha é colocada, os itens seguintes são movidos para o espaço deixado por itens mais curtos.

Um layout com colunas, em que os itens preenchem as colunas sem lacunas.
Neste layout, as colunas são definidas e os itens são preenchidos por alvenaria, em vez de linhas rígidas.

Com display: masonry

Para criar um layout de alvenaria, use o valor de masonry para a propriedade display. Isso cria um layout de alvenaria com faixas de coluna que você define (ou são definidas pelo conteúdo) e alvenaria no outro eixo. O primeiro item é exibido no bloco e no início inline (ou seja, no canto superior esquerdo em inglês), e os itens são dispostos na direção inline.

Para definir faixas, use masonry-template-tracks com os valores de listagem de faixas usados no layout de grade do CSS.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(3, 1fr);
  gap: 10px;
}

Com display: grid

Para criar um layout de alvenaria, primeiro crie um layout de grade usando o valor de grid para a propriedade display. Defina colunas com a propriedade grid-template-columns e atribua a grid-template-rows o valor masonry.

Isso vai criar um layout como o esperado com itens de grade posicionados automaticamente. No entanto, os itens em cada linha usam um layout de alvenaria e serão reorganizados para ocupar o espaço deixado por itens menores na linha anterior.

.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry;
  gap: 10px;
}

Pontos a considerar entre as duas opções

Uma diferença importante entre esses métodos é que, com a versão display: masonry, você recebe um layout de alvenaria mesmo que não especifique nenhuma faixa com masonry-template-tracks. Portanto, display: masonry pode ser tudo o que você precisa. Isso ocorre porque o valor inicial de masonry-template-tracks é repeat(auto-areas, auto). O layout cria o maior número de faixas de tamanho automático que cabem no contêiner.

Fluxo invertido com disposição em blocos

A especificação inclui maneiras de mudar a direção do fluxo de alvenaria. Por exemplo, você pode mudar o fluxo a ser mostrado do início ao fim.

Um layout com colunas, em que os itens que preenchem as colunas o fazem a partir da parte de baixo do layout.
Neste layout, as colunas são definidas e os itens são preenchidos por alvenaria, começando no final do bloco.

Com display: masonry

Crie um layout de alvenaria com display: masonry e use masonry-direction com um valor de column-reverse.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(3, 1fr);
  masonry-direction: column-reverse;
}

Com display: grid

Crie um layout de alvenaria com display: grid e grid-template-rows: masonry. Em seguida, use a propriedade grid-auto-flow com um novo valor de row-reverse para fazer com que os itens sejam dispostos a partir do final do bloco do contêiner de grade.

.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry;
  grid-auto-flow: row-reverse;
}

Pontos a considerar entre as duas opções

A versão display: masonry é muito semelhante ao funcionamento do flexbox. Mude a direção em que as colunas fluem usando a propriedade masonry-direction com um valor de column-reverse.

A versão da grade CSS usa grid-auto-flow. Como definido atualmente, grid-auto-flow: row-reverse e grid-auto-flow: column-reverse teriam o mesmo efeito. Isso pode ser confuso, já que você pode esperar que eles façam algo diferente.

Masonry para linhas

Você também pode mudar a direção para definir linhas.

Um layout com linhas, em que os itens preenchem as linhas sem lacunas.
Neste layout, as linhas são definidas e os itens são preenchidos por alvenaria, em vez de colunas rígidas.

Com display: masonry

Crie um layout de alvenaria com display: masonry e defina o valor de masonry-direction como row. A menos que você queira que as linhas tenham um tamanho de bloco específico, não é necessário especificar o tamanho da faixa, já que o padrão é auto. As faixas serão dimensionadas de acordo com o conteúdo que contêm.

.masonry {
  display: masonry;
  masonry-direction: row;
}

Com display: grid

.masonry {
  display: grid;
  grid-template-columns: masonry;
  grid-template-rows: repeat(3, 1fr);
}

Pontos a serem considerados entre as duas opções

Assim como no fluxo invertido, mudar a versão display: masonry de colunas para linhas significa mudar o valor de masonry-direction. Com a versão de grade, você precisa alternar os valores das propriedades grid-template-columns e grid-template-rows. Ou, se estiver usando a abreviação, mude a ordem da sintaxe.

Com esses dois exemplos de fluxo de troca, a versão display: masonry parece mais intuitiva. Há uma única propriedade que controla o fluxo masonry-direction, que recebe um dos seguintes valores:

  • row
  • column
  • row-reverse
  • column-reverse

Em seguida, adicione todas as informações de dimensionamento necessárias a masonry-template-tracks, considerando que o valor padrão automático não é o que você precisa.

Com a grade, para fazer a direção inversa, você precisa usar a propriedade grid-auto-flow e, para fazer a disposição de blocos de linhas, mude o valor das propriedades grid-template-*. Também não é possível, na sintaxe atual da grade, deixar o valor do eixo da grade indefinido. Sempre é necessário especificar as propriedades grid-template-* no eixo que não tem um valor de masonry.

Posicionar itens

Em ambas as versões, é possível posicionar itens explicitamente usando o posicionamento baseado em linha que você já conhece do layout de grade. Nas duas versões, só é possível posicionar itens no eixo da grade, que é o eixo com as faixas predefinidas. Não é possível posicionar itens no eixo que está fazendo o layout de alvenaria.

Com display: masonry

O CSS a seguir define um layout de alvenaria com quatro colunas. O eixo da grade é portanto colunas. O item com uma classe de a é colocado da primeira linha da coluna até a terceira linha da coluna, abrangendo duas faixas com as novas propriedades masonry-track-*. Isso também pode ser definido como uma abreviação de masonry-track: 1 / 3;.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(4, 1fr);
}

.a {
  masonry-track-start: 1;
  masonry-track-end: 3;
}

Com display: grid

O CSS a seguir define um layout de alvenaria com quatro colunas. O eixo da grade é portanto colunas. O item com uma classe de a é colocado da primeira linha da coluna até a terceira linha da coluna, abrangendo duas faixas com as propriedades grid-column-*. Isso também pode ser definido como uma abreviação de grid-column: 1 / 3;.

Se o eixo da grade for colunas, as propriedades grid-row-* serão ignoradas. Se o eixo da grade for linhas, as propriedades grid-columns-* serão ignoradas.

.masonry {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
}

.a {
  grid-column-start: 1;
  grid-column-end: 3;
}

É possível usar linhas nomeadas com as duas sintaxes. Os exemplos a seguir mostram uma grade com duas linhas de colunas chamadas a.

Com display: masonry

As linhas nomeadas são definidas no valor da lista de faixas de masonry-template-tracks. O item pode ser colocado após qualquer linha com o nome a.

.masonry {
  display: masonry;
  masonry-template-tracks: 100px [a] auto [a] auto 100px;
}

.item {
  masonry-track: a;
}

Com display: grid

As linhas nomeadas são definidas no valor da lista de faixas de grid-template-columns. O item é colocado após a primeira linha com o nome a. Se a propriedade grid-row for definida, ela será ignorada.

.masonry {
  display: grid;
  grid-template-columns: 100px [a] auto [a] auto 100px;
  grid-template-rows: masonry;
}

.item {
  grid-column: a;
  grid-row: a; /* ignored */
}

Também é possível usar áreas nomeadas nas duas sintaxes. Os exemplos a seguir mostram uma grade com três faixas chamadas "a", "b" e "c".

Com display: masonry

As faixas são nomeadas como o valor de masonry-template-areas. Como nenhum tamanho de faixa foi definido, os três são definidos como o tamanho auto. O item é colocado na faixa "a".

.masonry {
  display: masonry;
  masonry-template-areas: "a b c";
}

.item {
  masonry-track: a;
}

Isso funciona da mesma forma se você estiver definindo linhas ou colunas. A única diferença é a propriedade masonry-direction.

Com display: grid

Para colunas, a sintaxe é basicamente idêntica. Da mesma forma, como nenhum tamanho de faixa foi definido, os três são padronizados para o tamanho auto, mas ainda é necessário indicar explicitamente que o outro eixo é de alvenaria:

.masonry {
  display: grid;
  grid-template-areas: "a b c";
  grid-template-rows: masonry;
}

.item {
  grid-column: a;
}

No entanto, para linhas, o valor precisa ser escrito de maneira diferente, porque grid-template-areas está definindo uma área bidimensional, e cada linha é gravada como uma string separada:

.masonry {
  display: grid;
  grid-template-areas: "a" "b" "c"; /* Note the difference, each row is quoted. */
  grid-template-columns: masonry;
}

.item {
  grid-row: a;
}

Pontos a considerar entre as duas opções

Com qualquer posicionamento, a sintaxe display: masonry funciona melhor quando se trata de mudar de direção. Como a propriedade masonry-track-* funciona em qualquer direção do eixo da grade, basta mudar o valor de masonry-direction para mudar a direção. Com a versão de grade, pelo menos, você vai precisar de propriedades redundantes para ativar a troca. No entanto, consulte os exemplos anteriores para conferir outras maneiras de mudar de direção com a versão da grade.

Abreviações

Nesta postagem, as formas longas foram usadas para deixar mais claro quais propriedades estão em uso. No entanto, as versões display: masonry e display: grid podem ser definidas usando abreviações.

Com display: masonry

A abreviação display: masonry usa a palavra-chave masonry. Para criar o layout básico de alvenaria, use o seguinte CSS:

.masonry {
  display: masonry;
  masonry: repeat(3, 1fr);
}

Para criar um layout de fileiras simples:

.masonry {
  display: masonry;
  masonry: row;
}

Para definir faixas e um layout baseado em linhas com a abreviação:

.masonry {
  display: masonry;
  masonry: repeat(3, 1fr) row;
}

Com display: grid

Para criar o layout de alvenaria básico usando a abreviação grid.

.masonry {
  display: grid;
  grid: masonry / repeat(3, 1fr);
}

Para criar um layout de fileiras simples:

.masonry {
  display: grid;
  grid: repeat(3, auto) / masonry;
}

Em exemplos mais complexos, como a sintaxe geral de display:masonry é mais simples, mais propriedades podem ser agrupadas na abreviação sem se tornar muito complexa.

Por exemplo, imagine criar três colunas, "a", "b" e "c", preenchidas de baixo para cima.

Com display:masonry

Em display: masonry, todos os três podem ser definidos juntos na abreviação:

.masonry {
  display: masonry;
  masonry: column-reverse "a b c";
}

Como o tamanho é automático, não é necessário especificar os tamanhos, mas se você quisesse um tamanho específico, ele poderia ser adicionado. Por exemplo: masonry: column-reverse 50px 100px 200px "a b c";.

Além disso, cada componente pode ser reordenado livremente. Não há uma ordem específica que você precisa lembrar. Se você quiser fazer linhas, basta trocar column-reverse por row ou row-reverse. O restante da sintaxe permanece o mesmo.

Com display: grid

No display: grid, esses três aspectos precisam ser definidos separadamente:

.masonry {
  display: grid;
  grid-template-rows: masonry;
  grid-template-areas: "a b c";
  grid-auto-flow: wrap-reverse;
}

Assim como no exemplo de disposição em blocos, isso faz com que todas as colunas tenham o tamanho auto, mas, se você quiser fornecer tamanhos explícitos, faça o seguinte:

.masonry {
  display: grid;
  grid: masonry / 50px 100px 200px;
  grid-template-areas: "a b c";
  grid-auto-flow: wrap-reverse;
}

Ou se você quiser usar "grade" para definir tamanhos e nomes de área todos juntos:

.masonry {
  display: grid;
  grid: "a b c" masonry / 50px 100px 200px;
  grid-auto-flow: wrap-reverse;
}

Em ambos os exemplos, a ordem é estritamente necessária e diferente se você quiser linhas. Por exemplo, a mudança para linhas fica assim:

.masonry {
  display: grid;
  grid: 50px 100px 200px / masonry;
  grid-template-areas: "a" "b" "c";
}

Ou, para colocar tudo em uma abreviação:

.masonry {
  display: grid;
  grid: "a" 50px "b" 100px "c"  200px / masonry;
}

Pontos a considerar entre as duas opções

A abreviação display: masonry provavelmente será amplamente usada, já que é uma abreviação relativamente simples. Em muitos casos, para um layout de massote "padrão", você define apenas as definições de faixa. Todos os outros valores podem assumir o padrão.

A versão display: grid usa a abreviação grid, que é bastante complexa e, na nossa experiência, é usada com menos frequência pelos desenvolvedores. Como mostrado nos exemplos anteriores, mesmo quando usado para layouts simples de alvenaria, é necessário cuidado ao definir a ordem dos valores.

Outras considerações

Esta postagem analisa alguns casos de uso comuns atuais, mas não sabemos o que o futuro reserva para a grade ou a disposição em blocos. Um grande argumento para usar a sintaxe display: masonry separada é que ela permite que as duas se diferenciem no futuro. Em particular com valores iniciais, como os de masonry-template-tracks, pode ser útil fazer algo diferente na alvenaria do que a grade. Não é possível mudar os padrões da grade se usarmos a versão display: grid, o que pode limitar as coisas que queremos fazer no futuro.

Nesses exemplos, você pode conferir lugares em que o navegador precisa ignorar propriedades válidas na grade se estiver usando o layout de bloco. Por exemplo, grid-template-areas, em que a maioria dos valores é eliminada, porque define um layout de grade bidimensional. Na disposição de blocos, definimos apenas uma direção.

Envie seu feedback

Confira esses exemplos e também o rascunho da especificação que mostra cada versão ao lado da outra. Comente sobre o que você pensa sobre o Issue 9041 ou, se preferir escrever uma postagem no seu próprio blog ou nas mídias sociais, informe-nos no X ou LinkedIn.