首页 > 代码库 > CSS3与页面布局学习总结——多种页面布局

CSS3与页面布局学习总结——多种页面布局

一、负边距与浮动布局

1.1、负边距

所谓负边距就是margin取负值的情况,如margin:-40px;margin-left:-100%。当一个元素与另一个元素margin取负值时将拉近距离。常见用法如下:

1.1.1、向上移动

当多个元素同时从标准流中脱离开来时,如果前一个元素的宽度为100%宽度,后面的元素通过负边距可以实现上移。当负的边距超过自身的宽度将上移,只要没有超过自身宽度就不会上移,示例如下:

示例代码:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>负边距</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
            
            #div1 {
                height: 100px;
                background: lightblue;
                width: 100%;
                float: left;
            }
            
            #div2 {
                height: 100px;
                background: lightgreen;
                width: 30%;
                float: left;
                margin-left: -100%;
            }
        </style>
    </head>

    <body>
        <div id="div1">div1
        </div>
        <div id="div2">div2
        </div>
    </body>

</html>

div2的margin-left:-29%时的运行结果:

技术分享

div2的margin-left:-30%(为自己自身宽度)时的运行结果:

技术分享

 div2的margin-left:-100%时的运行结果:

技术分享

1.1.2、去除列表右边框

开发中常需要在页面中展示一些列表,如商品展示列表等,如果我们要实现如下布局:

技术分享

示例代码:

技术分享
<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>负边距</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
            
            #div1 {
                width: 800px;
                margin: 0 auto;
                border: 3px solid lightblue;
                overflow: hidden;
                margin-top: 10px;
            }
            
            .box {
                width: 180px;
                height: 180px;
                margin: 0 20px 20px 0;
                background: lightgreen;
                float: left;
            }
        </style>
    </head>

    <body>
        <div id="div1">
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
        </div>
    </body>

</html>
View Code

运行结果:

技术分享

但是上面的效果中右边多出了20px的距离,底下多出20px空白,解决方法如下:将包裹在外层最近的div的右边距赋值为-20px(margin-right:20px),同时最外层div的宽度也要减去多出的那20px(从800px变为780px),下面多出的20px则给div的高度设小20px即可,代码如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>负边距</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
            #div1 {
                width: 780px;
                height: 380px;
                margin: 0 auto;
                border: 3px solid lightblue;
                overflow: hidden;
                margin-top: 10px;
            }
            .box {
                width: 180px;
                height: 180px;
                margin: 0 20px 20px 0;
                background: lightgreen;
                float: left;
            }
            #div2{
                margin-right: -20px;
            }
        </style>
    </head>
    <body>
        <div id="div1">
            <div id="div2">
                <div class="box">
                </div>
                <div class="box">
                </div>
                <div class="box">
                </div>
                <div class="box">
                </div>
                <div class="box">
                </div>
                <div class="box">
                </div>
                <div class="box">
                </div>
                <div class="box">
                </div>
            </div>
        </div>
    </body>
</html>

方法是使用了边距折叠,基本原理如下图所示:

技术分享

1.1.3、负边距+定位,实现水平垂直居中

具体参考前面的随笔:多种垂直居中的办法

1.1.4、去除列表最后一个li元素的border-bottom

 技术分享

方法一:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>负边距</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
                list-style: none;
            }
            #news {
                width: 200px;
                border: 2px solid lightblue;
                margin: 20px 0 0 20px;
            }
            
            #news li{
                height: 26px;
                line-height: 26px;
                border-bottom: 1px dashed   lightblue;
            }
            .lastLi{
                margin-bottom:-1px ;
            }
        </style>
    </head>
    <body>
        <div id="news">
            <ul>
                <li>Item A</li>
                <li>Item B</li>
                <li>Item C</li>
                <li>Item D</li>
                <li class="lastLi">Item E</li>
            </ul>
        </div>
    </body>
</html>

技术分享

方法二:

使用CSS3中的新增加选择器,选择最后一个li,不使用类样式,好处是当li的个数不确定时更加方便。

如果li的border-bottom颜色与ul的border颜色是一样的时候,在视觉上是被隐藏了。如果其颜色不一致的时候还是有问题,给ul写个overflow:hidden;就可以解决这个问题。

1.2、双飞翼布局

经典三列布局,也叫做圣杯布局【Holy Grail of Layouts】是Kevin Cornell在2006年提出的一个布局模型概念,在国内最早是由淘宝UED的工程师传播开来,在中国也有叫法是双飞翼布局,它的布局要求有几点:

1、三列布局,中间宽度自适应,两边定宽; 
2、中间栏要在浏览器中优先展示渲染; 
3、允许任意列的高度最高;
4、要求只用一个额外的DIV标签; 
5、要求用最简单的CSS、最少的HACK语句;

