Nancy's Studio.

深入学习CSS布局

Word count: 3,154 / Reading time: 13 min
2018/11/12 Share

0x00前言

CSS是个神奇的东西,可以把一个简陋的网页修饰得十分高大上,同时对于初学者来说很好上手,几天就可以快速入门做出一些网页。但是实际上想把CSS里面的知识学透也不是一件容易的事,因为实现某种效果往往会有多种不同的方式,几个常见的属性结合在一起很有可能会得到意想不到的结果,这里面有很多东西要去考虑,需要多去练习和总结才能做到灵活运用。

0x01涉及到的一些基本属性

position

描述
absolute 生成绝对定位的元素,相对于 static 定位(unpositioned)以外的第一个父元素进行定位。 元素的位置通过 “left”, “top”, “right” ,”bottom” 属性进行规定。
fixed 生成固定定位的元素,相对于浏览器窗口进行定位。 元素的位置通过 “left”, “top”, “right” , “bottom” 属性进行规定。
relative 生成相对定位的元素,相对于其正常位置进行定位。 因此,”left: 20px” 会向元素的 LEFT 位置添加 20 像素。
static 默认值。没有定位(unpositioned),元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
inherit 规定应该从父元素继承 position 属性的值。
sticky 新增属性:粘性定位,该定位基于用户滚动的位置。它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed; 它会固定在目标位置。(Internet Explorer, Edge 15 及更早 IE 版本不支持 sticky 定位。 Safari 需要使用 -webkit-prefix。)
  • 如果绝对定位(position属性的值为absolute)的元素没有“positioned”祖先元素,那么它会相对于文档的 body 元素,并且随着页面滚动而移动。一个“positioned”元素是指 position 值不是 static 的元素。

display

描述
none 此元素不会被显示。
block 此元素将显示为块级元素,此元素前后会带有换行符。
inline 默认。此元素会被显示为内联元素,元素前后没有换行符。
inline-block 行内块元素。(CSS2.1 新增的值)
list-item 此元素会作为列表显示。
run-in 此元素会根据上下文作为块级元素或内联元素显示。
table 此元素会作为块级表格来显示(类似 table),表格前后带有换行符。
inline-table 此元素会作为内联表格来显示(类似 table),表格前后没有换行符。
table-row-group 此元素会作为一个或多个行的分组来显示(类似 tbody)。
table-header-group 此元素会作为一个或多个行的分组来显示(类似 thead)。
table-footer-group 此元素会作为一个或多个行的分组来显示(类似 tfoot)。
table-row 此元素会作为一个表格行显示(类似 tr)。
table-column-group 此元素会作为一个或多个列的分组来显示(类似 colgroup)。
table-column 此元素会作为一个单元格列显示(类似 col)
table-cell 此元素会作为一个表格单元格显示(类似 td 和 th)
table-caption 此元素会作为一个表格标题显示(类似 caption)
inherit 规定应该从父元素继承 display 属性的值。

还有一些有趣的display值戳这里

display 是CSS中最重要的用于控制布局的属性。每个元素都有一个默认的 display 值,这与元素的类型有关。对于大多数元素它们的默认值通常是 blockinline

  • 常见的块级标签:div,p,form,ul,ol,h1~h6,table,dl,hr,address,fieldset,header,footer,section…
  • 常见的行级标签:span,a,img,input,select,label,textarea,b或strong,i或em…

float

描述
left 元素向左浮动。
right 元素向右浮动。
none 默认值。元素不浮动,并会显示在其在文本中出现的位置。
inherit 规定应该从父元素继承 float 属性的值。

float 属性定义元素在哪个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。

0x02弹性盒子–Flex Container

附链接:阮一峰的flex布局教程

模型说明

当元素表现为flex框时,他们沿着两个轴来布局:

img

主轴(main axis)是沿着flex元素放置的方向延伸的轴。该轴的开始和结束被称为main start和main end。 交叉轴(cross axis)是垂直于flex元素放置方向的轴。该轴的开始和结束被称为cross start和cross end。 设置了display:flex的元素被称为flex容器(flex container) 在flex容器中表现为柔性的盒子的元素被称为flex项。

