not a better man

前端技术

圣杯布局

圣杯布局示意图

对css的关注比较少,疫情期间,最近同事远程面试聊起圣杯布局,我不知道什么叫圣杯布局,表面上对其不屑,当查了相关文档,其实发现自己除了flex 布局来实现对应的逻辑,利用float来布局,我自己是实现不了,当然我也不能落后,那我们来扒一扒圣杯布局的来龙去脉。

说起圣杯布局 ,最初的出处是Matthew Levine 2006年 1月30日 在In Search of the Holy Grail 这片文章中提出来的。圣杯布局就是 一块区域分为 左,中, 右 三个可视区域,左 右的 宽度是固定,但是中间的宽度占据剩余的整个屏幕。

这个该怎么搞,目前已经是2020年了,利用flex进行布局在前端已经大行其道,grid 布局 也开始展露头脚。利用css2.1浮动布局慢慢的要退出历史舞台了。2006年对我来说已经上古时代。flex 弹性布局 实现这种布局其实很简单。

<div class="container">
  <div class="left"></div>
  <div class="center"></div>
  <div class="right"></div>
</div>

圣杯布局的html 的结构如上所示,left 为左边区域,center 为中间区域 ,right 为右边区域。

flex 实现

flex的相关介绍可以查看阮一峰的这篇文章Flex 布局教程:语法篇 我们将 container 设置成flex 的容器 ,那么left ,center ,right 就变成了 容器中flex item ,要使center 能够占领剩余的空间 ,对其使用 flex-grow 属性就能够实现对应的效果

.container {
  display:flex;
  height:600px;
}
.left {
  width:150px;
  height:100%;
  background:blue;
}
.center{
  flex-grow:1;
  height:100%;
  background:gray;
}
.right{
  width:150px;
  height:100%;
  background:orange;
}

效果如下所示:

圣杯布局的flex版本演示效果

flex 可以算目前编写代码最少,也最容易理解的实现方式。

float布局的实现

假如我们回到2006年,在作者所处的那个年代,flex 还没有提出来(2009年才出来),我们该怎么实现了。那么这个时候我们应该结合盒模型float布局来实现对应的功能,盒模型 三大件 margin padding width .

首先 我们想到是 上面的三个子元素都是block 元素,默认都占据一行,如下图所示:

块状元素

为了让三个并排,那么我们需要对三个使用float 进行浮动,但是这个时候会考虑到一个问题,进行浮动的时候,中间的元素宽度是随父元素的宽度进行变换的。这个实现才是其中的难点,怎么去搞呢?(todo

中间元素的宽度是随父元素的宽度变化的,那么我们可以设置 中间元素的width 为100% ,此外我们知道左右两边元素的宽度,利用 padding-leftpadding-right 设置父元素填充区的宽度。

代码如下所示, 我们将center提为第一个孩子目录

<div class="container">
  <div class="center"></div>
  <div class="left"></div>
  <div class="right"></div>
</div>

.container {
            padding:0 150px;
            outline: 1px dotted red;
            overflow: auto;
}
.center {
            float: left;
            width: 100%;
            height: 400px;
            background: gray;
}
.left {
            float: left;
            width: 150px;
            height: 400px;
            background:blue;
}

.right {
            float: left;
            width: 150px;
            height: 400px;
            background: orange;
}
float布局方案

float布局的时候,我们有个疑问,为什么要把 center 写在第一位,而不是按照 left center right 的顺序写法?

这个时候我怎么让左右元素占据父元素的padding区域空间呢,这个时候我们可以想起定位 ,目前父元素是的定位是static 定位,我们设置left 和 right 为relative定位 这个时候让 left 占据左边,第一步:我们可以设置 margin-right:-100%; 这个时候是向左移动父元素的宽度,从父元素的边框位开始,其实也是中间元素的实际宽度,我们可以看下面的动画。

设置相对定位和margin-left

这个时候再设置right:150px 就将左边的块实现了

<div class="container">
  <div class="center"></div>
  <div class="left"></div>
  <div class="right"></div>
</div>

.container {
            padding:0 150px;
            outline: 1px dotted red;
            overflow: auto;
}
.center {
            float: left;
            width: 100%;
            height: 400px;
            background: gray;
}
.left {
            position:relative;
            margin-left:-100%;
            right:150px;
            float: left;
            width: 150px;
            height: 400px;
            background:blue;
}

.right {
            float: left;
            width: 150px;
            height: 400px;
            background: orange;
}
左边布局的实现

右边布局的实现 也是利用margin-rightrelative 进行

.right {
            position: relative;
            float: left;
            margin-right: -150px;
            width: 150px;
            height: 400px;
            background: orange;
}
实现
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>css3</title>
    <style>
        .container {
            padding:0 150px;
            outline: 1px dotted red;
            overflow: auto;
        }
        .center {
            float: left;
            width: 100%;
            height: 400px;
            background: gray;
        }
        .left {
            position: relative;
            margin-left: -100%;
            right:150px;
            transition: all 6s;
            float: left;
            width: 150px;
            height: 400px;
            background:blue;
        }

        .right {
            position: relative;
            float: left;
            margin-right: -150px;
            width: 150px;
            height: 400px;
            background: orange;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="center"></div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>

</html>

绝对定位实现

绝对定位的实现,也很简单,left 和right 相对于父元素进行定位。中间center 设置为100% 代码如下

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>css3</title>
    <style>
        .container {
            position: relative;
            padding:0 150px;
            outline: 1px dotted red;
            overflow: auto;
        }
        .center {
           
            width: 100%;
            height: 400px;
            background: gray;
        }
        .left {
            position: absolute;
            left:0px;
            top:0px;
            width: 150px;
            height: 400px;
            background:blue;
        }

        .right {
            position: absolute;
            top:0px;
            right: 0px;
            width: 150px;
            height: 400px;
            background: orange;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="center"></div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>

</html>

上面使用了 三种方式来实现圣杯布局,其中flex 来实现,个人认为是最简单的实现方式,不需要过多思考,解放大脑

flex布局性能 vs float布局性能

使用flex 布局还是使用float呢?我们其实要考虑的是 float 布局性能更好,还是flex布局更好.flex布局对性能的影响主要体现在哪方面?

发表评论