在不增加额外标签的情况下,圣杯布局已经非常完美,圣杯布局使用了相对定位,以后布局是有局限性的,而且宽度控制要改的地方也多。在淘宝UED(User Experience Design)探讨下,增加多一个div就可以不用相对布局了,只用到了浮动和负边距,这就是我们所说的双飞翼布局,实现的代码如下:

技术分享
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>双飞翼布局</title>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
            html,body{
                height: 100%;
                font-size: 30px;
                color: white;
            }
            #container{
                width: 90%;
                margin: 0 auto;
                height: 100%;
            }
            #header,#footer{
                height: 12.5%;
                background: lawngreen;
            }
            #main{
                height: 75%;
            }
            #center,#left,#right{
                height: 100%;
                float: left;
            }
            #center{
                width: 100%;
                background: lightblue;
            }
            #left{
                background: palegreen;
                width: 20%;
                margin-left: -100%;
            }
            #right{
                background: pink;
                width: 20%;
                margin-left: -20%;
            }
            #main-inner{
                padding-left: 20%;
            }
        </style>
    </head>
    <body>
        <div id="container">
            <div id="header">
                header
            </div>
            <div id="main">
                <div id="center">
                    <div id="main-inner">
                        center
                    </div>
                </div>
                <div id="left">
                    left
                </div>
                <div id="right">
                    right
                </div>
            </div>
            <div id="footer">
                footer
            </div>
        </div>
    </body>
</html>
View Code

运行结果:

技术分享

示例中增加一个main-inner的目的是因为当left上移时与center重叠了,left覆盖了center,通过main-inner的padding将left占用的位置空出。

1.3、多栏布局

1.3.1、栅格系统

栏栅格系统就是利用浮动实现的多栏布局,在bootstrap中用的非常多,这里以一个980像素的宽实现4列的栅格系统,示例代码如下:

技术分享
<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>栅格系统</title>
        <style type="text/css">
            * {
                padding: 0;
                margin: 0;
            }
            
            html,
            body {
                height: 100%;
            }
            
            #container {
                width: 980px;
                margin: 0 auto;
                height: 10%;
            }
            
            #container div {
                height: 100%;
            }
            
            .col25 {
                width: 25%;
                background: lightgreen;
                float: left;
            }
            
            .col50 {
                width: 50%;
                background: lightblue;
                float: left;
            }
            
            .col75 {
                width: 75%;
                background: lightcoral;
                float: left;
            }
        </style>
    </head>

    <body>
        <div id="container">
            <div class="col50">
                A
            </div>
            <div class="col50">
                B
            </div>
            <div class="col25">
                C
            </div>
        </div>
    </body>

</html>
View Code

运行结果:

技术分享

技术分享

技术分享

同样的原理可以轻易扩展到8列,10列,16列的栅格系统。

1.3.2、多列布局

栅格系统并没有真正实现分栏效果(如word中的分栏),CSS3为了满足这个要求增加了多列布局模块,如果需要实现多列布局模块先看看这几个CSS3属性:

column-count:<integer> | auto
功能:设置或检索对象的列数 
适用于:除table外的非替换块级元素, table cells, inline-block元素
<integer>: 用整数值来定义列数。不允许负值 
auto: 根据 <‘ column-width ‘> 自定分配宽度

column-gap:<length> | normal
功能:设置或检索对象的列与列之间的间隙 
适用于:定义了多列的元素
计算值:绝对长度值或者normal

column-rule:<‘ column-rule-width ‘> || <‘ column-rule-style ‘> || <‘ column-rule-color ‘>
功能:设置或检索对象的列与列之间的边框。与border属性类似。 
适用于:定义了多列的元素

columns:<‘ column-width ‘> || <‘ column-count ‘>
功能:设置或检索对象的列数和每列的宽度
适用于:除table外的非替换块级元素, table cells, inline-block元素
<‘ column-width ‘>: 设置或检索对象每列的宽度 
<‘ column-count ‘>: 设置或检索对象的列数

示例代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            #content{
                text-indent: 2em;
                column-count: 3;
                column-gap: 30px;
                column-rule: 2px solid lightgreen;
                line-height: 26px;
                font-size: 14px;
            }
        </style>
    </head>
    <body>
        <div id="content">
            CSS即层叠样式表(Cascading StyleSheet)。 在网页制作时采用层叠样式表技术,可以有效地对页面的布局、字体、颜色、背景和其它效果实现更加精确的控制。 只要对相应的代码做一些简单的修改,就可以改变同一页面的不同部分,或者页数不同的网页的外观和格式。CSS3是CSS技术的升级版本,CSS3语言开发是朝着模块化发展的。以前的规范作为一个模块实在是太庞大而且比较复杂,所以,把它分解为一些小的模块,更多新的模块也被加入进来。这些模块包括: 盒子模型、列表模块、超链接方式 、语言模块 、背景和边框 、文字特效 、多栏布局等。CSS即层叠样式表(Cascading StyleSheet)。 在网页制作时采用层叠样式表技术,可以有效地对页面的布局、字体、颜色、背景和其它效果实现更加精确的控制。 只要对相应的代码做一些简单的修改,就可以改变同一页面的不同部分,或者页数不同的网页的外观和格式。CSS3是CSS技术的升级版本,CSS3语言开发是朝着模块化发展的。以前的规范作为一个模块实在是太庞大而且比较复杂,所以,把它分解为一些小的模块,更多新的模块也被加入进来。这些模块包括: 盒子模型、列表模块、超链接方式 、语言模块 、背景和边框 、文字特效 、多栏布局等。
        </div>
    </body>