容器属性

flex-direction:用于指定主轴的方向

  • row:默认值,主轴为水平方向,起点在左端
  • row-reverse:主轴为水平方向,起点在右端
  • column:主轴为垂直方向,起点在上沿
  • column-reverse:主轴为垂直方向,起点在下沿

flex-wrap:用于定义换行方式

  • nowrap:(默认)不换行

    img

  • wrap:换行,第一行在上方 img

  • wrap-reverse:换行,第一行在下方 img

flex-flow:flex-direction属性和flex-wrap属性的简写形式

默认值为:row nowrap 。

justify-content:定义项目在主轴上的对齐方式。

  • flex-start:左对齐(默认值)
  • flex-end:右对齐
  • center:居中
  • space-between:两端对齐,项目之间间隔相等
  • space-around:每个项目两侧的间隔相等

img

align-item:定义在交叉轴上的对齐方式

  • flex-start:交叉轴起点对齐
  • flex-end:交叉轴终点对齐
  • center:交叉轴中点对齐
  • stretch(默认值):如果项目没有设置高度或设为auto,将占满整个容器的高度
  • baseline:项目的第一行文字的基线对齐

img

align-content:定义多轴线对齐方式

如果项目只有一根轴线,该属性不起作用。

  • flex-start:与交叉轴起点对齐
  • flex-end:与交叉轴终点对齐
  • center:与交叉轴中点对齐
  • stretch:轴线占满整个交叉轴
  • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布
  • space-around:每根轴线两侧的间隔都相等

img

项目属性

order:定义项目的排列顺序

数值越小,排列越靠前。 order: number;

flex-grow:定义项目的放大比例

默认值为0,即如果存在剩余空间,也不放大。 flex-grow: number;

如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话);如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

img

flex-shrink:定义项目的缩小比例

默认值为1,即如果空间不足,项目缩小。 flex-shrink: number;

如果所有项目的flex-shrink属性都为1,当空间不足时都等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时前者不缩小。

img

flex-basis

定义在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间。默认值为auto,即项目本来的大小。可以设置为跟width和height属性一样的值,即项目占据固定空间。

flex

是flex-grow,flex-shrink和flex-basis的缩写,默认值为0,1,auto。

align-self

允许单个项目有与其他项目不一样的对齐方式,可覆盖align-item值,默认为auto,表示继承父元素的align-item属性,如果没有父元素,则等同于stretch。

该属性可能取6个值,除了auto,其他都与align-items属性完全一致。

img

flex布局实例

附flex实例教程 详见教程示例。

补充:

flex属性是flex-grow、flex-shrink、flex-basis属性的简写,默认值为0 1 auto;设置 flex: 1; 表示所有子元素都有相同的长度,且忽略其内部的内容;设置 flex: auto; 相当于 flex:1 1 auto;,设置 flex: none; 相当于 flex: 0 0 auto;

0x03基本居中布局

  • 设置text-align: center;(水平居中,且只对行内元素和display为inline或inline-block的元素有效)

水平居中

  • 行内元素水平居中text-align:center

  • width:100px; margin:0 auto;

  • 利用tabledisplay:table; margin:0 auto;

  • 利用absolute+transform

    1
    2
    .parent{ position:relative; }
    .child{ position:absolute; left:50%; tranform: translateX(-50%); }
  • 利用flex

    1
    2
    .parent{ display: flex; }
    .child{ margin: 0 auto; }
    1
    .parent{ display:flex; justify-content:center; }

垂直居中

