你的浏览器不支持canvas

Enjoy life!

css面试题目 - 布局总结

Date: Author: JM

本文章采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。

一、布局总结

常用布局有以下:

layout

二、布局展示

  • 单栏布局

layout

  • 两栏布局

layout

  • 三栏布局和圣杯布局

layout

  • 等分布局和等高布局

layout

三、当要写布局时的思维方向

  • 先从大布局下手,再到小布局
  • 是否固定宽高?
  • inlin-block? block?
  • 浮动布局?
  • 定位布局?
  • 弹性布局?
  • 表格布局?
  • 网格布局?
  • column布局?

四、单栏布局

4.1 水平居中

  • inline-block + text-align 【demo

思路:text-align: center 让行内元素水平居中。【表现为inline 或者 inline-block 的都可以实现】

<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        width: 500px;
        height: 300px;
        text-align: center; /* 关键代码 */
        background: grey;
    }
    .child {
        display: inline-block; /* 关键代码 */
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout


  • absolute + transform【demo

思路:利用定位中水平方向偏移50%,再通过transform 将定位元素自身偏移-50%来使中心回到正确的位置

注意点:

  1. 子元素的宽度不是必须的
  2. transform 只能兼容到 IE9
<section class="parent">
    <div class="child">水平居中</div>
</section>
<style>
    .parent {
        position: relative;
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        position: absolute; /* 关键代码 */
        left: 50%; /* 关键代码 */
        transform: translateX(-50%); /* 关键代码 */
        /*width: 100px;*/
        /*height: 100px;*/
        background: red;
    }
</style>

layout


  • absolute + margin 【demo

思路:利用定位中水平方向偏移50%,在知道子元素宽度的情况下(即:子元素有设置固定宽度),再设置 margin-left 的值为子元素的宽度的一半,并设置为负值。

注意点:

  1. 子元素定宽
  2. 兼容性好
<section class="parent">
    <div class="child">水平居中</div>
</section>
<style>
    .parent {
        position: relative;
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        position: absolute; /* 关键代码 */
        left: 50%; /* 关键代码 */
        margin-left: -50px; /* 关键代码 */
        width: 100px; /* 关键代码 */
        background: red;
    }
</style>

layout


  • flex + justify-content 【demo

思路: 通过容器表现为flex,用justify-content水平居中

注意点:

  1. 支持IE10+
  2. 子元素可不定宽
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        display: flex; /* 关键代码 */
        justify-content: center; /* 关键代码 */
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout


  • 子元素定宽 + margin 【demo

思路:在子元素定宽的情况下,加上 margin: 0 auto 就可以实现水平居中

注意点:

  1. 子元素必须定宽
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        width: 100px; /* 关键代码 */
        height: 100px;
        margin: 0 auto; /* 关键代码 */
        background: red;
    }
</style>

layout


  • table + margin 【demo

思路:子元素设置为table,加上 margin: 0 auto 就可以实现水平居中

注意点:

  1. 子元素可不定宽 或者 子元素必须有内容才有效
<section class="parent">
    <div class="child">子元素必须有内容,table才有效</div>
</section>
<style>
    .parent {
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        display: table; /* 关键代码 */
        margin: 0 auto; /* 关键代码 */
        background: red;
    }
</style>

layout

4.2 垂直居中

  • position + transform 【demo

思路:这里利用的是定位中垂直方向偏移50%,再通过transform将定位元素自身偏移-50%来使得中心回到正确的位置

注意点:

  1. 父元素要定高
  2. .用了transform只能兼容到IE9
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        position: relative;
        height: 300px;
        background: grey;
    }
    .child {
        position: absolute; /* 关键代码 */
        top: 50%; /* 关键代码 */
        transform: translateY(-50%); /* 关键代码 */
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout


  • position + margin 【demo

思路:这里利用的是定位中垂直方向偏移50%,再通过margin-top将定位元素自身偏移-50%来使得中心回到正确的位置

注意点:

  1. 父元素要定高,子元素要定高
  2. 用了transform只能兼容到IE9
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        position: relative;
        height: 300px;
        background: grey;
    }
    .child {
        position: absolute; /* 关键代码 */
        top: 50%; /* 关键代码 */
        margin-top: -50px; /* 关键代码 */
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout


  • flex + align-items 【demo
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        display: flex; /* 关键代码 */
        align-items: center; /* 关键代码 */
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout


  • table-cell + vertical-align 【demo

思路:父元素设置display: table-cell; 以及 vertical-align: middle

注意点:

  1. 子元素可不定宽高;但在不定宽高的情况下,必须有内容
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        display: table-cell; /* 关键代码 */
        vertical-align: middle; /* 关键代码 */
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        /*width: 100px;*/
        /*height: 100px;*/
        background: red;
    }
