您的位置:新葡亰496net > 新葡亰官网 > 新葡亰496net:布局十八般武艺都在这里了,等高

新葡亰496net:布局十八般武艺都在这里了,等高

发布时间:2019-08-10 13:31编辑:新葡亰官网浏览(172)

    等高分栏布局小结

    2016/02/06 · CSS · 等高分栏

    原文出处: 流云诸葛   

    上一篇文章《圣杯布局小结》总结了几种常见的分栏布局方法,这几个方法都可以实现多栏页面下,所有栏的高度可动态变化,某一栏宽度自适应的布局效果,能满足工作中很多布局需求。后来我在搜集更多关于分栏布局的文章时,发现了一个新的问题,这个问题在前面那篇文章中也有朋友在评论里跟我提起,就是如何在实现分栏布局的同时保证每栏的高度相同。我发现这种等高分栏布局的情况,在网站里面其实也很常见,所以本文总结了几种可用的方法来解决这个新的需求。

    圣杯布局小结

    2016/01/30 · HTML5 · 1 评论 · 圣杯布局

    原文出处: 流云诸葛   

    圣杯布局,很久之前就听过,但是一直都没详细了解过,最近因为做了一个项目,借鉴了薪人薪事这个公司的产品页面,才第一次用到这种布局方式。于是就花了点时间,测了下它实现常见分栏布局的代码,每段代码都非常简单,但布局效果很完美,比我以前用的方式好用不少。本文是对它实现方式的一些总结,希望可以把这种技术推荐给跟我之前一样对它比较陌生的开发人员:)

    目录

    • 常用居中
      1. 垂直居中
      2. 新葡亰496net:布局十八般武艺都在这里了,等高分栏布局小结。水平居中
      3. 垂直水平居中
    • 单列布局
    • 双列&三列布局

    CSS 布局十八般武艺都在这里了

    2017/03/25 · CSS · 布局

    原文出处: 码蜂社   

    1. 方法一:万能的flex

    跟上篇文章不同,这次把flex这种方法放在了第一位,因为相比较起来,它是所有分栏布局方法里面,优点最多的,如果兼容性允许的话,很有必要在任何时候都优先使用它完成页面布局。如果你打开上篇文章,找到倒数第二部分关于flex实现分栏布局的代码,或者把上篇文章提供的代码下载下来,直接预览flex_layout.html,你会发现上篇文章的那段代码其实已经做到了等高分栏布局,同一段代码,可以实现上篇文章中提到的五种分栏布局,还可以实现本文提到的等高布局的情况,这种能力其它方法真的无法比拟。而它之所以能实现等高布局,跟一个flex的css属性有关系,这个属性是:align-item。它的默认值是:stretch,在flex item元素比如layout__main或layout__aside的高度未定义或者为auto的情况下,会拉伸flex item元素的高度或宽度,铺满flex的交叉轴,详细的原理可以通过上文提供的flex学习资源去了解,这里只做一个简单的引用说明。

    1. 从2个实际的需求说起

    今年有2个项目,都是管理系统的项目,这种项目的界面特点基本都是左侧边栏显示菜单,右侧显示网页主体或者是顶部的导航栏显示菜单,导航栏以下显示网页主体,我这两个项目都是第一种类型:

    项目一:

    新葡亰496net 1

    项目二:

    新葡亰496net 2

    在做项目一的时候,采用了以前做ERP软件的一些做法,右边的网页主体区域放置的是一个iframe,用来显示每个菜单点击之后的页面,这样每个菜单点击之后,外部页面都不会刷新,并且滚动也只发生在iframe里面,外部页面的菜单区域和顶部导航栏的状态始终不会改变,用户操作起来非常便捷。这种界面布局的做法非常简单,只要侧边栏和网页主体区域都采用固定定位即可:

    <div class="sidebar"></div> <div class="page-content"></div> .sidebar { position: absolute; width: 200px; left: 0; bottom: 0; top: 50px; border-right: 1px solid #E7E7E7; } .page-content { position: absolute; left: 205px; bottom: 0; top: 50px; right: 0; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <div class="sidebar"></div>
    <div class="page-content"></div>
     
    .sidebar {
        position: absolute;
        width: 200px;
        left: 0;
        bottom: 0;
        top: 50px;
        border-right: 1px solid #E7E7E7;
    }
     
    .page-content {
        position: absolute;
        left: 205px;
        bottom: 0;
        top: 50px;
        right: 0;
    }

    由于这个项目是一个内部项目,所以采用这种界面结构完全是可以接受的,毕竟这只是一个管理系统,可以不那么在乎用户体验什么的。最近做项目二的时候,情况就不一样了,这个项目是一个企业级的管理应用,它不再是一个单纯的管理系统,而是面向外部用户提供的参与平台业务的一个终端应用,从用户体验的角度来说,项目一那种固定死板的方式不太拿得出手给别人用,不然别人肯定会认为你的应用做的很low。相对于项目一的界面,项目二有以下特点:

    1)菜单点击之后,界面是整体刷新,没有iframe了;

    2)侧边栏和主体内容栏的高度都是不固定的;

    3)网页滚动的时候,是页面整体滚动,而不是只滚动主体内容。

    几个礼拜前,看到薪人薪事融资的新闻,心想这是个什么公司,怎么之前都没听过,做什么业务的,于是就百度了下,注册了账号,进去体验了一下它的产品,后来发现它做的其实是一个SAAS应用,界面上看是一个典型的管理系统的风格,但是整体体验还不错,当时就觉得以后说不定有参考借鉴的价值。正好上周临时安排要做项目二,根据项目一提了一些要求,于是就想到薪人薪事的应用了。只有3天时间,工作除了界面之外,还有4个业务模块的功能要完成,为了完成这个东西,界面布局完全参考了薪人薪事的做法,由于以前没用过这种布局方式,所以觉得很新奇,就专门搜集知识学习了一下,才发现这个方法就是以前听过的圣杯布局。项目二所用的布局方法就是圣杯布局方式中侧边栏固定,主体内容栏自适应的一种做法。

    常用居中

    CSS布局

    布局是CSS中一个重要部分,本文总结了CSS布局中的常用技巧,包括常用的水平居中、垂直居中方法,以及单列布局、多列布局的多种实现方式(包括传统的盒模型布局和比较新的flex布局实现),希望能给需要的小伙伴带来一些帮助。

    2. 方法二:使用table或者伪table

    上篇文章中还有另外两种布局方法没有介绍,第一种就是这里要说的table布局或者伪table布局。table布局用的就是table tr td这些元素去实现,相信绝大部分web开发人员在入门html时,首先接触到的布局方法肯定就是table布局了,这种方法简单高效,用它做任何分栏布局都不是问题,只是因为table的嵌套结构太多,html冗杂,又不利于DOM的操作和渲染,用来布局不符合语义,总之缺点较多,所以目前的环境下,用的情况越来越少了。伪table布局其实跟table布局类似,只不过借助于css,可以让我们不直接使用table tr td这些直接的表格元素,而是通过display: table, display: table-row, display: table-cell,改变元素的显示特性,让浏览器把这些元素当成table来渲染,这种渲染的表现跟用真实的table没有啥区别,就连那些table专用的css属性,比如table-layout,border-collapse和border-spacing,都能产生效果。table布局的方法已经很少被采用了,本文也就没必要再去介绍,但是伪table布局的方法值得学习一下,经过这两天的学习,发现伪table的方式相比直接用表格布局,有不少的优点,值得运用到工作中去。不过在说明使用伪table布局的方法之前,得先了解一些伪table相关的知识:

    1)可用于伪table表现的display属性值有:

    新葡亰496net 3

    2)当把一个元素的display属性设置成以上列出的值后,就可以把这个元素看成与该属性对应的表格元素,比如table-cell对应的就是td;同时,这个元素会拥有跟表格元素一样的特性,比如display: table或者inline-table的元素可以使用table-layout,border-collapse和border-spacing这三个原本只有table才能生效的属性;display:table-cell的元素跟td一样,对宽度高度敏感,对margin值无反应,对padding有效。

    3)关于table-cell还有一点要说明的就是,它会被其他一些CSS属性破坏,例如float, position:absolute,所以这些个属性不能同时使用。

    4)跟直接使用表格元素不同的是,在使用表格元素的时候需要完全遵守表格元素嵌套结构,也就是下面这种:

    <table> <thead> <th></th> </thead> <tbody> <tr> <td></td> </tr> </tbody> <tfoot> <th></th> </tfoot> </table>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <table>
        <thead>
            <th></th>
        </thead>
        <tbody>
            <tr>
                <td></td>
            </tr>
        </tbody>
        <tfoot>
            <th></th>
        </tfoot>
    </table>

    而使用伪table的那些属性时,可以仅单独使用某一个属性,浏览器会在这些元素的外层包裹缺失的来保证伪table元素框嵌套结构的完整性,这些框跟常提到的行框一样都是不可见的,网上有的文章里也把这种做法叫做匿名表格。下面的这个代码中,tb-cell元素的外层没有加display: table-row和display: table的元素:

    .tb-cell { display: table-cell; padding: 10px; border: 1px solid #ccc; } <div class="tb-cell">这是第1个display: table-cell;的元素。</div> <div class="tb-cell">这是第2个display: table-cell;的元素。</div>

    1
    2
    3
    4
    5
    6
    7
    8
    .tb-cell {
        display: table-cell;
        padding: 10px;
        border: 1px solid #ccc;
    }
     
    <div class="tb-cell">这是第1个display: table-cell;的元素。</div>
    <div class="tb-cell">这是第2个display: table-cell;的元素。</div>

    这是第1个display: table-cell;的元素。这是第2个display: table-cell;的元素。

    1
    这是第1个display: table-cell;的元素。这是第2个display: table-cell;的元素。

    但是看到的效果是(蓝色背景是它们父层的一个包裹元素: width: 800px;margin-left: auto;margin-right: auto):

    新葡亰496net 4

    因为浏览器自动在这两个元素的外层,加了跟能够跟tr和table起相同作用的框,来包含这两个元素形成的框,所以这两个元素看起来就跟实际的表格效果一样。假如浏览器没有做这个处理,这两个元素之间是不可能没有间隙的,中间会有一个因为换行符显示出来的空格。这种自动添加的框都是行内框,不是块级框。

    接下来看看如何通过这些伪table的属性来完成上文的分栏布局以及本文要求的等高分栏布局,玩法有很多:(本文相关源码下载)

    玩法一:模拟直接用表格布局(对应源码中table_layout1.html)

    这种方法的思路是布局时完全按照表格的嵌套层次来处理,把display: table, display: table-row, display: table-cell都用上,相当于就是利用完整的table来做,比如说要实现上文的布局三(3栏布局,2个侧边栏分别固定在左边和右边,中间是主体内容栏),就可以这么干:

    <div class="layout"> <div class="layout__row"> <aside class="layout__col layout__aside layout__aside--left">左侧边栏宽度固定</aside> <div class="layout__col layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度都会自动增加</div> <aside class="layout__col layout__aside layout__aside--right">右侧边栏宽度固定</aside> </div> </div>

    1
    2
    3
    4
    5
    6
    7
    <div class="layout">
        <div class="layout__row">
            <aside class="layout__col layout__aside layout__aside--left">左侧边栏宽度固定</aside>
            <div class="layout__col layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度都会自动增加</div>
            <aside class="layout__col layout__aside layout__aside--right">右侧边栏宽度固定</aside>
        </div>
    </div>

    <style type="text/css"> .layout { display: table; width: 100%; } .layout__row { display: table-row; } .layout__col { text-align: center; display: table-cell; } .layout__col .layout__col { border-left: 10px solid #fff; } .layout__main { background-color: #4DBCB0; } .layout__aside { width: 200px; background-color: #daf1ef; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <style type="text/css">
        .layout {
            display: table;
            width: 100%;
        }
        .layout__row {
            display: table-row;
        }
        .layout__col {
            text-align: center;
            display: table-cell;
        }
        .layout__col .layout__col {
            border-left: 10px solid #fff;
        }
        .layout__main {
            background-color: #4DBCB0;
        }
        .layout__aside {
            width: 200px;
            background-color: #daf1ef;
        }
    </style>

    效果还是那个效果,而且天生支持等高布局:

    新葡亰496net 5

    这个布局原理跟使用table是完全一样的,所以使用起来非常容易(以上提供的是针对上文布局三的实现,其它四个布局的实现不会再一一介绍了,源码里面也不会提供,因为相对比较简单)。

    这种伪table布局有什么特点呢:

    1)相比直接用表格元素,这种做法不需要考虑语义,表格元素是有语义的,主要是用来显示网页上列表型的数据内容,虽然可以完成布局,但是布局结构都是没有语义的,所以直接用表格不合适,而这种伪table布局的特点就是:它没有语义,但是可以像表格那样布局;

    2)html的层次结构相比直接用table元素也要简单一些,我们这里只用到了3层,直接用table元素的话可能还有tbody这一层;

    3)相比上文提到的那些布局方法,如圣杯布局和双飞翼布局,这个做法在css方面相对简单,在html方面也只多了一层嵌套;

    4)缺点是分栏之间的间隔不能用margin和padding来做,如果用margin,这个属性在display: table-cell的元素上根本不会生效;如果用padding,那像demo里面各栏的背景色就都会连到一块,做不出间隔的效果,如果在layout__col里面再嵌套一层,在这一层设置背景色的话,又会增加html的层次,也不是很好。我这里是投了个巧,用border处理了一下。

    玩法二:去掉display: table-row(对应源码中的table_layout2.html)

    前面说过,浏览器会用匿名表格的方式,添加缺失的框,所以玩法一中的代码,把layout-row完全去掉,一点都不影响布局效果:

    新葡亰496net:布局十八般武艺都在这里了,等高分栏布局小结。div class="layout"> aside class="layout__col layout__aside layout__aside--left">左侧边栏宽度固定aside> div class="layout__col layout__main">内容栏宽度自适应br>高度增加一点,旁边的高度都会自动增加div> aside class="layout__col layout__aside layout__aside--right">右侧边栏宽度固定aside> div>

    1
    2
    3
    4
    5
    div class="layout">
        aside class="layout__col layout__aside layout__aside--left">左侧边栏宽度固定aside>
        div class="layout__col layout__main">内容栏宽度自适应br>高度增加一点,旁边的高度都会自动增加div>
        aside class="layout__col layout__aside layout__aside--right">右侧边栏宽度固定aside>
    div>

    style type="text/css"> .layout { display: table; width: 100%; } .layout__col { text-align: center; display: table-cell; } .layout__col .layout__col { border-left: 10px solid #fff; } .layout__main { background-color: #4DBCB0; } .layout__aside { width: 200px; background-color: #daf1ef; } style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    style type="text/css">
        .layout {
            display: table;
            width: 100%;
        }
        .layout__col {
            text-align: center;
            display: table-cell;
        }
        .layout__col .layout__col {
            border-left: 10px solid #fff;
        }
        .layout__main {
            background-color: #4DBCB0;
        }
        .layout__aside {
            width: 200px;
            background-color: #daf1ef;
        }
    style>

    玩法三:去掉display: table(对应源码中的table_layout3.html)

    根据玩法二,可以试想一下是否能再把display: table这一个属性给去掉,反正浏览器还会再添加框来包裹:

    <div class="layout"> <aside class="layout__col layout__aside layout__aside--left">左侧边栏宽度固定</aside> <div class="layout__col layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度都会自动增加</div> <aside class="layout__col layout__aside layout__aside--right">右侧边栏宽度固定</aside> </div>

    1
    2
    3
    4
    5
    <div class="layout">
        <aside class="layout__col layout__aside layout__aside--left">左侧边栏宽度固定</aside>
        <div class="layout__col layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度都会自动增加</div>
        <aside class="layout__col layout__aside layout__aside--right">右侧边栏宽度固定</aside>
    </div>

    <style type="text/css"> .layout__col { text-align: center; display: table-cell; } .layout__col .layout__col { border-left: 10px solid #fff; } .layout__main { background-color: #4DBCB0; } .layout__aside { width: 200px; min-width: 200px; background-color: #daf1ef; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <style type="text/css">
        .layout__col {
            text-align: center;
            display: table-cell;
        }
        .layout__col .layout__col {
            border-left: 10px solid #fff;
        }
        .layout__main {
            background-color: #4DBCB0;
        }
        .layout__aside {
            width: 200px;
            min-width: 200px;
            background-color: #daf1ef;
        }
    </style>

    效果是:

    新葡亰496net 6

    这个并没有达到我们的效果,因为我需要主体内容栏能够自适应宽度。产生这个效果的原因是什么,就是因为没有加显示display: table这一层,浏览器自动加了一个框,不过这个框是行内框,导致主体内容栏显示的宽度就跟内容的宽度一致了。为了解决这个问题,可以这么干,html结构不变,css稍加改动:

    .layout__main { width: 3000px; background-color: #4DBCB0; } .layout__aside { width: 200px; min-width: 200px; background-color: #daf1ef; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    .layout__main {
        width: 3000px;
        background-color: #4DBCB0;
    }
     
    .layout__aside {
        width: 200px;
        min-width: 200px;
        background-color: #daf1ef;
    }

    关键的代码就是红色新增的那两行,首先给主体内容栏设置一个很长的宽度,而且只能用具体的长度设置,不能用百分比,然后给侧边栏设置一个最小宽度,免得主体内容栏把侧边栏的宽度给挤掉了。这个原理就是因为display: table-cell的作用,导致layout__main跟layout__aside表现出跟td元素一样的特性,td默认的宽度就是可自动调整的,即使宽度设置的很大,也不会撑破table的宽度,这里虽然那个自动添加的框看不到,但是这个框的最大宽度也就是浏览器的宽度,layout__main不会打破这个宽度的,所以可以放心使用。

    玩法四:去掉layout这一层包裹元素(对应源码:table_layout4.html)

    如果网站比较简单,去掉layout这一层包裹元素也是可以的:

    <header>顶部</header> <aside class="layout__col layout__aside layout__aside--left">左侧边栏宽度固定</aside> <div class="layout__col layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度都会自动增加</div> <aside class="layout__col layout__aside layout__aside--right">右侧边栏宽度固定</aside> <footer>底部</footer>

    1
    2
    3
    4
    5
    <header>顶部</header>
    <aside class="layout__col layout__aside layout__aside--left">左侧边栏宽度固定</aside>
    <div class="layout__col layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度都会自动增加</div>
    <aside class="layout__col layout__aside layout__aside--right">右侧边栏宽度固定</aside>
    <footer>底部</footer>

    <style type="text/css"> .layout__col { text-align: center; display: table-cell; line-height: 50px; } .layout__col .layout__col { border-left: 10px solid #fff; } .layout__main { width: 3000px; background-color: #4DBCB0; } .layout__aside { width: 200px; min-width: 200px; background-color: #daf1ef; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <style type="text/css">
        .layout__col {
            text-align: center;
            display: table-cell;
            line-height: 50px;
        }
        .layout__col .layout__col {
            border-left: 10px solid #fff;
        }
        .layout__main {
            width: 3000px;
            background-color: #4DBCB0;
        }
        .layout__aside {
            width: 200px;
            min-width: 200px;
            background-color: #daf1ef;
        }
    </style>

    以上四种做法都能实现我们想要的分栏等高布局,兼容性方面,不考虑IE8及以下,其它浏览器几乎没有问题。

    由于匿名表格的作用,导致采用伪table布局的方法变得非常简洁,上文之所以没提到这个做法,是因为完全不知道有匿名表格这回事,我也是写这篇文章才学习到的,学完之后,发现又找到了一个做分栏布局的好办法,希望前面的这些介绍能帮助你掌握好这个用法。实际上伪table的这些属性,尤其是table-cell,用途非常多,本文没有办法一一介绍,但是能提供一个思路,将来工作中也许有很多其它布局场景,我们都可以想想用table-cell来处理。

    2. 圣杯布局的传统实现方法

    利用圣杯布局的方法,可以轻松实现下面的布局效果:

    新葡亰496net 7

    下面来一一说明上图中五种布局效果的实现方法(本文相关代码下载,本部分的布局方法在代码中对应grail_layout{1,5}.html)。

    1)布局一:2栏布局,侧边栏固定在左边,右侧是主体内容栏:

    <div class="layout"> <aside class="layout__aside">侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> </div>

    1
    2
    3
    4
    <div class="layout">
        <aside class="layout__aside">侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
    </div>

    <style type="text/css"> .layout:after { clear: both; content: " "; display: table; } .layout__aside, .layout__main { float: left; } .layout { padding-left: 210px; } .layout__main { width: 100%; } .layout__aside { width: 200px; margin-left: -210px; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <style type="text/css">
        .layout:after {
            clear: both;
            content: " ";
            display: table;
        }
        .layout__aside, .layout__main {
            float: left;
        }
        .layout {
            padding-left: 210px;
        }
        .layout__main {
            width: 100%;
        }
        .layout__aside {
            width: 200px;
            margin-left: -210px;
        }
    </style>

    效果是:

    新葡亰496net 8

    2)布局二:2栏布局,侧边栏固定在右边,左侧是主体内容栏:

    <div class="layout"> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside">侧边栏宽度固定</aside> </div>

    1
    2
    3
    4
    <div class="layout">
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside">侧边栏宽度固定</aside>
    </div>

    <style type="text/css"> .layout:after { clear: both; content: " "; display: table; } .layout { padding-right: 210px; } .layout__main { width: 100%; float: left; } .layout__aside { float: right; width: 200px; margin-right: -210px; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <style type="text/css">
        .layout:after {
            clear: both;
            content: " ";
            display: table;
        }
        .layout {
            padding-right: 210px;
        }
        .layout__main {
            width: 100%;
            float: left;
        }
        .layout__aside {
            float: right;
            width: 200px;
            margin-right: -210px;
        }
    </style>

    效果是:

    新葡亰496net 9

    3)布局三:3栏布局,2个侧边栏分别固定在左边和右边,中间是主体内容栏:

    <div class="layout"> <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside> </div>

    1
    2
    3
    4
    5
    <div class="layout">
        <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside>
    </div>

    <style type="text/css"> .layout:after { clear: both; content: " "; display: table; } .layout__aside, .layout__main { float: left; } .layout { padding:0 210px; } .layout__main { width: 100%; } .layout__aside { width: 200px; } .layout__aside--left { margin-left: -210px; } .layout__aside--right { margin-right: -210px; float: right; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <style type="text/css">
        .layout:after {
            clear: both;
            content: " ";
            display: table;
        }
        .layout__aside, .layout__main {
            float: left;
        }
        .layout {
            padding:0 210px;
        }
        .layout__main {
            width: 100%;
        }
        .layout__aside {
            width: 200px;
        }
        .layout__aside--left {
            margin-left: -210px;
        }
        .layout__aside--right {
            margin-right: -210px;
            float: right;
        }
    </style>

    效果是:

    新葡亰496net 10

    4)布局四:3栏布局,2个侧边栏同时固定在左边,右边是主体内容栏:

    <div class="layout"> <aside class="layout__aside layout__aside--first">第1个侧边栏宽度固定</aside> <aside class="layout__aside layout__aside--second">第2个侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> </div>

    1
    2
    3
    4
    5
    <div class="layout">
        <aside class="layout__aside layout__aside--first">第1个侧边栏宽度固定</aside>
        <aside class="layout__aside layout__aside--second">第2个侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
    </div>

    <style type="text/css"> .layout:after { clear: both; content: " "; display: table; } .layout__aside, .layout__main { float: left; } .layout { padding-left: 420px; } .layout__main { width: 100%; } .layout__aside { width: 200px; } .layout__aside--first { margin-left: -420px; } .layout__aside--second { margin-left: -210px; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <style type="text/css">
        .layout:after {
            clear: both;
            content: " ";
            display: table;
        }
        .layout__aside, .layout__main {
            float: left;
        }
        .layout {
            padding-left: 420px;
        }
        .layout__main {
            width: 100%;
        }
        .layout__aside {
            width: 200px;
        }
        .layout__aside--first {
            margin-left: -420px;
        }
        .layout__aside--second {
            margin-left: -210px;
        }
    </style>

    效果是:

    新葡亰496net 11

    5)布局五:3栏布局,2个侧边栏同时固定在右边,左边是主体内容栏:

    <div class="layout"> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside layout__aside--first">第1个侧边栏宽度固定</aside> <aside class="layout__aside layout__aside--second">第2个侧边栏宽度固定</aside> </div>

    1
    2
    3
    4
    5
    <div class="layout">
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside layout__aside--first">第1个侧边栏宽度固定</aside>
        <aside class="layout__aside layout__aside--second">第2个侧边栏宽度固定</aside>
    </div>

    <style type="text/css"> .layout:after { clear: both; content: " "; display: table; } .layout { padding-right: 420px; } .layout__main { width: 100%; float: left; } .layout__aside { width: 200px; float: right; } .layout__aside--first { margin-right: -210px; } .layout__aside--second { margin-right: -420px; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <style type="text/css">
        .layout:after {
            clear: both;
            content: " ";
            display: table;
        }
        .layout {
            padding-right: 420px;
        }
        .layout__main {
            width: 100%;
            float: left;
        }
        .layout__aside {
            width: 200px;
            float: right;
        }
        .layout__aside--first {
            margin-right: -210px;
        }
        .layout__aside--second {
            margin-right: -420px;
        }
    </style>

    效果是:

    新葡亰496net 12

    PS:

    1)本文提供的这个布局方法,比网上看到的更加简洁一些,主要是因为不考虑兼容IE8及以下,不考虑把layout__main这个元素放在最前面,虽然经典的做法都要求把layout__main做法放在前面,这样可以让网页主体内容优先渲染,我认为这种考虑是完全多余的,2个元素的渲染顺序不同,实际上的用户体验差别又有多大呢,为了一个肉眼看不到的差异,而采用更复杂的做法,不值得;

    2)css布局类的命名采用了BEM的命名规则,这个可以帮助你写出结构化,规范化的css,有兴趣的可以去了解:

    3)在使用以上方法时,需注意html结构中layout__main与layout__aside的顺序;

    垂直居中

    单行文本垂直居中

    <div class="parent">
        <div class="child">child</div>
    </div>
    
    .parent {
       line-height: 200px;
    }
    

    图片垂直居中

    <div class="parent">
        ![](image.png)
    </div>
    
    .parent {
        line-height: 200px;
    }
    .parent img {
        vertical-align: middle;
    }
    

    table方法

    <div class="parent">
        <div class="child">child</div>
    </div>
    
    .parent {
        display: table;
        height: 100px;
    }
    
    .child {
        text-align: center;
        display: table-cell;
        vertical-align: middle;
    }
    

    flex方法

    <div class="parent">
        <div class="child">child</div>
    </div>
    
    .parent {
       display: flex;
       align-items: center;
    }
    

    css translate

    .parent {
        height: 100px;
        /*不设置高度则要设置如下*/
        /*position:relative;*/
    }
    
    .child {
        /*不设置高度则要设置绝对定位*/
        /*position:absolute;*/
        position: relative;
        top: 50%;
        transform: translateY(-50%);
    }
    

    目录

    1. 常用居中方法
      • 水平居中
      • 垂直居中
    2. 单列布局
    3. 二列&三列布局
      • float margin
      • position margin
      • 圣杯布局(float 负margin)
      • 双飞翼布局(float 负margin)
      • flex布局
    4. 总结

    3. 方法三:使用绝对定位

    上文没有介绍的另外一种分栏布局方法就是这里要介绍的绝对定位。之所以没介绍这个方法,是因为上文介绍的都是分栏自适应布局的方法,而绝对定位的做法,不能完全做到我们想要的分栏自适应布局,分栏自适应有两个原则:第一是主体内容栏宽度自适应,这点绝对定位是可以做到的;第二点是所有栏的高度都能动态变化,并且不能导致父容器高度塌陷,不能在各栏内部出现滚动或溢出的情况,这点绝对定位不容易做到适用所有场景。而本文又把这种布局方法拿出来介绍,是因为绝对定位做等高布局很容易,所以用绝对定位做等高分栏布局是一种可行的办法,只是这种方法适用的场景有一些限制,需要根据实际情况考虑是否要采用。

    做法一:所有栏都采用绝对定位(对应源码中absolute_layout1.html)

    <header>顶部</header> <div class="layout"> <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside> <div class="layout__main">内容栏宽度自适应</div> <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside> </div> <footer>底部</footer>

    1
    2
    3
    4
    5
    6
    7
    <header>顶部</header>
    <div class="layout">
        <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside>
        <div class="layout__main">内容栏宽度自适应</div>
        <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside>
    </div>
    <footer>底部</footer>

    <style type="text/css"> .layout { height: 300px; position: relative; } .layout__aside, .layout__main { position: absolute; top: 0; bottom: 0; } .layout__main { left: 210px; right: 210px; } .layout__aside { width: 200px; } .layout__aside--left { left: 0; } .layout__aside--right { right: 0; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <style type="text/css">
        .layout {
            height: 300px;
            position: relative;
        }
        .layout__aside, .layout__main {
            position: absolute;
            top: 0;
            bottom: 0;
        }
        .layout__main {
            left: 210px;
            right: 210px;
        }
        .layout__aside {
            width: 200px;
        }
        .layout__aside--left {
            left: 0;
        }
        .layout__aside--right {
            right: 0;
        }
    </style>

    效果:

    新葡亰496net 13

    这种布局方法的特点是:

    1)主体内容栏是自适应的;

    2)所有栏完全等高,效果跟flex布局和伪table布局的效果一样;

    从这两点来看,这种绝对定位的方法还是比较好用的,不过它有一个非常大的使用限制,就是父元素的高度没有办法通过它的内部元素给撑起来,要用的话,必须想办法让父元素有高度,适合做父元素高度可知或者全屏布局。比如以下这个代码就是全屏布局的一个例子(对应源码中absolute_layout2.html):

    header>顶部header> div class="layout"> aside class="layout__aside layout__aside--left">左侧边栏宽度固定aside> div class="layout__main">内容栏宽度自适应div> aside class="layout__aside layout__aside--right">右侧边栏宽度固定aside> div> footer>底部footer>

    1
    2
    3
    4
    5
    6
    7
    header>顶部header>
    div class="layout">
        aside class="layout__aside layout__aside--left">左侧边栏宽度固定aside>
        div class="layout__main">内容栏宽度自适应div>
        aside class="layout__aside layout__aside--right">右侧边栏宽度固定aside>
    div>
    footer>底部footer>

    <style type="text/css"> html,body { margin: 0; height: 100%; } footer { position: absolute; bottom: 0; width: 100%; } .layout { width: 100%; position: absolute; top: 50px; bottom: 50px; } .layout__aside, .layout__main { position: absolute; top: 0; bottom: 0; } .layout__main { left: 210px; right: 210px; } .layout__aside { width: 200px; } .layout__aside--left { left: 0; } .layout__aside--right { right: 0; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <style type="text/css">
        html,body {
            margin: 0;
            height: 100%;
        }
        footer {
            position: absolute;
            bottom: 0;
            width: 100%;
        }
        .layout {
            width: 100%;
            position: absolute;
            top: 50px;
            bottom: 50px;
        }
        .layout__aside, .layout__main {
            position: absolute;
            top: 0;
            bottom: 0;
        }
        .layout__main {
            left: 210px;
            right: 210px;
        }
        .layout__aside {
            width: 200px;
        }
        .layout__aside--left {
            left: 0;
        }
        .layout__aside--right {
            right: 0;
        }
    </style>

    效果:

    新葡亰496net 14

    做法二:侧边栏绝对定位,主体内容栏保持流式布局(对应源码中absolute_layout3.html)

    <div class="layout"> <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside> <div class="layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度都会自动增加</div> <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside> </div>

    1
    2
    3
    4
    5
    <div class="layout">
        <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside>
        <div class="layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度都会自动增加</div>
        <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside>
    </div>

    <style type="text/css"> .layout { position: relative; } .layout__aside { position: absolute; top: 0; bottom: 0; } .layout__main { margin: 0 210px; } .layout__aside { width: 200px; } .layout__aside--left { left: 0; } .layout__aside--right { right: 0; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <style type="text/css">
        .layout {
            position: relative;
        }
        .layout__aside {
            position: absolute;
            top: 0;
            bottom: 0;
        }
        .layout__main {
            margin: 0 210px;
        }
        .layout__aside {
            width: 200px;
        }
        .layout__aside--left {
            left: 0;
        }
        .layout__aside--right {
            right: 0;
        }
    </style>

    效果:

    新葡亰496net 15

    这个方法的特点是:

    1)主体内容栏是宽度自适应的;

    2)所有栏也是完全等高的;

    上面的代码中,layout__main通过magin来给侧边栏留出空间,其实也可以在layout元素上添加padding来处理,作用是一样的。这个方法相比前一个方法好一点的是,父元素的高度可以通过主体内容栏给撑起来,不过由此也带来了一个新问题,就是内容栏高度不够的时候,侧边栏就会出现溢出或者滚动,解决这个新问题的办法有2个:第一,如果侧边栏的内容都是已知的,并且没有折叠展开这种会改变侧边栏内容高度的功能,那么可以给layout设置一个min-height来处理;第二,如果侧边栏的内容是动态的,除了给layout加min-height之外,还得在每次改变侧边栏内容的时候,主动去调整主体内容栏的高度,如果主体内容栏的高度小于侧边栏的高度,就要更新主体内容栏的高度。不过如果你的内容栏的内容很多,侧边栏内容较少的话,就不用考虑这个新问题了。

    绝对定位的做法就是这样,第一种限制较高;第二种稍微强一些,在一些场景下,可能还得借助JS来处理,所以综合起来不算是一个非常好的方式。只有你的布局需求恰好满足它的条件时,可能才会考虑使用它,就像上文中我提出的项目一的需求,就一定要用绝对定位的布局来做。

    3. 圣杯布局传统实现方法的一种变体

    第2部分介绍的方法,使用诀窍是:

    1)layout元素根据分栏布局的要求设置合适的padding,比如布局一,需配置padding-left;

    2)layout__main和layout__aside元素都需要浮动,layout__main需配置float: left;layout__aside需根据分栏布局要求配置合适的float值,比如布局一,需配置为float: left;而布局二需配置float: right;

    3)layout__main和layout__aside的顺序也很关键,具体内容可对比前面五种布局的html;

    4)layout__aside需根据分栏布局要求,配置合适的margin-left或margin-right,比如布局一,需配置margin-left;布局二需配置margin-right。

    虽然我不喜欢一定要坚持把layout__main放在前面,但是从第2部分这种方法的思路,衍生出的另外一种方法,却不得不要求始终把layout__main放在最前面,这种变体做法,也被称之为双飞翼布局。下面来看看双飞翼布局的实现方法(考虑到篇幅问题,本处仅提供布局三的代码,要想了解五种布局的详细方法,可以通过在第2部分提供的下载链接下载源码去了解,本部分的布局方法在代码中对应wing_layout{1,5}.html)

    1)布局三:3栏布局,2个侧边栏分别固定在左边和右边,中间是主体内容栏:

    <div class="layout__main-wrapper"> <div class="layout__main">主内容栏宽度自适应</div> </div> <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside> <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside> <footer class="clear">底部</footer>

    1
    2
    3
    4
    5
    6
    <div class="layout__main-wrapper">
        <div class="layout__main">主内容栏宽度自适应</div>
    </div>
    <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside>
    <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside>
    <footer class="clear">底部</footer>

    <style type="text/css"> .clear { clear: both; } .layout__main-wrapper,.layout__aside { float: left; } .layout__main-wrapper { width: 100%; } .layout__main { margin: 0 210px; } .layout__aside { width: 200px; } .layout__aside--left { margin-left: -100%; } .layout__aside--right { margin-left: -200px; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <style type="text/css">
        .clear {
            clear: both;
        }
        .layout__main-wrapper,.layout__aside {
            float: left;
        }
        .layout__main-wrapper {
            width: 100%;
        }
        .layout__main {
            margin: 0 210px;
        }
        .layout__aside {
            width: 200px;
        }
        .layout__aside--left {
            margin-left: -100%;
        }
        .layout__aside--right {
            margin-left: -200px;
        }
    </style>

    这段代码的效果与第2部分布局三的效果一样,这种布局的诀窍是:

    1)可以没有layout这一层包裹元素;

    2)浮动清除需在外部元素上处理;

    3)float和margin属性的设置方向相对统一,基本都是一个方向即可;

    4)布局四和布局五实现起来,双飞翼布局还需要借助position:relative才行,相对要复杂一点。

    水平居中
    <div class="parent">
         <div class="child">child</div>
    </div>
    

    行内元素:对父元素设置text-align:center;

    定宽块状元素: 设置左右margin值为auto;

    不定宽块状元素: 设置子元素为display:inline,然后在父元素上设置text-align:center;

    css3 translate

    .parent {
    position: relative;
    }
    .child {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
    }
    

    通用方案: flex布局,对父元素设置display:flex;justify-content:center;

    .parent,
    .child {
        border: 1px solid red;
    }
    .child {
         /*display: inline;*/
    }
    .parent {
         /*text-align: center;*/
        display: flex;
        justify-content: center;
    }```
    #####水平垂直居中
    

    position: absolute/fixed;
    width: 200px;
    height: 200px;
    top: 50%;
    left: 50%;
    margin-top: -100px;
    margin-left: -100px;
    background: red;

    position: fixed/absolute;
    width: 160px;
    height: 160px;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
    background: pink;

    position: absolute;
    width: 80px;
    height: 80px;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    -webkit-transform: translate(-50%, -50%);
    -moz-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
    background: green;

    #### 单列布局
    ![](http://upload-images.jianshu.io/upload_images/2065390-25c6a8e53ff1f2f9.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)
    特征:**定宽、水平居中**
    常见的单列布局有两种:
    一种是header、content、footer宽度都相同,其一般不会占满浏览器的最宽宽度,但当浏览器宽度缩小低于其最大宽度时,宽度会自适应。
    一种是header、footer宽度为浏览器宽度,但content以及header和footer里的内容却不会占满浏览器宽度。
    
    对于第一种,对header、content、footer统一设置width或max-width,并通过margin:auto实现居中。
    

    <div class="layout">
    <div id="header">头部</div>
    <div id="content">内容</div>
    <div id="footer">尾部</div>
    </div>

    .layout {
        /* width: 960px; */
        /*设置width当浏览器窗口宽度小于960px时,单列布局不会自适应。*/
        max-width: 960px;
        margin: 0 auto;
    }
    
    对于第二种,header、footer的内容宽度为100%,但header、footer的内容区以及content统一设置width 或 max-width,并通过margin:auto实现居中。
    

    <div id="header">
    <div class="layout">头部</div>
    </div>
    <div id="content" class="layout">内容</div>
    <div id="footer">
    <div class="layout">尾部</div>
    </div>

    .layout {
        /* width: 960px; */
        /*设置width当浏览器窗口宽度小于960px时,单列布局不会自适应。*/
        max-width: 960px;
        margin: 0 auto;
    }
    
    
    #### 二列&三列布局
    ![](http://upload-images.jianshu.io/upload_images/2065390-06862f5dabd3ef11.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)
    二列布局的特征是侧栏固定宽度,主栏自适应宽度。三列布局的特征是两侧两列固定宽度,中间列自适应宽度。
    之所以将二列布局和三列布局写在一起,是因为二列布局可以看做去掉一个侧栏的三列布局,其布局的思想有异曲同工之妙。对于传统的实现方法,主要讨论上图中前三种布局,经典的带有侧栏的二栏布局以及带有左右侧栏的三栏布局,对于flex布局,实现了上图的五种布局。
    ######a. float margin
    **原理说明**:设置两个侧栏分别向左向右浮动,中间列通过外边距给两个侧栏腾出空间,中间列的宽度根据浏览器窗口自适应。
    

    <div id="content">
    <div class="sub">sub</div>
    <div class="extra">extra</div>
    <div class="main">main</div>
    </div>

    **布局步骤**:
    对两边侧栏分别设置宽度,并对左侧栏添加左浮动,对右侧栏添加有浮动。
    对主面板设置左右外边距,margin-left的值为左侧栏的宽度,margin-right的值为右侧栏的宽度。
    

    .sub{ width: 100px; float: left;}
    .extra{ width: 200px; float: right;}
    .main{ margin-left: 100px; margin-right: 200px;}

    **一些说明**:
    注意DOM文档的书写顺序,先写两侧栏,再写主面板,更换后则侧栏会被挤到下一列(圣杯布局和双飞翼布局都会用到)。  
    这种布局方式比较简单明了,但缺点是渲染时先渲染了侧边栏,而不是比较重要的主面板。
    
    **二列的实现方法**
    如果是左边带有侧栏的二栏布局,则去掉右侧栏,不要设置主面板的margin-right值,其他操作相同。反之亦然。
    ######b. position margin
    **原理说明**:通过绝对定位将两个侧栏固定,同样通过外边距给两个侧栏腾出空间,中间列自适应。
    

    <div class="sub">left</div>
    <div class="main">main</div>
    <div class="extra">right</div>

    **布局步骤**:
    对两边侧栏分别设置宽度,设置定位方式为绝对定位。
    设置两侧栏的top值都为0,设置左侧栏的left值为0, 右侧栏的right值为0。
    对主面板设置左右外边距,margin-left的值为左侧栏的宽度,margin-right的值为右侧栏的宽度。
    

    .sub, .extra { position: absolute; top: 0; width: 200px;}
    .sub { left: 0;}
    .extra { right: 0; }
    .main { margin: 0 200px;}

    **一些说明**:
    本方法不限制DOM书写顺序,先写主面板会使主面板部分优先渲染(一般主面板会比侧栏内容重要)。
    与上一种方法相比,本种方法是通过定位来实现侧栏的位置固定。
    如果中间栏含有最小宽度限制,或是含有宽度的内部元素,则浏览器窗口小到一定程度,主面板与侧栏会发生重叠。
    
    **二列的实现方法**
    如果是左边带有侧栏的二栏布局,则去掉右侧栏,不要设置主面板的margin-right值,其他操作相同。反之亦然。
    ######c. 圣杯布局(float   负margin)
    **原理说明**:
    主面板设置宽度为100%,主面板与两个侧栏都设置浮动,常见为左浮动,这时两个侧栏会被主面板挤下去。通过负边距将浮动的侧栏拉上来,左侧栏的负边距为100%,刚好是窗口的宽度,因此会从主面板下面的左边跑到与主面板对齐的左边,右侧栏此时浮动在主面板下面的左边,设置负边距为负的自身宽度刚好浮动到主面板对齐的右边。为了避免侧栏遮挡主面板内容,在外层设置左右padding值为左右侧栏的宽度,给侧栏腾出空间,此时主面板的宽度减小。由于侧栏的负margin都是相对主面板的,两个侧栏并不会像我们理想中的停靠在左右两边,而是跟着缩小的主面板一起向中间靠拢。此时使用相对布局,调整两个侧栏到相应的位置。
    

    <div id="bd">
    <div class="main"></div>
    <div class="sub"></div>
    <div class="extra"></div>
    </div>

    **布局步骤**:
    三者都设置向左浮动。
    设置main宽度为100%,设置两侧栏的宽度。
    设置 负边距,sub设置负左边距为100%,extra设置负左边距为负的自身宽度。
    设置main的padding值给左右两个子面板留出空间。
    设置两个子面板为相对定位,sub的left值为负的sub宽度,extra的right值为负的extra宽度。
    

    <style>
    .main {
    float: left;
    width: 100%;
    }

    .sub {
        float: left;
        width: 190px;
        margin-left: -100%;
        position: relative;
        left: -190px;
    }
    
    .extra {
        float: left;
        width: 230px;
        margin-left: -230px;
        position: relative;
        right: -230px;
    }
    
    #bd {
        padding: 0 230px 0 190px;
    }
    

    </style>

    **一些说明**
    DOM元素的书写顺序不得更改。
    主面板部分优先渲染(一般主面板会比侧栏内容重要)。
    当面板的main内容部分比两边的子面板宽度小的时候,布局就会乱掉。可以通过设置main的min-width属性或使用双飞翼布局避免问题。
    
    **二列的实现方法**
    如果是左边带有侧栏的二栏布局,则去掉右侧栏,不要设置主面板的padding-right值,其他操作相同。反之亦然。
    ######d. 双飞翼布局(float   负margin )
    **原理说明**:
    双飞翼布局和圣杯布局的思想有些相似,都利用了浮动和负边距,但双飞翼布局在圣杯布局上做了改进,在main元素上加了一层div, 并设置margin,由于两侧栏的负边距都是相对于main-wrap而言,main的margin值变化便不会影响两个侧栏,因此省掉了对两侧栏设置相对布局的步骤。
    

    <div class="main-wrap">
    <div class="main">#main</div>
    </div>
    <div class="sub"></div>
    <div class="extra"></div>

    **布局步骤**:
    三者都设置向左浮动。
    设置main-wrap宽度为100%,设置两个侧栏的宽度。
    设置 负边距,sub设置负左边距为100%,extra设置负左边距为负的自身宽度。
    设置main的margin值给左右两个子面板留出空间。
    

    <style>
    .main-wrap {
    float: left;
    width: 100%;
    }

    .sub {
        float: left;
        width: 190px;
        margin-left: -100%;
    }
    
    .extra {
        float: left;
        width: 230px;
        margin-left: -230px;
    }
    
    .main {
        margin: 0 230px 0 190px;
    }
    

    </style>

    **一些说明**
    主面板部分优先渲染(一般主面板会比侧栏内容重要)。
    圣杯采用的是padding,而双飞翼采用的margin,解决了圣杯布局main的最小宽度不能小于左侧栏的缺点。
    双飞翼布局不用设置相对布局,以及对应的left和right值。
    通过引入相对布局,可以实现三栏布局的各种组合,例如对右侧栏设置position: relative; left: 190px;,可以实现sub extra main的布局。
    
    **二列的实现方法**
    如果是左边带有侧栏的二栏布局,则去掉右侧栏,不要设置main-wrap的margin-right值,其他操作相同。反之亦然。
    ######e. flex布局
    
    [Flex 布局教程:语法篇 - 阮一峰的网络日志](http://link.zhihu.com/?target=http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool)
    [Flex 布局教程:实例篇 - 阮一峰的网络日志](http://link.zhihu.com/?target=http://www.ruanyifeng.com/blog/2015/07/flex-examples.html)
    以下是五种布局的flex布局代码:
    

    <div class="layout">
    <aside class="aside">侧边栏宽度固定</aside>
    <div class="main">主内容栏宽度自适应</div>
    </div>
    <div class="layout">
    <div class="main">主内容栏宽度自适应</div>
    <aside class="aside">侧边栏宽度固定</aside>
    </div>
    <div class="layout">
    <aside class="aside">左侧边栏宽度固定</aside>
    <div class="main">主内容栏宽度自适应</div>
    <aside class="aside">右侧边栏宽度固定</aside>
    </div>
    <div class="layout">
    <aside class="aside">第1个侧边栏宽度固定</aside>
    <aside class="aside">第2个侧边栏宽度固定</aside>
    <div class="main">主内容栏宽度自适应</div>
    </div>
    <div class="layout">
    <div class="main">主内容栏宽度自适应</div>
    <aside class="aside">第1个侧边栏宽度固定</aside>
    <aside class="aside">第2个侧边栏宽度固定</aside>
    </div>

    <style>
    .layout {
    display: flex;
    }

    .main {
        flex: 1;
    }
    
    .aside {
        width: 200px;
    }
    

    </style>

    1.常用居中方法

    居中在布局中很常见,我们假设DOM文档结构如下,子元素要在父元素中居中:

    XHTML

    <div class="parent"> <div class="child"></div> </div>

    1
    2
    3
    <div class="parent">
        <div class="child"></div>
    </div>

    4. 方法四:借助边框,背景实现假等高

    前面介绍了几种分栏等高布局,有table布局,伪table布局,绝对定位布局,flex布局,这四种布局方法在实现等高布局时,属于完全等高的情况,就是说他们布局出来的页面,各栏的真实高度都是相同的,并且在任意栏的内容动态变化时,其它栏的高度都能相应地自动调整,如果布局的时候用的是这几个布局方法,那么等高的问题就不存在了。不过回看一下上文内容的话,上文提到的3种布局方式:圣杯布局,双飞翼布局,float布局,不用JS的话,就无法做到这种完全等高的效果。这三种布局,只能考虑借助边框和背景实现视觉上的等高,也就是假等高的做法。毕竟从效果上来说,如果没有设置背景和边框的话,即使是完全等高,视觉上也看不出来,所以假等高的做法是值得采用的。

    做法一:利用背景图片

    以布局容器宽度固定的左中右三栏布局说明这个做法的步骤,首先制作一张高度较小,宽度跟布局容器宽度相同的背景图片,把这张图片作为布局容器的背景图垂直平铺。这张背景图要求跟页面一样也是分栏,而且每栏的宽度和栏之间的间隔都跟页面布局里面的栏位宽度和栏位间隔相同,这样才能保证,背景图片的每个栏位与页面里面的每个栏位重合。因为页面里面的每个栏位底下,都有一个背景图片的栏位跟它对应,所以即使某一栏高度不够,但是视觉上这个栏位的高度跟布局容器的高度是相同的,这就是借助背景图来达到视觉等高的原理。这个做法的经典例子就是,它的布局效果是这样的:

    新葡亰496net 16

    看起来这是一个三栏等高布局,分栏是通过float实现的,等高却不是完全等高,而是通过背景图片实现的,它在布局容器上用了下面这张背景图:

    新葡亰496net 17

    新葡亰496net 18

    它的布局html结构是(马赛克掉的是header,导航栏,footer,跟分栏布局没有关系,所以注掉了):

    新葡亰496net 19

    然后各栏只要都向左浮动,配置好宽度就行:

    新葡亰496net 20新葡亰496net 21新葡亰496net 22

    前面说明这个做法的步骤包括举的例子都针对的是布局容器宽度固定的左中右三栏布局,如果是自适应的分栏布局,又该怎么处理?下面以上文圣杯布局的布局三如何借助背景图片做到等高效果来说明(为了减少篇幅,其它四种布局不会一一说明,但是这五种布局在源码中都有demo页面可查看,分别对应grail_bg_layout{1,5}.html)。

    布局三:3栏布局,2个侧边栏分别固定在左边和右边,中间是主体内容栏:

    div class="layout--wrapper"> div class="layout"> aside class="layout__aside layout__aside--left">左侧边栏宽度固定aside> div class="layout__main">内容栏宽度自适应br>高度增加一点,旁边的高度看起来都跟内容栏高度一样div> aside class="layout__aside layout__aside--right">右侧边栏宽度固定aside> div> div>

    1
    2
    3
    4
    5
    6
    7
    div class="layout--wrapper">
        div class="layout">
            aside class="layout__aside layout__aside--left">左侧边栏宽度固定aside>
            div class="layout__main">内容栏宽度自适应br>高度增加一点,旁边的高度看起来都跟内容栏高度一样div>
            aside class="layout__aside layout__aside--right">右侧边栏宽度固定aside>
        div>
    div>

    <style type="text/css"> .layout:after { content: " "; clear: both; display: table; } .layout__aside, .layout__main { float: left; height: 100%; } .layout--wrapper { background: url(aside_left.png) left top repeat-y #4DBCB0; } .layout { background: url(aside_right.png) right top repeat-y; padding:0 210px; } .layout__main { width: 100%; } .layout__aside { width: 200px; } .layout__aside--left { margin-left: -210px; } .layout__aside--right { margin-right: -210px; float: right; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <style type="text/css">
        .layout:after {
            content: " ";
            clear: both;
            display: table;
        }
        .layout__aside, .layout__main {
            float: left;
            height: 100%;
        }
        .layout--wrapper {
            background: url(aside_left.png) left top repeat-y #4DBCB0;
        }
        .layout {
            background: url(aside_right.png) right top repeat-y;
            padding:0 210px;
        }
        .layout__main {
            width: 100%;
        }
        .layout__aside {
            width: 200px;
        }
        .layout__aside--left {
            margin-left: -210px;
        }
        .layout__aside--right {
            margin-right: -210px;
            float: right;
        }
    </style>

    效果:

    新葡亰496net 23

    实现这个等高效果的关键是:

    1)去掉在layout__aside layout__main上设置的背景色;

    2)制作2张背景图片,宽度都是210 * 10,分别用来做两个侧边栏的背景:

    aside_left.png : 新葡亰496net 24

    aside_right.png: 新葡亰496net 25

    3) html结构稍微调整下,加一层wrapper

    4)layout–wrapper的背景如下设置:

    background: url(aside_left.png) left top repeat-y #4DBCB0;

    这样左侧边栏和内容栏就都有了背景,左侧边栏与内容栏之间的间隔效果也出来了。

    5)layout的背景如下设置:

    background: url(aside_right.png) right top repeat-y;

    这样右侧边栏就有了背景,右侧边栏与内容栏之间的间隔效果也出来了。

    以上就是利用背景图做假等高效果的全部内容,这个做法对于要用背景来呈现等高效果的布局是非常好用的一个方法,虽然网上都说它的缺点是用到了图片,布局一改,图片就要改,我个人认为这并不是缺点,因为这样的需求变动,第一是无法避免,第二是变动地次数不一定很多,第三即使变了改起来也是两三分钟的事,要是自己会点PS,那弄起来就更简单了。能解决问题的简单方法就是最好的办法。

    做法二: 利用边框重叠

    首先得说这个做法,适合要用边框来呈现等高效果的布局,也就是说各栏不能有背景,否则看起来边框是等高了,但是背景没有等高。它的原理要分成两部分来说,如果是2栏布局,做法比较简单,比如左右分栏的布局,给侧边栏加一个右边框,给内容栏加一个左边框,然后给内容栏加上负的margin-left,让2个边框重合,这样不管哪个栏位内容多,边框重叠之后的高度就跟整体的高度一致了,也就达到了我们想要的等高效果;如果是多栏布局,这种边框重叠的方式不能做到所有场景下的视觉等高,比如说左中右三栏布局,现在是按边框重叠的办法实现了下等高,当左边栏的内容动态增加很多时,右边侧边栏跟内容栏的边框整体高度,并不会动态增加,然后就会形成错层的效果,对于这种情况,可以利用绝对定位,用额外的空元素模拟栏与栏之间的边框效果。

    下面以上文圣杯布局的布局一和布局三如何借助边框重叠和模拟做到等高效果来说明(为了减少篇幅,其它布局不会一一说明,但是这几种布局在源码中都有demo页面可查看,分别对应grail_border_layout{1,3}.html)。

    1)布局一:2栏布局,侧边栏固定在左边,右侧是主体内容栏:

    <div class="layout"> <aside class="layout__aside">侧边栏宽度固定</aside> <div class="layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度看起来都跟内容栏高度一样</div> </div>

    1
    2
    3
    4
    <div class="layout">
        <aside class="layout__aside">侧边栏宽度固定</aside>
        <div class="layout__main">内容栏宽度自适应<br>高度增加一点,旁边的高度看起来都跟内容栏高度一样</div>
    </div>

    <style type="text/css"> .layout:after { content: " "; clear: both; display: table; } .layout__aside, .layout__main { float: left; } .layout { padding-left: 201px; } .layout__main { width: 100%; margin-left: -1px; border-left: 1px solid #ccc; } .layout__aside { width: 200px; border-right: 1px solid #ccc; margin-left: -201px; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <style type="text/css">
        .layout:after {
            content: " ";
            clear: both;
            display: table;
        }
        .layout__aside, .layout__main {
            float: left;
        }
        .layout {
            padding-left: 201px;
        }
        .layout__main {
            width: 100%;
            margin-left: -1px;
            border-left: 1px solid #ccc;
        }
        .layout__aside {
            width: 200px;
            border-right: 1px solid #ccc;
            margin-left: -201px;
        }
    </style>

    要点是:

    1)要重新调整layout的padding值,和layout__aside的margin值,栏与栏之间不能有间隔;

    2)layout__main设置-1px的margin-left和1px的border-left;layout__aside设置1px的border-right

    效果:

    新葡亰496net 26

    布局三:3栏布局,2个侧边栏分别固定在左边和右边,中间是主体内容栏:

    <div class="layout"> <aside class="layout__division layout__division--left"></aside> <aside class="layout__division layout__division--right"></aside> <aside class="layout__aside layout__aside--left">左侧边栏宽度固定<br>再加点东西<br>再加点东西</aside> <div class="layout__main">内容栏宽度自适应<br>高度增加一点</div> <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside> </div>

    1
    2
    3
    4
    5
    6
    7
    <div class="layout">
        <aside class="layout__division layout__division--left"></aside>
        <aside class="layout__division layout__division--right"></aside>
        <aside class="layout__aside layout__aside--left">左侧边栏宽度固定<br>再加点东西<br>再加点东西</aside>
        <div class="layout__main">内容栏宽度自适应<br>高度增加一点</div>
        <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside>
    </div>

    <style type="text/css"> .layout:after { content: " "; clear: both; display: table; } .layout__aside, .layout__main { float: left; height: 100%; } .layout { padding:0 201px; position: relative; } .layout__main { width: 100%; } .layout__aside { width: 200px; } .layout__aside--left { margin-left: -201px; } .layout__aside--right { margin-right: -201px; float: right; } .layout__division { position: absolute; border-left: 1px solid #ccc; height: 100%; } .layout__division--left { left:200px; } .layout__division--right { right:200px; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <style type="text/css">
        .layout:after {
            content: " ";
            clear: both;
            display: table;
        }
        .layout__aside, .layout__main {
            float: left;
            height: 100%;
        }
        .layout {
            padding:0 201px;
            position: relative;
        }
        .layout__main {
            width: 100%;
        }
        .layout__aside {
            width: 200px;
        }
        .layout__aside--left {
            margin-left: -201px;
        }
        .layout__aside--right {
            margin-right: -201px;
            float: right;
        }
        .layout__division {
            position: absolute;
            border-left: 1px solid #ccc;
            height: 100%;
        }
        .layout__division--left {
            left:200px;
        }
        .layout__division--right {
            right:200px;
        }
    </style>

    效果:

    新葡亰496net 27

    布局三这个做法的原理比真实的边框重叠还要简单些,但是不如那种方法简洁,毕竟要增加没有用的html元素,所以不算是一个好方法。

    最后综合比较背景和边框这两种假等高做法,更值得推荐的是做法一,边框这种效果,通过背景图也是可以做出来的,而且边框能够实现的视觉效果有限,利用边框的多栏等高布局还得增加冗余的HTML元素,缺陷比较明显。

    4. 圣杯布局的纯浮动实现

    前面两种方法都有2个共同点:

    1)layout__main或layout__main-wrapper和layout__aside都会同时浮动;

    2)都得借助负值属性实现。

    其实还存在一种更加简洁的做法,不需要浮动layout__main或layout__main-wrapper,也不需要借助负值属性,只要浮动layout__aside,给layout__main加上合适的margin值,就可以利用浮动元素的特性,完成想要的分栏布局效果。还是以布局三为例,说明这种方式,其它方式可以从源码中查看,对应的是float_layout{1,5}.html:

    <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside> <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> <footer class="clear">底部</footer>

    1
    2
    3
    4
    <aside class="layout__aside layout__aside--left">左侧边栏宽度固定</aside>
    <aside class="layout__aside layout__aside--right">右侧边栏宽度固定</aside>
    <div class="layout__main">主内容栏宽度自适应</div>
    <footer class="clear">底部</footer>

    <style type="text/css"> .clear { clear: both; } .layout__main { margin: 0 210px; } .layout__aside--left { width: 200px; float: left; } .layout__aside--right { width: 200px; float: right; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <style type="text/css">
        .clear {
            clear: both;
        }
     
        .layout__main {
            margin: 0 210px;
        }
     
        .layout__aside--left {
            width: 200px;
            float: left;
        }
     
        .layout__aside--right {
            width: 200px;
            float: right;
        }
    </style>

    这段代码的效果与第2部分布局三的效果一样,这种方法的特点是:

    1)清除浮动需借助外部元素;

    2)layout__main上面不能使用clear属性。

    水平居中

    子元素为行内元素还是块状元素,宽度一定还是宽度未定,采取的布局方案不同。下面进行分析:

    行内元素:对父元素设置text-align:center;
    定宽块状元素: 设置左右margin值为auto;
    不定宽块状元素: 设置子元素为display:inline,然后在父元素上设置text-align:center;
    通用方案: flex布局,对父元素设置display:flex;justify-content:center;

    5. 结束语

    本文介绍了4种可以做到完全等高的分栏自适应布局方法,对于上文的几种分栏布局:圣杯布局,双飞翼布局,float布局,也提供了一个简单高效的方法可以做到视觉上的假等高效果,这些方法都是可靠有效的,只要满足自己的工作需求,喜欢用哪种就用哪种,毕竟工作的目的是完成工作目标,而不是尝试哪种工具好用。但如果公司的产品不考虑那些陈旧的浏览器的话,我觉得所有的布局只需要三个方法:flex,table-cell和position,其它的圣杯布局,双飞翼布局,float布局就让它成为经典,留在自己的博客总结中就好。PS: 虽然上文我在推荐圣杯布局,但是我已经打算把我的项目二的布局方式换成table-cell来搞了。

    本文内容繁多,相信耽误您不少时间,谢谢阅读,提前祝您新年快乐:)

    本文相关源码下载

    1 赞 5 收藏 评论

    新葡亰496net 28

    5. 圣杯布局的flex实现

    flex布局是一种新的网页布局方式,目前的兼容性如下:

    新葡亰496net 29

    如果你还没有了解过flex布局,建议你赶紧去学习,虽然它在pc上兼容性还有点问题,但是在移动端已经完全没有问题了,微信官方推出的weui这个框架就大量地使用了这种布局,以下是2个学习这种布局方式的非常好的资源:

    flex布局即将成为网页布局的首选方案,当你看到用flex来实现圣杯布局的代码有多简单的时候,你就会觉得前面那句话一点都没错。使用flex,可以只用同一段css实现第2部分提到的五种布局:

    <div class="layout"> <aside class="layout__aside">侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> </div> <div class="layout"> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside">侧边栏宽度固定</aside> </div> <div class="layout"> <aside class="layout__aside">左侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside">右侧边栏宽度固定</aside> </div> <div class="layout"> <aside class="layout__aside">第1个侧边栏宽度固定</aside> <aside class="layout__aside">第2个侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> </div> <div class="layout"> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside">第1个侧边栏宽度固定</aside> <aside class="layout__aside">第2个侧边栏宽度固定</aside> </div>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <div class="layout">
        <aside class="layout__aside">侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
    </div>
    <div class="layout">
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside">侧边栏宽度固定</aside>
    </div>
    <div class="layout">
        <aside class="layout__aside">左侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside">右侧边栏宽度固定</aside>
    </div>
    <div class="layout">
        <aside class="layout__aside">第1个侧边栏宽度固定</aside>
        <aside class="layout__aside">第2个侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
    </div>
    <div class="layout">
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside">第1个侧边栏宽度固定</aside>
        <aside class="layout__aside">第2个侧边栏宽度固定</aside>
    </div>

    <style type="text/css"> .layout { display: flex; } .layout__main { flex: 1; } .layout__aside { width: 200px; } .layout > .layout__aside:not(:first-child), .layout > .layout__main:not(:first-child){ margin-left: 10px; } </style>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <style type="text/css">
        .layout {
            display: flex;
        }
        .layout__main {
            flex: 1;
        }
        .layout__aside {
            width: 200px;
        }
        .layout > .layout__aside:not(:first-child),
        .layout > .layout__main:not(:first-child){
            margin-left: 10px;
        }
    </style>

    效果与第2部分每种布局做法的结果一模一样,但是代码减少了很多,而且适用的场景更多,比如4栏布局,5栏布局。

    垂直居中

    垂直居中对于子元素是单行内联文本、多行内联文本以及块状元素采用的方案是不同的。

    父元素一定,子元素为单行内联文本:设置父元素的height等于行高line-height
    父元素一定,子元素为多行内联文本:设置父元素的display:table-cellinline-block,再设置vertical-align:middle;
    块状元素:设置子元素position:fixed(absolute),然后设置margin:auto;
    通用方案: flex布局,给父元素设置{display:flex; align-items:center;}

    7. 结束语

    本文提供了4种圣杯布局的方法,每种方法在当前或者将来的工作中,肯定会有很多场景都需要使用,所以有必要完全掌握这些方法,内容不多,也不复杂,希望能对你有用,谢谢阅读:)

    补充:原本只想介绍圣杯布局这一种方法,后来觉得这样的内容有点粗糙,于是又专门去学习了另外2种分栏布局的方法,补充到了文章里面(也就是第3、4部分),所以文章虽然题为圣杯布局,但实际上讲的是分栏布局的常用方法,只有第2部分才能算是准确的圣杯布局的内容。由于本文在发布前后编辑了多次,导致标题跟内容有些脱节,请勿见怪:(

    本文相关代码下载

    1 赞 21 收藏 1 评论

    新葡亰496net 30

    2.单列布局

    新葡亰496net 31特征:定宽、水平居中

    常见的单列布局有两种:

    • 一种是headercontentfooter宽度都相同,其一般不会占满浏览器的最宽宽度,但当浏览器宽度缩小低于其最大宽度时,宽度会自适应。
    • 一种是headerfooter宽度为浏览器宽度,但content以及headerfooter里的内容却不会占满浏览器宽度。

    对于第一种,对headercontentfooter统一设置widthmax-width,并通过margin:auto实现居中。

    DOM文档:

    XHTML

    <div class="layout"> <div id="header">头部</div> <div id="content">内容</div> <div id="footer">尾部</div> </div>

    1
    2
    3
    4
    5
    <div class="layout">
      <div id="header">头部</div>
      <div id="content">内容</div>
      <div id="footer">尾部</div>
    </div>

    CSS清单:

    CSS

    .layout{ /* width: 960px; *//*设置width当浏览器窗口宽度小于960px时,单列布局不会自适应。*/ max-width: 960px; margin: 0 auto; }

    1
    2
    3
    4
    5
      .layout{
      /*   width: 960px; *//*设置width当浏览器窗口宽度小于960px时,单列布局不会自适应。*/
        max-width: 960px;
        margin: 0 auto;
      }

    对于第二种,headerfooter的内容宽度为100%,但headerfooter的内容区以及content统一设置max-width,并通过margin:auto实现居中。

    DOM文档:

    XHTML

    <div id="header"> <div class="layout">头部</div> </div> <div id="content" class="layout">内容</div> <div id="footer"> <div class="layout">尾部</div> </div>

    1
    2
    3
    4
    5
    6
    7
    <div id="header">
      <div class="layout">头部</div>
    </div>
    <div id="content" class="layout">内容</div>
    <div id="footer">
      <div class="layout">尾部</div>
    </div>

    CSS清单:

    CSS

    .layout{ /* width: 960px; *//*设置width当浏览器窗口宽度小于960px时,单列布局不会自适应。*/ max-width: 960px; margin: 0 auto; }

    1
    2
    3
    4
    5
      .layout{
      /*   width: 960px; *//*设置width当浏览器窗口宽度小于960px时,单列布局不会自适应。*/
        max-width: 960px;
        margin: 0 auto;
      }

    3. 二列&三列布局

    新葡亰496net 32

    二列布局的特征是侧栏固定宽度,主栏自适应宽度。三列布局的特征是两侧两列固定宽度,中间列自适应宽度。

    之所以将二列布局和三列布局写在一起,是因为二列布局可以看做去掉一个侧栏的三列布局,其布局的思想有异曲同工之妙。对于传统的实现方法,主要讨论上图中前三种布局,经典的带有侧栏的二栏布局以及带有左右侧栏的三栏布局,对于flex布局,实现了上图的五种布局。

    a. float margin

    原理说明:设置两个侧栏分别向左向右浮动,中间列通过外边距给两个侧栏腾出空间,中间列的宽度根据浏览器窗口自适应。

    DOM文档:

    XHTML

    <div id="content"> <div class="sub">sub</div> <div class="extra">extra</div> <div class="main">main</div> </div>

    1
    2
    3
    4
    5
    <div id="content">
        <div class="sub">sub</div>
        <div class="extra">extra</div>
        <div class="main">main</div>
    </div>

    布局步骤:

    1. 对两边侧栏分别设置宽度,并对左侧栏添加左浮动,对右侧栏添加有浮动。
    2. 对主面板设置左右外边距,margin-left的值为左侧栏的宽度,margin-right的值为右侧栏的宽度。

    CSS清单:

    CSS

    .sub{ width: 100px; float: left; } .extra{ width: 200px; float: right; } .main{ margin-left: 100px; margin-right: 200px; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    .sub{
        width: 100px;
        float: left;
    }
    .extra{
        width: 200px;
        float: right;
    }
    .main{
        margin-left: 100px;
        margin-right: 200px;
    }

    一些说明:

    * 注意DOM文档的书写顺序,先写两侧栏,再写主面板,更换后则侧栏会被挤到下一列(圣杯布局和双飞翼布局都会用到)。* 这种布局方式比较简单明了,但缺点是渲染时先渲染了侧边栏,而不是比较重要的主面板。

    二列的实现方法

    如果是左边带有侧栏的二栏布局,则去掉右侧栏,不要设置主面板的margin-right值,其他操作相同。反之亦然。

    b. position margin

    原理说明:通过绝对定位将两个侧栏固定,同样通过外边距给两个侧栏腾出空间,中间列自适应。

    DOM文档:

    XHTML

    <div class="sub">left</div> <div class="main">main</div> <div class="extra">right</div>

    1
    2
    3
    <div class="sub">left</div>
    <div class="main">main</div>
    <div class="extra">right</div>

    布局步骤:

    1. 对两边侧栏分别设置宽度,设置定位方式为绝对定位。
    2. 设置两侧栏的top值都为0,设置左侧栏的left值为0, 右侧栏的right值为0。
    3. 对主面板设置左右外边距,margin-left的值为左侧栏的宽度,margin-right的值为右侧栏的宽度。

    CSS清单:

    CSS

    .sub, .extra { position: absolute; top: 0; width: 200px; } .sub { left: 0; } .extra { right: 0; } .main { margin: 0 200px; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    .sub, .extra {
        position: absolute;
        top: 0;
        width: 200px;
    }
    .sub {
        left: 0;
    }
    .extra {
        right: 0;
    }
    .main {
        margin: 0 200px;
    }

    一些说明:

    • 与上一种方法相比,本种方法是通过定位来实现侧栏的位置固定。
    • 如果中间栏含有最小宽度限制,或是含有宽度的内部元素,则浏览器窗口小到一定程度,主面板与侧栏会发生重叠。

    二列的实现方法

    如果是左边带有侧栏的二栏布局,则去掉右侧栏,不要设置主面板的margin-right值,其他操作相同。反之亦然。

    c. 圣杯布局(float 负margin padding position)

    原理说明

    主面板设置宽度为100%,主面板与两个侧栏都设置浮动,常见为左浮动,这时两个侧栏会被主面板挤下去。通过负边距将浮动的侧栏拉上来,左侧栏的负边距为100%,刚好是窗口的宽度,因此会从主面板下面的左边跑到与主面板对齐的左边,右侧栏此时浮动在主面板下面的左边,设置负边距为负的自身宽度刚好浮动到主面板对齐的右边。为了避免侧栏遮挡主面板内容,在外层设置左右padding值为左右侧栏的宽度,给侧栏腾出空间,此时主面板的宽度减小。由于侧栏的负margin都是相对主面板的,两个侧栏并不会像我们理想中的停靠在左右两边,而是跟着缩小的主面板一起向中间靠拢。此时使用相对布局,调整两个侧栏到相应的位置。

    DOM文档:

    XHTML

    <div id="bd"> <div class="main"></div> <div class="sub"></div> <div class="extra"></div> </div>

    1
    2
    3
    4
    5
    <div id="bd">        
        <div class="main"></div>        
        <div class="sub"></div>        
        <div class="extra"></div>  
    </div>

    布局步骤:

    1. 三者都设置向左浮动。
    2. 设置main宽度为100%,设置两侧栏的宽度。
    3. 设置 负边距,sub设置负左边距为100%,extra设置负左边距为负的自身宽度。
    4. 设置main的padding值给左右两个子面板留出空间。
    5. 设置两个子面板为相对定位,sub的left值为负的sub宽度,extra的right值为负的extra宽度。

    CSS清单:

    CSS

    .main { float: left; width: 100%; } .sub { float: left; width: 190px; margin-left: -100%; position: relative; left: -190px; } .extra { float: left; width: 230px; margin-left: -230px; position: relative; right: -230px; } #bd { padding: 0 230px 0 190px; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    .main {        
        float: left;      
        width: 100%;  
    }  
    .sub {      
        float: left;        
        width: 190px;        
        margin-left: -100%;              
        position: relative;  
        left: -190px;  
    }  
    .extra {        
        float: left;        
        width: 230px;        
        margin-left: -230px;
        position: relative;
        right: -230px;  
    }
    #bd {        
        padding: 0 230px 0 190px;  
    }

    一些说明

    • DOM元素的书写顺序不得更改。
    • 当面板的main内容部分比两边的子面板宽度小的时候,布局就会乱掉。可以通过设置mainmin-width属性或使用双飞翼布局避免问题。

    二列的实现方法

    如果是左边带有侧栏的二栏布局,则去掉右侧栏,不要设置主面板的padding-right值,其他操作相同。反之亦然。

    d. 双飞翼布局(float 负margin margin)

    原理说明

    双飞翼布局和圣杯布局的思想有些相似,都利用了浮动和负边距,但双飞翼布局在圣杯布局上做了改进,在main元素上加了一层div, 并设置margin,由于两侧栏的负边距都是相对于main-wrap而言,main的margin值变化便不会影响两个侧栏,因此省掉了对两侧栏设置相对布局的步骤。

    DOM文档:

    XHTML

    <div id="main-wrap" class="column"> <div id="main">#main</div> </div> <div class="sub"></div> <div class="extra"></div>

    1
    2
    3
    4
    5
    <div id="main-wrap" class="column">
          <div id="main">#main</div>
    </div>
    <div class="sub"></div>        
    <div class="extra"></div>

    布局步骤:

    1. 三者都设置向左浮动。
    2. 设置main-wrap宽度为100%,设置两个侧栏的宽度。
    3. 设置 负边距,sub设置负左边距为100%,extra设置负左边距为负的自身宽度。
    4. 设置main的margin值给左右两个子面板留出空间。

    CSS清单:

    CSS

    .main-wrap { float: left; width: 100%; } .sub { float: left; width: 190px; margin-left: -100%; } .extra { float: left; width: 230px; margin-left: -230px; } .main { margin: 0 230px 0 190px; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    .main-wrap {        
        float: left;      
        width: 100%;  
    }  
    .sub {      
        float: left;        
        width: 190px;        
        margin-left: -100%;  
    }  
    .extra {        
        float: left;        
        width: 230px;        
        margin-left: -230px;
    }
    .main {    
        margin: 0 230px 0 190px;
    }

    一些说明

    • 圣杯采用的是padding,而双飞翼采用的margin,解决了圣杯布局main的最小宽度不能小于左侧栏的缺点。
    • 双飞翼布局不用设置相对布局,以及对应的left和right值。
    • 通过引入相对布局,可以实现三栏布局的各种组合,例如对右侧栏设置position: relative; left: 190px;,可以实现sub extra main的布局。

    二列的实现方法

    如果是左边带有侧栏的二栏布局,则去掉右侧栏,不要设置main-wrapmargin-right值,其他操作相同。反之亦然。

    e. flex布局

    如果你还没有学习flex布局,阮一峰老师的两篇博文将会很适合你。

    阮一峰的博客——flex语法
    阮一峰的博客——flex布局案例

    以下是五种布局的flex布局代码:

    DOM文档

    XHTML

    <div class="layout"> <aside class="layout__aside">侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> </div> <div class="layout"> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside">侧边栏宽度固定</aside> </div> <div class="layout"> <aside class="layout__aside">左侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside">右侧边栏宽度固定</aside> </div> <div class="layout"> <aside class="layout__aside">第1个侧边栏宽度固定</aside> <aside class="layout__aside">第2个侧边栏宽度固定</aside> <div class="layout__main">主内容栏宽度自适应</div> </div> <div class="layout"> <div class="layout__main">主内容栏宽度自适应</div> <aside class="layout__aside">第1个侧边栏宽度固定</aside> <aside class="layout__aside">第2个侧边栏宽度固定</aside> </div>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <div class="layout">
        <aside class="layout__aside">侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
    </div>
    <div class="layout">
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside">侧边栏宽度固定</aside>
    </div>
    <div class="layout">
        <aside class="layout__aside">左侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside">右侧边栏宽度固定</aside>
    </div>
    <div class="layout">
        <aside class="layout__aside">第1个侧边栏宽度固定</aside>
        <aside class="layout__aside">第2个侧边栏宽度固定</aside>
        <div class="layout__main">主内容栏宽度自适应</div>
    </div>
    <div class="layout">
        <div class="layout__main">主内容栏宽度自适应</div>
        <aside class="layout__aside">第1个侧边栏宽度固定</aside>
        <aside class="layout__aside">第2个侧边栏宽度固定</aside>
    </div>

    CSS清单

    CSS

    .layout { display: flex; } .layout__main { flex: 1; } .layout__aside { width: 200px; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .layout {
        display: flex;
    }
    .layout__main {
        flex: 1;
    }
    .layout__aside {
        width: 200px;
    }

    与之前所讲的几种传统布局方案相比,flex布局的代码可谓异常简洁,而且非常通用,利用简单的三行CSS即实现了常见的五种布局。

    总结

    传统的布局方法基于盒状模型,依赖 display属性 position属性 float属性,逻辑相对复杂,对于实现一些特殊效果,例如垂直居中,尤其复杂繁琐。而flex布局中的flex容器可以根据实际可用空间动态调整子元素的宽高比和顺序,使元素能够尽可能地利用可用空间,同时也能通过缩小来避免超出。flex布局提供了一套简便、完整、响应式的布局方案。

    flex布局将是CSS布局的趋势,还未正式成为标准的gird布局也异常吸睛,于是知乎上很多刚入门的小伙伴
    有了疑惑 2017年,圣杯和双飞翼布局已经淘汰了,真的?,对于此我个人仍然坚持我的观点2017年,圣杯和双飞翼布局已经淘汰了,真的? – Shelley Lee 的回答 – 知乎,至少在目前过渡阶段,仍然坚持夯实基础,稳步向前。

    本文完。

    PS:以后会继续写Flex布局和Grid布局相关文章,欢迎持续关注,也欢迎大家对文章提出建议或意见。

    参考链接
    CSS垂直居中和水平居中
    圣杯布局小结
    双飞翼布局介绍-始于淘宝UED_慕课猿问
    我熟知的三种三栏网页宽度自适应布局方法 ” 张鑫旭-鑫空间-鑫生活
    常见的几种布局总结

    1 赞 26 收藏 评论

    新葡亰496net 33

    本文由新葡亰496net发布于新葡亰官网,转载请注明出处:新葡亰496net:布局十八般武艺都在这里了,等高

    关键词:

上一篇:新葡亰496netH5移动端知识点总结

下一篇:没有了