(除去使用absolute定位的一些其他方法)

  • 使用flex+align-items

    1
    2
    3
    4
    .parent{
    display: flex;
    align-items: center;
    }
  • 使用table-cell+vertical-align

    1
    2
    3
    4
    .parent{
    display: table-cell;
    vaertical-align: middle;
    }
  • 单行内联元素垂直居中

    1
    2
    3
    4
    #box{
    height: 120px;
    line-height: 120px; /*把行高设成高度值*/
    }
  • 多行内联元素垂直居中

    1
    2
    3
    4
    5
    6
    .parent{
    height: 100px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    }

    或者利用table表布局

    1
    2
    3
    4
    5
    6
    7
    8
    .parent{
    display: table;
    height: 100px;
    }
    .child{
    display: table-cell;
    vertical-align: middle;
    }

水平垂直居中对齐

  • 使用绝对定位进行水平垂直居中

    1
    2
    3
    4
    5
    6
    .parent{ position:relative; }
    .child{ width:200px; height:100px; position:absolute; left:50%; top:50%; margin-left:-100px; margin-top:-50px; }

    /*用translate与之类似*/
    .parent{ position:relative; }
    .child{ width:200px; height:100px; position:absolute; left:50%; top:50%; transform(-50%,-50%); }
  • 另一种使用绝对定位的方法

    1
    2
    .parent{ position:relative; }
    .child{ width:100px; height:100px; position:absolute; left:0; right:0; top:0; bottom:0; margin:auto; }

    如果改变left,right , top , bottom的值可以让元素向某个方向偏移。

  • 绝对定位+CSS3(未知高度)

    1
    2
    3
    4
    5
    6
    7
    .parent{ position:relative; }
    .child{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    }
  • 用table-cell实现

    1
    2
    3
    4
    5
    6
    .parent{
    display: table;
    }
    .child{
    display:table-cell; vertical-align: middle; text-align: center;
    }
  • 一个神奇的水平居中方法(利用float,position和clear的结合)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <style>
    .parent{ width:300px; height:200px; border:1px solid red; } /*设置父容器*/
    .wrapper{ /*自适应内容的宽度*/
    float: left;
    position: relative;
    left: 50%; /*先让wrapper位于父容器宽度一半地方*/
    clear: both; /*避免让后面的wrapper左浮动后与当前wrapper位于同一行*/
    }
    .child{
    position: relative; /*在当前元素上进行相对定位*/
    left: -50%; /*左移元素自身宽度的一半*/
    white-space: nowrap;
    border: 1px solid blue;
    }
    </style>
    <div class="parent">
    <div class="wrapper">
    <div class="child">这是第一个尝试</div>
    </div>
    <div class="wrapper">
    <div class="child">再试试这个</div>
    </div>
    </div>
  • flex实现

    1
    2
    3
    4
    5
    .parent{ 
    display:flex;
    justify-content:center; /*横轴居中*/
    align-items:center; /*纵轴居中*/
    }
  • flex/grid与marign:auto

    1
    2
    3
    4
    5
    6
    7
    .parent{ 
    height: 100vh; /*必须有高度*/
    display: grid; /*或设成flex*/
    }
    .child{
    margin: auto;
    }

0x04多列布局

参考链接

左列定宽,右列自适应

float+margin-left实现

1
2
.left{ float:left; width:100px; }
.right{ margin-left:100px; }

float+overflow实现

1
2
.left{ width:100px; float:left;}
.right{ overflow:hidden; }

设置right-fix盒子

1
2
3
4
5
6
7
8
9
10
11
<style>
.left{ width:100px; float:left; }
.right-fix{ width:100%; margin-left:-100px; float:right; }
.right{ margin-left:100px; }
</style>
<div class="parent">
<div class="left"></div>
<div class="right-fix">
<div class="right"></div>
</div>
</div>

使用table实现

1
2
3
.parent{ display:table; table-layout:fixed; width:100%; }
.left{ width:100px; }
.right,.left{ display:table-cell; }

使用flex实现

1
2
3
.parent{ display:flex; }
.left{ width:100px; }
.right{ flex:1; } /*直接填补右侧空余宽度*/

右列定宽,左列自适应

float+margin实现

1
2
.left{ float:left; width:100%; margin-right:-100px; }
.right{ float:right; width:100px; }

