1 盒模型

:::info 盒模型是指HTML元素的内容计算宽高的方式,比较常用的有标准盒模型(W3C标准)和IE盒模型 ::: 标准盒模型:width = content宽度
IE盒模型:width = content宽度+padding+border
在CSS属性中可以用box-sizing来控制,默认值为content-box,表示标准盒模型
如果需要切换成IE盒模型,可以使用border-box属性

  1. box-sizing: border-box / content-box(默认值);

现在项目中基本使用的是border-box属性,避免content的宽度为100%后,padding与border的宽度会把屏幕撑开

2 外边距合并

:::info 外边距合并是指同一个BFC内相邻的元素或者空的元素的垂直方向的外边距重叠后会发生合并 ::: 发生的条件
垂直方向,相邻元素(兄弟元素,父子元素)或者空元素,margin重叠,同一个BFC区域中,以上条件必须全部满足

重叠后外边距计算方式

  • 同为正值或者负值:取绝对值最大的外边距为当前重叠元素间的外边距
  • 一个为正一个为负值:两个外边距相加后得到的结果即为重叠元素的外边距

解决方法:

  • 将其中元素设置为BFC区域,元素在不同的BFC区域中即可
  • 父子元素或空元素:可以通过给父元素添加border或padding等内容使两个元素的margin被隔开

    3 BFC

    :::info BFC是块格式化上下文,是CSS在渲染过程中生成的一个块状区域(容器),它是浮动元素与在文档流元素的交互区域,规定了这个区域内的Block-Level Box如何布局,并且不会影响区域外的元素的布局 ::: 注意该区域的行内元素布局不会受到BFC特性的影响

    BFC的特性与创建

    BFC的特性:

  • 同一个BFC的垂直方向元素外边距重叠时会发生合并

  • BFC不会与浮动元素重叠
  • BFC在计算高度时会计算子元素中浮动元素的高度,所以不会出现父元素高度塌陷问题
  • BFC内部布局不会影响外部元素的布局

常见的出现BFC的场景:

  • html根元素是一个BFC
  • 浮动元素,float不为none
  • position为absolute或fixed
  • overflow不为visible
  • display为inline-block、table、inline-table、table-cell、table-row的元素
  • display为flow-root的元素
  • display为flex、inline-flex、grid、inline-grid元素的直接子元素

    display: flow-root

    由于创建BFC的属性都有其真正的含义,故在创建BFC的时候会有一些副作用,比如

    1. float: left; /* 造成元素浮动 */
    2. overflow:hiddent; /* 截断溢出内容 */

    display: flow-root创建了一个无副作用的BFC

    BFC的应用场景

    主要是利用BFC的一些特性来解决问题
    HTML结构如下:

    1. <div class='bfcPage'>
    2. <div class='box1'>box1</div>
    3. <div class='box2'>box2</div>
    4. </div>
  • 解决外边距合并问题

在box1或者box2的样式中添加创建BFC的属性,比如overflow: hidden或者display: flow-root,使box1与box2不在同一个BFC中

  1. .bfcPage {
  2. display: flow-root;
  3. }
  4. .box1 {
  5. margin-bottom: 20px;
  6. width: 50px;
  7. height: 50px;
  8. background-color: aquamarine;
  9. }
  10. .box2 {
  11. margin-top: 30px;
  12. background-color: #eee;
  13. overflow: hidden;
  14. }
  • 进行布局或解决父元素高度坍塌问题

box1是浮动元素,box2是BFC

  1. .bfcPage {
  2. display: flow-root;
  3. }
  4. .box1 {
  5. float: left;
  6. width: 50px;
  7. height: 50px;
  8. background-color: aquamarine;
  9. }
  10. .box2 {
  11. margin-left: 20px;
  12. background-color: #eee;
  13. overflow: hidden;
  14. }

效果如下:
image.png

bfcPage的高度为50px,高度被浮动元素撑开
BFC内元素不会与浮动元素重叠,所以box1与box2并排展示,并没有被覆盖,可以进行两列自适应布局
tipsbox1是浮动元素,脱离文档流,box2的margin-left是相当于bfcPage的左边框而言,由于box1的宽度为50,而box2的左边距为20,所以box1与box2之间没有间距

4 水平垂直居中

水平垂直居中有多种方法,position+transfrom,flex等,可以分为2种情况讨论

子元素定宽高

HTML结构如下,A定宽高

  1. <div className="mainpage">
  2. <div className="test size">A</div>
  3. </div>

则CSS样式使用position: absolute 和margin-left在已知宽高的情况下移动

  1. .mainpage {
  2. position: relative;
  3. width: 300px;
  4. height:300px;
  5. background-color: aqua;
  6. }
  7. .size{
  8. width: 60px;
  9. height:60px;
  10. background-color: crimson;
  11. }
  12. .test {
  13. position: absolute;
  14. left: 50%;
  15. top: 50%;
  16. margin-left: -30px;
  17. margin-top: -30px;
  18. }

