一、CSS常见的两种盒模型及其区别

盒模型也称为框模型,就是从盒子顶部俯视所得的一张平面图,用于描述元素所占用的空间它有两种盒模型

  • content-box W3C盒模型
  • border-box IE盒模型(IE6以下,不包括IE6)
  • padding-box (FireFox 曾经支持)
  • margin-box (浏览器未实现)

image.pngimage.png
理论上两者的主要区别是二者的盒子宽高是否包括元素的内边距+边框,当用CSS给给某个元素定义高或宽时

  • IE盒模型中内容的宽高将会包含内边距+边框
  • 而W3C盒模型并不会包含

设置div元素的宽度为100px;
在IE盒模型中的宽度是100px,
W3C盒模型中的宽度为122px(宽度+内边距+边框)

  1. div{
  2. padding:10px;
  3. margin:10px;
  4. border:1px solid #ccddff;
  5. width:100px;
  6. }
  • 盒子宽度 = width+padding左右+border左右
  • 盒子高度 = height+padding上下+border上下

CSS 改变盒模型的类型

新增了box-sizing属性来来改变盒模型的类型

  • content-box (默认值) 代表W3C盒模型,定义盒子宽高 = 内容宽高(content)
  • border-box (IE盒模型) 定义盒子宽高 = 内容宽高(content) + 内边距(padding) + 边框(border)

image.pngimage.png

<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设置失败,解决方法如下:
margin-top 塌陷.jpg

  • 方法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 最开始是用来实现文字环绕效果的

image.png

  • 父元素如果没有设置尺寸(一般是高度不设置),父元素内整体浮动的元素无法撑开父元素,父元素需要清除浮动
  • 浮动元素之间没有垂直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>

清除浮动

当不给父元素设置宽高时,父元素的宽高会被子元素的内容撑开。但是当子元素设置浮动属性后,子元素会溢出到父元素外,父元素的宽高也不会被撑开了,称之为 高度塌陷
image.png

  • 通过增加尾元素清除浮动
    • :after /<br>/clear: both
  • 创建父级 BFC
  • 父级设置高度

清除浮动1:使用 after 伪元素

image.png
该方法本质也是在末尾添加一个看不见的块元素来清除浮动。该方法也不存在语义化的问题,是目前的主流清除浮动的方法

.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, 分别表示左侧不允许浮动元素、右侧不允许浮动元素、左右两侧均不允许浮动元素
image.png

清除浮动3:使用 br 标签

br 自带 clear 属性,clear 属性有 left、right 和 all 三个属性值可选
传统盒子模型布局 - 图10
该方法同上一个方法添加空标签一样,也达到了清除浮动的目的,同上一个方法相比,语义化明显些了,但是也存在结构样式行为分离 的问题,不推荐使用

清除浮动4:给父元素设置 overflow

image.png
添加 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>

image.png

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>

image.png

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

image.png
从上图中我们不难发现,设置 position:relative 属性后

  • 不添加额外属性(left,right,top,bottom)等,它表现的如同 static 一样,如: box_1
  • 设置属性(left,right,top,bottom)会使元素偏离正常位置,如: box_2
  • 元素的偏移会覆盖相邻元素,如: 设置属性后的box_2叠加在box_3上
  • 定位元素是浮动的正常的文档流之上的,可以用 z-index 属性来设置元素的层级

absolute

image.png
absolute 会相对于最近的 除 static 定位以外 的元素进行定位
在使用时要注意设置父元素(或祖先元素)的 position 属性
若父元素(或祖先元素)都没有设置定位属性,absolute 会找到最上层即浏览器窗口,相对于它进行定位了

fixed

image.png
fixed 是相对于浏览器窗口的定位,一旦位置确定, 元素位置也不会改变
不像 absolute,它的位置与父元素息息相关,父元素移动它也会跟着动
从上图我们可以看出,fixed 元素是脱离文档流的,之后的元素会“无视”它,不会给它腾出空间