一、CSS常见的两种盒模型及其区别
盒模型也称为框模型,就是从盒子顶部俯视所得的一张平面图,用于描述元素所占用的空间它有两种盒模型
- content-box W3C盒模型
- border-box IE盒模型(IE6以下,不包括IE6)
padding-box (FireFox 曾经支持)margin-box (浏览器未实现)
理论上两者的主要区别是二者的盒子宽高是否包括元素的内边距+边框,当用CSS给给某个元素定义高或宽时
- IE盒模型中内容的宽高将会包含内边距+边框
- 而W3C盒模型并不会包含
设置div元素的宽度为100px;
在IE盒模型中的宽度是100px,
W3C盒模型中的宽度为122px(宽度+内边距+边框)
div{
padding:10px;
margin:10px;
border:1px solid #ccddff;
width:100px;
}
- 盒子宽度 = width+padding左右+border左右
- 盒子高度 = height+padding上下+border上下
CSS 改变盒模型的类型
新增了box-sizing属性来来改变盒模型的类型
- content-box (默认值) 代表W3C盒模型,定义盒子宽高 = 内容宽高(content)
- border-box (IE盒模型) 定义盒子宽高 = 内容宽高(content) + 内边距(padding) + 边框(border)
<style type="text/css">
.box {
width: 250px;
height: 200px;
padding: 20px;
border: 5px solid #ccddff;
background-color: #ffccdd;
text-align: center;
box-sizing:content-box;
/* box-sizing: border-box; */
}
</style>
<body>
<div class="box">box-sizing:content-box</div>
</body>
margin相关技巧
设置元素水平居中
margin:xxx auto;
margin-top 塌陷
在两个盒子嵌套时候,内部的盒子设置的margin-top会加到外边的盒子上,导致内部的盒子margin-top设置失败,解决方法如下:
- 方法1 外部盒子设置一个边框
- 方法2 外部盒子设置 overflow:hidden
- 方法3 使用伪元素类: ```css .clearfix::before { content: ‘ ‘; display: table; }
//使用:把.clearfix 要解决的外部盒子标签中去,相当于解决方法1
<a name="FbpKo"></a>
#### css元素溢出
| **属性** | **描述** |
| --- | --- |
| visible | 默认值。内容不会被修剪,会呈现在元素框之外 |
| auto | 如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容 |
| inherit | 规定应该从父元素继承 overflow 属性的值 |
| hidden | 内容会被修剪,并且其余内容是不可见的<br />此属性还有清除浮动、清除margin-top塌陷的功能 |
| scroll | 内容会被修剪,但是浏览器会显示滚动条以便查看其余的内容 |
<a name="X1Gbq"></a>
## 二、BFC 块级格式化上下文
BFC(块级格式化上下文)是一个独立的渲染区域,让处于 BFC 内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响
<a name="Bdr2Y"></a>
#### BFC触发条件
- IE下为 Layout,可通过 zoom:1 触发
- 根元素
- position != (static | relative),比如可以为absolute/fixed
- display: inline-block / table/table-cell/table-caption
- float != none
- ovevflow != visible
<a name="Fo36h"></a>
#### BFC规则
- 属于同一个 BFC 的两个相邻 Box 垂直排列,一个接一个地放置
- 属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。Box垂直方向的距离由margin决定,你要避免相邻块元素外边距重叠的话,那你就要避免产生BFC
- BFC 中子元素的 margin box 的左边, 与包含块 (BFC) border box的左边相接触 (子元素 absolute 除外)
- BFC 的区域不会与 float 的元素区域重叠
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此
- 计算 BFC 的高度时,浮动子元素也参与计算
- 文字层不会被浮动层覆盖,环绕于周围
<a name="Ujp2a"></a>
#### BFC应用
- 阻止margin重叠
- 可以包含浮动元素 ——清除内部浮动(清除浮动的原理是两个div都位于同一个 BFC 区域之中)
- 自适应两栏布局
- 可以阻止元素被浮动元素覆盖
<a name="z4MjK"></a>
#### BFC和普通文档流的区别
| **BFC** | **普通文档流** |
| --- | --- |
| 浮动的元素会被父级计算高度(父级触发BFC) | 浮动的元素不会被父级计算高度 |
| 非浮动元素不覆盖浮动元素的位置(非浮动元素触发 BFC) | 非浮动元素会覆盖浮动元素的位置 |
| margin 不会传递给父级(父级触发了BFC) | margin 会传递给父级 |
| 两个相邻元素的上下 margin 不会重叠 | 两个相邻元素的上下 margin 会重叠 |
[
](https://blog.csdn.net/qiao_xi/article/details/102470703)
<a name="DT762"></a>
## 三、 层叠上下文 display + float + position
前端开发就像盖房子,html 是构成房子的砖瓦, css决定这些砖瓦的位置和对它美化装饰<br />在实际开发中,前端在拿到设计稿后,都会先梳理页面的大致结构,构思完页面的布局后,再进行 coding。大多数网站都有着相似的布局,掌握这些“套路”便可以快速高效的完成开发工作
<a name="q0lSx"></a>
### 层叠上下文
触发条件
- html (根层叠上下文)
- position
- css3属性
- flex
- transform
- opacity
- filter
- will-change
- -webkit-overflow-scrolling
层叠等级:层叠上下文在z轴上的排序
- 在同一层叠上下文中,层叠等级才有意义
- z-index 的优先级最高
![image.png](https://cdn.nlark.com/yuque/0/2021/png/604921/1625026719696-13d22407-d0c8-4b1b-a39d-112b5146ef69.png#clientId=u92aa2f5d-955f-4&from=paste&height=838&id=u19de478f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=838&originWidth=1096&originalType=binary&ratio=1&size=297696&status=done&style=none&taskId=ud9bbc082-71e6-4710-80f1-fbd5c98db15&width=1096)
<a name="1ffcb643"></a>
### display
| 属性 | 描述 |
| --- | --- |
| none | 元素隐藏且不占位置 |
| inherit | 表示元素从父元素继承 display 属性值 |
| block | 将元素设置为**块级元素** |
| inline | 将元素设置为**内联元素** |
| inline-block | 元素**以内联块**显示 |
| flex | [flex 布局](https://www.yuque.com/yilvqingfeng-vvqbc/kg8loo/ty4y4h) |
- inline(行内元素)
- 使元素变成行内元素,拥有行内元素的特性,即可以与其他行内元素共享一行,不会独占一行
- 不能更改元素的height,width的值,大小由内容撑开
- 可以使用padding上下左右都有效,margin只有left和right产生边距效果,但是top和bottom就不行
- block(块级元素)
- 使元素变成块级元素,独占一行,在不设置自己的宽度的情况下,块级元素会默认填满父级元素的宽度
- 能够改变元素的height,width的值
- 可以设置padding,margin的各个属性值,top,left,bottom,right都能够产生边距效果
- inline-block(融合行内于块级)
- 结合了inline与block的一些特点,结合了上述inline的第1个特点和block的第2,3个特点
<a name="a2DpD"></a>
### 块级元素和行内元素
<a name="c3Mcr"></a>
#### 块级元素
块元素,也可以称为行元素,它在布局中的行为:
```html
1、支持全部的样式,可以给块级元素设置宽高、内边距、外边距等盒模型属性;
2、如果没有设置宽度,默认的宽度为父级宽度100%
3、块级元素可以包含块级元素和行内元素;
4、盒子占据一行、即使设置了宽度
常见的块级元素:
<div>
<h1> ~ <h6>
<p>
<ul>
<li>
<ol>
<dl>
<dt>
<dd>
<table>
<address>
<form>
内联元素
内联元素,也可以称为行内元素,它们在布局中的行为:
1、行内元素不会独占一行,只会占领自身宽高所需要的空间(宽高由内容决定);
2、支持部分样式,给行内元素设置宽高不会起作用,margin 值只对左右起作用,padding 值也只对左右起作用;
3、行内元素一般不可以包含块级元素,只能包含行内元素和文本;
4、盒子并在一行
5、代码换行,盒子之间会产生间距
6、子元素是内联元素,父元素可以用text-align属性设置子元素水平对齐方式
解决内联元素间隙的方法
1、去掉内联元素之间的换行
2、将内联元素的父级设置font-size为0,内联元素自身再设置font-size
常见的行内元素等
<a >
<b >
<label >
<span >
<img >
<em >
<strong >
<i >
<input >
内联块元素
内联块元素,也叫行内块元素,是新增的元素类型,现有元素没有归于此类别的,
img和input元素的行为类似这种元素,但是也归类于内联元素,我们可以用display属性将块元素或者内联元素转化成这种元素。它们在布局中表现的行为:
1、支持全部样式
2、如果没有设置宽高,宽高由内容决定
3、盒子并在一行
4、代码换行,盒子会产生间距
5、子元素是内联块元素,父元素可以用text-align属性设置子元素水平对齐方式。
⚠️注意: 这三种元素,可以通过display属性来相互转化,不过实际开发中,块元素用得比较多。所以我们经常把内联元素转化为块元素,少量转化为内联块,而要使用内联元素时,直接使用内联元素,而不用块元素转化了。
可代替元素
细心的你可能会发现,给 img 标签设置宽高是可以影响图片大小的
- 这是因为 img 是可替代元素,可替代元素具有内在的尺寸,所以宽高可以设定
- html 中的 input、button、textarea、select 都是可替代元素
- 这些元素即使是空的,浏览器也会根据其标签和属性来决定显示的内容
float浮动布局
float 属性定义元素在哪个方向浮动,常用属性值有:
- left(左浮动)
- right(右浮动)
设置了 float 浮动的元素特性有:
- 会脱离文档流,然后向左或向右移动,直到碰到父容器的边界或者碰到另一个浮动元素后结束浮动
- 相邻浮动的块元素可以并在一行,超出父级宽度就换行
- 浮动让行内元素或块元素自动转化为行内块元素,此时不会有行内块元素间隙问题
- 块级元素会忽略 float 元素,文本和行内元素却会环绕它,所以 float 最开始是用来实现文字环绕效果的
- 父元素如果没有设置尺寸(一般是高度不设置),父元素内整体浮动的元素无法撑开父元素,父元素需要清除浮动
- 浮动元素之间没有垂直margin的合并
x轴滚动不换行: 设置外层宽度,float浮动
<style>
div.box {
width: auto;
border: 2px solid rgba(0, 0, 0, .2);
overflow: hidden;
overflow-x: auto;
}
ul {
width: calc(200px * 21);
}
ul li,
ul p {
float: left;
width: 200px;
height: 50px;
background-color: red;
list-style-type: none;
}
.move {
animation: identifier 100s ease forwards;
}
@keyframes identifier {
from {}
to {
/* transform: translateX(-10000px); */
margin-left: -10000px;
}
}
</style>
<div class="box">
<ul>
<!-- li{$}*20 -->
<p class="move">0</p>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
<li>16</li>
<li>17</li>
<li>18</li>
<li>19</li>
<li>20</li>
</ul>
</div>
x轴滚动不换行: 未知不设外层宽度
<style>
ul.box {
width: auto;
white-space: nowrap;
border: 2px solid rgba(0, 0, 0, .2);
overflow: hidden;
overflow-x: auto;
}
.box li,
.box p {
display: inline-block;
width: 200px;
height: 50px;
background-color: red;
}
.move {
animation: identifier 100s ease forwards;
}
@keyframes identifier {
from {}
to {
/* transform: translateX(-10000px); */
margin-left: -10000px;
}
}
</style>
<ul class="box">
<!-- li{$}*20 -->
<p class="move">0</p>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
<li>16</li>
<li>17</li>
<li>18</li>
<li>19</li>
<li>20</li>
</ul>
清除浮动
当不给父元素设置宽高时,父元素的宽高会被子元素的内容撑开。但是当子元素设置浮动属性后,子元素会溢出到父元素外,父元素的宽高也不会被撑开了,称之为 高度塌陷
- 通过增加尾元素清除浮动
- :after /<br>/clear: both
- 创建父级 BFC
- 父级设置高度
清除浮动1:使用 after 伪元素
该方法本质也是在末尾添加一个看不见的块元素来清除浮动。该方法也不存在语义化的问题,是目前的主流清除浮动的方法
.container::after {
content: ' ';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix:after,.clearfix:before{ content: " ";display: table;}
.clearfix:after{ clear:both;}
.clearfix{zoom:1;} /*IE */
清除浮动2:通过添加额外的标签,利用 clear:both 来清除浮动
clear 属性用来定义哪一侧不允许其他元素浮动,常见的值有 left 、right、both, 分别表示左侧不允许浮动元素、右侧不允许浮动元素、左右两侧均不允许浮动元素
清除浮动3:使用 br 标签
br 自带 clear 属性,clear 属性有 left、right 和 all 三个属性值可选
该方法同上一个方法添加空标签一样,也达到了清除浮动的目的,同上一个方法相比,语义化明显些了,但是也存在结构样式行为分离 的问题,不推荐使用
清除浮动4:给父元素设置 overflow
添加 overflow 不仅减少了代码量,还不存在语义化的问题,但是也可能因为内容增加导致超出尺寸的内容被隐藏
前面两个方法带有 clear 关键字,很好理解,但是仅仅设置 overflow: hidden; 为什么就能清除浮动呢?
- 这里要引入一个概念:BFC块级格式化上下文,BFC 的一个特性便是可以包含浮动元素,
- 设置 overflow: hidden 满足了创建一个 BFC 的条件,其实就是创建 BFC,利用 BFC 固有特性清除浮动
左右栏流动布局对比
实现左流动,右固定宽度,用CSS Table表格与dispaly:float对比
CSS Table 搭配 width: calc(100%-300px)
<style type="text/css">
* { font-size: 32px; }
#div1 {
width: calc(100% - 300px);
display: table-cell;
vertical-align: middle;
text-align: center;
color: #ffffff;
background-color: #906CD7;
}
#div2 {
width: 300px;
height: 200px;
display: table-cell;
vertical-align: middle;
text-align: center;
color: honeydew;
background-color: #7080D7;
}
</style>
<body>
<div style="width: 100%;display: table;">
<div id="div1">calc(100%-200px);display: table-cell</div>
<div id="div2">display: table-cell</div>
</div>
</body>
float
<style type="text/css">
* { font-size: 32px; }
#div1 {
float: right;
width: 300px;
height: 200px;
text-align: center;
line-height: 200px;
background-color: #7080D7;
color: honeydew;
}
#div2 {
height: 200px;
line-height: 200px;
text-align: center;
margin-right: 300px;
background-color: #906CD7;
color: #ffffff;
}
</style>
<body>
<div style="width: 100%;display: table;">
<div id="div1"> float: right;</div>
<div id="div2">margin-right: 300px;</div>
</div>
</body>
position(定位)
在布局中很重要的因素就是定位,position 属性就是用来定义元素的定位机制。position 的常用属性值有
属性 | 描述 | 定位元素的偏移 |
---|---|---|
relative | 相对定位,相对于元素的正常位置进行定位 生成相对定位元素,元素所占据的文档流的位置保留,元素本身相对自身原位置进行偏移。 |
left right top bottom |
absolute | 绝对定位,相对于除 static 定位以外的元素进行定位 生成绝对定位元素,元素脱离文档流,不占据文档流的位置,可以理解为漂浮在文档流的上方,相对于上一个设置了定位的父级元素来进行定位,如果找不到,则相对于body元素进行定位 |
|
fixed | 固定定位,相对于浏览器窗口进行定位 生成固定定位元素,元素脱离文档流,不占据文档流的位置,可以理解为漂浮在文档流的上方,相对于浏览器窗口进行定位 网站中的固定 header 和 footer 就是用固定定位来实现的 |
|
static | 默认值,没有定位属性,元素正常出现在文档流中 相当于取消定位属性或者不设置定位属性 |
|
inherit | 继承父元素的 position 属性值 |
文档流(normal flow) 的概念
- 文档流(normal flow) 的概念,按理来说应该翻译成普通流,文档流是大多数人的叫法
- 文档流指盒子按照html标签编写的顺序依次从上到下,从左到右排列,块元素占一行,行内元素在一行之内从左到右排列,先写的先排列,后写的排在后面,每个盒子都占据自己的位置
- “流”可以想象成流动的水,当我们打开屏幕,浏览网页,滚动鼠标,网页的内容就像是水流一样滑过
- 当我们给元素的 positon 属性设置 absolute、fixed 时便会脱离文档流。不再遵循从上到下,从左到右的规律
relative
从上图中我们不难发现,设置 position:relative 属性后
- 不添加额外属性(left,right,top,bottom)等,它表现的如同 static 一样,如: box_1
- 设置属性(left,right,top,bottom)会使元素偏离正常位置,如: box_2
- 元素的偏移会覆盖相邻元素,如: 设置属性后的box_2叠加在box_3上
- 定位元素是浮动的正常的文档流之上的,可以用 z-index 属性来设置元素的层级
absolute
absolute 会相对于最近的 除 static 定位以外 的元素进行定位
在使用时要注意设置父元素(或祖先元素)的 position 属性
若父元素(或祖先元素)都没有设置定位属性,absolute 会找到最上层即浏览器窗口,相对于它进行定位了
fixed
fixed 是相对于浏览器窗口的定位,一旦位置确定, 元素位置也不会改变
不像 absolute,它的位置与父元素息息相关,父元素移动它也会跟着动
从上图我们可以看出,fixed 元素是脱离文档流的,之后的元素会“无视”它,不会给它腾出空间