天天看点

三栏布局的五种办法(双飞翼布局,圣杯布局,flex弹性盒子布局等)

面试题目:假设高度一定,请写出三栏布局,左右宽度300px,中间宽度自适应,中间栏要放在文档流前面优先渲染;

先说一下我的想法,三栏布局,三栏就是三个栏目板块放在一行,最开始我看见的是左右定宽,中间自适应,最先想到的是是外面放一个大div,让他们直接inline-block,一个左浮动一个右浮动,中间100%宽度,这显然是一个贼蠢又错误的想法,这道题核心是中间栏放在文档流前面优先渲染, 所以遵循浏览器自上而下 加载代码的原则,应该把这个div盒子放在最前面,所以我的想法是先创建一个大div盒子叫min100%放在最前面,left和right左右俩个盒子放在后面,然后利用margin-left的负值将left和right移动上一行也就是这个min盒子左右边,然后在这个min的div盒子里面放一个小盒子不设宽度,叫他自适应,同时也优先渲染,虽然说的有点乱,但应该就是双飞翼布局

一、双飞翼布局

双飞翼布局据说是玉伯大大提出来的,始于淘宝UED,双飞翼布局用来诠释三栏布局就是把三栏布局比作一个大鸟,中间自适应那栏是鸟的身体,left和right那俩个栏是他们的翅膀;

其中的margin-left负值我也不太明白,最开始他们都是float:left,所以最开始margin-left是0;负的margin-left会让元素沿文档流向左移动,如果负的值较大,比如说-100%,相当于直接向左移动出100%一整行的距离,因为left左边是父元素边框,所以直接跳到上一行左移,移动100%距离相当于直接从上一行的末尾开始左移,移到上一行的开头,right在上一行末尾是因为负值300px,刚好是right的宽度,所以他从上一行的末尾开始向左移移动了300px;如果加大right的负值,他会继续向左移

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>双飞翼布局</title>
    <style type="text/css">
        .left, .main, .right /*并集标签选择器将共同属性写在一起,减少代码冗余*/{
            float: left;
            min-height: 130px;
            text-align: center;
        }
        .left {
            margin-left:-100%;/*设置margin-left-100%是为了让left向左移动一整行的位置*/
            background:orange ;
            width: 300px;
        }

        .right {
            margin-left: -300px;/*让right移动到上一行的末尾*/
            background-color: olive;
            width: 300px;
        }
        .main {
            background-color: #ccc;
            width: 100%;/*宽度占一整行*/
        }
        .content{
            margin: 0 300px 0 300px;/*排除掉俩边left和right盒子的300px宽度,宽度自适应*/
        }
    </style>
</head>
<body>
<div class="container">
      <div class="main">
           <div class="content">main</div>
         </div>
      <div class="left">left</div>
      <div class="right">right</div>
</div>
</body>
</html>
           
三栏布局的五种办法(双飞翼布局,圣杯布局,flex弹性盒子布局等)

二、圣杯布局

圣杯布局是Kevin Cornell在2006年提出的一个布局模型概念,相当于中间那栏是圣杯主体,left和right俩栏是圣杯耳朵;用到定位的属性关系加上margin-left负值的特性来完成。

和双飞翼布局异同:他们解决办法一半是相同的,都是使用float浮动,利用了margin-left负值的特性,让他们移动到上一行,使三栏并排,形成三栏布局;不同的是双飞翼布局改变了html结构,多用了一个div,少用4个css属性,减少了相对定位的麻烦,比圣杯布局思路简单一点;

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>圣杯布局</title>
    <style type="text/css">
     body{
            min-width: 900px;
        }
        .container {
            padding: 0 300px 0 300px;/*用padding300px给left和right俩个盒子留出位置*/
        }
        .left, 
        .main, 
        .right {
            position: relative;/*利用相对定位*/
            min-height: 130px;
            float: left;
        }
        .left {
            left: -300px;/*利用相对定位将这个盒子左移到之前container的padding值留白的地方,right同此理,使中间自适应;*/
            margin-left: -100%;/*利用margin-left  -100%*让其移动到main这一行上面*/
            background: orange;
            width: 300px;
        }
        .right {
            right: -300px;
            margin-left: -300px;
            background-color: olive;
            width: 300px;
        }
        .main {
            background-color: #ccc;
            width: 100%;
        }
    </style>
