how to replicate pinterest.com's absolute div stacking layout
Solution 1
You could also check on the jQuery Plug-in Masonry, for this kind of functionality.
Solution 2
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.
Solution 3
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
Solution 4
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:
- DIVs are not very different in height.
- You don't mind some minor violations of ordering (some elements that were below can be pulled up above).
- 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)
Related videos on Youtube
chrickso
Updated on November 17, 2020Comments
-
chrickso over 3 years
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.
-
Andrew WC Brown over 9 yearsI 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/1
-
-
Bojangles almost 13 years+1 For having a look through their source code.
-
ant_Ti almost 13 yearsIt was interesting for me but i think there is beter solution with less js calculations
-
Bojangles almost 13 yearsYou could use
display: inline-block
I suppose, but items of differing vertical height wouldn't sit together. -
ant_Ti almost 13 yearsbetter to use columns containers (divs with
float:left;
and last one withoverflow: hidden;
) and store elements there -
Bojangles almost 13 yearsGood point. If you really wanted to go the JavaScript route, you could use jQuery Masonry?
-
chrickso almost 13 yearsI'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?
-
chrickso almost 13 yearsGetting them to fit together vertically is the magic I'm after so floating/online blocks are not an option.
-
ant_Ti almost 13 years
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 posible -
Michael Giovanni Pumo almost 13 yearsHow 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?
-
hollandben over 12 yearshere's a solid tutorial - benholland.me/javascript/…
-
ahmet alp balkan about 12 yearsTruly amazing library. Now I'm using it without any problems.
-
oers about 12 yearsFeedback 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 possible
-
Michael L Watson over 11 yearsThis solution seems to load faster than masonry
-
Hanna about 11 yearsAccording to Evan Sharp the IDs are completely unrelated and this answer doesn't really help much.
-
Lukas Oppermann almost 11 yearsHey, 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.
-
esp almost 11 years@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.
-
esp almost 11 years@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.
-
Ramje almost 11 yearswhich do you find better? the wookmark or the masonry?
-
nerdburn over 10 yearsI prefer this over masonry, seems faster like Michael said.
-
ptgamr almost 10 years@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.
-
Lukmo over 9 years@hollandben's link is dead, new link : benholland.me/javascript/2012/02/20/…
-
Muhammad Umer over 8 yearshttps has expired or something