盒子模型

组成:

  • content(内容区)
  • border(边框)
  • padding(内边距)
  • margin(外边距)

盒子大小

盒子的大小值得就是盒子在容器中实际所占据的高度和宽度(默认情况下我们通过css设置的widthheight只是设置了content(内容区)的高度和宽度,实际上盒子模型所占据的高度和宽度是按照下面来计算的)

实际的宽度:

实际宽度 = margin-left + border-left + padding-left + width(content-width) + padding-right + border-right + margin-right

实际的高度:

实际的高度 = margin-top + border-top + padding-top + height(content-height) + padding-bottom + border-bottom + margin-bottom

比如下面图片的实际宽度和实际高度是多少呢?

实际宽度和实际高度是多少呢

使用上述公式,就能算出示例中的高宽值

实际宽度 = 20+6+20+400+20+6+20 = 492

实际的高度 = 20+6+20+100+20+6+20 = 192

更改盒子模型的计算方式

一般情况下,css设置的width,height设置的都是content-width,content-height,但是我们也可以通过css,改变css里面的width,和height设置的是什么

box-sizing:content-box(默认情况)

  • 一开始的css显示效果和代码,可以看到,Child container刚刚好等于父元素的宽度
    • 也就是实际的宽度 = 父元素的宽度
1
2
box-sizing: content-box;
width: 100%;

显示效果

  • 添加了border为10px,并且设置了padding:5px
    • 可以看到内容超过了父元素,溢出了
    • 实际的宽度 = 父元素的宽度 + border-left + border-right + padding-left + padding-right
1
2
3
4
box-sizing: content-box;
width: 100%;
border: solid #5B6DCD 10px;
padding: 5px;

添加了border为10px,并且设置了padding:5px后的效果

box-sizing:border-box

  • 只将box-sizing修改为border-box,效果就完全不同
  • 实际的宽度 = 父元素的宽度
  • 因为box-sizing设置的为border-box所以css当中设置的width属性包括了border的宽度和padding的宽度(注意,不包括margin!)
1
2
3
4
box-sizing: border-box;
width: 100%;
border: solid #5B6DCD 10px;
padding: 5px;

只将box-sizing修改为border-box

div(块元素)水平方向布局

  • 看过上面,我们知道水平方向上的位置必须要满足
    • margin-left + border-left + padding-lef + width + padding-right + border-right + margin-right = 父元素内容区的宽度
  • 如果不满足上方等式,等式就会自动去调整

这七个值中有三个值可以设置为auto

1
2
3
4
5
width

margin-left

margin-right
  • 调整的情况 (等式当中含有auto值没有auto的情况)
