como replicar o layout de empilhamento div absoluto de pinterest.com [fechado]

104

Estou tentando replicar o layout div do Pinterest.com, especificamente como o número de colunas se ajusta para caber mais / menos no redimensionamento do navegador e o empilhamento vertical não depende da altura das colunas adjacentes. O código-fonte mostra que cada div é a posição absoluta. Um cofundador respondeu a uma postagem do Quora afirmando que isso é feito com jQuery e CSS personalizados. Eu gostaria que os resultados fossem classificados da esquerda para a direita. Qualquer orientação que você pudesse fornecer para fazer isso seria muito apreciada.

chrickso
fonte
Eu próprio codifiquei com Jquery e CSS simples. Se você quiser que isso mude no redimensionamento, basta envolvê-lo em uma função e assistir ao redimensionamento no elemento do contêiner jsfiddle.net/92gxyugb/1
Andrew WC Brown

Respostas:

79

Você também pode verificar no jQuery Plug-in Masonry , para este tipo de funcionalidade.

Prumo.
fonte
3
Biblioteca verdadeiramente incrível. Agora estou usando sem problemas.
AhmetB - Google
183

Eu escrevi o script do Pinterest. Os IDs não estão relacionados ao layout e são usados ​​para outro JS relacionado à interação. Esta é a base de como funciona:

Antecipadamente:

  • Posicione absolutamente os recipientes de pinos
  • Determine a largura da coluna
  • Determine a margem entre as colunas (a calha)

Configure uma matriz:

  • Obtenha a largura do contêiner pai; calcular o número de colunas que cabem
  • Crie uma matriz vazia, com um comprimento igual ao número de colunas. Use esta matriz para armazenar a altura de cada coluna conforme você constrói o layout, por exemplo, a altura da coluna 1 é armazenada como matriz [0]

Faça um loop em cada pino:

  • Coloque cada pino na coluna mais curta no momento em que for adicionado
  • "esquerda:" === a coluna # (matriz de índice) vezes a largura da coluna + margem
  • "top:" === O valor na matriz (altura) para a coluna mais curta naquele momento
  • Finalmente, adicione a altura do pino à altura da coluna (valor da matriz)

O resultado é leve. No Chrome, o layout de uma página inteira com mais de 50 pinos leva <10 ms.

Evan Sharp
fonte
4
O que você quer dizer com calcular a altura da coluna? Como você sabe qual deve ser a altura dele se não souber o número e a altura dos itens dentro dele? Alguma chance de você conseguir fazer o layout de algum pseudo código para demonstrar?
Michael Giovanni Pumo
22
aqui está um tutorial sólido - benholland.me/javascript/…
hollandben
1
Feedback de um usuário anonymus (encontrado na fila de edição): Curiosamente, fiz exatamente o mesmo script em jQuery, com a pequena diferença de realmente criar uma tabela com 1 linha e N colunas, e apenas anexá-los à coluna mais curta da esquerda para a direita prioridade. Mesmo que eu também tenha adicionado uma constante de "diferença de altura mínima" necessária para realmente pular uma coluna ao posicionar da esquerda para a direita, isso dá ao layout uma exibição cronologicamente intuitiva sem perder as alturas sendo tão uniformes quanto possível
oas de
1
@MichaelGiovanniPumo Acho que a altura deve ser conhecida antes do layout (no caso do Pinterest), eles não têm um estado "inicial" com divs sobrepostos. Isso não pode ser feito se a altura não for conhecida.
ptgamr
1
O link de @ hollandben está morto, novo link: benholland.me/javascript/2012/02/20/…
Lukmo
57

Lançamos um plugin jQuery porque recebemos a mesma pergunta várias vezes para Wookmark . Ele cria exatamente esse tipo de layout. Veja aqui - plugin Wookmark jQuery

GBKS
fonte
4
Esta solução parece carregar mais rápido do que a alvenaria
Michael L Watson
qual você acha melhor? o wookmark ou a alvenaria?
Ramje
Eu prefiro isso ao invés de alvenaria, parece mais rápido como Michael disse.
nerdburn
2

Tendo olhado todas as opções, acabei implementando o layout semelhante ao Pinterest desta forma:

Todos os DIVs são:

div.tile {
    display: inline-block;
    vertical-align: top;
}

Isso faz com que eles se posicionem em linhas melhor do que quando estão flutuando.

Então, quando a página é carregada, eu itero todos os DIVs em JavaScript para remover as lacunas entre eles. Funciona muito bem quando:

  1. Os DIVs não são muito diferentes em altura.
  2. Você não se importa com algumas pequenas violações de pedidos (alguns elementos que estavam abaixo podem ser puxados para cima).
  3. Você não se importa que a linha de fundo seja de altura diferente.

O benefício desta abordagem - seu HTML faz sentido para mecanismos de pesquisa, pode funcionar com JavaScript desabilitado / bloqueado por firewall, a sequência de elementos em HTML corresponde à sequência lógica (os itens mais recentes antes dos mais antigos)

esp
fonte
Ei, você poderia me dizer como você calculou o deslocamento que você teve que subtrair? E também como você resolveu o problema do último elemento estar do lado direito, porque há um elemento que é um pouco maior e empurra para lá.
Lukas Oppermann
@LukasOppermann 1) O deslocamento para o ladrilho é a soma do deslocamento do ladrilho na mesma coluna da linha anterior e a diferença entre a altura do ladrilho mais alto na linha anterior e a altura do ladrilho na mesma coluna na linha anterior. Dê uma olhada em dev.sheeporpig.com/news (primeiro você precisa clicar no link dev.sheeporpig.com/sheep/3210 para obter acesso ao site de desenvolvimento - para que você possa ver scripts descompactados e comentados em arquivos separados), arquivo de script stock_news.js, função compressTiles.
esp
@LukasOppermann 2) Se você usa CSS como resposta (especialmente display: inline-block), isso não acontece. Isso só acontece se você flutuar: deixou seus divs. Eu não uso float.
esp
0

Eles dividem entidades por colunas com ids (solução ruim ... melhor usar nomes de classes) e então calculam posições por grupos de colunas

ant_Ti
fonte
2
1 Por dar uma olhada em seu código-fonte.
Bojangles de
Foi interessante para mim, mas acho que há uma solução melhor com menos cálculos js
ant_Ti
Você poderia usar display: inline-block, suponho, mas itens de alturas verticais diferentes não se encaixariam juntos.
Bojangles de
1
melhor usar contêineres de colunas (divs com float:left;e o último com overflow: hidden;) e armazenar elementos lá
ant_Ti
4
Bom ponto. Se você realmente quisesse seguir a rota do JavaScript, poderia usar o jQuery Masonry?
Bojangles de
0

Você poderia usar flutuadores e dimensionar as larguras de div usando porcentagens junto com a largura mínima para forçar os divs a cair automaticamente quando a largura mínima for atingida? É a forma como o fizemos funcionar em http://www.goldtree.co.za/work

Eu sou Goldtree
fonte