How to implement waterfall layout with native js?
Concept:
Waterfall flow, also known as waterfall flow layout. It is a relatively popular website page layout, which is visually represented as an uneven multi column layout. As the page scrolls downward, this layout will also constantly load data blocks and attach them to the current tail. The earliest website adopting this layout is Pinteres, which has gradually become popular in China. Most domestic fresh stations are basically of this style.
Layout features:
-
Dazzling: the whole page is dominated by pictures, and pictures of different sizes are arranged according to certain rules.
-
Aestheticism: the style of pictures is mainly aestheticism.
-
Simple operation: when browsing the website, you just need to slide the mouse wheel slightly, and all the wonderful pictures can be presented in front of you.
Application scenario:
-
For example, the following figure is Suning's official website
-
For example, the following figure: website layout
Principle:
The waterfall layout is characterized by equal width and unequal height. In order to minimize the gap in the last line, you need to place the picture below the shortest picture in the first line from the second line, and so on. The parent element is set to relative positioning, and the element where the picture is located is set to absolute positioning. Then locate each element by setting the top and left values.
To put it simply:
-
Fix the width of the picture, divide the size of the browser window by the width of each picture, and find the number of columns to be divided
-
Position each picture
-
Each time the column with the minimum height is found, the picture is added to the column
Process oriented - specific code:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Process oriented: simulating waterfall flow</title> <style> * { margin: 0; padding: 0; } .box { width: 600px; margin: 0 auto; border: 1px solid #000; position: relative; } .box>div { width: 100px; border: 1px solid pink; box-sizing: border-box; position: absolute; } </style> </head> <body> <div class="box"> </div> <script> // Waterfall core: // 1. Fix the width of the picture, divide the size of the browser window by the width of each picture, and find the number of columns to be divided // 2. Position each picture // 3. Each time the column with the minimum height is found, add the picture to the column var box = document.querySelector('.box'); // Function to generate random numbers: get a random integer between two numbers (excluding the maximum and minimum values) function rdNum(min, max) { return Math.ceil(Math.random() * (max - min)) + min } // Encapsulation function: to obtain the minimum value in the array function getMin(abc) { return Math.min.apply(null, abc); } // Record the height of each element in each column var arr = [0, 0, 0, 0]; // Dynamically generate random height, go to the smallest column in the array, and add up the numbers for (var i = 0; i < 20; i++) { // Get the minimum value in each column array var minVal = getMin(arr); // Gets the index of the minimum value of the array for each column var index = arr.findIndex(function(item, index) { return item === minVal; }); // Generate a random number --- that is, the height of each div var randomNum = rdNum(40, 150); // Dynamically create div Tags var div = document.createElement('div'); // The content of div is index div.innerText = i; // box width var boxWidth = box.offsetWidth; console.log(boxWidth); // Set the height of div div.style.height = randomNum + 'px'; console.log(div.style.height); // Set the distance from each div to the left div.style.left = index * (((boxWidth - 4 * 100) / (4 - 1)) + 100) + 'px'; // The distance to the top is the minimum value of each column div.style.top = minVal + 'px'; box.appendChild(div); // The random number is added to the array element of the smallest column in the array arr[index] += randomNum; //randomNum: the height of each div / / index: the index to get the minimum value of the array in each column / / arr[index] is the value of the minimum array element in each column console.log(arr) } box.style.height = Math.max.apply(null, arr) + 'px' </script> </body> </html>
Object oriented - specific code:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Object oriented: simulating waterfall flow</title> <style> * { margin: 0; padding: 0; } .box { width: 600px; margin: 0 auto; border: 1px solid red; position: relative; } .box>div { border: 1px solid orange; box-sizing: border-box; position: absolute; } .container { width: 800px; margin: 100px auto; border: 1px solid #000; } .container>div { border: 1px solid orange; box-sizing: border-box; } </style> </head> <body> <div class="box"></div> <div class="container"></div> <script> function Pubu(obj) { this.box = document.querySelector(obj.el); this.column = obj.column; this.width = obj.width; this.show(); } Pubu.prototype.rdNum = function(max, min) { return Math.ceil(Math.random() * (max - min)) + min; } Pubu.prototype.getMin = function(abc) { return Math.min.apply(null, abc); } Pubu.prototype.getIndex = function(abc, def) { return abc.findIndex(function(item) { return item === def; }) } Pubu.prototype.createDv = function(i, randomNum, index, minVal) { var dv = document.createElement('div'); dv.innerText = i; dv.style.width = this.width + 'px'; dv.style.position = 'absolute'; dv.style.height = randomNum + 'px'; dv.style.left = index * ((this.box.offsetWidth - this.width * this.column) / (this.column - 1) + this.width) + 'px'; dv.style.top = minVal + 'px'; this.box.appendChild(dv); } Pubu.prototype.show = function() { this.box.style.position = 'relative'; var arr = new Array(this.column); arr.fill(0); for (var i = 0; i < 20; i++) { var minVal = this.getMin(arr); var index = this.getIndex(arr, minVal); var randomNum = this.rdNum(40, 150); this.createDv(i, randomNum, index, minVal); arr[index] += randomNum; this.box.style.height = Math.max.apply(null, arr) + 'px'; } } new Pubu({ el: '.box', column: 4, width: 110 }) new Pubu({ el: '.container', column: 7, width: 100 }) </script> </body>
- design sketch: