CSS布局方式

168 阅读12分钟

网页元素一般分为 普通流,浮动流,定位流。其中普通流和浮动流在一个层级上,定位流>浮动流>普通流。

css布局方式有以下几种:

float布局position布局flex布局grid布局

一、float布局: none | left | right | inherit

1. Float 属性指定一个元素应沿其容器的左侧或右侧放置(容器的边框,或者碰到另外一个浮动元素),允许文本和内联元素环绕它,原本设计是为了实现文字环绕图片的效果(报纸上常见的效果)

2. float会将元素 inline-block

某些情况下它会修改 display 值的计算值。如 block、inline 都会成为 inline-block。所以如果行内级元素设置float,是不需要再去设置 display 的,如:

span {
    float: left;
    display: inline-block; /* 多余的设置 */
}

3. 使用float(元素浮动)代表元素会脱离文档流(被移出正常的文档流),然后向左(float:left)或向右平移(float:right)

  • 如果浮动元素的上一个兄弟元素是块级元素的,浮动元素直接在新的一行进行左右平移
  • 如果浮动元素的上一个兄弟元素是行内级元素的话,就涉及到行盒的情况了,那么就在当前行盒进行左右平移,且外顶部对齐当前行盒的顶部。当当前行不够,则换行向左或者向右浮动。
  • 如果浮动元素比较多的话,会一个接一个(向左或者向右水平排放),直到填满容器一整行,之后换行至下一行。

4. float会导致**“浮动高度塌陷**”:

如果浮动元素的父元素没有设定高度,当其子元素浮动后,父元素就因为内部没有子元素撑起从而高度变为0

从而就有清除浮动的几种方式。

二、position 布局: static,absolute, fixed, relative

  1. static: 默认值,任意 position: static; 的元素不会被特殊的定位

2. absolute(绝对定位): 脱离文档流,相对与最近**position**不为**static**的父元素进行定位,可以使用left,right,top,buttom进行定位。

3. relative(相对定位):  relative 不脱离文档流相对于自己来定位的。relative 的元素尽管表面上看到它偏离了原来的位置,但它实际上在文档流中还是没变。根据top,right,bottom,left的值按照它理应所在的位置进行偏移,relative的“相对的”意思也正体现于此。

4.  fixed脱离文档流,相对于浏览器窗口来进行定位的,toprightbottomleft 属性都可用。

三、flex布局:

Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局

**flex 容器**中默认存在两条轴,**水平主轴**(main axis) 和**垂直的交叉轴**(cross axis),这是默认的设置,当然你可以通过修改使垂直方向变为主轴,水平方向变为交叉轴,

单元块被称之为 flex item,每个项目占据的主轴空间为 (main size), 占据的交叉轴的空间为 (cross size)

注意:当时设置 flex 布局之后,子元素的 float、clear、vertical-align 的属性将会失效。

(1). flex容器:

要实现flex布局,首先需要指定一个容器,任何一个容器内部的元素都恶意进行flex布局。任何一个容器都可以通过如下手段指定为flex容器:

.container {
    display: flex | inline-flex;       //可以有两种取值 块状或 行内的 flex 容器盒子
}

六种属性可以设置在容器上,它们分别是:

  • flex-direction

  • flex-wrap

  • flex-flow

  • justify-content

  • align-items

  • align-content

1. flex-direction: 决定主轴的方向(即项目的排列方向)

.container {
    flex-direction: row | row-reverse | column | column-reverse;
}

默认值为:row, 主轴为水平方向,起点在左端(左->右)。

与row相反的row-reverse:主轴为水平方向,起点在右端(右->左)

Colum:主轴为垂直方向 ,起点为上方(上->下)

Colum-reverse:主轴为垂直方向,起点是下方(下->上)

2. flex-wrap: 决定容器内项目是否可换行

注:以下例子默认主轴为水平方向

.container{
    flex-wrap: nowrap | wrap | wrap-reverse
}

默认值:nowrap 不换行,即当主轴尺寸固定时,当空间不足时,项目尺寸会随之调整而并不会挤到下一行。

wrap:换行,即当项目主轴总尺寸超出容器时换行,项目会随之调整换到下一行。第一行在上方。

