【CSS】面试官:请你写一个三栏布局!

164 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

很多面试官在面试时会给求职者出这样一个问题,“如果要你实现三栏布局,你有哪些方式?”。这道题在我们前端er在求职时会遇到的高频题。“三栏布局”其实说的就是左右栏宽度固定,中间栏宽度自适应。

最近花了一点时间对三栏布局的几种方式进行了实现,以下分享一下我的几种思路。

图片.png

三栏布局实现

absolute 绝对定位

每个元素都设置为绝对定位 absolute,设置中间自适应元素的 leftright 对应左右元素的高。

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

<style>
    body {
        margin0;
    }

    .main {
        width100%;
        height100px;
        position: relative;
    }

    .left {
        width100px;
        height100%;
        background-color: aqua;
        position: absolute;
        left0;
    }

    .center {
        flex1;
        height100%;
        background-color: red;
        position: absolute;
        left100px/*left 的宽度*/
        right150px/*right 的宽度*/
    }
    
    .right {
        width150px;
        height100%;
        background-color: blueviolet;
        position: absolute;
        right0;
    }
</style>

float 浮动

使用浮动实现:中间列设置 margin: 0 左右宽度 且不用设置宽度,左右两列分别向左右浮动。

内容必须放在最后面

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

<style>
    body {
        margin0;
    }

    .main {
        width100%;
        height100px;
    }

    .left {
        float: left;
        width100px;
        height100%;
        background-color: aqua;
    }

    .right {
        float: right;
        width100px;
        height100%;
        background-color: blueviolet;
    }

    .center {
        margin-left100px;
        margin-right100px;
        height100%;
        background-color: red;
    }
</style>

flex 弹性布局

使用弹性布局实现,与使用浮动实现不同,要注意三栏按顺序排列,即leftcenterright

设置中间列 flex: 1,使其自动收缩。flex: 1 对应于flex-grow: 1;, flex-shrink: 1, flex-basis: 0%;,表明元素弹性伸展和收缩。

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

<style>
    body {
        margin0;
    }

    .main {
        width100%;
        height100px;
        display: flex;
    }

    .left {
        width100px;
        height100%;
        background-color: aqua;
    }

    .center {
        flex1;
        height100%;
        background-color: red;
    }

    .right {
        width150px;
        height100%;
        background-color: blueviolet;
    }
</style>

圣杯布局和双飞翼布局

在学习实现三栏布局的同时接触到两个概念,圣杯布局和双飞翼布局。这两个布局的思想其实就是三栏布局,只不过它们的实现方式有所不同。

圣杯布局

将最外层的 padding-leftpadding-right 设置成左右两列的宽度。每一列都设置 float: left

左边列设置 margin-left: -100%,右边列设置margin-left: -自己的宽度,再将左右两个列用相对布局 position: relative 并分别配合 leftright 属性,以便左右两列移动后不遮挡中间列。

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

<style>
    .main {
        height: 100px;
        padding-left: 100px;
        padding-right: 150px;
    }

    .left {
        width: 100px;
        height: 100%;
        background-color: aqua;
        float: left;
        margin-left: -100%;
        position: relative;
        left: -100px;
    }

    .center {
        width: 100%;
        height: 100%;
        background-color: red;
        float: left;
    }

    .right {
        width: 150px;
        height: 100%;
        background-color: blueviolet;
        float: left;
        margin-left: -150px;
        position: relative;
        right: -150px;
    }
</style>

双飞翼布局

中间一列优先渲染:内容在 html 里面必须放在前面

自适应中间列的必须放在 leftright 前面,且包含在一个父 div 里。内容列的父 div、左列和有列都设置为向左浮动。左列设置 margin-left: -100%,右列设置margin-left: -自己的宽度,中间内容列设置 margin: 0 左右的宽度

<div class="bg">
    <div class="main">
        <div class="center"></div>
    </div>
    <div class="left"></div>
    <div class="right"></div>
</div>
    
<style>
    .bg {
        width: 100%;
        height: 100px;
    }

    .main {
        width: 100%;
        height: 100%;
        float: left;
    }

    .main .center {
        height: 100%;
        margin-left: 100px;
        margin-right: 150px;
        background-color: aqua;
    }

    .left,
    .right {
        height: 100%;
        float: left;
        background-color: red;
    }

    .left {
        width: 100px;
        margin-left: -100%;
    }

    .right {
        width: 150px;
        margin-left: -150px;
    }
</style>

margin 负值(个人见解)

上面几种实现方式有几种使用了 margin: 负值,之前都是使用正值,负值的用法与正值有所区别,在这里记录一下。 浅谈margin负值

要明白 margin 负值的作用,首先我们先学习一下 margin 的参考线。 margin 有两类参考线,一类是 topleft,一类是 rightbottom

  • lefttop

    包含块内容区域的左边和上边或相接元素 margin 的右边和下边做参考线

  • rightbottom

    元素本身 border 的右边和下边做参考线

magin-left: -100%

这个百分比是以父元素内容长度的百分比,该父元素内容长度需要去除 paddingmaginborder。所以 margin-left: -100% 其实就是相对于左边的参考线向左移动父元素内容长度的距离。

最后

欢迎大家在评论区一起交流,一起进步!