</html>

运行结果:

技术分享

二、弹性布局(Flexbox)

假设在项目中有一个这样的需求:同一行有3个菜单,每个菜单占1/3的宽度,怎么实现?

可能你会这样实现:

技术分享
<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>flex</title>
        <style type="text/css">
            * {
                padding: 0;
                margin: 0;
                list-style: none;
            }
            
            html,
            body {
                height: 100%;
            }
            
            #menu {
                width: 980px;
                margin: 0 auto;
            }
            #menu li{
                width: 33.3%;
                float: left;
            }
        </style>
    </head>

    <body>
        <ul id="menu">
            <li><a href="#" class="item">公司简介</a></li>
            <li><a href="#" class="item">商品展示</a></li>
            <li><a href="#" class="item">后台管理</a></li>
        </ul>
    </body>

</html>
View Code

结果:

技术分享

上面的办法有明显的不足就是可扩展性太差,因为如果再添加一项就会有一个菜单项会换行,解决方法是:CSS3中提供了强大的弹性盒布局。示例:

技术分享
<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>flex</title>
        <style type="text/css">
            * {
                padding: 0;
                margin: 0;
                list-style: none;
            }
            
            html,
            body {
                height: 100%;
            }
            
            #menu {
                width: 980px;
                margin: 0 auto;
                display: flex;  /*当前块为弹性盒*/
            }
            #menu li{
                flex: auto;  /*弹性盒中的单项*/
                float: left;
            }
            #menu li a{
                display:block;
                height: 26px;
                line-height: 26px;
                border:1px solid cornflowerblue;
                margin-right: 2px;
                text-decoration: none;
                text-align: center;
            }
        </style>
    </head>

    <body>
        <ul id="menu">
            <li><a href="#" class="item">公司简介</a></li>
            <li><a href="#" class="item">商品展示</a></li>
            <li><a href="#" class="item">后台管理</a></li>
            <li><a href="#" class="item">企业文化</a></li>
            <li><a href="#" class="item">在线咨询</a></li>
        </ul>
    </body>

</html>
View Code

运行结果:

技术分享

技术分享

display属性值flex: 将对象作为弹性伸缩盒显示

flex:none | <flex-grow> <flex-shrink > || <flex-basis>
功能:设置或检索弹性盒模型对象的子元素如何分配空间
适用于:flex子项
none: none关键字的计算值为: 0 0 auto 
<flex-grow>: 用来指定扩展比率,即剩余空间是正值时此「flex子项」相对于「flex容器」里其他「flex子项」能分配到空间比例。
在「flex」属性中该值如果被省略则默认为「1」 
<flex-shrink>: 用来指定收缩比率,即剩余空间是负值时此「flex子项」相对于「flex容器」里其他「flex子项」能收缩的空间比例。
在收缩的时候收缩比率会以伸缩基准值加权
在「flex」属性中该值如果被省略则默认为「1」 
<flex-basis>: 用来指定伸缩基准值,即在根据伸缩比率计算出剩余空间的分布之前,「flex子项」长度的起始数值。
在「flex」属性中该值如果被省略则默认为「0%」
在「flex」属性中该值如果被指定为「auto」,则伸缩基准值的计算值是自身的 <width> 设置,如果自身的宽度没有定义,则长度取决于内容。

示例:如下情况每个元素的计算宽是多少

<ul class="flex">
 <li>a</li>
 <li>b</li>
 <li>c</li>
</ul>
.flex{display:flex;width:800px;margin:0;padding:0;list-style:none;}
.flex :nth-child(1){flex:1 1 300px;}
.flex :nth-child(2){flex:2 2 200px;}
.flex :nth-child(3){flex:3 3 400px;}