除了使用margin-left/top的方式将元素移到中间位置外,还可以使用transform

  1. .test {
  2. position: absolute;
  3. left: 50%;
  4. top: 50%;
  5. transform: translate(-30px, -30px);
  6. }

还可以使用margin:auto

  1. .test {
  2. position: absolute;
  3. left:0;
  4. right:0;
  5. top:0;
  6. bottom:0;
  7. margin:auto;
  8. }

使用calc进行计算属性,但比较消耗性能

  1. .test {
  2. position: absolute;
  3. left:calc(50% - 30px);
  4. top:calc(50% - 30px);
  5. }

以上几种水平垂直居中只适用于定宽高的情况

子元素不定宽高

HTML结构如下

  1. <div className="mainpage">
  2. <div className="test">A</div>
  3. </div>

使用flex,只用设置容器就可以实现,子元素不需要进行设置

  1. .mainpage{
  2. display: flex;
  3. justify-content: center;
  4. align-items: center;
  5. width: 300px;
  6. height:300px;
  7. background-color: aqua;
  8. }

使用line-height + vertical-align,需要将子元素改成行内元素生效

  1. .mainpage {
  2. width: 300px;
  3. height:300px;
  4. line-height:300px; /* 行内元素垂直居中,会被继承 */
  5. text-align: center; /* 行内元素水平居中,会被继承 */
  6. font-size: 0px; /* 消除空白节点 */
  7. background-color: aqua;
  8. }
  9. .test {
  10. vertical-align: middle;
  11. line-height: normal; /* line-height会被继承,所以需要重新设置 */
  12. display: inline-block; /* 设置成行内元素text-align才会生效 */
  13. font-size: 14px; /* font-size也会继承 */
  14. background-color: crimson;
  15. }

vertical-align只对行内元素生效,vertical-align: middle可以让元素近似于垂直居中(涉及到基线问题)
也可以使用绝对定位和transform

  1. .mainpage {
  2. width: 300px;
  3. height:300px;
  4. position:relative;
  5. background-color: aqua;
  6. }
  7. .test {
  8. position: absolute;
  9. left: 50%;
  10. top: 50%;
  11. transform: translate(-50%, -50%);
  12. }

还可以使用table-cell,不需要设置子元素的样式,但是如果有多个子元素,子元素是垂直排列的

  1. .mainpage {
  2. width: 300px;
  3. height:300px;
  4. display: table-cell;
  5. vertical-align:middle;
  6. background-color: aqua;
  7. }

如果需要多个子元素并行排列,需要设置子元素

  1. .mainpage {
  2. width: 300px;
  3. height:300px;
  4. display: table-cell;
  5. vertical-align: middle;
  6. background-color: aqua;
  7. }
  8. .test {
  9. display: inline-block;
  10. }

5 两列布局

一列定宽,一列自适应

以左列定宽,右列自适应为例:HTML结构如下

  1. <div className="mainpage">
  2. <div className="testa">A</div>
  3. <div className="testb">B</div>
  4. </div>

可以通过flex来实现

  1. .mainpage {
  2. width: 100%;
  3. height:100%;
  4. display: flex;
  5. background-color: aqua;
  6. }
  7. .testa {
  8. width: 300px;
  9. flex-grow:0;
  10. flex-shrink: 0;
  11. background-color:chocolate;
  12. }
  13. .testb {
  14. flex-grow: 1;
  15. flex-shrink: 1;
  16. background-color:violet;
  17. }

float实现,需要清除浮动

  1. .mainpage {
  2. width: 100%;
  3. height:100%;
  4. background-color: aqua;
  5. }
  6. .testa {
  7. float: left;
  8. width: 300px;
  9. height:100%;
  10. background-color:chocolate;
  11. }
  12. .testb {
  13. height:100%;
  14. margin-left: 300px;
  15. background-color:violet;
  16. }

绝对定位实现

  1. .mainpage {
  2. width: 100%;
  3. height:100%;
  4. position: relative;
  5. background-color: aqua;
  6. }
  7. .testa {
  8. width: 300px;
  9. height:100%;
  10. position: absolute;
  11. top: 0;
  12. left: 0;
  13. background-color:chocolate;
  14. }
  15. .testb {
  16. position: absolute;
  17. top: 0;
  18. left: 300px;
  19. right: 0;
  20. height:100%;
  21. background-color:violet;
  22. }

一列不定宽,一列自适应

使用flex实现

  1. .mainpage {
  2. width: 100%;
  3. height:100%;
  4. display: flex;
  5. background-color: aqua;
  6. }
  7. .testa {
  8. flex-grow:0;
  9. flex-shrink: 0;
  10. background-color:chocolate;
  11. }
  12. .testb {
  13. flex-grow: 1;
  14. flex-shrink: 1;
  15. background-color:violet;
  16. }