</style>

layout

4.3 水平垂直居中

  • table-cell + vertical-align + inline-block + text-align 【demo

注意点:

  1. 子元素可不定宽高;在没宽高的情况下,必须有内容
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        display: table-cell; /* 关键代码 */
        text-align: center; /* 关键代码 */
        vertical-align: middle; /* 关键代码 */
        width: 500px;
        height: 300px;
        text-align: center;
        background: grey;
    }
    .child {
        display: inline-block; /* 关键代码 */
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout


  • absolute + transform 【demo

注意点:

  1. 父元素必须定高
  2. 使用transform ,支持IE10+
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        position: relative;   /* 关键代码 */
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        position: absolute; /* 关键代码 */
        top: 50%; /* 关键代码 */
        left: 50%; /* 关键代码 */
        transform: translate(-50%, -50%); /* 关键代码 */
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout


  • absolute + margin 【demo

注意点:

  1. 子元素必须定宽高
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        position: relative;   /* 关键代码 */
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        position: absolute; /* 关键代码 */
        top: 50%; /* 关键代码 */
        left: 50%; /* 关键代码 */
        margin-top: -50px; /* 关键代码 */
        margin-left: -50px; /* 关键代码 */
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout


  • flex + justify-content + align-items 【demo
<section class="parent">
    <div class="child"></div>
</section>
<style>
    .parent {
        display: flex; /* 关键代码 */
        justify-content: center; /* 关键代码 */
        align-items: center; /* 关键代码 */
        width: 500px;
        height: 300px;
        background: grey;
    }
    .child {
        width: 100px;
        height: 100px;
        background: red;
    }
</style>

layout

五、两栏布局

5.1 一列定宽,一列自适应

5.1.1 左定宽,右自适应

  • float + overflow 【demo

思路:浮动元素会脱离文档流,会影响其下面兄弟元素的布局,导致发生元素重叠;设置 overflow 非 visible,可以使其兄弟元素新建一个bfc,避免发生元素重叠

<div class="container">
    <aside class="aside">aside</aside>
    <main class="main">main</main>
</div>
<style>
    .container {
        background: gray;
    }
    .aside {
        float: left; /* 关键代码 */
        width: 200px;
        margin-right: 20px;
        background: red;
    }
    .main {
        overflow: hidden; /* 关键代码 */
        background: blue;
    }
</style>

layout


  • float + margin 【demo

思路:左栏定宽,左栏左浮动;右栏设置margin-left的值为“负”左栏的宽度

注意点:

  1. 左栏必须定宽
<div class="container">
    <aside class="aside">aside</aside>
    <main class="main">main</main>
</div>
<style>
    .container {
        background: gray;
    }
    .aside {
        float: left; /* 关键代码 */
        width: 200px;
        margin-right: 20px;
        background: red;
    }
    .main {
        margin-left: 220px; /* 关键代码 */
        background: blue;
    }
</style>

layout


  • position【demo

思路:左右两栏都设置为绝对定位元素,其top值都为0;左栏left值为0,右栏的left值为左栏的宽度,并且设置右栏的right值为0

注意点:

  1. 左栏必须定宽
<div class="container">
    <aside class="aside">aside</aside>
    <main class="main">main</main>
</div>
<style>
    .container {
        position: relative;
        background: gray;
    }
    .aside {
        position: absolute; /* 关键代码 */
        top: 0; /* 关键代码 */
        left: 0; /* 关键代码 */
        width: 200px;
        background: red;
    }
    .main {
        position: absolute; /* 关键代码 */
        top: 0; /* 关键代码 */
        left: 200px; /* 关键代码 */
        right: 0; /* 关键代码 */
        background: blue;
    }
</style>

layout


思路:父元素设置display: flex,左栏定宽,右栏设置为flex: 1,让其自适应

注意点:

  1. 支持IE9+
<div class="container">
    <aside class="aside">aside</aside>
    <main class="main">main</main>
</div>
<style>
    .container {
        display: flex; /* 关键代码 */
        background: gray;
    }
    .aside {
        width: 200px;
        background: red;
    }
    .main {
        flex: 1; /* 关键代码 */
        background: blue;
    }
</style>

layout


思路:父元素定宽并且设置display: table,左右两栏都设置为 table-cell,左栏定宽,右栏会自适应

注意点:

  1. 父元素定宽,左栏定宽
<div class="container">
    <aside class="aside">aside</aside>
    <main class="main">main</main>
</div>
<style>
    .container {
        width: 100%; /* 关键代码 */
        display: table; /* 关键代码 */
        background: gray;
    }
    .aside {
        display: table-cell; /* 关键代码 */
        width: 200px;
        background: red;
    }
    .main {
        display: table-cell; /* 关键代码 */
        background: blue;
    }
</style>

layout


思路:父元素设置display: grid,由属性 grid-template-columns 控制有多少列,每列的宽度是多少

注意点:

  1. 左由两栏可不设置宽度,由属性 grid-template-columns 决定每列的宽度
<div class="container">
    <aside class="aside">aside</aside>
    <main class="main">main</main>
</div>
<style>
    .container {
        display: grid; /* 关键代码 */
        grid-template-columns: 200px auto; /* 关键代码:有多少列,每列的宽度 */
        background: gray;
    }
    .aside {
        background: red;
    }
    .main {
        background: blue;
    }
</style>

layout

5.1.2 右定宽,左自适应

  • float + margin 【demo

思路:右栏定宽,右栏右浮动;左栏设置 margin-right 为右栏的宽度

注意点:

  1. 注意html结构:右栏 ===》 左栏
<div class="container">
    <main class="main">右main</main>
    <aside class="aside">左aside</aside>
</div>
<style>
    .container {
        background: gray;
    }
    .aside {
        margin-right: 200px; /* 关键代码 */
        background: red;
    }
    .main {
        float: right; /* 关键代码 */
        width: 200px; /* 关键代码 */
        background: blue;
    }
</style>

layout


  • float + overflow 【demo

思路:右栏定宽,右栏右浮动;左栏设置 overflow

注意点:

  1. 注意html结构:右栏 ===》 左栏
<div class="container">
    <main class="main">右main</main>
    <aside class="aside">左aside</aside>
</div>
<style>
    .container {
        background: gray;
    }
    .aside {
        overflow: hidden; /* 关键代码 */
        background: red;
    }
    .main {
        float: right; /* 关键代码 */
        width: 200px; /* 关键代码 */
        background: blue;
    }
</style>

layout


思路:父元素设置 display: flex,右栏定宽,左栏设置为flex: 1,让其自适应

注意点:

  1. 左栏必须定宽
  2. 支持IE9+
<div class="container">
    <aside class="aside">左aside</aside>
    <main class="main">右main</main>
</div>
<style>
    .container {
        display: flex; /* 关键代码 */
        background: gray;
    }
    .aside {
        flex: 1; /* 关键代码 */
        background: red;
    }
    .main {
        width: 200px;
        background: blue;
    }
</style>

layout


思路:父元素定宽并且设置display: table,左右两栏都设置为 table-cell,右栏定宽,左栏会自适应

注意点:

  1. 右栏必须定宽
  2. 支持IE9+
<div class="container">
    <aside class="aside">aside</aside>
    <main class="main">main</main>
</div>
<style>
    .container {
        width: 100%; /* 关键代码 */
        display: table; /* 关键代码 */
        background: gray;
    }
    .aside {
        display: table-cell; /* 关键代码 */
        background: red;
    }
    .main {
        display: table-cell; /* 关键代码 */
        width: 200px;
        background: blue;
    }
</style>

layout


思路:父元素设置display: grid,由属性 grid-template-columns 控制有多少列,每列的宽度是多少

注意点:

  1. 左由两栏可不设置宽度,由属性 grid-template-columns 决定每列的宽度
<div class="container">
    <aside class="aside">左aside</aside>
    <main class="main">右main</main>
</div>
<style>
    .container {
        display: grid; /* 关键代码 */
        grid-template-columns: auto 200px ; /* 关键代码:有多少列,每列的宽度 */
        background: gray;
    }
    .aside {
        background: red;
    }
    .main {
        background: blue;
    }
</style>

layout

5.3 总结

左右布局都可以用以下方法实现:

  • 浮动布局
  • 定位布局
  • 弹性布局
  • 表格布局
  • 网格布局

5.2 上下布局

  • 定位布局
  • 弹性布局
  • 表格布局
  • 网格布局

多列不定宽,一列自适应


对于本文内容有问题或建议的小伙伴,欢迎在文章底部留言交流讨论。