本例定义了父容器宽(即主轴宽)为800px,由于子元素设置了伸缩基准值flex-basis,相加300+200+400=900,那么子元素将会溢出900-800=100px;
由于同时设置了收缩因子,所以加权综合可得300*1+200*2+400*3=1900px;
于是我们可以计算a,b,c将被移除的溢出量是多少:
a被移除溢出量:(300*1/1900)*100,即约等于16px
b被移除溢出量:(200*2/1900)*100,即约等于21px
c被移除溢出量:(400*3/1900)*100,即约等于63px
最后a,b,c的实际宽度分别为:300-16=284px, 200-21=179px, 400-63=337px

可见算法比较麻烦,简单的做法如下:

技术分享
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>flex</title>
        <style type="text/css">
            * {
                padding: 0;
                margin: 0;
                list-style: none;
            }
            html,
            body {
                height: 100%;
            }
            #menu {
                width: 980px;
                margin: 0 auto;
                display: flex;
                /*当前块为弹性盒*/
            }
            #menu li {
                float: left;
            }
            #menu li a {
                display: block;
                height: 26px;
                line-height: 26px;
                border: 1px solid cornflowerblue;
                margin-right: 2px;
                text-decoration: none;
                text-align: center;
            }
            .a {
                flex: 1;
            }
            .b {
                flex: 2;
            }
            .c {
                flex: 3;
            }
        </style>
    </head>
    <body>
        <ul id="menu">
            <li class="a">
                <a href="#" class="item">公司简介</a>
            </li>
            <li class="b">
                <a href="#" class="item">商品展示</a>
            </li>
            <li class="c">
                <a href="#" class="item">后台管理</a>
            </li>
        </ul>
    </body>
</html>
View Code

运行结果:

技术分享

Flex容器可以设置属性flex-flow,取值为row,row-reverse,column,column-reverse四种值
row:显示在一行中

row-reverse:显示在一行中,反转

column:显示在一列中

column-reverse:显示在一列中 反转

技术分享
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>flex</title>
        <style type="text/css">
            * {
                padding: 0;
                margin: 0;
                list-style: none;
            }
            html,
            body {
                height: 100%;
                padding-top :20px;
            }
            #menu {
                width: 980px;
                margin: 0 auto;
                display: flex;
                /*当前块为弹性盒*/
                flex-flow: row-reverse;
                /*子项在一行中显示,反转*/
            }
            #menu li {
                flex: auto;
            }
            #menu li a {
                display: block;
                height: 26px;
                line-height: 26px;
                border: 1px solid cornflowerblue;
                margin-right: 2px;
                text-decoration: none;
                text-align: center;
            }
        </style>
    </head>
    <body>
        <ul id="menu">
            <li class="a">
                <a href="#" class="item">A公司简介</a>
            </li>
            <li class="b">
                <a href="#" class="item">B商品展示</a>
            </li>
            <li class="c">
                <a href="#" class="item">C后台管理</a>
            </li>
        </ul>
    </body>
</html>
View Code

技术分享

技术分享
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
                list-style: none;
            }
            html,body{
                height: 100%;
            }
            #mnue{
                width: 90%;
                height: 300px;
                margin: 0 auto;
                display: flex;/*当前块为弹性盒*/
                padding-top: 20px;
                /*flex-flow: row-reverse;*//*反转*/
                flex-flow: column;
            }
            #mnue li{
                /*flex: auto;*//*弹性盒中的单项*/        
                text-align: center;
                border: 1px dashed lightblue;
                margin-bottom: 5px;
            }
            #mnue li a{
                text-decoration: none;
                display: block;
                height: 26px;
                line-height: 26px;
                border: 1px solid lawngreen;
                margin-right: 2px;
                text-align: center;
            }
            .a{ /*按比例*/
                flex: 1;
            }
            .b{
                flex: 2;
            }
            .c{
                flex: 3;
            }
        </style>
    </head>
    <body>
        <ul id="mnue">
            <li class="a"><a href="#" class="item">个人概况</a></li>
            <li class="b"><a href="#" class="item">项目经验</a></li>
            <li class="c"><a href="#" class="item">自我评价</a></li>
            <!--<li><a href="http://www.mamicode.com/#" class="item">执有凭证</a></li>
            <li><a href="http://www.mamicode.com/#" class="item">社会经验</a></li>
            <li><a href="http://www.mamicode.com/#" class="item">工作年龄</a></li>-->
        </ul>
    </body>
</html>
View Code

技术分享

三、流式布局(Fluid)

固定布局和流式布局在网页设计中最常用的两种布局方式。固定布局能呈现网页的原始设计效果,流式布局则不受窗口宽度影响,流式布局使用百分比宽度来限定布局元素,这样可以根据客户端分辨率的大小来进行合理的显示。

固定布局效果:

技术分享

 流式布局效果:

技术分享

利用前面的知识点可以实现这两种布局,这里就不去实现了

三、瀑布流布局

瀑布流布局是流式布局的一种。是当下比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。

3.1、常见瀑布流布局网站