也可以使用BFC
tips这个也可以用在一列定宽,一列自适应的场景

  1. .mainpage {
  2. width: 100%;
  3. height:100%;
  4. background-color: aqua;
  5. }
  6. .testa {
  7. float: left;
  8. height:100%;
  9. background-color:chocolate;
  10. }
  11. .testb {
  12. height:100%;
  13. display: flow-root;
  14. background-color:violet;
  15. }

6 三列布局

HTML结构如下

  1. <div className="mainpage">
  2. <div className="testa">A</div>
  3. <div className="testb">B</div>
  4. <div className="testc">C</div>
  5. </div>

两边定宽,中间自适应

万能的flex,flex对布局简直好用

  1. .mainpage {
  2. width: 100%;
  3. height:100%;
  4. display: flex;
  5. background-color: aqua;
  6. }
  7. .testa, .testc {
  8. width: 100px;
  9. flex-grow:0;
  10. flex-shrink: 0;
  11. background-color:chocolate;
  12. }
  13. .testb {
  14. flex-grow: 1;
  15. flex-shrink: 1;
  16. background-color:violet;
  17. }

使用float,中间的元素一定要float,脱离文档流,否则会把最右边的元素挤到下一行

  1. .mainpage {
  2. width: 100%;
  3. height:100%;
  4. box-sizing: border-box;
  5. padding: 0 100px;
  6. background-color: aqua;
  7. }
  8. .testa{
  9. width: 100px;
  10. height:100%;
  11. float: left;
  12. margin-left: -100px;
  13. background-color:chocolate;
  14. }
  15. .testc{
  16. width: 100px;
  17. height:100%;
  18. float: right;
  19. margin-right: -100px;
  20. background-color:chocolate;
  21. }
  22. .testb {
  23. float: left; // 一定要float,脱离文档流,否则会把C挤到下一行
  24. width: 100%;
  25. height:100%;
  26. background-color:violet;
  27. }

两列靠左,一列靠右,垂直居中

使用flex和margin-left,flex的子元素使用margin auto时会有意想不到的效果

  1. .mainpage {
  2. width: 100%;
  3. height:100%;
  4. display: flex;
  5. justify-content: flex-start;
  6. align-items: center;
  7. background-color: aqua;
  8. }
  9. .testa {
  10. width: 100px;
  11. height: 30px;
  12. background-color:chocolate;
  13. }
  14. .testb {
  15. width: 100px;
  16. height: 50px;
  17. background-color:violet;
  18. }
  19. .testc {
  20. width: 100px;
  21. height: 80px;
  22. margin-left: auto;
  23. background-color:chocolate;
  24. }

7 flex 布局

HTML结构如下

  1. <div className="mainpage">
  2. <div className="testa">A</div>
  3. <div className="testa">A</div>
  4. <div className="testa">A</div>
  5. <div className="testa">A</div>
  6. </div>

一行3列居中,最后不足三列的靠左

可以对最后一项使用margin-right:auto,但是需要判断最后一项是不是3的倍数
对flex布局的子元素使用margin,可以实现任意行的左右对齐,而不会影响其他行

  1. .mainpage{
  2. display: flex;
  3. flex-wrap: wrap;
  4. align-items: center;
  5. justify-content: space-around;
  6. width: 300px;
  7. height:300px;
  8. background-color: aqua;
  9. }
  10. .testa {
  11. height: 50px;
  12. width: 90px;
  13. background-color: chocolate;
  14. &:last-child {
  15. margin-right: auto;
  16. }
  17. &:nth-child(3n){
  18. margin-right: 0;
  19. }
  20. }

正方形div,且随父元素的宽高变化,长宽比例固定

可以使用&:after来实现div正方形,原因在于margin/padding设置百分百时都是以父元素的width来进行计算的,伪元素设置padding和margin时根据容器的宽度来计算的

  1. .mainpage{
  2. width: 100%;
  3. background-color: aquamarine;
  4. }
  5. .testa {
  6. display: inline-block;
  7. width:20%;
  8. background-color: cadetblue;
  9. &:nth-child(2n) {
  10. background-color: coral;
  11. }
  12. &:before {
  13. content: '';
  14. display: inline-block;
  15. padding-bottom: 100%;
  16. width: 0.1px;
  17. vertical-align: middle; /* 2个inline-block会上下错位,原因是基线变了,可以设置vertical-align来改变基线 */
  18. }
  19. }

也可以使用vw,将宽度设置为vw
1vw与1vh表示视口宽度和高度的的1%,假设4个子元素并排显示,且为正方形宽高自适应,可以将元素的高度设置为25vw,就可以实现宽高自适应了

参考