怎么实现系列:1.瀑布流布局

407 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

系列介绍

经常会被面试官问到这个怎么实现,或者怎么实现xx?

有些功能或者效果没有做过或者实现过,回答不出来,场面一度有些尴尬

于是打算出一个怎么实现系列,来实现xx功能或者xx效果,以此来提升自己的实战效果和能力。

本系列是一个开放系列,我实现的不一定是最好的,欢迎大家交流讨论

场景

面试官:你都用过什么布局?

我:我经常使用flex弹性布局

面试官:那你说下瀑布流布局怎么实现

(思考了一分钟)

我:呃...这个我没实现过

面试官:...

查阅资料

不会实现没有关系,后面马上去查阅相关资料,学习一下怎么实现瀑布流布局

什么是瀑布流

瀑布流又称瀑布流式布局,是比较流行的一种网站页面布局方式。即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片的原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置

方案一 用js来实现瀑布流

主要是利用绝对定位来实现

给父元素一个相对定位,子元素给一个绝对定位。用js计算好子元素的高度,然后再给子元素赋值left和top,从而让子元素放置到指定位置

方案二 用multi-columns来实现

multi-columns最早用来做文本的多列排列,也可以用来做瀑布流布局,实现容器内的元素按照多少列排序

主要是用到 column-count 这个css属性,控制展示多少列

方案三用flex弹性布局来实现

可以利用弹性布局的特性来实现瀑布流布局

由于我经常用弹性布局,所以我采用方案三弹性布局,来实现瀑布流布局

实现

  1. 创建一个html文件

  2. 在body里面创建一个ul标签,作为容器

    <ul class="container"></ul>
    
  1. 在body里创建要给script标签,利用js生成100个li标签

    
    <script>
                let container = document.querySelector(".container")
                let fragment = document.createDocumentFragment()
                Array.from({ length: 100 }).forEach(() => {
                    let li = document.createElement("li")
                    li.style.height = Math.ceil(Math.random() * 100) + 50 + "px"
                    fragment.appendChild(li)
                })
                container.appendChild(fragment)
    </script>
    

    这一步主要是创建一个文档片段,然后创建100个li标签,给li标签一个随机高度和一个类名,添加到文档片段里。等创建完100个li后,再一次性从文档片段添加到容器里

  2. 在head标签里添加style标签,写ul和li标签的样式

    
    <style>
                .container {
                    display: flex;
                    flex-direction: column;
                    list-style: none;
                }
                .item {
                    width: 100px;
                    background-color: orange;
                }
    </style>
    

    这时候到浏览器查看效果,发现li标签只是在一列展示,并没有排成多列。

0001.png 这是因为没有给容器一个固定高度,所以容器的高度由子元素撑开,故展示成一列

解决方法,给容器一个高度即可。

同时还要让子元素换行,通过flex-wrap: wrap; 来让子元素换行


    .container {
                    width: 1100px;
                    height: 100vh;
                    display: flex;
                    flex-direction: column;
                    flex-wrap: wrap;
                    list-style: none;
                }

再到浏览器查看效果

0002.png 发现所有元素都挤到一起了,给li元素加个margin让它挤开一点

.item {
                width: 100px;
                background-color: orange;
                margin-bottom: 5px;
                margin-right: 5px;
            }

最终效果

0003.png