鼻祖:Pinterest
通用类:豆瓣市集,花瓣网,我喜欢,读图知天下
美女图片:图丽网
时尚资讯类:看潮网
时尚购物类:蘑菇街,美丽说,人人逛街,卡当网
品牌推广类:凡客达人
家居o2o类:新巢网小猫家
微博社交类: 都爱看
搞笑图片类:道趣儿
艺术收藏类:微艺术
潮流图文分享:荷都分享网

技术分享

3.2、特点

优点

1、有效的降低了界面复杂度,节省了空间:我们不再需要臃肿复杂的页码导航链接或按钮了。

2、对触屏设备来说,交互方式更符合直觉:在移动应用的交互环境当中,通过向上滑动进行滚屏的操作已经成为最基本的用户习惯,而且所需要的操作精准程度远远低于点击链接或按钮。

3、更高的参与度:以上两点所带来的交互便捷性可以使用户将注意力更多的集中在内容而不是操作上,从而让他们更乐于沉浸在探索与浏览当中。

缺点

1. 有限的用例:
无限滚动的方式只适用于某些特定类型产品当中一部分特定类型的内容。
例如,在电商网站当中,用户时常需要在商品列表与详情页面之间切换,这种情况下,传统的、带有页码导航的方式可以帮助用户更稳妥和准确的回到某个特定的列表页面当中。

2. 额外的复杂度:
那些用来打造无限滚动的JS库虽然都自称很容易使用,但你总会需要在自己的产品中进行不同程度的定制化处理,以满足你们自己的需求;另外这些JS库在浏览器和设备兼容性等方面的表现也参差不齐,你必须做好充分的测试与调整工作。

3. 再见了,页脚:
如果使用了比较典型的无限滚动加载模式,这就意味着你可以和页脚说拜拜了。
最好考虑一下页脚对于你的网站,特别是用户的重要性;如果其中确实有比较重要的内容或链接,那么最好换一种更传统和稳妥的方式。
千万不要耍弄你的用户,当他们一次次的浏览到页面底部,看到页脚,却因为自动加载的内容突然出现而无论如何都无法点击页脚中的链接时,他们会变的越发愤怒。

5. SEO:

集中在一页当中动态加载数据,与一页一页的输出相比,究竟那种方式更利于SEO,这是你必须考虑的问题。对于某些以类型网站来说,在这方面进行冒险是很不划算的。

6. 关于页面数量的印象:
其实站在用户的角度来看,这一点并非负面;不过,如果对于你的网站来说,通过更多的内容页面展示更多的相关信息(包括广告)是很重要的策略,那么单页无限滚动的方式对你并不适用。

3.3、masonry实现瀑布流布局

masonry是一个响应式网格布局库(非jQuery)。(Cascading grid layout library)

如果使用CSS+JavaScript当然可以实现瀑布流布局,但相对麻烦,masonry是一个javascript插件,通过该插件可以轻松实现瀑布流布局,和CSS中float的效果不太一样的地方在 于,float先水平排列,然后再垂直排列,使用Masonry则垂直排列元素,然后将下一个元素放置到网格中的下一个开发区域。这种效果可以最小化处理 不同高度的元素在垂直方向的间隙。

官网:http://masonry.desandro.com/

源码:https://github.com/desandro/masonry

技术分享

3.3.1、下载并引用masonry

可以去官网或github下载“masonry.pkgd.min.js”,将下载到的插件添加到项目中,并在页面中添加引用,如下所示:

<script src="http://www.mamicode.com/js/masonry/masonry.pkgd.min.js" type="text/javascript" charset="utf-8"></script>
  • masonry.pkgd.js un-minified
  • masonry.pkgd.min.js minified

CDN:

<script src="https://unpkg.com/masonry-layout@4.1/dist/masonry.pkgd.js"></script>
<!-- or -->
<script src="https://unpkg.com/masonry-layout@4.1/dist/masonry.pkgd.min.js"></script>

3.3.2、准备内容

在页面中使用HTML+CSS准备需要使用瀑布流显示的内容,如下所示:

