盒模型 边距重叠 BFC 清除浮动

113 阅读6分钟

内联、块级元素

inline, inline-block, block 区别

inline 无法设置宽高,margin 只能设置左右

盒模型

box-sizing: content-box | border-box | inherit

标准盒模型 content-box

width or height = content

IE盒模型 border-box

width or height = content + padding + border

获得宽高

getBoundingClientRect:developer.mozilla.org/zh-CN/docs/…

返回值是一个 DOMRect 对象,是包含整个元素的最小矩形(包括 padding 和 border)。该对象使用 left、top、right、bottom、x、y、width 和 height 这几个以像素为单位的只读属性描述整个矩形的位置和大小。除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的。

  • 获取屏幕的高度和宽度(屏幕分辨率): window.screen.height/width
  • 获取屏幕工作区域的高度和宽度(去掉状态栏): window.screen.availHeight/availWidth
  • 网页全文的高度和宽度: document.body.scrollHeight/Width
  • 滚动条卷上去的高度和向右卷的宽度: document.body.scrollTop/scrollLeft
  • 网页可见区域的高度和宽度(不加 border ): document.body.clientHeight/clientWidth
  • 网页可见区域的高度和宽度(加 border ): document.body.offsetHeight/offsetWidth

offsetLeft、offsetWidth、clientWidth、scrollWidth、style.width 区别

offset 以父元素作为参照点(父元素的定位不能是 static ),当前元素相对于父元素左边的偏移量,如果没有父元素那么参照点就是 body。

边距重叠

外边距重叠基本概念

