Knowledge is endless, but why do we still have to keep learning it. The reason is very simple, because we want to produce more knowledge, so that more people can not finish learning! Front-end technology is constantly innovating, we want to do that let others have endless knowledge of the people!
1. What is waterfall flow?
Waterfall, also known as waterfall layout, is a popular web layout that visually presents a jagged, multi-column layout that loads chunks of data and appends them to the end of the page as the scroll bars scroll down. This layout is common on some image-based sites, such as some common sites:
From the above two pictures, we can easily understand what waterfall layout is. We can see that the height of each picture is different, but their width is uniform, and the gap between each picture is even.
The characteristics of waterfall flow layout are summarized as follows:
- The width of the content box is fixed, but the height is not.
- Content boxes are arranged from left to right, and when one row is full, the remaining content boxes are placed in order behind the shorter column.
2. Why waterfall flow layout
1. Attract users
When viewing a waterfall layout (not lazy loading here), users get the illusion that information is constantly being updated, which triggers their curiosity and keeps them sliding down.
2. Good visual experience
Waterfall flow layout can break the conventional site layout layout, give users a bright sense of freshness, users will feel very fresh when browsing content, bring a good visual experience.
3. Better adapt to mobile terminals
Because mobile devices have smaller screens than computers, one screen doesn’t display much content, so you may have to turn pages a lot. A waterfall layout allows users to scroll through content. (This is a bit like lazy loading)
3. Implementation principle
We have summarized two characteristics of waterfall flow layout:
- The width of the content box is fixed, but the height is not.
- Content boxes are arranged from left to right, and when one row is full, the remaining content boxes are placed in order behind the shorter column.
Then it is not difficult to figure out its implementation principle according to the two characteristics:
First we calculated a line can accommodate a few columns elements (because we need to browsing on a different device), and then by comparing calculation to find out a list of minimizing the sum of this column elements in height, and then the next line of minimizing the sum of the first element added to the height of the column below, then continue to calculate all column height of minimizing the sum of the column, You then continue adding new elements to the column with the smallest sum of heights until all elements are added.
May rao such a long paragraph or some small partners do not understand, we still look at the picture to speak, this is the easiest to understand;
(1) First let’s put a line
(2) Find the smallest column of the sum of the heights of all the elements and add new elements below that column
(3) Then continue to calculate, obtain the column with the smallest sum of heights, and continue to add new elements in that column
After looking at these pictures, it is clear that there is a lot of calculation, constantly adding new elements, until all elements are added. But we all know that some elements are block-level elements, so one element occupies a row, and there’s a little guy here who thinks, well, we can float, right? Let’s keep experimenting.
Now that you understand how the waterfall flow layout is implemented, let’s write some concrete code to implement it.
4. Implementation steps and methods
1. Create a floating layout
First let’s add some
Left floatingGive these separately
Layout set by left float
This is the layout set by the left float, and we can see that in the second row, the seventh box float is positioned according to the third box. On the third line, the seventh box blocked the tenth box, so we couldn’t finish the layout.
2. Locate the device
We have already known that floating layout can not meet our needs, so we seek another way of layout, that is, through positioning, after setting positioning attributes for each box, we can dynamically set the corresponding top and left values to make the boxes orderly arranged for us.
(1) Add relative positioning attributes to the parent elements of all boxes, and add absolute positioning attributes to all boxes:
Position: relative; Position: absolute;Copy the code
(2) After positioning, the interface we get is like this:
(3) How to determine the number of columns in a row:
Since the width of our interface is changing, the number of columns needs to change as well. The principle of dynamically setting the number of columns is roughly as follows:
1. Obtain the page width
2. Get the width of each box
3. Number of columns to display = page width/box width
** Note: ** Usually there is a gap between the boxes, so our formula becomes as follows:
Column = pageWidth/itemWidth + Gap
Arrange the first row
-
We have a lot of boxes, too many boxes for us to manage, so we put all the boxes in an array arR, starting at zero, with I for boxes. So how do we know if this box should be in the first row. The for loop must be in the first row when ** I (index of all boxes) <column (number of columns displayed) **. For example, if we have five boxes in a row, the fifth box will have an index of 4, and since 4 is less than 5, it will be in the first row, and if the index is 6, and since 6 is greater than 5, it will be in the second row. That’s basically what the code looks like
If (I < columns) {// Determine the first row items[I].style. Top = 0; items[i].style.left = (itemWidth + gap) * i + ‘px’; }
-
Knowing that the boxes are in line 1, we just need to set the left value of the boxes dynamically.
-
Left = I *(itemWidth+gap) left= I *(itemWidth+gap) left= I *(itemWidth+gap)
Having said that, let’s draw a picture to understand:
(5) Obtain the height sum of all columns
- After the first row is sorted, we need to arrange the second row, but we need to use the top value for the second row. As mentioned in the previous principle, we just arrange by the minimum sum of the heights of each column, so here we need to calculate the sum of the heights of all columns in the first row and save it.
- We define an array arR to hold the height.
We need to get the height as soon as the page enters, that is, write it in onload, because the loading characteristic of the image is: wait until the page is loaded, so if it is not written in the entry function, it may not get the height.
(6) Arrange the second row
- Get the smallest column in the array, and place the
2
The first1
A box is placed beneath it; - At this time
left
The value is the lowest column of heightoffsetLeft
;top
Value is the first1
Row height Height of the smallest column (upper and lower gaps can be added for aesthetic layoutgap
). - Record the index of the smallest height column
index
, will be used later in the calculation; - After setting this, you will find that all the following boxes are stacked below the minimum column height. The reason is that the minimum column height has not changed, and the height of the box below should be added to create a new height. We need to recalculate the minimum height of all columns after adding a box to the minimum column.
Look at the picture: We see all the other boxes under and below the sixth box.
(7) Re-obtain the height of the minimum height column
- After the first box in the second row, the minimum height column has changed and we need to recalculate
- Height of minimum column of current height = height of minimum column of current height + gap + height of box of picture below
Now you see why we keep index.
(8) Set it as responsive
- Encapsulate the entire styling part into a function that registers a resize event in onLoad to trigger the styling part of the code whenever the page changes.
Change the width of pageWidth in real time so that the waterfall stream is a responsive effect
(9) add lazy loading effect
Lazy loading implementation principle can refer to my last article, said very clearly detailed. The general principle is illustrated by a diagram:
(X) All code (not including lazy loading code)
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, < span style> * {margin: 0; max-width: 100%; clear: both; padding: 0; } .item { float: left; display: flex; justify-content: center; align-items: center; font-size: 30px; font-weight: 700; color: aliceblue; margin-right: 15px; margin-bottom: 15px; width: 205px; position: absolute; } .item-1 { background-color: rgb(206, 169, 169); height: 300px; }.item-2 { background-color: rgb(131, 226, 174); height: 150px; }.item-3 { background-color: rgb(77, 30, 30); height: 350px; }.item-4 { background-color: rgb(49, 62, 134); height: 300px; }.item-5 { background-color: rgb(230, 99, 99); height: 200px; }.item-6 { background-color: rgb(206, 169, 169); height: 300px; }.item-7 { background-color: rgb(124, 126, 145); height: 400px; }.item-8 { background-color: rgb(169, 199, 38); height: 230px; }.item-9 { background-color: rgb(114, 128, 53); height: 300px; }.item-10 { background-color: rgb(48, 54, 18); height: 260px; }.item-11 { background-color: rgb(118, 122, 96); height: 230px; }.item-12 { background-color: rgb(118, 122, 96); height: 240px; }.item-13 { background-color: rgb(118, 122, 96); height: 250px; }.item-14 { background-color: rgb(118, 122, 96); height: 270px; }.item-15 { background-color: rgb(118, 122, 96); height: 330px; }.item-16 { background-color: rgb(118, 122, 96); height: 200px; }.item-17 { background-color: rgb(118, 122, 96); height: 100px; }.item-18 { background-color: rgb(118, 122, 96); height: 400px; }.item-19 { background-color: rgb(118, 122, 96); height: 340px; }.item-20 { background-color: rgb(118, 122, 96); height: 350px; }.item-21 { background-color: rgb(118, 122, 96); height: 360px; }.item-22 { background-color: rgb(118, 122, 96); height: 370px; } </style> </head> <body> <div id="box"> <div class="item item-1">1</div> <div class="item item-2">2</div> <div class="item item-3">3</div> <div class="item item-4">4</div> <div class="item item-5">5</div> <div class="item item-6">6</div> <div class="item item-7">7</div> <div class="item item-8">8</div> <div class="item item-9">9</div> <div class="item item-10">10</div> <div class="item item-11">11</div> <div class="item item-12">12</div> <div class="item item-13">13</div> <div class="item item-14">14</div> <div class="item item-15">15</div> <div class="item item-16">16</div> <div class="item item-17">17</div> <div class="item item-18">18</div> <div class="item item-19">19</div> <div class="item item-20">20</div> <div class="item item-21">21</div> <div class="item item-22">22</div> </div> </body> <script> var items = document.getElementsByClassName('item'); Var gap = 10; Onload = function () {waterFall(); } function waterFall() {var pageWidth = getClient().width; var itemWidth = items[0].offsetWidth; var columns = parseInt(pageWidth / (itemWidth + gap)); var arr = []; For (var I = 0; i < items.length; I ++){if(I < columns) {items[I].style. Top = 0; items[i].style.left = (itemWidth + gap) * i + 'px'; arr.push(items[i].offsetHeight); Var minHeight = arr[0]; var minHeight = arr[0]; var index = 0; for(var j = 0; j < arr.length; If (minHeight > arr[j]){minHeight = arr[j]; index = j; Top = gap items[I].style. Top = arr[index] +gap + 'px'; items[i].style.left = items[index].offsetLeft + 'px'; Arr [index] = arr[index] + items[I]. OffsetHeight + gap; Onresize = function () {waterFall(); Function getClient() {return {width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, height: Window. The innerHeight | | document. DocumentElement. ClientHeight | | document. The body. The clientHeight}} / / scrollTop compatibility processing function getScrollTop() { return window.pageYOffset || document.documentElement.scrollTop; } </script> </html>Copy the code
** Note: ** If you want to add lazy loading effect, you can refer to my previous article, which is more detailed, because there is no in
5. To summarize
Here, our waterfall flow layout layout is also finished, talk about the process is more wordy, but also in order to let more people can easily understand. From the overall implementation point of view, we have two main priorities:
-
Waterfall layout uses positioning to dynamically change the top and left values of elements.
-
Gets the column of the minimum height sum and saves its index so that the element in the next row knows where to put it.
6. The source code
For more source code, visit GitHub: Javascript