技术分享
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>瀑布流布局</title>
        <style type="text/css">
            #grid {
                width: 1000px;
                margin: 0 auto;
            }
            
            .grid-item {
                width: 200px;
                float: left;
            }
            
            .a {
                background: lightblue;
                height: 200px;
            }
            
            .b {
                background: lightcoral;
                height: 300px;
            }
            
            .c {
                background: lightgreen;
                height: 500px;
            }
            
            .d {
                background: lightsalmon;
                height: 350px;
            }
            
            .e {
                background: lightseagreen;
                height: 150px;
            }
        </style>
    </head>

    <body>
        <div id="grid">
            <div class="grid-item a">
            </div>
            <div class="grid-item b">
            </div>
            <div class="grid-item a">
            </div>
            <div class="grid-item b">
            </div>
            <div class="grid-item a">
            </div>
            <div class="grid-item b">
            </div>
            <div class="grid-item a">
            </div>
            <div class="grid-item b">
            </div>
            <div class="grid-item a">
            </div>
            <div class="grid-item b">
            </div>
            <div class="grid-item a">
            </div>
            <div class="grid-item b">
            </div>
            <div class="grid-item c">
            </div>
            <div class="grid-item d">
            </div>
            <div class="grid-item e">
            </div>
            <div class="grid-item c">
            </div>
            <div class="grid-item d">
            </div>
            <div class="grid-item e">
            </div>
            <div class="grid-item c">
            </div>
            <div class="grid-item d">
            </div>
            <div class="grid-item e">
            </div>
            <div class="grid-item c">
            </div>
            <div class="grid-item d">
            </div>
            <div class="grid-item e">
            </div>
            <div class="grid-item c">
            </div>
            <div class="grid-item d">
            </div>
            <div class="grid-item e">
            </div>
            <div class="grid-item c">
            </div>
            <div class="grid-item d">
            </div>
            <div class="grid-item e">
            </div>
        </div>
        <script src="js/masonry/masonry.pkgd.min.js" type="text/javascript" charset="utf-8"></script>
    </body>

</html>
View Code

没有使用瀑布流布局时的效果:

技术分享

3.3.3、初始化插件

使用jQuery:

$(‘.grid‘).masonry({
  // options...
  itemSelector: ‘.grid-item‘,
  columnWidth: 200
});

原生JavaScript:

// init with element
var grid = document.querySelector(‘.grid‘);
var msnry = new Masonry( grid, {
  // options...
  itemSelector: ‘.grid-item‘,
  columnWidth: 200
});

使用HTML属性:

<div class="grid" data-masonry=‘{ "itemSelector": ".grid-item", "columnWidth": 200 }‘>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  ...
</div>

常用属性如下:

itemSelector : ‘.item‘,//瀑布流布局中的单项选择器
columnWidth : 240 ,//一列的宽度
isAnimated:true,//使用jquery的布局变化,是否启用动画
animationOptions:{
//jquery animate属性 渐变效果 Object { queue: false, duration: 500 }
},
gutterWidth:0,//列的间隙 Integer
isFitWidth:true,//是否适应宽度 Boolean
isResizableL:true,//是否可调整大小 Boolean
isRTL:false,//是否使用从右到左的布局 Boolean

 

初始化代码如下:

技术分享
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>瀑布流布局</title>
        <style type="text/css">
            #grid{
                width: 1000px;
                margin: 0 auto;
            }
            .grid-item{
                width:200px;
                float: left;
            }
            .a{
                height: 200px;
                background: lightblue;
            }
            .b{
                height: 100px;
                background: lightgreen;
            }
            .c{
                height: 250px;
                background: orangered;
            }
            
            .d{
                height: 400px;
                background: lawngreen;
            }
            .e{
                height: 350px;
                background: yellow;
            }
        </style>
    </head>
    <body>
        <div id="grid">
            <div class="grid-item a"></div>
            <div class="grid-item b"></div>
            <div class="grid-item c"></div>
            <div class="grid-item a"></div>
            <div class="grid-item d"></div>
            <div class="grid-item e"></div>
            <div class="grid-item c"></div>
            <div class="grid-item a"></div>
            <div class="grid-item d"></div>
            <div class="grid-item a"></div>
            <div class="grid-item e"></div>
            <div class="grid-item c"></div>
            <div class="grid-item a"></div>
            <div class="grid-item d"></div>
            <div class="grid-item e"></div>
            <div class="grid-item c"></div>
            <div class="grid-item b"></div>
            <div class="grid-item a"></div>
            <div class="grid-item d"></div>
            <div class="grid-item a"></div>
            <div class="grid-item e"></div>
            <div class="grid-item c"></div>
            <div class="grid-item a"></div>
            <div class="grid-item d"></div>
            <div class="grid-item e"></div>
            <div class="grid-item c"></div>
            <div class="grid-item d"></div>
            <div class="grid-item e"></div>
        </div>
        <script src="js/masonry/masonry.pkgd.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            var msnry=new Masonry(#grid,{
                itemSelector:.grid-item,
                columnWidth:200
            });
        </script>
    </body>
</html>
View Code

运行结果:

技术分享

3.3.4、使用了图片的瀑布流

