Preface:

Waterfall layout, also known as waterfall layout, is a popular way of web page layout. That is, multiple lines of elements of equal width are arranged, the following elements are successively added to the following, the same width and different heights are scaled according to the original proportion of the picture until the width meets our requirements, and then placed in the specified position according to the rules.

What is waterfall flow layout:

First look at the effect:

  • The picture is arranged with many lines of equal width elements, and the following elements are successively added to the back of the picture. The same width and different heights are scaled according to the original proportion of the picture until the width meets our requirements, and then placed in the specified position according to the rules.
  • For easy understanding, here is the HTML, CSS code

Incomplete HTML code:

<div id="container">
        <div class="box">
            <div class="box-img">
                <img src="./img/1.jpg" alt="">
            </div>
        </div>
        <div class="box">
            <div class="box-img">
                <img src="./img/2.jpg" alt="">
            </div>
        </div>
        <div class="box">
            <div class="box-img">
                <img src="./img/3.jpg" alt="">
            </div>
        </div>
     </div>.<! -- Omit the picture, how many pictures to decide -->
Copy the code

Complete CSS code

* {padding: 0;
        margin: 0;
    }
    #container{
        position: relative;
    }
    .box{
        float: left;
        padding: 15px;
    }
    .box-img {
        width: 150px;
        padding: 5px;
        border: 1px solid #ccc ;
        box-shadow: 0 0 5px #ccc;
        border-radius: 5px;
    }
    .box-img img{
        width: 100%;
        height: auto;
    }
Copy the code

How to achieve:

Simply put, if you want to achieve a waterfall flow layout, there are several things that need to be done

1. Get pictures

function getChildElemnt() {
    const contentArr = []// Define the array ready to install the diagram
    const parent = document.getElementById(container)// Get the entire page
    const allContent = parent.getElementsByTagName(The '*')// Get the entire tag
    console.log(allContent);
    for (var i = 0; i < allContent.length; i++) {
      if (allContent[i].className == 'box') {
        contentArr.push(allContent[i])// Put the class='box' label into the array}}console.log(contentArr);
    return contentArr// Return an array
 }
Copy the code

2. Set picture broadband

 var ccontent = getChildElemnt()
  var imgWidth = ccontent[0].offsetWidth// Make all images equal to the width of the first image
Copy the code

3. Calculate the maximum number of images that can be stored in a line on a browser page

var dWidth=document.documentElement.clientWidth// Page width
var num = Math.floor(dWidth/ imgWidth)
// math.floor () rounds down
Copy the code

4. Compare height

  • Because in a waterfall layout, when the first row is full, the first image in the second row should be placed below the smallest image in the first row
var BoxHeightArr = []// Define an array to place the height of each image in order
    for (var i = 0; i < ccontent.length; i++) {
      if (i < num) {
        BoxHeightArr[i] = ccontent[i].offsetHeight// Store the height of the image in the array
      } else {// When the first line has no more images to store
        var minHeight = Math.min.apply(null, BoxHeightArr)// Compare the smallest height of the previous row}}Copy the code

5. Get the position of the minimum height image in the previous row

// Define a getMinHeightLocation function, passing in all the images in the row above BoxHeightArr, and the minimum height of the image in the row above minHeight
  function getMinHeightLocation(BoxHeightArr, minHeight) {
    for (var i in BoxHeightArr) {
      if (BoxHeightArr[i] === minHeight) {// When the height of the picture equals the minimum height, the position of the picture is the position of the minimum height picture
        return i
      }
    }
  }
Copy the code

Illustration 6.

    for (var i = 0; i < ccontent.length; i++) {
    if (i < num) {
      BoxHeightArr[i] = ccontent[i].offsetHeight
    } else {
      var minHeight = Math.min.apply(null, BoxHeightArr)
      var minIndex = getMinHeightLocation(BoxHeightArr, minHeight)
      ccontent[i].style.position = 'absolute'// The image to be inserted is absolutely positioned, i.e. the position of the element is specified by the "left", "top", "right" and "bottom" attributes
      ccontent[i].style.top = minHeight + 'px'// Make the distance from the top of the inserted image equal to the height of the image below it
      ccontent[i].style.left = ccontent[minIndex].offsetLeft + 'px'// Make the distance from the image to the left of the image to be inserted exactly equal to the distance from the image below
      BoxHeightArr[minIndex] = BoxHeightArr[minIndex] + ccontent[i].offsetHeight// After inserting the image, set the height of this position to the sum of the height of the two images}}Copy the code

The complete code is as follows:

Optimize code to improve performance

window.onload = function() {
  imgLocation('container'.'box')// Constructor imgLocation
}
// Use window.onload = function() {} instead of waiting for the body page to call

// Get the current number of images to display
function imgLocation(parent, content) {// make parent='container', content='box'
  // Remove all contents under parent
  var cparent = document.getElementById(parent)
  var ccontent = getChildElemnt(cparent, content)
  var imgWidth = ccontent[0].offsetWidth
  var num = Math.floor(document.documentElement.clientWidth / imgWidth)
  cparent.style.cssText = `width: ${imgWidth * num} px`

  var BoxHeightArr = []
  for (var i = 0; i < ccontent.length; i++) {
    if (i < num) {
      BoxHeightArr[i] = ccontent[i].offsetHeight
    } else {
      var minHeight = Math.min.apply(null, BoxHeightArr)
      var minIndex = getMinHeightLocation(BoxHeightArr, minHeight)
      ccontent[i].style.position = 'absolute'
      ccontent[i].style.top = minHeight + 'px'
      ccontent[i].style.left = ccontent[minIndex].offsetLeft + 'px'
      BoxHeightArr[minIndex] = BoxHeightArr[minIndex] + ccontent[i].offsetHeight
    }
  }
  // console.log(BoxHeightArr);
}


function getChildElemnt(parent, content) {parent='container'And the content ='box'
  const contentArr = []
  const allContent = parent.getElementsByTagName(The '*')
  console.log(allContent);
  for (var i = 0; i < allContent.length; i++) {
    if (allContent[i].className == content) {
      contentArr.push(allContent[i])
    }
  }
  console.log(contentArr);
  return contentArr
}

function getMinHeightLocation(BoxHeightArr, minHeight) {
  for (var i in BoxHeightArr) {
    if (BoxHeightArr[i] === minHeight) {
      return i
    }
  }
}

Copy the code

I am a junior student in school, and I am also summarizing while learning. If there is something wrong with my writing, please comment 🙏🙏🙏