html和css的布局规则
html/css 的布局规则:
想了解 html/css 的布局规则,重要的不是规则是什么,而是什么因素会影响你使用对应的规则。当你理解了这些因素,那么相同场景下,你自然而然会想到使用什么规则。
场景(场景和关联)
举个例子:
- 土地:大小,价格,建什么东西
一句话概括就是:往容器放东西,怎么放。
土地:容器
大小和价格: 因素
东西:元素
怎么放:规则
那么,应用到浏览器中:
容器:也就是我们的浏览器视口(viewport)
因素:矩形、坐标系、边界
元素:盒模型
规则:文档流、定位、浮动、BFC、flex 等等
前面提到,要了解布局规则,重要的不是规则是什么,而是什么因素会影响你使用对应的规则,那么我们分别介绍下容器、因素、元素、规则,并从中建立关联。
容器(viewport):
web 浏览器视口指的是我们可见的区域,不包括浏览器菜单。移动设备的视口默认值为 980px,一般情况下这比移动设备要大,那么内容就会显示不完全,如果直接缩放那会导致字体变小。为了让视口的值等于移动设备的宽度,我们会在 html 的头部添加以下标签:
1 | <meta name="viewport" content="width=device-width" /> |
因素:
- 矩形:可缩放 -> 响应式布局
- 坐标系:拖拽、视差 -> 定位、滚动条、层叠上下文元素
- 边界:视口有边界、坐标系无边界
可见,容器的不同因素直接影响着我们在实现某种效果时使用哪些规则。接下来看看元素。
元素:
- 标准盒模型:块模型、行内模型
- 怪异盒模型
- 弹性盒模型
先了解下盒模型的结构,从里到外:content → padding → border → margin,各个部分组合在一起就是我们页面上看到的内容
标准盒模型:
我们常说的盒模型指的是 W3C 标准盒模型
- 元素的
width
、height
只包含 content 区域 - 盒子实际大小等于
width
+padding
+border
盒子的实际宽度我们可以看做是总宽度,和元素本身设置的 width 不是一个概念
我们布局中广泛应用的模型,分为块模型和行内模型,我们叫做块元素和行内元素。
块元素display: block
可以将元素设置为块元素,它拥有以下行为:
- 它占据父元素的所有宽度,绝大数情况下(不包含行内块元素)
- 独占一行
- 拥有
width
和height
属性 - 它的
margin
、border
、padding
属性会将盒子周边的元素给“推开”
行内元素display: inline
可以将元素设置为行内元素,也叫行内元素,它拥有以下行为:
- 盒子不会独占一行
width
和height
属性不起作用- 水平方向的外边距、内边距、边框会被应用,且会把其它
inline
状态的盒子推开 - 垂直方向的外边距、内边距、边框会被应用,但不会把其它
inline
状态的盒子推开
默认为行内元素有:a、span、em、strong
除了标准盒模型,还有怪异盒模型,也可以称 IE 盒模型。因为 IE8 之前,IE 默认使用怪异盒模型,并且没有可用的机制来切换。
怪异盒模型
- 元素的
width
、height
不仅包括content
,还包括padding
和border
- 盒子实际的大小取决于 width
图中我们给盒子设置了width: 200px
,padding: 10px
,那么 content 就会被挤压为 180px(200 - padding * 2)。
应用:使用怪异盒模型能解决 1px 边框线问题。
box-sizing
box-sizing
属性可以切换盒模型模式,默认值是content-box
,可选择有border-box
、inherit
content-box
:w3c 标准盒模型border-box
:IE 盒模型inherit
:从父元素集成 box-sizing
属性的值
弹性盒模型
对于一些特殊布局,如水平垂直居中,采用传统布局不容易实现,采用弹性盒模型就很方便实现。
推荐阮一峰老师的文章:Flex 布局教程,再补充容易忽视的几点:
作用在 flex 容器上
display: flex:
默认: align-items: stretch、flex-direction: row
align-content:
指定如何在纵轴上 项目之间和周围 分配空间。单轴下(flex-wrap: nowrap)此属性不生效
align-items:
初始值:stretch
stretch:表示 flex 项目会被拉伸至最高的项目高度的高度
flex-flow: row wrap === flex-direction: row + flex-wrap: wrap
作用在 flex 项目上
flex-grow:
初始值:0
flex-shrink:
初始值:1
flex-basic:
初始值:auto,即项目本身的大小
指定了 flex 项目在主轴上的初始大小(如果主轴是水平轴,那就是 flex 项目的宽,否则是高)
flex: 1 200px === flex: 1 + flex-basic: 200px
指定了 flex 项目在主轴上初始化(width: 200px)后,按比例分配剩余空间
flex 缩写
flex === flex-grow flex-shrink flex-basic
flex: 1
flex: 1,此属性可以按同等比例分配项目的大小,那么它的完整写法是什么呢?
不等于 1 1 auto
重点理解下缩写下 flex-basic 的作用:
在按比例分配项目之前,计算项目是否有多余的空间,默认为 auto,即项目自身的大小。
如果设置为 auto,那么按照项目自身大小初始化后等比例分配剩余空间,也就会出现项目大小不一样的情况,所以不是 1 1 auto。
等于 1 1 带单位的长度值
假设我们设置为 1 1 0px,按照 0px 初始化后等比例分配剩余空间,那每个项目的大小就会相同。
flex 常用布局
需求:同一行内,如果有一个标题占两行,整行标题都占两行,否则默认一行。标题超出两行时用省略号表示,效果如下:
这个需求的难点在于卡片的高度不是固定的。有什么办法可以让同行内的标题高度保持统一?
先看一个两行超出隐藏的实现
1 | .title { |
1 | <div class="title"> |
先来重点理解display: flex
和 flex 下的height: 100%
- 当我们给容器设置 display: flex 时,那么 align-items 属性的值为 stretch,即同一行内的 flex 项目会被拉伸至最高的项目高度的高度
- 给 flex 项目设置 height: 100%,会填充容器剩余高度。
实现:
- 把容器设置为弹性盒子
display: flex
- 给标题设置
height: 100%
- 给标题兄弟元素设置
flex-shrink: 0
1 | <div class="section"> |
1 | .section { |
规则
下面介绍文档流、定位、浮动、BFC 等布局规则。
文档流:
在不对页面元素进行任何控制的情况下,浏览器默认的布局方式。从上到下,从左到右。
定位(position):
解决某个元素随页面发生变化而固定位置,它不作为一种主要布局方式,而是用于管理和微调页面中一些特殊项的位置
- 静态定位:默认值,不做任何
- 相对定位:相对自己定位,不会脱离文档流
- 绝对定位:相对于 html,会脱离文档流,或相对于最近被定位的祖先元素定位。多配个相对定位使用
- 固定定位:相对于浏览器视口固定定位
- 粘性定位:初始像静态定位,当它的位置相对视口达到预设值时,就会想固定定位一样被固定住
浮动(float)
在传统布局里,信息是纵向排列(从上到下)的,浮动可使信息横向排列。浮动会脱离文档流,正常文档流的元素会围绕着浮动元素。
- left:左浮
- right:右浮
- none:不浮动
- inherit:继承父元素浮动属性
在使用浮动时,我们得清楚的知道我们要把元素摆放在哪个位置。因为使用浮动时,可能会存在可视化布局与源顺序不同。
假设现源顺序布局为如下
1 | div1 div2 div3 |
我们给 div2 和 div3 同时设置 float: right
,那么视觉效果就为:
1 | div1 div3 div2 |
这是因为 div2 在源顺序上比 div3 等级更高(在 DOM 上,div2 先出现,并声明了 float: right
),所以在视觉上更靠右。
BFC:块级格式化上下文(block format context )
定义:可以看作是一块独立的区域空间,拥有普通盒子没有的一些特性。它解决个体之间的位置交互问题。
触发 BFC 的方法:
- html 根元素
- position: absolute、fixed
- display: flex、inline-block、table-cell
- overflow: 除 visibility
- float: 除 none
来看下元素间的交互问题以及解决方法:
- 同一块 BFC 下,相邻垂直方向盒子外边距会发生重叠:
1 | <div class="box"> |
1 | .box { |
我们给每个 child 设置了margin: 50px
,但它们的间距不是 100px,而是 50px,如果我们想让间距变成 100px,那么只要给其中一个盒子设置为 BFC,这样就不再同一块 BFC 下
1 | <div class="box"> |
1 | .box { |
- 浮动问题:
1 | <div style="border: 1px solid #000;"> |
为外层 div 添加overflow: hidden
1 | <div style="border: 1px solid #000;overflow: hidden;"> |
- 元素被浮动元素覆盖的问题
1 | <div style="height: 400px;"> |
给被浮动元素覆盖的元素添加overflow: hidden
1 | <div style="height: 400px;"> |
小结:
解决塌陷:给其中一个盒子设置为 BFC,这样就不再同一块 BFC 下
清除浮动:给浮动元素父元素设置为 BFC
防止元素被浮动元素覆盖:给元素设置 BFC,就不会被浮动元素覆盖
IFC:行内格式化上下文(inline formatting context)
让块水平居中
1 | .p { |
1 | <div class="p"> |
总结(对 html/css 规则)
抽象点来说,容器就是一个可以容纳个体的空间,当我们把一个个个体放到容器时,容器的因素决定了我们使用什么规则来存放从而更加合理。
具体点来说,视口就是我们的容器,元素就是个体,视口的因素(矩形、坐标系和边界等)决定了我们使用什么规则来布局。元素分为标准盒模型、IE 盒模型和弹性盒模型,规则分为文档流、定位、浮动、BFC 等等。
参考:
https://zhuanlan.zhihu.com/p/183050328
https://blog.csdn.net/weixin_41682025/article/details/110343448