wrap-reverse: 换行,即当项目主轴总尺寸超出容器时换行,项目会随之调整换到下一行。第一行在下方。

3. flex-flow: flex-direction 和 flex-wrap 的简写形式,建议分开书写

.container {
    flex-flow: <flex-direction> || <flex-wrap>;
}

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

.container{
    justify-content: flex-start| flex-end|center|space-around|space-between|space-evenly|stretch
}

建立在主轴为水平方向时测试,即 flex-direction: row

默认值**flex-start:**左对齐

flex-end: 右对齐

center: 水平居中

space-around: 每个项目两侧的间隔相等,所以项目之间的间隔比项目与边缘的间隔大一倍。

preview

space-between: 两端对齐,每个项目中间间隔相等两端对齐,即剩余空间等分成间隙。

**space-evenly: **

均匀排列每个元素,每个元素之间间隔相等
**stretch:** 若宽度未设置,则

元素会被拉伸以适应容器的大小

5. align-items: 定义了项目在交叉轴上的对齐方式

.container{
    align-items: flex-start| flex-end|center| baseline | stretch
}

默认stretch:当项目未设置高度或者设置为auto时,将占满整个容器的高度(容器高度设置为100px,则项目高度为100px)

**flex-start:**交叉轴起点对齐,假设容器高度设置为 100px,而项目分别为 20px, 40px, 60px, 80px, 100px, 则如下图显示。

**flex-end:**交叉轴终点对齐,假设容器高度设置为 100px,而项目分别为 20px, 40px, 60px, 80px, 100px, 则如下图显示。

center: 交叉轴中点对齐

**baseline:**项目以第一行文字基线对齐

6. align-content: 定义了多根轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用。

.container {
    align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

当你 flex-wrap 设置为 nowrap 的时候,容器仅存在一根轴线,因为项目不会换行,就不会产生多条轴线。

当你 flex-wrap 设置为 wrap 的时候,容器可能会出现多条轴线,这时候你就需要去设置多条轴线之间的对齐方式了。

默认stretch:项目未设置宽度或者height:auto时,项目的高度平分多条轴线垂直方向上的空间。

当设置了高度,则高度不会撑开,但是项目还是会平分垂直方向的空间。

flex-start: 多条轴线在交叉轴上的起点对齐

flex-end: 多条轴线在交叉轴上的终点对齐。

**center:**多条轴线在交叉轴的中间对齐

**space-around:**每个轴线两侧的间隔相等,所以轴线中间的间隔会比边缘大一倍。

**space-between:**轴线两端对齐,每条轴上中间间隔相等,即剩余空间等分成间隙。

(2)Flex 项目(Flex item)

有六种属性可运用在 item 项目上:

  • order
  • flex-basis
  • flex-grow
  • flex-shrink
  • flex
  • align-self

**1. order:可以定义项目的排列顺序,数值越小,排列越靠前。**默认值为 0,数值可以为负数。

.item{
    order: <Number>
}

2. flex-basis: 定义了在分配多余空间之前,项目占据的主轴空间,浏览器根据这个属性,计算主轴是否有多余空间

.item {
    flex-basis: <length> | auto;
}

默认值:auto,即项目本来的大小, 这时候 item 的宽高取决于 width 或 height 的值

当主轴为水平方向的时候,当设置了 flex-basis,项目的宽度设置值会失效,flex-basis 需要跟 flex-grow 和 flex-shrink 配合使用才能发挥效果。

  • 当 flex-basis 值为 0 % 时,是把该项目视为零尺寸的,故即使声明该尺寸为 140px,也并没有什么用。
  • 当 flex-basis 值为 auto 时,则跟根据尺寸的设定值(假如为 100px),则这 100px 不会纳入剩余空间。

3. flex-grow: 定义项目的放大比例(伸张因子)

.item{
    flex-grow: <Number>
}

默认值为 0,即如果存在剩余空间,也不放大.

所有的项目都以 flex-basis 的值进行排列后,仍有剩余空间,那么这时候 flex-grow 就会发挥作用了。

当容器的宽度不够,且flex-wrap:nowrap,flex-grow不生效

4. flex-shrink: 定义了项目的缩小比例(收缩因子)

.item{
    flex-shrink:<number>
}

默认值: 1,即如果空间不足,该项目将缩小,负值对该属性无效。当所有项目的宽度总和超过容器宽度,也未设置flex-shirnk,则会整体按同等比例缩小。

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

5. flex: flex-grow, flex-shrink 和 flex-basis的简写

.item{
    flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
} 

flex 的默认值是以上三个属性值的组合。假设以上三个属性同样取默认值,则 flex 的默认值是 0 1 auto。

关于 flex 取值,还有许多特殊的情况,可以按以下来进行划分:

  • 当 flex 取值为一个非负数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%,如下是等同的:
.item {flex: 1;}
.item {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0%;
}
  • 当 flex 取值为 0 时,对应的三个值分别为 0 1 0%
.item {flex: 0;}
.item {
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: 0%;
}
  • 当 flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1,有如下等同情况(注意 0% 是一个百分比而不是一个非负数字)
.item-1 {flex: 0%;}
.item-1 {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0%;
}

.item-2 {flex: 24px;}
.item-2 {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 24px;
}
  • 当 flex 取值为两个非负数字,则分别视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%,如下是等同的:
.item {flex: 2 3;}
.item {
    flex-grow: 2;
    flex-shrink: 3;
    flex-basis: 0%;
}
  • 当 flex 取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow 和 flex-basis 的值,flex-shrink 取 1,如下是等同的:
.item {flex: 11 32px;}
.item {
    flex-grow: 11;
    flex-shrink: 1;
    flex-basis: 32px;
}

建议优先使用这个属性,而不是单独写三个分离的属性。

注:在同一时间,flex-shrink 和 flex-grow 只有一个能起作用,空间足够时,flex-grow 就有发挥的余地,而空间不足时,flex-shrink 就能起作用。

  • 当flex-wrap 的值为 wrap | wrap-reverse 时,表明可以换行,既然可以换行,一般情况下空间就总是足够的,即可以使用使用 flex-grow ,flex-shrink 当然就不会起作用,

  • 当flex-wrap值为nowrap,且子项宽度和不及父容器宽度时,flex-grow 会起作用,子项会根据 flex-grow 设定的值放大(为0的项不放大), 且子项宽度和超过父容器宽度时,flex-shrink 会起作用,子项会根据 flex-shrink 设定的值进行缩小(为0的项不缩小)。但这里有一个较为特殊情况,就是当这一行所有子项 flex-shrink 都为0时,也就是说所有的子项都不能缩小,就会出现讨厌的横向滚动条

6. align-self: 允许单个项目有与其他项目不一样的对齐方式

单个项目覆盖 align-items 定义的属性

默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。

.item {
     align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

例:容器 align-items 设置为 flex-start,而第三个项目align-self为flex-end即会出现如下图的情况。

四、grid布局

网格布局(Grid)是最强大的 CSS 布局方案。

它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。以前,只能通过复杂的 CSS 框架达到的效果,现在浏览器内置了。

Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局

指定一个容器采用网格布局。默认情况下,容器元素都是块级元素,但也可以设成行内元素

.contaier{ display: grid | inline-grid; }

.contaier{
  display: inline-grid;
}

注意,设为网格布局以后,容器子元素(项目)的floatdisplay: inline-blockdisplay: table-cellvertical-aligncolumn-*等设置都将失效。

容器指定了网格布局以后,接着就要划分行和列。grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高。

.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
}

指定了一个三行三列的网格,列宽和行高都是100px。除了使用单位,也可以设置百分比。

repeat:

.container {
  display: grid;
  grid-template-columns: repeat(3, 33.33%);
  grid-template-rows: repeat(3, 33.33%);
}

使用repeat(number, 百分比)也能达到上面效果。

auto-fill

.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
}
//表示每列宽度100px,然后自动填充,直到容器不能放置更多的列。

fr关键字:代表比例关系

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
//代表第一列与第二列比例相同

.container {
  display: grid;
  grid-template-columns: 1fr 2fr;
}
//代表第二列比例比第一列大一倍

auto 关键字:自已决定长度

grid-template-columns: 100px auto 100px;

参考文章