</head>
<body>
<div class="container">
      <div class="main">main</div>
      <div class="left">left</div>
      <div class="right">right</div>
</div>
</body>
</html>
           
三栏布局的五种办法(双飞翼布局,圣杯布局,flex弹性盒子布局等)

之前圣杯布局没加 body{min-width: 900px; }之前会出现下图情况,就是缩小窗口宽度到一定宽度,布局会乱,可能是相对定位的影响;加上body{min-width: 900px; }之后就恢复正常了,如果left是200px,right是300px的话就是min-width:700px

三栏布局的五种办法(双飞翼布局,圣杯布局,flex弹性盒子布局等)

三、flex弹性盒子布局

Flex是Flexible Box的缩写,俗称“弹性盒子布局”,任何一个容易都可以用flex布局

下面代码主要应用flex的order属性设置排列顺序,用flex-basis设置left和right的固定宽度

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>flex 三栏式布局</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .container{
            display: flex;
            display: -webkit-flex;/*加这些前缀是为了解决css3兼容浏览器的问题,用这些浏览器内核加载*/
            display: -moz-flex;
            flex-direction: row;/*规定灵活项目的方向,row默认值,默认水平显示*/
            box-sizing: border-box;/*计算的时候去掉border边框*/
            border: 1px solid red;
            margin: 0 auto;
            min-height:150px;
        }
        .min{
            flex: 1;/*让所有弹性盒子的子元素都有相同的长度*/
            background-color:#ccc ;
        }
        .left{
            flex-basis: 300px;/*用于设置弹性盒子伸缩基准值,也就是宽度*/
            order: -1;/*设定弹性盒子的子元素的顺序,-1就是为了让left排在min左边*/
            background-color: orange;
        }
        .right{
            flex-basis: 300px;
            background-color:orangered;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="min">中间布局</div>
    <div class="left">左侧布局</div>
    <div class="right">右侧布局</div>
</div>
</body>
</html>
           

四、绝对定位布局

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>绝对定位布局</title>
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
        }
        .container{
            position: relative;
            width: 100%;

        }
        .main, .right,.left{
            top: 0;
            height: 150px;
            text-align: center;
        }
        .main{
            top:0;
            left:300px;
            right:300px;
            position: absolute;
            background-color: blue;
        }
        .right{
            position: absolute;
            width: 300px;
            right: 0;
            background-color: red;
        }
        .left{
            position: absolute;
            width: 300px;
            background-color: green;
            left: 0;
        }
    </style>
</head>
<body>
<div class="container">
      <div class="main">main</div>
        <div class="left">left</div>
        <div class="right">right</div>
     
</div>
</body>
</html>
           

绝对定位使元素的位置与文档流无关,因此不占据空间,所以之前我自己想设置margin左右边距值,使min左右空出left和right盒子的宽度会出现以下问题,margin值的设立使布局出现偏差,以及混乱;

.main{
            top:0;
             margin:0 300px;
            background-color: blue;
        }
           
三栏布局的五种办法(双飞翼布局,圣杯布局,flex弹性盒子布局等)
.main{
            top:0;
             margin:0 300px;
            background-color: blue;
            position: absolute;
        }
           
三栏布局的五种办法(双飞翼布局,圣杯布局,flex弹性盒子布局等)

所以应该用position定位的left和right值来留出左右盒子宽度让main自适应是最正确了

.main{
            top:0;
            left:300px;
            right:300px;
            position: absolute;
            background-color: blue;
        }
           
三栏布局的五种办法(双飞翼布局,圣杯布局,flex弹性盒子布局等)

五、 table布局

这个布局高度由内容决定,再多的三栏布局不想研究了,前面几个布局研究了一天,累了,就这几个够我用了

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>绝对定位布局</title>
    <style media="screen">
        .container{
            display: table;
            width:100%;
        }
        .container>div{
            display: table-cell;
        }
        .left{
            width: 100px;
            background:orange;
        }
        .main{
            background: #ccc;
        }
        .right{
            width: 200px;
            background: orangered;
        }
    </style>

</head>
<body>
<div class="container">
    <div class="left">left</div>
    <div class="main">center</div>
    <div class="right">right</div>
</div>
</body>
</html>
           
三栏布局的五种办法(双飞翼布局,圣杯布局,flex弹性盒子布局等)