两个垂直的相邻的块级元素,当上下两个边距相遇时,其外边距会产生重叠现象,切重叠后的外边距,等于其中较大者。(tips:水平方向不会发生

外边距叠加的三种情况

  1. 同级元素叠加 ( 相邻元素,上元素的下边距与下元素的上边距发生重叠,取外边距的较大值 )

<section class="parent">
  <article class="brother1"></article>
  <article class="brother2"></article>
</section>
<style>
  html * {
    margin: 0;
    padding: 0;
  }
  .brother1 {
    height: 100px;
    margin-bottom: 20px;
    background: red;
  }
  .brother2 {
    height: 100px;
    margin-top: 10px;
    background: yellow;
  }
</style>
  1. 父子元素叠加( 如果没有 padding 和 border 将外边距分隔开,父子相邻的上下外边距也会合并,取较大值 )

<section class="parent">
  <article class="child"></article>
</section>
<style>
  html * {
    margin: 0;
    padding: 0;
  }
  .parent {
    background: red;
    overflow: hidden;  // 写了这个,父元素高度110px,不写父元素高度100px
  }
  .parent .child {
    height: 100px;
    margin-top: 10px;
    background: yellow;
  }
</style>

3.空元素 ( 空元素指没有子元素或没有文字内容的元素,如 br hr

hr 元素默认有 1px 边框,所以不会合并 )

<div>
  <hr/>
</div>
<style>
  html * {
    margin: 0;
    padding: 0;
  }
  div {
    width: 200px;
    height: 100px;
    margin-top: 10px;
    background: red;
  }
  hr {
    border: none;
    margin-top: 20px;
    margin-bottom: 10px;
    background: yellow;
  }
</style>

折叠后的计算规则

  1. margin 都是正值的时候取较大的 margin值
  2. margin 都是负值的时候,取绝对值较大的值,然后向负方向位移
  3. margin 有正有负,从负值中选绝对值最大的,从正值中取绝对值最大的,然后相加
  4. 相邻的 margin 要一起参与计算

BFC

BFC基本概念

直译为:块级格式化上下文,是一个独立的渲染区域

BFC特性

  • 内部的 Box 会在垂直方向上一个接一个的放置。
  • 垂直方向上的距离由 margin 决定
  • BFC 的区域不会与 float 的元素区域重叠。
  • 计算 BFC 的高度时,浮动子元素也参与计算
  • BFC 就是页面上的一个独立容器,容器里面的子元素不会影响外面元素。

创建BFC

  • 根元素
  • position: absolute/fixed
  • display: inline-block/table-cell/flex
  • float元素
  • overflow !== visibleoverflow = hidden/scroll/auto

BFC使用场景

避免 margin 重叠

把不想进行边距重叠的元素,包裹在一个父级元素中,并设置成 BFC

<section class="margin">
  <p></p>
  <p></p>
</section>

// 将第二个p标签,包裹在一个父元素中,并设置成BFC
<section class="margin">
  <p></p>
  <div style="overflow:hidden;">
    <p></p>
  </div>
</section>

<style>
  html * {
    margin: 0;
    padding: 0;
  }
  p {
    background: yellow;
    width: 200px;
    height: 100px;
    margin: 30px;
  }
</style>

自适应两栏布局 or 防止文字环绕

因为浮动的特性,如果不对 right 进行处理,会有部分区域出现在 left 下面,通过使 right 成为 BFC 可以解决这个问题

同理,如果不设置 BFC,right 里面的文字会被覆盖

<div class="left">我是浮动元素</div>
<div class="right">如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;如果不设置BFC,我的文字会被覆盖;如果不设置BFC,我的文字会环绕;</div>

<style>
  .left {
    float: left;
    width: 100px;
    height: 100px;
    background: yellow;
  }
  .right {
    overflow: hidden;
    height: 130px;
    background: red;
  }
</style>

清除浮动

如果不给父元素设置高度,子元素设置浮动的时候,会发生高度塌陷,所以要清除浮动

<section class="father">
  <div class="child"></div>
</section>
<style>
  .father {
    background: yellow;
    overflow: hidden;   // 设置BFC清除浮动
  }
  .child {
    float: left;
    width: 100px;
    height: 100px;
    background: red;
  }
</style>

清除浮动

清除浮动的原因

为了解决父元素因为子元素浮动引起的内部高度为 0 的问题(即:高度塌陷问题)

清楚浮动的常用方法

额外标签法

在最后一个浮动标签后新加一个标签,给其设置 clear: both

原理:clear: both 的本质就是闭合浮动,让父盒子闭合出口和入口,不让子盒子出来

优点通俗易懂,方便

缺点:添加无意义的标签,语义化差(不推荐使用)

<section class="father">
  <div class="big">big</div>
  <div class="small">small</div>
  <div class="clear">额外标签法</div>
</section>
<div class="footer"></div>
<style>
  .father {
    width: 400px;
    border: solid 1px deeppink;
  }
  .big {
    float: left;
  	width: 200px;
    height: 200px;
    background: gray;
  }
  .small {
  	float: left;
    width: 120px;
    height: 120px;
    background: blue;
  }
  .footer {
  	width: 900px;
    height: 100px;
    background: black;
  }
  .clear {
    clear: both;
  }
</style>

父级添加 overflow 属性

通过设置 BFC 的方式,清除浮动

优点:代码简洁

缺点:内容增多的时候,容易造成不会自动换行导致内容被隐藏掉,无法显示要溢出的元素(不推荐)

<style>
  .father {
    width: 400px;
    border: 1px solid deeppink;
    overflow: hidden;
  }
</style>

使用 after 伪元素清除浮动

优点:符合闭合浮动思想,结构语义化正确

缺点:ie6-7 不支持伪元素 :after,使用 zoom:1 触发 hasLayout

<section class="father clearfix">
  <div class="big">big</div>
  <div class="small">small</div>
</section>
<div class="footer"></div>
<style>
  .clearfix::after {  /*伪元素是行内元素 正常浏览器清除浮动的方法*/
    content: "";
    display: block;
    clear: both;
    visibility: hidden;
  }
  .clearfix {
    *zoom: 1; /*ie6清除浮动的方式,*号只有IE6-7执行,其他浏览器不执行*/
  }
</style>