## 原生实现
```html
<!DOCTYPE html>
<html lang="zh-CN">
<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>瀑布流</title>
<style>
ul {
position: relative;
margin: 0 auto;
width: 500px;
}
li {
position: absolute;
width: 240px;
list-style: none;
background-color: #FCC;
}
li:nth-of-type(2n) {
background-color: #FFC;
}
li:nth-of-type(3n) {
background-color: #CCF;
}
li:nth-of-type(4n) {
background-color: #CFF;
}
</style>
</head>
<body>
<div>
<ul>
<li style="height: 400px;"></li>
<li style="height: 1200px;"></li>
<li style="height: 100px;"></li>
<li style="height: 200px;"></li>
<li style="height: 700px;"></li>
<li style="height: 320px;"></li>
<li style="height: 500px;"></li>
<li style="height: 100px;"></li>
<li style="height: 900px;"></li>
<li style="height: 320px;"></li>
</ul>
</div>
</body>
<script>
(function (colSpace = 20, bottomSpace = 20) {
// 外层容器
const container = document.querySelector("ul");
// 所有待整理的块
const blocks = document.querySelectorAll("li");
// 块宽度
const blockWidth = (function () {
if (window.getComputedStyle) {
return (parseFloat(getComputedStyle(container, null).width) - colSpace) / 2;
} else {
return (parseFloat(container.currentStyle.width) - colSpace) / 2;
}
})();
let leftHeight = 0;
let rightHeight = 0;
function setToLeft(/** @type {HTMLElement} */ e) {
let sty;
if (window.getComputedStyle) {
sty = getComputedStyle(e, null);
} else {
sty = e.currentStyle;
}
e.style.left = '0px';
e.style.top = leftHeight + 'px';
leftHeight += (parseFloat(sty.height) + bottomSpace);
}
function setToRight(/** @type {HTMLElement} */ e) {
let sty;
if (window.getComputedStyle) {
sty = getComputedStyle(e, null);
} else {
sty = e.currentStyle;
}
e.style.left = (parseFloat(sty.width) + colSpace) + 'px';
e.style.top = rightHeight + 'px';
rightHeight += (parseFloat(sty.height) + bottomSpace);
}
blocks.forEach(function (e, index) {
console.log(leftHeight, rightHeight);
if (leftHeight <= rightHeight) {
setToLeft(e);
} else {
setToRight(e);
}
if (leftHeight >= rightHeight) {
container.style.height = leftHeight + 'px';
} else {
container.style.height = rightHeight + 'px';
}
})
})();
</script>
</html>
```
## 原生瀑布流实战
```html
<!DOCTYPE html>
<html lang="zh-CN">
<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>瀑布流实战</title>
<style>
* {
margin: 0;
padding: 0;
}
#app {
position: relative;
margin: 0 auto;
width: 90%;
}
li {
display: block;
width: 100%;
list-style: none;
}
li img {
display: block;
width: 100%;
}
</style>
</head>
<body>
<div id="app">
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/Plu5bckpgsOiXBG.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/3wNeMhUq2ayWds7.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/Iup7gHNKPx5GTjq.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/AJy15ouHpjOxIvg.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/Plu5bckpgsOiXBG.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/Plu5bckpgsOiXBG.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/3wNeMhUq2ayWds7.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/Iup7gHNKPx5GTjq.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/AJy15ouHpjOxIvg.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/Plu5bckpgsOiXBG.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/AJy15ouHpjOxIvg.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/Plu5bckpgsOiXBG.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/3wNeMhUq2ayWds7.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/AJy15ouHpjOxIvg.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/Plu5bckpgsOiXBG.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/Iup7gHNKPx5GTjq.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/3wNeMhUq2ayWds7.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/Iup7gHNKPx5GTjq.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/AJy15ouHpjOxIvg.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/Plu5bckpgsOiXBG.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/Iup7gHNKPx5GTjq.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/AJy15ouHpjOxIvg.jpg" /></li>
</ul>
<ul class="block">
<li><img data-src="https://s2.loli.net/2022/01/27/3wNeMhUq2ayWds7.jpg" /></li>
<li><img data-src="https://s2.loli.net/2022/01/27/AJy15ouHpjOxIvg.jpg" /></li>
</ul>
</div>
</body>
<script>
/**
*
* @param {Number} col 瀑布流设置多少列
* @param {Number} ccolSpace 每列之间空多少位置
* @param {Number} bottomSpace 每一个块底部留多少位置
*
*/
function waterfall(col = innerWidth < 1145 ? 2 : 3, colSpace = 20, bottomSpace = 20) {
// 外层容器
const container = document.querySelector("#app");
// 所有待整理的块
const blocks = document.querySelectorAll(".block");
// 块宽度
const blockWidth = (function () {
if (window.getComputedStyle) {
return (parseFloat(getComputedStyle(container, null).width) - (colSpace * (col - 1))) / col;
} else {
return (parseFloat(container.currentStyle.width) - (colSpace * (col - 1))) / col;
}
})();
// 存放每一列的高度
const heights = [];
for (let i = 0; i < col; i++) {
// 每一列初始赋值0
heights[i] = 0;
}
// 设置块的位置
function setLocation(/** @type {HTMLElement} */ e, /** @type {Number} */ colNumber) {
/** @type {CSSStyleDeclaration} */
var sty;
// 兼容性样式获取写法
if (window.getComputedStyle) {
sty = getComputedStyle(e, null);
} else {
sty = e.currentStyle;
}
// 设置块的left、top、width
e.style.cssText = `position: absolute; left: ${(blockWidth + colSpace) * colNumber}px; top: ${heights[colNumber]}px; width: ${blockWidth}px;`;
// 累加列的高度
heights[colNumber] += (parseFloat(sty.height) + bottomSpace);
}
blocks.forEach(function (e, index) {
// 在数组中寻找最低高度所对应的列
let isi = heights.findIndex(function (n) {
// 获取所有列中最低的高度
return n == Math.min(...heights);
});
// 传入要设置位置的块,以及要设置到的列数
setLocation(e, isi);
});
container.style.height = Math.max(...heights) + 'px';
};
window.onload = function () {
const imgs = document.querySelectorAll('#app img');
let count = 0;
Array.from(imgs).forEach((/** @type {HTMLImageElement} */ img, index, arr) => {
img.src = img.dataset.src;
img.addEventListener('load', function () {
count++;
if (count == arr.length) {
waterfall(4);
}
})
})
}
</script>
</html>
```
这种图片加载方式还挺暴力的,可以使用[imagesloaded](https://github.com/desandro/imagesloaded)这个库。
[学习,记录] 原生JS实现瀑布流