使用table实现

1
2
3
.parent{ display:table; table-layout:fixed; width:100%; }
.left{ display:table-cell; }
.right{ width:100px; display:table-cell; }

使用flex实现

1
2
3
.parent{ display:flex; }
.left{ flex:1; }
.right{ width:100px; }

两侧定宽,中间栏自适应

float+margin实现(有异议)

1
2
3
.left{ width:100px; float:left; }
.center{ float:left; width:100%; margin-right:-200px; }
.right{ width:100px; float:right; }

用table实现

1
2
3
.parent{ width:100%; display:table; table-layout:fixed }
.left,.middle,.right{ display:table-cell; }
.left,.right{ width:100px; }

用flex实现

1
2
3
.parent{ display:flex; }
.left,.right{ width:100px; }
.middle{ flex:1; }

一列不定宽,一列自适应

float+overflow实现

1
2
.left{ float:left; }
.right{ overflow:hidden; }

用flex实现

1
2
.parent{ display:flex; }
.right{ flex:1; }

多列等分布局

float实现

1
2
3
4
5
6
7
8
9
<style>
.parent{ margin-left:-20px } /*假设列之间的间距为20px*/
.column{ float:left; width:25%; box-sizing:border-box; }
</style>
<div class="parent">
<div class="column">1</div>
<div class="column">2</div>
<div class="column">3</div>
</div>

flex实现

1
2
3
4
5
6
7
.parent{ display:flex; }
.column{ flex:1; }
.column+.column{ margin-left:20px; }

/*另一种确定column宽度的情况*/
.parent{ display:flex; justify-content:space-between; }
.column{ width:350px; }

0x05响应式布局

参考资料

CATALOG
  1. 1. 0x00前言
  2. 2. 0x01涉及到的一些基本属性
    1. 2.1. position
    2. 2.2. display
    3. 2.3. float
  3. 3. 0x02弹性盒子–Flex Container
    1. 3.1. 模型说明
    2. 3.2. 容器属性
      1. 3.2.1. flex-direction:用于指定主轴的方向
      2. 3.2.2. flex-wrap:用于定义换行方式
      3. 3.2.3. flex-flow:flex-direction属性和flex-wrap属性的简写形式
      4. 3.2.4. justify-content:定义项目在主轴上的对齐方式。
      5. 3.2.5. align-item:定义在交叉轴上的对齐方式
      6. 3.2.6. align-content:定义多轴线对齐方式
    3. 3.3. 项目属性
      1. 3.3.1. order:定义项目的排列顺序
      2. 3.3.2. flex-grow:定义项目的放大比例
      3. 3.3.3. flex-shrink:定义项目的缩小比例
      4. 3.3.4. flex-basis
      5. 3.3.5. flex
      6. 3.3.6. align-self
    4. 3.4. flex布局实例
  4. 4. 0x03基本居中布局
    1. 4.1. 水平居中
    2. 4.2. 垂直居中
    3. 4.3. 水平垂直居中对齐
  5. 5. 0x04多列布局
    1. 5.1. 左列定宽,右列自适应
      1. 5.1.1. float+margin-left实现
      2. 5.1.2. float+overflow实现
      3. 5.1.3. 设置right-fix盒子
      4. 5.1.4. 使用table实现
      5. 5.1.5. 使用flex实现
    2. 5.2. 右列定宽,左列自适应
      1. 5.2.1. float+margin实现
      2. 5.2.2. 使用table实现
      3. 5.2.3. 使用flex实现
    3. 5.3. 两侧定宽,中间栏自适应
      1. 5.3.1. float+margin实现(有异议)
      2. 5.3.2. 用table实现
      3. 5.3.3. 用flex实现
    4. 5.4. 一列不定宽,一列自适应
      1. 5.4.1. float+overflow实现
      2. 5.4.2. 用flex实现
    5. 5.5. 多列等分布局
      1. 5.5.1. float实现
      2. 5.5.2. flex实现
  6. 6. 0x05响应式布局