Three Ways to Realize Waterfall Flow Layout
- 2021-07-18 06:47:32
- OfStack
Use javascript, jquery, css to implement waterfall flow layout:
Method 1: Use JavaScript:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Waterfall flow layout </title>
<style>
*{padding:0;margin:0;}
.clearfix:after,
.clearfix:before {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
.main {
position: relative;
-webkit-column-width: 210px;
-moz-column-width: 210px;
-webkit-column-gap: 5px;
-moz-column-gap: 5px;
}
.box {
float: left;
padding: 15px 0 0 15px;
}
.box .pic {
width: 180px;
height: auto;
padding: 10px;
border-radius: 5px;
box-shadow: 0 0 5px #cccccc;
border: 1px solid #cccccc;
}
.box .pic img {
display: block;
width: 100%;
}
</style>
</head>
<body>
<div class="main clearfix" id="main">
<div class="box">
<div class="pic"><img src="./images/0.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/1.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/2.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/3.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/4.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/5.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/6.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/7.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/8.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/9.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/10.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/11.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/12.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/13.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/14.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/15.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/16.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/17.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/18.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/19.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/20.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/21.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/22.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/23.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/24.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/25.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/26.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/27.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/28.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/29.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/25.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/26.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/27.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/28.jpg"></div>
</div>
<div class="box">
<div class="pic"><img src="./images/29.jpg"></div>
</div>
</div>
<script>
window.onload = function(){
waterfall('main','box');
// Simulation json Data
var dataJson = {'data': [{'src':'30.jpg'},{'src':'31.jpg'},{'src':'32.jpg'},{'src':'33.jpg'},{'src':'34.jpg'},{'src':'35.jpg'},{'src':'36.jpg'},{'src':'37.jpg'},{'src':'38.jpg'},{'src':'39.jpg'},{'src':'40.jpg'},{'src':'41.jpg'},{'src':'42.jpg'},{'src':'43.jpg'},{'src':'44.jpg'},{'src':'45.jpg'}]};
// Eavesdropping scroll Events
window.onscroll = function(){
var isPosting = false;
if(checkScollSlide('main','box') && !isPosting){
var oParent = document.getElementById('main');
for(var i in dataJson.data){
isPosting = true;
var oBox = document.createElement('div');
oBox.className = 'box';
oBox.innerHTML = '<div class="pic"><img src="./images/'+dataJson.data[i].src+'"></div>';
oParent.appendChild(oBox);
}
isPosting = false;
waterfall('main','box');
}
}
}
/*
* parent Parent element id clsName Block element class */
function waterfall(parent,clsName){
// Get the parent element
var oParent = document.getElementById(parent),
// Get all box
aBoxArr = oParent.getElementsByClassName(clsName),
// Single box Width
iBoxW = aBoxArr[0].offsetWidth,
// Number of columns
cols = Math.floor(document.documentElement.clientWidth / iBoxW);
oParent.style.cssText = 'width:'+iBoxW*cols+'px;margin:0 auto;';
// Store all heights
var hArr = [];
for(var i = 0; i < aBoxArr.length; i++){
if(i < cols){
hArr[i] = aBoxArr[i].offsetHeight;
}else{
// Get hArr Minimum value
var minH = Math.min.apply(null,hArr),
// hArr Minimum value index index
minHIndex = getMinHIndex(hArr,minH);
aBoxArr[i].style.cssText = 'position:absolute;top:'+minH+'px;left:'+aBoxArr[minHIndex].offsetLeft+'px;';
// Update after adding elements hArr
hArr[minHIndex] += aBoxArr[i].offsetHeight;
}
}
}
// Get the minimum value index
function getMinHIndex(arr,val){
for(var i in arr){
if(arr[i] == val){
return i;
}
}
}
// Check whether the loading data conditions are met ,parent Parent element id clsName Block element class
function checkScollSlide(parent,clsName){
var oParent = document.getElementById(parent),
aBoxArr = oParent.getElementsByClassName(clsName),
// Finally 1 A box Element's offsetTop+ Highly 1 Half
lastBoxH = aBoxArr[aBoxArr.length - 1].offsetTop + aBoxArr[aBoxArr.length - 1].offsetHeight / 2,
// Compatible js Standard mode and hybrid mode
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
height = document.documentElement.clientHeight || document.body.clientHeight;
return lastBoxH < scrollTop + height ? true : false;
}
</script>
</body>
</html>
Mode 2: Use jquery: (html structure is the same as css)
$( window ).on( "load", function(){
waterfall('main','box');
// Analog data json
var dataJson = {'data': [{'src':'30.jpg'},{'src':'31.jpg'},{'src':'32.jpg'},{'src':'33.jpg'},{'src':'34.jpg'},{'src':'35.jpg'},{'src':'36.jpg'},{'src':'37.jpg'},{'src':'38.jpg'},{'src':'39.jpg'},{'src':'40.jpg'},{'src':'41.jpg'},{'src':'42.jpg'},{'src':'43.jpg'},{'src':'44.jpg'},{'src':'45.jpg'}]};
window.onscroll=function(){
var isPosting = false;
if(checkscrollside('main','box') && !isPosting){
isPosting = true;
$.each(dataJson.data,function(index,dom){
var $box = $('<div class="box"></div>');
$box.html('<div class="pic"><img src="./images/'+$(dom).attr('src')+'"></div>');
$('#main').append($box);
waterfall('main','box');
isPosting = false;
});
}
}
});
/*
parend Parent id
clsName Element class
*/
function waterfall(parent,clsName){
var $parent = $('#'+parent);// Parent element
var $boxs = $parent.find('.'+clsName);// All box Element
var iPinW = $boxs.eq( 0 ).width()+15;// 1 Block box box Width of
var cols = Math.floor( $( window ).width() / iPinW );// Number of columns
$parent.width(iPinW * cols).css({'margin': '0 auto'});
var pinHArr=[];// Used for storage The height of all block boxes in each column.
$boxs.each( function( index, dom){
if( index < cols ){
pinHArr[ index ] = $(dom).height(); // Heights of all columns
}else{
var minH = Math.min.apply( null, pinHArr );// Array pinHArr The minimum value in minH
var minHIndex = $.inArray( minH, pinHArr );
$(dom).css({
'position': 'absolute',
'top': minH + 15,
'left': $boxs.eq( minHIndex ).position().left
});
// Modify after adding elements pinHArr
pinHArr[ minHIndex ] += $(dom).height() + 15;// Update column height after adding block box
}
});
}
// Check whether the loading data condition is met, that is, trigger the add block box function waterfall() Height: Last 1 The distance between the block box and the top of the web page + Self-high 1 Half ( Implementation starts loading before rolling through )
function checkscrollside(parent,clsName){
// Finally 1 Block box
var $lastBox = $('#'+parent).find('.'+clsName).last(),
lastBoxH = $lastBox.offset().top + $lastBox.height()/ 2,
scrollTop = $(window).scrollTop(),
documentH = $(document).height();
return lastBoxH < scrollTop + documentH ? true : false;
}
The third way: use css: (html structure is the same as above)
.clearfix:after,
.clearfix:before {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
.main {
position: relative;
[color=#ff0000]-webkit-column-width: 210px;
-moz-column-width: 210px;
-webkit-column-gap: 5px;
-moz-column-gap: 5px;[/color]
}
.box {
float: left;
padding: 15px 0 0 15px;
}
.box .pic {
width: 180px;
height: auto;
padding: 10px;
border-radius: 5px;
box-shadow: 0 0 5px #cccccc;
border: 1px solid #cccccc;
}
.box .pic img {
display: block;
width: 100%;
}
Comparison of waterfall flow implementation methods;
Javascript native mode/jquery mode
1. Need to calculate, the number of columns = browser window width/picture width, and the picture positioning is to calculate the position of the picture according to the height of each column;
2. The picture sorting is arranged horizontally according to the calculated position of the picture, and the position is calculated, which is relatively standard
Css mode
1. No calculation is needed, the browser automatically calculates, only the column width needs to be set, and the performance is high;
2. The column width changes with the browser window size, and the user experience is not good;
3. The pictures are sorted in vertical order, disrupting the display order of pictures;
4. Picture loading still depends on javascript/jquery