how to replicate pinterest.com's absolute div stacking layout [closed]
Asked Answered
U

7

105

I am looking to replicate Pinterest.com's div layout, specifically how the number of columns adjusts to fit more/less on browser resize and the vertical stacking is not dependent on adjacent column heights. The source code shows that each div is position absolute. A co-founder has answered a Quora post stating it is done with custom jQuery and CSS. I would like the results sorted left to right. Any direction you could provide to make it myself would be greatly appreciated.

Unlade answered 18/8, 2011 at 14:46 Comment(1)
I coded my own with simple Jquery and CSS. If you want this to change on resize you just wrap it in a function and watch on resize on container element jsfiddle.net/92gxyugb/1Intracellular
B
79

You could also check on the jQuery Plug-in Masonry, for this kind of functionality.

Biannual answered 29/2, 2012 at 22:7 Comment(1)
Truly amazing library. Now I'm using it without any problems.Winglet
T
183

I wrote the Pinterest script. The ID's are unrelated to the layout, and are used for other interaction-related JS. Here's the base of how it works:

Beforehand:

  • Absolutely position the pin containers
  • Determine column width
  • Determine margin between columns (the gutter)

Setup an array:

  • Get the width of the parent container; calculate the # of columns that will fit
  • Create an empty array, with a length equaling the # of columns. Use this array to store the height of each column as you build the layout, e.g. the height of column 1 is stored as array[0]

Loop through each pin:

  • Put each pin in the shortest column at the moment it is added
  • "left:" === the column # (index array) times the column width + margin
  • "top:" === The value in the array (height) for the shortest column at that time
  • Finally, add the height of the pin to the column height (array value)

The result is lightweight. In Chrome, laying out a full page of 50+ pins takes <10ms.

Tarra answered 20/8, 2011 at 1:13 Comment(6)
How do you mean calculate the height of the column? How do you know how high it should be if you don't know the number and height of items within it? Any chance you could layout some pseudo code to demonstrate?Lithophyte
here's a solid tutorial - benholland.me/javascript/…Phalanx
Feedback from an anonymus user (found in edit queue): Curiously I did exactly the same script in jQuery, with the slight difference of actually creating a table with 1 row and N columns, and just appending them to the shortest column from left to right priority. Even though I also added a "Minimum height difference" Constant required to actually skip a column when positioning from left to right, this gives the layout a chronologically intuitive display without loosing the heights being as even as possibleIlarrold
@MichaelGiovanniPumo I think the height should be known prior to the layout (in case of Pinterest), they do not have an "initial" state which have divs overlap each other. This can not be done if height is not known.Detached
@hollandben's link is dead, new link : benholland.me/javascript/2012/02/20/…Isochor
https has expired or somethingOutstare
B
79

You could also check on the jQuery Plug-in Masonry, for this kind of functionality.

Biannual answered 29/2, 2012 at 22:7 Comment(1)
Truly amazing library. Now I'm using it without any problems.Winglet
S
56

We released a jQuery plugin because we got the same question several times for Wookmark. It creates exactly this type of layout. View it here - Wookmark jQuery plugin

Smothers answered 17/12, 2011 at 12:53 Comment(3)
This solution seems to load faster than masonryDoretheadoretta
which do you find better? the wookmark or the masonry?Nippy
I prefer this over masonry, seems faster like Michael said.Leighleigha
C
2

Having looked at all options, I ended up implementing the layout similar to Pinterest in this way:

All DIVs are:

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

This makes them position in rows better than when they are floated.

Then when the page is loaded, I iterate all DIVs in JavaScript to remove gaps between them. It works acceptably well when:

  1. DIVs are not very different in height.
  2. You don't mind some minor violations of ordering (some elements that were below can be pulled up above).
  3. You don't mind the bottom line being of different height.

The benefit of this approach - your HTML make sense for search engines, can work with JavaScript disabled/blocked by firewall, the sequence of elements in HTML matches the logical sequence (the newer items before older)

Charpoy answered 8/5, 2013 at 17:33 Comment(3)
Hey, could you tell me how you calculated the offset you had to substract? And also how did you solve the problem of the last element being on the right side, because there is one element that is a little bit bigger and pushes it there.Miun
@LukasOppermann 1) The offset for the tile is the sum of the offset for the tile in the same column in the previous row and the difference between the height of the highest tile in the previous row and the height of the tile in the same column in the previous row. Have a look at dev.sheeporpig.com/news (you first need to click on the link dev.sheeporpig.com/sheep/3210 to get access to the development site - so you can see uncompressed&commented scripts in separate files), script file stock_news.js, function compressTiles.Charpoy
@LukasOppermann 2) If you use CSS as in answer (especially display:inline-block) it doesn't happen. It only happens if you float:left your divs. I don't use float.Charpoy
S
0

They split entities by columns with ids (bad solution... better use class names) and then calculate positions by column groups

Stome answered 18/8, 2011 at 14:56 Comment(9)
+1 For having a look through their source code.Rivarivage
It was interesting for me but i think there is beter solution with less js calculationsStome
You could use display: inline-block I suppose, but items of differing vertical height wouldn't sit together.Rivarivage
better to use columns containers (divs with float:left; and last one with overflow: hidden;) and store elements thereStome
Good point. If you really wanted to go the JavaScript route, you could use jQuery Masonry?Rivarivage
I'm trying to wrap my head around what the code would look like to: on browser resize > grab the new width > determine how many columns will fit > add/remove columns > assign the next available column # to div > determine absolute position based on end of previous div in that column. Am I missing any steps? Any tutorials u could point me to for positioning divs based on browser width & retriggered on resize?Unlade
Getting them to fit together vertically is the magic I'm after so floating/online blocks are not an option.Unlade
jQuery.Masonry is the simplest way but not the best. The main idea of good frontend developer is to use less js and more css if it's posibleStome
According to Evan Sharp the IDs are completely unrelated and this answer doesn't really help much.Pythian
L
0

You could use floats and size your div widths using percentages together with min-width to force divs to automatically fall of once minimum width is reached? Its the way we got it working on http://www.goldtree.co.za/work

Ladle answered 23/5, 2012 at 19:48 Comment(0)
A
0

Why dont you try this, simple js stuff

http://vanilla-masonry.desandro.com/index.html

Or even this with jQuery and having scroll loading as well.

http://masonry.desandro.com/index.html

Amourpropre answered 24/5, 2012 at 12:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.