Categorias
Projetos
CSS

Item Flow: o novo sistema de layout para CSS

Item Flow: o novo sistema de layout para CSS

Duas semanas atrás, Jen Simmons, da equipe do Webkit, compartilhou um artigo sobre um novo módulo de layout chamado Item Flow.

A ideia é unificar o flex-flow e o grid-auto-flow em um sistema unificado. Esse caminho levará à integração do CSS masonry na nova sintaxe.

Em outubro de 2024, Ahmad Shadeed publicou suas considerações sobre se o masonry deveria fazer parte do CSS grid ou ser uma nova sintaxe independente (display: masonry).

Atualmente, o Item Flow está sendo discutido pelo CSS Working Group. O objetivo deste artigo é compartilhar notas enquanto a nova sintaxe é explorada.

A curva de aprendizado é mínima

Apesar de ser uma nova proposta, ela se integra bem com a sintaxe atual de grid e flexbox. Ao observar a sintaxe previamente sugerida de display: masonry, fica claro à primeira vista que há uma curva de aprendizado considerável, mesmo para quem é especialista em CSS.

.layout {
display: masonry;
masonry-template-tracks: repeat(auto-fit, minmax(180px, 1fr));
masonry-direction: column;
gap: 1rem;
}

Já com o Item Flow, a sensação é de estar em casa. Melhor ainda, alternar de um grid normal para um com masonry requer apenas a mudança da propriedade item-flow.

.layout {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1rem;
}
.layout:has(.card:nth-last-child(n + 10)) {
item-flow: row collapse;
}

Se o display: masonry fosse usado, o código ficaria assim:

.layout {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1rem;
}
.layout:has(.card:nth-last-child(n + 10)) {
display: masonry;
masonry-template-tracks: repeat(auto-fit, minmax(180px, 1fr));
masonry-direction: column;
}

O que parece melhor: alterar uma única propriedade CSS (item-flow) ou um tipo de display completamente novo?

Flexbox Packing

Dense

Um dos pontos discutidos é o uso de packing para flexbox. No CSS Grid, é possível aplicar grid-auto-flow: dense, que permite ao navegador reordenar os itens como achar melhor.

.layout {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-auto-flow: dense;
}

Vale notar que usar dense reordena os itens. É confuso e pode causar problemas de acessibilidade, mas é assim que funciona.

Duas opções de flexbox packing: encolher itens levemente para caber mais, ou reordenar itens como o modo dense do grid
Duas opções de flexbox packing: encolher itens ou reordená-los.
Três variações de lista de tags demonstrando wrap padrão, packing denso com encolhimento e packing denso com reordenação
Variações de empacotamento em flexbox: padrão, denso com encolhimento e denso com reordenação.

Balance

Ao ler o artigo do Webkit, há uma sugestão para item-pack: balance. Resumidamente, essa propriedade balancearia os itens flex e tentaria fazer algo similar ao text-wrap: balance, mas para itens flex.

Representação visual da distribuição balanceada de itens flex com item-pack: balance
Distribuição balanceada de itens flex com item-pack: balance.

Usando nowrap para grid

Há algumas ressalvas sobre isso. Por que seria necessário nowrap no Grid? Por padrão, o grid faz wrap, exceto em um caso: quando se usa grid-auto-flow: column, que não faz wrap.

.layout {
display: grid;
grid-auto-flow: column;
gap: 0.5rem;
}

A sintaxe proposta seria:

.container {
display: grid;
grid-auto-columns: 1fr;
item-wrap: nowrap;
}

Isso deveria dar a cada item a mesma quantidade de espaço sem fazer wrap. Mesmo que funcione, não fica exatamente claro qual problema (ou caso de uso) isso resolve.

Alguns exemplos de Item Flow

Um item flex, contêiner flex, com align-items

.layout {
flex: 1;
align-self: start;
display: flex;
align-items: center;
item-wrap: wrap;
item-pack: balance;
}

Há uma inconsistência na nomenclatura: por que existe o plural em align-items, mas não em item-pack, por exemplo? Mesmo que ambos afetem os itens filhos do flexbox.

Centralizar o item órfão em um grid

Digamos que há um grid de 2 colunas. Atualmente, no CSS Grid, não existe uma forma direta de centralizar o último item quando ele está sozinho na linha — algo que pode ser parcialmente contornado com CSS condicional usando :has e :nth-last-child.

E se isso pudesse ser feito diretamente com a nova sintaxe?

.layout {
display: grid;
grid-template-columns: 1fr 1fr;
item-wrap: balance;
gap: 1rem;
}
Comparação antes e depois mostrando o item órfão do grid centralizado com item-wrap: balance
Centralizando o item órfão do grid com item-wrap: balance.

Detecção de wrap (ou algo parecido)

A detecção de wrap é algo muito importante. Ahmad Shadeed escreveu sobre isso em 2023. Imagine se essa nova sintaxe pudesse permitir isso ou algo semelhante:

.list {
display: flex;
item-wrap: wrap;
@container wrap-state(wrap) {
/* fazer algo */
}
}

Perguntas do Webkit

O artigo original do Webkit incluiu algumas perguntas, e Ahmad Shadeed compartilhou suas respostas:

Combinar flex-flow e grid-auto-flow? “Sim. Parece bom.”

Usaria a nova sintaxe? “O uso do shorthand flex-flow e do grid-auto-flow é raro. Porém, a nova sintaxe seria usada quando necessário.”

Outras ideias de unificação? Adicionar bordas entre itens em ambos os sistemas.

Recursos mais empolgantes? Masonry (claro!), packing denso em flexbox e wrapping balanceado em flexbox.

Ideias adicionais? Detecção de wrap em flexbox.

Conclusão

Compartilhar essas reflexões em um post pareceu a melhor abordagem. É animador ver que essa nova sintaxe está ganhando atenção. Ela é ótima!

Para quem quer se aprofundar nos fundamentos que o Item Flow pretende unificar, vale conferir os posts sobre CSS Grid, grids intrinsecamente responsivas e funções de dimensionamento CSS.