Feedback necessário: como definir alvenaria CSS?

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 alvenaria 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 blocos 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 colunas 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 considerar 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 você usar 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, nomeadas "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. Deixe sua opinião nos comentários da Edição 9041 ou, se preferir, escreva uma postagem no seu próprio blog ou nas mídias sociais. Informe-nos no X ou LinkedIn.