widthmargin-leftmargin-right结果
auto/auto**宽度(width)自动调整为最大值,**选取的margin-right自动为0
autoauto/**宽度(width)自动调整为最大值,**选取的margin-left自动为0
autoautoauto**宽度(width)自动调整为最大值,**二个外边距自动设置为0
auto//**宽度(width)自动调整为最大值,**二个外边距自动设置为0
固定值autoauto宽度(width)不变,margin-left和margin-right自动调整(也就是水平居中)
固定值auto/宽度(width)不变,自动调整margin-left的值
固定值/auto宽度(width)不变,自动调整margin-right的值
固定值//宽度(width)不变,自动调整margin-right的值

总结:

  • 三者当中含有auto值的情况

    • width为auto的时候,总是保证width为最大值而其他设置为auto的自动设置为0
    • width为固定值的时候,自动调整已经设置为auto的值使其满足等式(margin-left + border-left + padding-lef + width + padding-right + border-right + margin-right = 父元素内容区的宽度)
  • 三者当中没有auto的情况

    • width为固定值发现其他值都没有写,没有一个auto,那么就自动调整margin-right的值(见得最多的)

例如下方例子:

  • 下方的例子说明auto的计算

  • 注意,没有写代表没有,如果填写了0,或者auto,就代表在css里面设置了margin-left或者其他的为0或者auto!

margin-leftborder-leftpadding-leftwidthpadding-rightborder-rightmargin-right父元素宽度结果
000auto000800pxwidth当中的auto设置为800px
auto00500px000800pxmargin-left的auto被设置为300px
000400px00auto800pxmargin-right的auto被设置为500px
没有写00700px00没有写800pxmargin-right的auto被设置为100px
auto105400px510auto700pxmargin-left和margin-right的auto被设置为(700-(10+5+400+5+10))/2=135px

宽度设置了下,其他都没有写

  • 所以为什么你经常看到设置了宽度后,在设置margin:0 auto就可以实现水平居中,就是利用上述原理
    • width固定,margin-left,margin-right为auto,那么浏览器会自动跳转auto的值,所以就实现了水平居中
div(块元素)垂直方向布局

块元素7个值没有auto的话就会自动调整margin-bottom其他和水平基本一样的,也是下面三个值可以设置auto,这里就不多说了

1
2
3
4
5
margin-top

height

margin-bottom

开启绝对定位元素的布局

先来大概了解下开启绝对定位后元素的参考父元素(也就是我们常说的包含块)
  • 正常情况下,包含块就是最近的开启了相对定位的块元素(当然,如果都没有开启,则参考html)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <style>
    .box1 {
    width: 400px;
    height: 400px;
    background-color: red;
    position: relative;
    }
    .box2 {
    width: 200px;
    height: 200px;
    background-color: green;
    }
    .box3 {
    width: 100px;
    height: 100px;
    background-color: blue;
    position: absolute;
    right: 0;
    }
    </style>
    </head>
    <body>
    <div class="box1">
    <div class="box2">
    <div class="box3"></div>
    </div>
    </div>
    </body>

    可以看到,box3是参考box1的,因为box1开启了相对定位

开启决定定位后,开启绝对定位后的元素也是需要满足一定条件约束的
  • 水平方向来说:(和平常没有开启定位的多了一个left,right)

left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 包含块的宽度

  • 垂直方向来说:(和平常没有开启定位的多了一个top,bottom)

top + margin-top+ border-top+ padding-top+ height+ padding-bottom+ border-bottom+ margin-bottom+ bottom = 包含块的宽度

水平方向布局

可以调整为auto的

1
2
3
4
5
margin-left
width
left
right
margin-right

需要满足

left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 包含块的宽度

如果9个值当中没有设置auto,则会自动调整right的值来满足(有点像未开启定位的块元素的水平布局一样,块元素其他7个值没有auto的话就会自动调整margin-right)

所以如果等式不满足的时候,就会自动调整leftright这两个值。

  • 例子:下面的例子就会自动调整right为-200px,使得等式成立
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<style>
.box1{
position: relative;
width: 200px;
height: 200px;
background-color: red;
}

.box2{
position:absolute;
width: 100px;
height: 100px;
background-color: green;
left: 300px;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>

</body>

浏览器查看box2的computed

浏览器computed查看

当然,你如果皮,把box2的right改为0

1
2
3
4
5
6
7
8
9
.box2{
position:absolute;
width: 100px;
height: 100px;
background-color: green;
left: 300px;
//新添加
right:0;
}

那么效果依旧不会变化~不过浏览器查看box2的computed的时候变成了这样子

把box2的right改为0后浏览器查看

  • 需要注意的是: 要设置left = 0; right = 0; 才能调整margin-left和margin-right,否则会自动调整left和right的值(不管computed有没有看到效果) 从而导致给margin-left、margin-right设置值会失效
垂直方向布局

可以调整为auto的

1
2
3
4
5
margin-top
height
left
right
margin-bottom

需要满足

top + margin-top+ border-top+ padding-top+ height + padding-bottom+ border-bottom+ margin-bottom+ bottom = 包含块的高度

如果9个值当中没有设置auto,则会自动调整bottom的值来满足(有点像块元素的垂直布局一样,块元素7个值没有auto的话就会自动调整margin-bottom)

所以如果等式不满足的时候,就会自动调整topbottom这两个值。

常用的一些效果
  • 开启定位后相对于包含块水平居中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//设置代码
.box2{
...
position:absolute;
left:0;
right:0;
margin:0 auto;
/* 或者 */
/* margin-left: auto; */
/* margin-right: auto; */
}

