瀑布流布局

感觉瀑布流布局还真的是不简单...先说一下我是在慕课网上下载的源代码,读不懂的地方看一遍视频,感觉还是不错的。 首先我们先看看效果吧~


我们先仔细的看一看瀑布流的特点啊,首先有一个父容器,他是居中的,这个父容器包含这n个小容器,小容器里面装着图片。小容器有margin,padding,border,图片是等宽不等高的,中间的缝隙相等,不会出现大块的空白。

首先,我们先看html的代码

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script type="text/javascript" src="js/waterfall.js"/></script>
    <title></title>
</head>
<body>
    <div id="main">
        <div class="pin">
            <div class="box">
                ![](./images/1.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/2.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/3.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/4.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/5.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/6.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/7.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/8.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/9.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/10.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/11.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/12.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/13.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/14.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/15.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/16.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/17.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/18.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/19.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/20.jpg)
            </div>
        </div>
        <div class="pin">
            <div class="box">
                ![](./images/21.jpg)
            </div>
        </div>
    </div>
</body>
</html>

其实我们在写代码的时候完全可以不用重复这么多的,我们可以用document.createElement()来创建元素并用obj.appendChild挂载到 #main 中,所以大家不要怕代码多。可是我们发居然在小容器里面还有一个容器,这是为什么呢?现在的布局很丑很简陋,先看看吧。

裸体HTML.png

额额额,好傻。现在我们为他加上一点css。

    *{padding: 0;margin:0;}//去除浏览器自带样式
    #main{ //父容器
        position: relative;//相对定位,这里相对于body
        margin:0 auto;//左右居中
    }
    .pin{
        padding: 15px 0 0 15px;//设置上边距,左边距为15px
        float:left;//向左浮动
    }
    .box{
        padding: 10px;
        border:1px solid #ccc;
        box-shadow: 0 0 6px #ccc;//灰色阴影
        border-radius: 5px;//圆角
    }
    .box img{//给小容器里的图片设置固定宽度,高度随意
        width:162px;
        height:auto;
    }
带css的效果.png

这个时候好看了一些,但是有大片的留白,也知道了为什么小容器pin中还有一层小容器,原来是因为要在border外面在加一层边距,可是为什么不用margin还要在套一层用padding呢? 我们先不管哦、
我们再给他加一点js吧

window.onload=function(){
    waterfall('main','pin');
}
function waterfall(parent,pin){
    var oParent=document.getElementById(parent);// 父级对象
    var aPin=getClassObj(oParent,pin);// 获取存储块框pin的数组aPin
    var iPinW=aPin[0].offsetWidth;// 一个块框pin的宽
    var num=Math.floor(document.documentElement.clientWidth/iPinW);//每行中能容纳的pin个数【窗口宽度除以一个块框宽度】
    oParent.style.cssText='width:'+iPinW*num+'px;ma rgin:0 auto;';//设置父级居中样式:定宽+自动水平外边距

    var pinHArr=[];//用于存储 每列中的所有块框相加的高度。
    for(var i=0;i<aPin.length;i++){//遍历数组aPin的每个块框元素
        var pinH=aPin[i].offsetHeight;
        if(i<num){
            pinHArr[i]=pinH; //第一行中的num个块框pin 先添加进数组pinHArr
        }else{
            var minH=Math.min.apply(null,pinHArr);//数组pinHArr中的最小值minH
            var minHIndex=getminHIndex(pinHArr,minH);
            aPin[i].style.position='absolute';//设置绝对位移
            aPin[i].style.top=minH+'px';
            aPin[i].style.left=aPin[minHIndex].offsetLeft+'px';
            //数组 最小高元素的高 + 添加上的aPin[i]块框高
            pinHArr[minHIndex]+=aPin[i].offsetHeight;//更新添加了块框后的列高
        }
    }
}
//通过父级和子元素的class类 获取该同类子元素的数组    
function getClassObj(parent,className){
    var obj=parent.getElementsByTagName('*');//获取 父级的所有子集
    var pinS=[];//创建一个数组 用于收集子元素
    for (var i=0;i<obj.length;i++) {//遍历子元素、判断类别、压入数组
        if (obj[i].className==className){
            pinS.push(obj[i]);
        }
    };
    return pinS;
}
//获取 pin高度 最小值的索引index
function getminHIndex(arr,minH){
    for(var i in arr){
        if(arr[i]==minH){
            return i;
        }
    }
}
function checkscrollside(){
    var oParent=document.getElementById('main');
    var aPin=getClassObj(oParent,'pin');
    var lastPinH=aPin[aPin.length-1].offsetTop+Math.floor(aPin[aPin.length-1].offsetHeight/2);//创建【触发添加块框函数waterfall()】的高度:最后一个块框的距离网页顶部+自身高的一半(实现未滚到底就开始加载)
    var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;//注意解决兼容性
    var documentH=document.documentElement.clientHeight;//页面高度
    return (lastPinH<scrollTop+documentH)?true:false;
    //到达指定高度后 返回true,触发waterfall()函数
}

好啦,我们来看看效果

完整.png

这个时候我们知道了,为什么要多加一个小容器并且使用padding属性了,因为小容器要使用绝对定位。

最后我们在总结一下使用瀑布流布局的步骤或者说是重点。

HTML部分:

  • 创建一个父容器;
  • 在父容器内部创建n个小容器 使用同一class,比如pin
  • 在每一个小容器里面创建一个div 使用用一个class,比如class

CSS部分:

  • 父容器使用绝对布局并居中
  • 小容器设置上左的内边距padding并向左浮动
  • 小容器里的可以写一些美化的东西:比如padding border box-shadow reduis等
  • 给div内部的图片设置固定宽度

JavaScript部分:

  • 获取小容器的宽度,用可视区域的宽度/小容器的宽度
  • 给小容器一个绝对位置并且赋值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容