Preciso implementar um layout de alvenaria bastante comum. No entanto, por várias razões, não quero usar JavaScript para fazer isso.
Parâmetros:
- Todos os elementos têm a mesma largura
- Os elementos têm uma altura que não pode ser calculada no lado do servidor (uma imagem mais várias quantidades de texto)
- Eu posso viver com um número fixo de colunas se precisar
existe uma solução trivial para isso que funciona em navegadores modernos, a column-count
propriedade.
O problema com essa solução é que os elementos são ordenados em colunas:
Embora eu precise que os elementos sejam ordenados em linhas, pelo menos aproximadamente:
Abordagens que tentei que não funcionam:
- Fazendo itens
display: inline-block
: desperdiça espaço vertical. - Fazendo itens
float: left
: lol, não.
Agora eu poderia alterar a renderização no servidor e reordenar os itens que dividem o número de itens pelo número de colunas, mas isso é complicado, propenso a erros (com base em como os navegadores decidem dividir a lista de itens em colunas), então eu gostaria para evitá-lo, se possível.
Existe alguma mágica flexível do flexbox que torna isso possível?
Respostas:
Flexbox
Um layout de alvenaria dinâmico não é possível com o flexbox, pelo menos não de maneira limpa e eficiente.
Flexbox é um sistema de layout unidimensional. Isso significa que ele pode alinhar itens ao longo de linhas horizontais OU verticais. Um item flexível está confinado à sua linha ou coluna.
Um sistema de grade real é bidimensional, o que significa que ele pode alinhar itens ao longo de linhas horizontais e verticais. Os itens de conteúdo podem se estender por linhas e colunas simultaneamente, o que os itens flexíveis não podem.
É por isso que o flexbox tem uma capacidade limitada para construir grades. É também uma razão pela qual o W3C desenvolveu outra tecnologia CSS3, o Grid Layout .
row wrap
Em um contêiner flexível com
flex-flow: row wrap
, os itens flexíveis devem quebrar em novas linhas .Isso significa que um item flexível não pode quebrar em outro item na mesma linha .
Observe acima como a div nº 3 se divide abaixo da div nº 1 , criando uma nova linha. Não pode quebrar abaixo da div # 2 .
Como resultado, quando os itens não são os mais altos da linha, o espaço em branco permanece, criando lacunas desagradáveis.
column wrap
Se você alternar para
flex-flow: column wrap
, um layout semelhante à grade é mais viável. No entanto, um contêiner na direção da coluna tem quatro problemas em potencial imediatamente:Como resultado, um contêiner na direção da coluna não é uma opção nesse caso e em muitos outros casos.
Grade CSS com dimensões de item indefinidas
O layout da grade seria uma solução perfeita para o seu problema se as várias alturas dos itens de conteúdo pudessem ser pré-determinadas . Todos os outros requisitos estão dentro da capacidade da Grid.
A largura e a altura dos itens da grade devem ser conhecidas para fechar as lacunas nos itens ao redor.
Portanto, o Grid, que é o melhor CSS para oferecer para a construção de um layout de alvenaria com fluxo horizontal, fica aquém neste caso.
De fato, até que uma tecnologia CSS chegue com a capacidade de fechar automaticamente as lacunas, o CSS em geral não tem solução. Algo assim provavelmente exigiria refletir o documento, então não tenho certeza de quão útil ou eficiente seria.
Você precisará de um script.
As soluções JavaScript tendem a usar posicionamento absoluto, o que remove os itens de conteúdo do fluxo de documentos para reorganizá-los sem falhas. Aqui estão dois exemplos:
Desandro Masonry
Como criar um site que funcione como o Pinterest
Grade CSS com dimensões de item definidas
Para layouts em que a largura e a altura dos itens de conteúdo são conhecidas, aqui está um layout de alvenaria que flui horizontalmente em CSS puro:
Demonstração do jsFiddle
Como funciona
inline-grid
seria a outra opção)grid-auto-rows
propriedade define a altura das linhas geradas automaticamente. Nesta grade, cada linha tem 50 px de altura.grid-gap
propriedade é uma abreviação paragrid-column-gap
egrid-row-gap
. Esta regra define um intervalo de 10 px entre os itens da grade. (Não se aplica à área entre itens e o contêiner.)A
grid-template-columns
propriedade define a largura das colunas definidas explicitamente.A
repeat
notação define um padrão de colunas (ou linhas) repetidas.A
auto-fill
função diz à grade para alinhar o maior número possível de colunas (ou linhas) sem sobrecarregar o contêiner. (Isso pode criar um comportamento semelhante ao flexflex-wrap: wrap
.)A
minmax()
função define um intervalo de tamanho mínimo e máximo para cada coluna (ou linha). No código acima, a largura de cada coluna será no mínimo 30% do contêiner e no máximo de qualquer espaço livre disponível.A
fr
unidade representa uma fração do espaço livre no contêiner da grade. É comparável àflex-grow
propriedade do flexbox .Com
grid-row
espan
estamos dizendo aos itens da grade quantas linhas eles devem se estender.Suporte do navegador para CSS Grid
Aqui está a imagem completa: http://caniuse.com/#search=grid
Recurso de sobreposição de grade legal no Firefox
Nas ferramentas de desenvolvimento do Firefox, quando você inspeciona o contêiner de grade, há um pequeno ícone de grade na declaração CSS. Ao clicar, exibe um esboço da sua grade na página.
Mais detalhes aqui: https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts
fonte
Essa é uma técnica recentemente descoberta que envolve o flexbox: https://tobiasahlin.com/blog/masonry-with-css/ .
O artigo faz sentido para mim, mas eu não tentei usá-lo, então não sei se há alguma ressalva, além das mencionadas na resposta de Michael.
Aqui está uma amostra do artigo, fazendo uso da
order
propriedade, combinada com:nth-child
.Fragmento de pilha
fonte
order
propriedade, fazendo com que pareça que os itens fluem da esquerda para a direita. Ainda assim, seu principal truqueflex-flow: column wrap
é mencionado na resposta acima. Além disso, ele não pode fluir os itens da maneira que uma alvenaria real faz; por exemplo, se o 3º e o 4º item couberem na 3ª coluna, eles fariam, o vinculado não. Mas, novamente, como eu disse, tudo depende de quais são os requisitos e, neste caso (essa pergunta), não funcionará como o solicitado.