//例子全部
<style>
.box1 {
position: relative;
width: 200px;
height: 200px;
background-color: red;
}

.box2 {
position: absolute;
width: 100px;
height: 100px;
background-color: green;
left: 0;
right: 0;
margin: 0 auto;
/* 或者 */
/* margin-left: auto; */
/* margin-right: auto; */
}
</style>
</head>

<body>
<div class="box1">
<div class="box2"></div>
</div>

</body>

效果

开启定位后相对于包含块水平居中

浏览器computed效果

浏览器computed查看效果

  • 开启定位后相对于包含块垂直居中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
.box2{
...
position:absolute;
top:0;
top:0;
margin:auto 0;
/* 或者 */
/* margin-top: auto; */
/* margin-bottom: auto; */
}

//完整代码
<style>
.box1 {
position: relative;
width: 200px;
height: 200px;
background-color: red;
}

.box2 {
position: absolute;
width: 100px;
height: 100px;
background-color: green;
top: 0;
bottom: 0;
margin: auto 0;
/* margin-top: auto;
margin-bottom: auto; */
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>

效果

开启定位后相对于包含块垂直居中

浏览器computed查看

浏览器computed查看效果

  • 开启定位后相对于包含块居中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 .box2 {
...
position: absolute;
left:0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
...
}

//完整代码
<style>
.box1 {
position: relative;
width: 200px;
height: 200px;
background-color: red;
}

.box2 {
position: absolute;
width: 100px;
height: 100px;
background-color: green;
left:0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>

效果

开启定位后相对于包含块居中

浏览器computed查看效果

浏览器computed查看效果

弹性盒

基本概念

  • 想看看也可以,这里说的简单的,也可以看看这位博主写的

  • 设置

    • display:flex开启弹性容器,将当前元素设置为块级的弹性容器
    • display:inline-flex开启弹性容器 设置为行内的弹性容器
  • 基本概念

    • 主轴
      • 弹性元素的排列方向(默认水平方向为主轴)
    • 侧轴
      • 和主轴垂直的叫侧轴

默认情况下的主轴侧轴方向

  • 特征
    • 弹性容器的子元素是弹性元素
    • 弹性元素可以同时是弹性容器

如下代码开启了弹性布局,div即为弹性容器,div下方的span em等即为弹性元素

1
2
3
4
5
6
7
<body>
<div style="display:flex">
<span>听我说</span>
<em>动感超人</em>
</div>
</body>
</html>

设置主轴

顺带一提记忆方法: 你知道display:flex是开启定位,那么就联想记忆,就认为flex就代表水平,然后flex-direction就是告诉容器水平是哪一个方向的 (row代表行,行当然是水平的,column代表列,列肯定是垂直的) 感兴趣的可以看看MDN的主轴API

方向 flex-direction
  • flex-direction:row(默认值)|row-reverse|column|column-reverse

flex-direction:row设置弹性容器当中的弹性元素在水平方向排列,并且弹性元素是从左到右排序(同时设置主轴的方向为水平方向) (默认值)

flex-direction:row

flex-direction:row-reverse设置弹性容器的弹性元素在水平方向排列并且是从右到左排列(同时设置主轴的方向为水平方向)

flex-direction:row-reverse

flex-direction:column设置弹性容器的弹性元素在垂直方向,并且是从上到下依次排列(同时设置主轴的方向为垂直方向)

flex-direction:column

flex-direction:column-reverse设置弹性容器的弹性元素在垂直方向,并且是从下到上排列(同时设置主轴的方向为垂直方向)

flex-direction:column-reverse

设置弹性元素在弹性容器上是否自动换行(重要) flex-wrap
  • flex-wrap:nowrap(默认值不换行) | wrap(换行) | wrap-reverse

flex-wrap:nowrap的情况

flex-wrap:nowrap

如果没有设置弹性元素:flex-shrink:0的话,那么弹性元素如果超过了弹性容器的宽度,那么会自动跳转宽度使其等于弹性容器的宽度!

flex-wrap:wrap换行

flex-wrap:wrap

flex-wrap:wrap-reverse 主轴相反的方向进行换行 不太好描述,感觉像叠叠乐一样

flex-wrap:wrap-reverse-效果1

flex-wrap:wrap-reverse-效果2

对齐方式 justify-content

大家都知道word当中有什么左对齐,居中对其,右对齐,二端对其,css也有~

  • justify-content:flex-start | flex-end | center | space-between | space-around
  • 设置如何顺着弹性容器主轴的方向分配弹性元素之间及其周围的空间(大白话就是主轴在哪里,我就按照你方向来分配其他没有被占据的空间)
  • 正确的理解应该是设置弹性元素在主轴上的对其方式
  • justify-content说明文档
  • 特别注意,这里的弹性元素会出现放不下被换行和垂直方向排布端正是因为设置了flex-wrap: wrap;align-content: flex-start;

justify-content:flex-start(可以说是默认值) 设置元素每一行在主轴开头(起始位置)开始排布

justify-content:flex-start

justify-content:flex-end设置元素沿着主轴终点开始排列

justify-content:flex-end

justify-content:space-between 设置每一行的空白元素平均分配到元素中间

justify-content:space-between

justify-content:space-around 设置每一行的空白元素分配到元素四周(注意:二个元素之间分配到的空白间距并不会取消,而是会叠加在一起)

justify-content:space-around

设置侧轴

元素对其方式 align-items
  • align-items:stretch(默认) |center| flex-start | flex-end | baseline

align-items:stretch 元素在侧轴上拉伸(如果没有设置height属性或者设置为auto就会拉伸) ,如果设置了width为固定值,那么这个效果就不会生效

align-items:stretch并且不设置width

align-items:center 设置侧轴元素居中排列

align-items:center

align-items:flex-start元素向侧轴起点对齐(以每一行为参考,可以想象下每一行有自己的主轴侧轴)

align-items:flex-start

align-items:flex-end 元素向侧轴终点对齐(以每一行为参考,可以想象下每一行有自己的主轴侧轴)

align-items:flex-end

空隙排布 align-content
  • align-content: flex-start | flex-end | space-between | space-around | center

图我就不自己截了,拿了其他的,原来作者找不到了..只找到一个转载的

align-content:flex-start

align-content:flex-start

align-content:flex-end

align-content:flex-end

align-content:space-between

align-content:space-between

align-content:space-around

align-content:space-around

align-content:center

align-content:center

一个小小的简写(一次性设置主轴方向和flex-wrap)

  • flex-flow: flex-direction flex-wrap
    • 比如flex-flow:row nowrap
针对弹性元素的属性(注意区分弹性容器和弹性元素)

再次强调下,弹性容器是外壳,弹性元素是内部~

flex-grow:number
  • 指定弹性元素的伸展系数,也就是当父元素(弹性容器)有空余的元素的时候如何分配(伸展)
    • 比如 flex-grow : 1 ; flex-grow : 2; flex-grow : 3 ;

原来的空隙

原来的空隙

设置 flex-grow : 1 ; flex-grow : 2; flex-grow : 3; [这些数字就是所占据的比例,比如1,就占1/(1+2+3)=1/6 也就是六分之一]

设置 `flex-grow : 1 ;  flex-grow : 2; flex-grow : 3 `

flex-shrink:number
  • 指定弹性元素的收缩系数,也就是如果当父元素(弹性容器)容纳不下子元素(弹性元素)的时候,如何减少

未设置flex-shrink,即为0

未设置flex-shrink,即为0

设置flex-shrink : 1 ; flex-shrink : 2 ; flex-shrink : 3 ;后的效果

设置flex-shrink : 1 ; flex-shrink : 2 ; flex-shrink : 3

flex-basis
  • flex-basis具体长度|auto —-设置弹性元素在主轴上的基础长度
  • flex-basis:100px;
    • 如果主轴为横向的,则此元素设置宽度
    • 如果主轴是纵向的,则此元素设置高度