正常布局流
浏览器在默认情况下,组织元素的布局方式:
- 任何元素都被包装成一个盒子,包含内容、内外边距以及边框
- 块级元素会基于其父元素的书写顺序进行放置,每个块级元素会在上一个元素下面另起一行,它们会被设置好的margin 分隔
- 内联元素的表现有所不同 --- 它们不会另起一行;只要在其父级块级元素的宽度内有足够的空间,它们与其他内联元素、相邻的文本内容(或者被包裹的)被安排在同一行。如果空间不够,溢出的文本或元素将移到新的一行
- 如果两个相邻的元素都设置了margin 并且两个margin有重叠,那么更大的设置会被保留,小的则会消失 --- 这被称为外边距叠加
定位(Position)
定位的目的即允许我们通过某种手段覆盖上述正常布局流文档,以按照我们想要的效果来进行排版
静态定位(static)
静态定位是每个元素获取的默认值——它只是意味着“将元素放入它在文档布局流中的正常位置 ——这里没有什么特别的,比如在某个规则中添加position属性,并使其值为static:
.positioned {
background: yellow;
position: static;
}
此代码和添加position属性之前没有任何区别,即:静态定位是每个元素的默认行为
相对定位(relative)
相对定位仍可以使该元素占据正常文本流,但是可以通过top、bottom、left和right属性修改它的最终位置,包括让它与页面上的其它元素重叠
.relative{
position: relative;
top: 30px;
left: 30px;
}
这里的结果表示,应用position: relative的元素相对于其原来所处的位置向下移动了30px,向右移动了30px
- relative 表现的和 static 一样,除非你添加了一些额外的属性
- 在一个相对定位(position属性的值为relative)的元素上设置 top 、 right 、bottom 和 left 属性会使其偏离其正常位置。其他的元素的位置则不会受该元素的影响发生位置改变来弥补它偏离后剩下的空隙
绝对定位
与相对定位不同,绝对定位的元素不再存在于正常文本流中。相反,它处于独立于正常文本流的一层,因此后面的元素会填补其空出的位置
.absolute{
position: absolute;
top: 30px;
left: 30px;
}
需要注意这里的结果,这和relative的结果很不一样,被设置为position: absolute的元素会相对于其父元素(这里是body)产生位置偏移,这里是距离父元素的顶部边框30px,距离父元素的左边框30px
这里有另一个例子,设置父元素的position值为relative会让其设置绝对定位的子元素看起来很不一样:
.relative {
position: relative;
width: 600px;
height: 400px;
}
.absolute {
position: absolute;
top: 120px;
right: 0;
width: 300px;
height: 200px;
}
因此一个元素的绝对定位的具体表现与其父元素的定位方式有很大关系:
如果元素是静态定位的。即如果它是 position: static ,那么它的绝对定位子元素会跳过它直接相对于body元素定位
z-index
当多个元素使用绝对定位时,难免会造成彼此之间的重叠,因此要决定哪些元素在哪些元素的顶部就显得非常重要,这也是为什么我们要设置z-index的原因
这实际上和图层原理很相似,凡是定位的元素都具有z-index的值为auto,实际上是0
如果不设置z-index的值,则元素的原始堆叠顺序是:在html标记中,定义顺序越靠后的元素将堆叠在靠前元素的上面
如果设置了z-index的值,则值越大的元素会叠加在值越小的元素上面
图中绿色背景框与黄色背景框都被设置成position:absolute,但因为绿色背景框的CSS规则中设置了z-index值:
z-index: 1;
而黄色背景框的z-index值默认为0,所以绿色叠加在了黄色上面
需要注意的是:z-index只接受无单位索引值;你不能指定你想要一个元素是Z轴上23像素—— 它不这样工作。 较高的值将高于较低的值,这取决于您使用的值。 使用2和3将产生与300和40000相同的效果
固定定位
还有一种类型的定位覆盖——fixed。 这与绝对定位(absolute)的工作方式完全相同,只有一个主要区别:绝对定位固定元素是相对于<html>或其最近的定位祖先,而固定定位固定元素则是相对于浏览器视口本身。 这意味着您可以创建固定的有用的UI项目,如持久导航菜单
position:sticky
还有一个可用的位置值称为 position: sticky,比起其他位置值要新一些。它基本上是相对位置和固定位置的混合体,它允许被定位的元素表现得像相对定位一样,直到它滚动到某个阈值点(例如,从视口顶部起10像素)为止,此后它就变得固定了。例如,它可用于使导航栏随页面滚动直到特定点,然后粘贴在页面顶部
例子:
https://www.w3school.com.cn/tiy/t.asp?f=css_position_sticky
参考:
https://zh.learnlayout.com/position.html
弹性盒子(FlexBox)
即便大多数情况下,使用float和position属性就能完成大多数布局,但还是有一些情况是这两种属性很难完成、甚至无法完成的,因此引入“弹性盒子”可以更好的帮助我们完成网页的自适应布局
flex模型说明
当一个元素表现为flex框时,它会沿着两个轴来进行布局:
主轴:是沿着 flex 元素放置的方向延伸的轴(比如页面上的横向的行、纵向的列)。该轴的开始和结束被称为 main start 和 main end
交叉轴:是垂直于 flex 元素放置方向的轴。该轴的开始和结束被称为 cross start 和 cross end
设置了 display: flex 的父元素(被称之为 flex 容器(flex container)。
在 flex 容器中表现为柔性的盒子的元素被称之为 flex 项(flex item)元素。
在了解了以上内容之后,即可开始说明flex布局的表现形式以及具体属性
flex父容器属性
要先使用flexbox模型,首先必须先定义flex容器:
html:
<div class="flex-container">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
CSS:
.flex-container {
display: flex;
}
通过display属性设置为flex,父容器将变得可以随浏览器窗口大小而伸缩
flex-direction:控制容器堆叠flex项目的方向
垂直从上到下
.flex-container {
display: flex;
flex-direction: column;
}
垂直从下到上
.flex-container {
display: flex;
flex-direction: column-reverse;
}
水平从左到右
.flex-container {
display: flex;
flex-direction: row;
}
水平从右到左
.flex-container {
display: flex;
flex-direction: row-reverse;
}
flex-wrap:控制容器内flex项目换行,默认值为“ nowrap ”
在必要的时候对flex项目进行换行处理
.flex-container {
display: flex;
flex-wrap: wrap;
}
此外该属性取值为wrap-reverse时,父容器将对flex项目进行倒序换行
flex-flow:简写属性,用来同时设置flex-direction和flex-wrap,比如:
.flex-container {
display: flex;
flex-flow: row wrap;
}
即相当于设置了 flex-direction:row ,flex-wrap:wrap
justify-content:用于定义flex项目在主轴上的对齐方式,以下说明取值效果:
center:中心对齐
flex-start:在容器开头对齐
flex-end:在容器末尾对齐
space-around:保留flex项目间与父容器边框之间的空隙
space-between:仅保留flex项目间的空隙
align-items:用于定义flex项目在交叉轴上的对齐方式
flex-start:交叉轴起点对齐
flex-end:交叉轴终点对齐
center:交叉轴中点对齐
stretch:若项目没有设置高度或设置为auto,flex项目将占满整个容器的高度(默认值)
baseline:项目的第一行文字的基线对齐
align-content:定义多轴线对齐方式,如果项目只有一根轴线,则该属性不起作用
flex-start:交叉轴起点对齐
flex-end:交叉轴终点对齐
center:交叉轴中点对齐
stretch:轴线上的项目占满整个交叉轴
space-between:与交叉轴两端对齐,轴线之间的间隔平均分布
space-around:每根轴线两侧的间隔都相等
完美居中
对flex父容器设置:
.flex-container {
display: flex;
height: 300px;
justify-content: center;
align-items: center;
}
结果如下:
子项目属性
order:定义项目的排列顺序,数值越小,排列越靠前
<div class="flex-container">
<div style="order: 3">1</div>
<div style="order: 2">2</div>
<div style="order: 4">3</div>
<div style="order: 1">4</div>
</div>
flex-grow:定义项目的放大比例。默认值为0,即如果存在是剩余空间,也不放大
<div class="flex-container">
<div style="flex-grow: 1">1</div>
<div style="flex-grow: 1">2</div>
<div style="flex-grow: 2">3</div>
</div>
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍
flex-shrink:定义项目的缩小比例,默认值为1,即如果空间不足,项目缩小
<div class="flex-container">
<div>1</div>
<div>2</div>
<div style="flex-shrink: 0">3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
</div>
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小
flex-basis:属性规定 flex 项目的初始长度
<div class="flex-container">
<div>1</div>
<div>2</div>
<div style="flex-basis:200px">3</div>
<div>4</div>
</div>
第三个弹性项目的初始长度为 200 像素
flex简写属性
flex 属性是 flex-grow、flex-shrink 和 flex-basis 属性的简写属性
比如:
<div class="flex-container">
<div>1</div>
<div>2</div>
<div style="flex: 0 0 200px">3</div>
<div>4</div>
</div>
使第三个弹性项目不可增长(0),不可收缩(0),且初始长度为 200 像素
align-self
- align-self 属性规定弹性容器内所选项目的对齐方式
- align-self 属性将覆盖容器的 align-items 属性所设置的默认对齐方式
- 允许单个项目有与其他项目不一样的对齐方式,可覆盖align-item值,默认为auto,表示继承父元素的align-item属性,如果没有父元素,则等同于stretch
BFC
不要试图去讲解 BFC 的定义!!
如何说明 BFC ,举例子!!不要试图去讲定义!
具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性
通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部
如何触发BFC
只要元素满足下面任一条件即可触发 BFC 特性:
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
具体应用
避免外边距折叠
同一个 BFC 下外边距会发生折叠,既然如此,把它们分别放到两个BFC里就行了
html:
<div class="container">
<p></p>
</div>
<div class="container">
<p></p>
</div>
CSS:
.container {
overflow: hidden;
}
p {
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
这时,两个盒子的边距变成了200px;
BFC可以包含浮动元素(清除浮动)
清除浮动的手法之一:
<div style="border: 1px solid #000;overflow: hidden">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
BFC可以阻止元素被浮动元素覆盖
设置float的文字环绕效果:
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一个左浮动的元素</div>
<div style="width: 200px; height: 200px;background: #eee">我是一个没有设置浮动, 也没有触发 BFC 元素, width: 200px; height:200px; background: #eee;</div>
这时候其实第二个元素有部分被浮动元素所覆盖,(但是文本信息不会被浮动元素所覆盖) 如果想避免元素被覆盖,可触第二个元素的 BFC 特性,在第二个元素中加入 overflow: hidden,就会变成:
这个方法可以用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度