技术分享
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>瀑布流布局</title>
        <style type="text/css">
            #grid{
                width: 800px;
                margin: 0 auto;
            }
            .grid-item{
                float: left;
            }        
        </style>
    </head>
    <body>
        <div id="grid">
            <div class="grid-item">
                <a href="#">
                    <img src="img/1.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/11546445.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/1257.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/1257.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/2.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/1468119761528.jpeg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/3.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/CR.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/lo.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/Cache_-342b6631b5a9c1b1..jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/i2.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/IMG_20160426_095411.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/psb (1).jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/lo.jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/psb (2).jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/psb (17).jpg" width="200"/>
                </a>
            </div>
            <div class="grid-item">
                <a href="#">
                    <img src="img/QQ.jpg" width="200"/>
                </a>
            </div>
        </div>
        <script src="js/masonry/masonry.pkgd.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            window.onload=function(){
                var msnry=new Masonry(#grid,{
                    itemSelector:.grid-item,
                    columnWidth:200
                });
            }
        </script>
    </body>
</html>
View Code

 

运行结果:

技术分享

注意:上面的示例中我们使用了window.onload事件,原因是如果图片没有加载完成就执行瀑布流布局会引起堆叠的问题,其实就是初始化是没有检测到图片的高度,window.onload在有许多图片的环境下会有性能问题,这里给大家介绍另一个组件。

3.4、imagesLoaded 图片加载

imagesLoaded 是一个用于来检测网页中的图片是否载入完成的 JavaScript 工具库。支持回调的获取图片加载的进度,还可以绑定自定义事件。可以结合 jQuery、RequireJS 使用。

官网:http://imagesloaded.desandro.com/

源码:https://github.com/desandro/imagesloaded

示例代码:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>imagesLoaded – 检测网页中的图片是否加载</title>
    </head>

    <body>
        <div id="div1">
            <img src="img/h/h(2).jpg" width="300" /><img src="img/h/h(1).jpg" width="300" />
        </div>
        <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/imagesloaded-master/imagesloaded.pkgd.min.js" type="text/javascript" charset="utf-8"></script>
        <script>
            imagesLoaded(document.querySelector(#div1), function(instance) {
                alert(所有的图片都加载完成了);
            });

            $(#div1).imagesLoaded()
                .always(function(instance) {
                    console.log(all images loaded);
                })
                .done(function(instance) {
                    console.log(all images successfully loaded);
                })
                .fail(function() {
                    console.log(all images loaded, at least one is broken);
                })
                .progress(function(instance, image) {
                    var result = image.isLoaded ? loaded : broken;
                    console.log(image is  + result +  for  + image.img.src);
                });
        </script>
    </body>

</html>

技术分享

3.5、Infinite Scroll 滚动分页

Infinite Scroll也是基于jQuery插件,是一个用于滚动分页的插件(当移动滚动条时将动态加载更多内容),有网友称这种效果为”无刷新无分页完美瀑布流”展现方式。

官网:http://infinite-scroll.com/

源码:https://github.com/infinite-scroll/infinite-scroll

常用属性:

$(‘#masonny-div‘).infinitescroll({
    navSelector  : "#next",   // 页面分页元素(成功后会被隐藏)
    nextSelector : "#next a", // 需要点击的下一页链接,和2的html要对应
    itemSelector : ".item"  , // ajax回来之后,每一项的selecter
    animate      : true,      //加载完毕是否采用动态效果
    extraScrollPx: 100,       //向下滚动的像素,必须开启动态效果
    // debug     : true,      //调试的时候,可以打开
    bufferPx     : 5,         //提示语展现的时长,数字越大,展现时间越短
    loading: {
        finishedMsg: ‘没有更多内容了‘, //当加载失败,或者加载不出内容之后的提示语
        img:  ‘loading-new.gif‘,   //自定义loadding的动画图
        msgText : ‘正在加载中...‘,    //加载时的提示语
        },
    },
    function( newElements, opt ) {
       //成功后执行自定义的函数
       //如果需要对新内容进行加工,就在这里实现
    }
};

属性与事件官网有详细的说明这里只列出来了部分,下面是官网列出的选择:

$(‘.selector‘).infinitescroll({
  loading: {
    finished: undefined,
    finishedMsg: "<em>Congratulations, you‘ve reached the end of the internet.</em>",
                img: null,
    msg: null,
    msgText: "<em>Loading the next set of posts...</em>",
    selector: null,
    speed: ‘fast‘,
    start: undefined
  },
  state: {
    isDuringAjax: false,
    isInvalidPage: false,
    isDestroyed: false,
    isDone: false, // For when it goes all the way through the archive.
    isPaused: false,
    currPage: 1
  },
  behavior: undefined,
  binder: $(window), // used to cache the selector for the element that will be scrolling
  nextSelector: "div.navigation a:first",
  navSelector: "div.navigation",
  contentSelector: null, // rename to pageFragment
  extraScrollPx: 150,
  itemSelector: "div.post",
  animate: false,
  pathParse: undefined,
  dataType: ‘html‘,
  appendCallback: true,
  bufferPx: 40,
  errorCallback: function () { },
  infid: 0, //Instance ID
  pixelsFromNavToBottom: undefined,
  path: undefined, // Can either be an array of URL parts (e.g. ["/page/", "/"]) or a function that accepts the page number and returns a URL
  maxPage:undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
});

3.5.1、异步加载普通页面

p1.html页面:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .item {
                height: 200px;
            }
        </style>
    </head>
    <body>
        <h2>产品列表</h2>
        <div id="items">
            <p class="item">产品一</p>
            <p class="item">产品一</p>
            <p class="item">产品一</p>
            <p class="item">产品一</p>
            <p class="item">产品一</p>
            <p class="item">产品一</p>
        </div>
        <a href="p2.html" id="next">下一页</a>
        <script src="../js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../js/infinite-scroll/jquery.infinitescroll.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            $(#items).infinitescroll({
                navSelector: "#next",  // 页面分页元素(成功后会被隐藏)
                nextSelector: "a#next",  // 需要点击的下一页链接,和2的html要对应
                itemSelector: ".item",  // ajax回来之后,每一项的selecter,比如每篇文章都有item这个class
                debug: true,  //是否调试
                dataType: html,  //数据类型
                maxPage: 3,  //最大页数
                path: function(index) {  //路径
                        return "p" + index + ".html";
                }
            }, function(newElements, data, url) {  //成功后的回调
                //console.log("路径:" + url);
                $(newElements).css(background-color, #ffef00);
                // $(this).append(newElements);
            });
        </script>
    </body>

</html>

p2.html页面:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>P2</title>
    </head>
    <body>
        <p class="item">产品二</p>
        <p class="item">产品二</p>
        <p class="item">产品二</p>
        <p class="item">产品二</p>
        <p class="item">产品二</p>
        <p class="item">产品二</p>
    </body>
</html>

p3.html页面:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>P3</title>
    </head>
    <body>
        <p class="item">产品三</p>
        <p class="item">产品三</p>
        <p class="item">产品三</p>
        <p class="item">产品三</p>
        <p class="item">产品三</p>
        <p class="item">产品三</p>
    </body>
</html>

运行结果:

技术分享

3.5.2、异步加载json并解析

m1.html页面:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>相册</title>
        <style type="text/css">
            .item {
                float: left;
                min-height: 300px;
            }
        </style>
    </head>
    <body>
        <h2>相册</h2>
        <div id="items">
            <p class="item"><img src="../img/i/1.jpg" /></p>
            <p class="item"><img src="../img/i/2.jpg" /></p>
            <p class="item"><img src="../img/i/3.jpg" /></p>
            <p class="item"><img src="../img/i/4.jpg" /></p>
            <p class="item"><img src="../img/i/5.jpg" /></p>
            <p class="item"><img src="../img/i/6.jpg" /></p>
        </div>
        <a href="m2.json" id="next"></a>
        <script src="../js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../js/infinite-scroll/jquery.infinitescroll.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            $(#items).infinitescroll({
                navSelector: "#next",
                nextSelector: "a#next",
                itemSelector: ".item",
                debug: true,
                dataType: json,
                maxPage: 3,
                appendCallback:false,
                path: function(index) {
                    return "m" + index + ".json";
                }
            }, function(data) {
                
                for(var i=0;i<data.length;i++){
                    $("<p class=‘item‘><img src=http://www.mamicode.com/‘../img/i/"+data[i]+".jpg‘ /></p>").appendTo("#items");
                }
                
            });
        </script>
    </body>
</html>

m2.json数据:

[7,8,9,10,11,12]

m3.json数据:

[13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]

运行结果:

技术分享

因为没有使用瀑布流布局所以有点不规整,这里主要演示分页。

四、响应式布局(Responsive)

4.1、媒介查询

技术分享

技术分享

4.2、媒介查询的应用位置

a)、内部样式

@media screen and (width:800px){ … }

b)、导入样式

@import url(example.css) screen and (width:800px);

c)、链接样式
<link media="screen and (width:800px)" rel="stylesheet" href="http://www.mamicode.com/example.css" />

d)、XML中应用样式
<?xml-stylesheet media="screen and (width:800px)" rel="stylesheet" href="http://www.mamicode.com/example.css" ?>

4.3、Hello World

在页面上放一个层,当屏幕大小在100-640之间时

示例代码:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>媒介查询</title>
        <style type="text/css">
            #div1 {
                background: lightblue;
                height: 100px;
            }
            
            @media only screen and (min-width: 100px) and (max-width: 640px) {
                #div1 {
                    background: lightgreen;
                    height: 200px;
                }
            }
        </style>
    </head>

    <body>
        <div id="div1">
            Hello World!
        </div>
    </body>

</html>

全屏时的运行效果:

技术分享

缩小浏览器的效果:

技术分享

 

CSS3与页面布局学习总结——多种页面布局