饥人谷技术博客

浮动、定位、BFC、外边距合并

2017-09-14  本文已影响0人  SHININGJACK

一、浮动元素有什么特征?对父容器、其他浮动元素、普通元素、文字分别有什么影响?

float指定一个元素沿着其容器左侧或者右侧放置,允许行内元素和文本围绕它。使用后,该元素会从正常流动中移除,虽然还会保持一定流动性(两个浮动碰到一起)。由于元素浮动后,脱离了普通文档流,并且一直左移或者右移直到碰到父元素边框或者另一个浮动元素才停止(一行占满会自动换行),所以,浮动元素会覆盖在普通文档流元素之上(如果有的话)。而且,父元素也会塌陷,不再包裹得住浮动元素。

参考:float | MDN

二、清除浮动指什么? 如何清除浮动? 两种以上方法

清除浮动,可以通过clear: left | right | both实现。或者对目标元素转换成不同的 BFC ,BFC后面再说,这里主要通过clear: both解决。直接上代码

1. 直接使用clear: both清除浮动,主要用于兄弟元素情况。

<style>
  .div1 {
    float: left;
    background-color: #333;
  }
  
  .div1,.div2 {
    width: 150px;
    height: 150px;
  }
    
  .div2 {
    background-color: #f03;
    clear: both;
  }
</style>
  <div class="div1"></div>
  <div class="div2"></div>

在线演示

2. 通过加一个额外标签,阻止父元素塌陷。

<style>
    .div1 {
        float: left;
        background-color: #333;
      }
  
    .div1,.div2 {
      width: 150px;
      height: 150px;
    }
    
    .div2 {
      background-color: #f03;
    }
  
    .clear {
      clear: both;
    }
</style>
<div class="div0">
  <div class="div1"></div>
  <div class="clear"></div>
</div>
<div class="div2"></div>

在线演示

3. 通过为父元素添加overflow:hidden来阻止父元素塌陷。

<style>
  .div0 {
    overflow: hidden;
  }
  
  .div1 {
    float: left;
    background-color: #333;
  }
  .div1,.div2 {
    width: 150px;
    height: 150px;
  }
  .div2 {
    background-color: #f00;
  }
</style>
<div class="div0">
  <div class="div1"></div>
</div>
<div class="div2"></div>

在线演示

三、有几种定位方式,分别是如何实现定位的,参考点是什么,使用场景是什么?

定位有四种:static --> 静态定位relative --> 相对定位absolute --> 绝对定位fixed --> 固定定位,下面详细说。

1. 静态定位。

positon: static其实就是元素默认值,正常的文档流。

2. 相对定位

position: relative是比静态定位强大一点点的定位。假如不为元素加上top、bottom、left、right,那么它表现得和静态定位一模一样。所以说它就是在静态定位的基础上多了个可选择移动效果,但在移动后,如top: 20px; left: 20px,该元素占据的空间还是原来位置,只是展示效果平移了而已,所以这样有可能覆盖其他元素。应用于不想脱离文档流,但又想平移的场景,同时relative也是absolute的参考对象,后面说。现在看个例子:

<style>
  div {
    display: inline-block;
    width: 200px;
    height: 200px;
  }
  
  .div1 {
    background-color: #333;
  }
  .div2 {
    background-color: #f00;
    position: relative;
    left: 20px;
    top: 20px;
  }
  .div3 {
    background-color: #0f0;
  }
</style>
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>

在线演示

3. 绝对定位

postion: absolute会使元素脱离文档流,变得无比强大,只有一个样式能束缚它,position: relative。所以要清楚的知道,绝对定位可以到处跑,但相对定位就是它的边界,就像悟空逃不出佛祖一样。如果父元素一直没有relative,它就会继续往上找,直到找到根元素或者relative祖先元素。与相对定位相比,绝对定位不再占据空间,可随意覆盖在任意元素上,只要它的z-index够大(z-inde后面说),举个例子:

<style>
  div {
    display: inline-block;
    width: 200px;
    height: 200px;
  }
  
  .div1 {
    background-color: #333;
  }
  .div2 {
    background-color: #f00;
    position: absolute;
    left: 20px;
    top: 20px;
  }
  .div3 {
    background-color: #0f0;
  }
</style>
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>

在线演示

4. 固定定位

position: fixed与绝对定位非常相似,除了两点:

举个例子:

<style>
  body{
    margin: 0;
  }
  .div1,.div2,.div3 {
    width: 100%;
    height: 500px;
  }
  .div1 {
    background-color: #333;
  }
  .div2 {
    background-color: #f00;
  }
  .div3 {
    background-color: #0f0;
  }
  .fixed {
    position: fixed;
    top: 0;
    left: 50%;
   
    
    margin-left: -100px;
    width: 200px;
    padding: 15px 0;
    border: 2px solid;
    text-align: center;
    background-color: #fff;
  }
</style>
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>
<div class="fixed">我就一直在这里</div>

在线演示

参考: 定位 | MDN

四、z-index有什么作用? 如何使用?

1. 没有z-index情况

你是否会有这个疑惑,当各种定位都跑到一起的时候,该显示谁呢?答案是:在没有z-index干扰之前,根据顺序显示,谁在最后,显示谁,举个例子:

  <style>
    body {
      margin: 0;
      font-size: 0;
    }
    div {
      display: inline-block;
      width: 200px;
      height: 200px;
    }
    
    .div1 {
      position: static;
      background-color: #333; 
    }
    
    .div2 {
      position: relative;
      background-color: #f00;
    }
    
    .div3 {
      position: absolute;
      background-color: #0f0;
      top: 0;
      left: 50px;
    }
    
    .div4 {
      position: fixed;
      background-color: #00f;
      top: 0;
      left: 300px;
    }
  </style>
  <div class="div1"></div>
  <div class="div2">
    <div class="div3"></div>
  </div>
  <div class="div4"></div>

在线演示

2. 开始使用z-index

那有没有一种办法,让前面的元素先显示呢?这就是z-index的作用了,默认定位的z-index: 0;为零(其实不是零,而是不存在,不存在和零在这里意思是不同的,下面分析)。谁的z-index大,就显示谁,还是刚才的例子,只不过加多一个z-index

/* 在 div3 那里加上 */
.div3 {
  z-index: 1;
}

在线演示
此时,div3应该跑出来了,不再被div4困住。想要div4再次显示,需要给div4加上z-index: 2(或者为 1 也可以,z-index相同,根据顺序显示)。因为,只要z-index比别人大 1 ,就可以达到覆盖效果,所以最好不要乱用,像直接写z-index: 9999这种是十分不妥的,万一以后你想覆盖它怎么办?而且要记住,只有当靠前的元素向覆盖后面的元素才用z-index,因为如果元素本来就是在最后,根据顺序显示,是无须加z-index的。

3. z-index: 0 和 默认没有(不写)z-index为什么不同

只要你设置了z-index,那么在为定位判断z-index时,要明白:只能在兄弟元素之间比较。举个例子:

  <style>
    body {
      margin: 0;
      font-size: 0;
    }
    div {
      display: inline-block;
      width: 200px;
      height: 200px;
    }
    
    .div1 {
      position: static;
      background-color: #333; 
    }
    
    .div2 {
      position: relative;
      background-color: #f00;
      z-index: 0;
    }
    
    .div3 {
      position: absolute;
      background-color: #0f0;
      top: 0;
      left: 50px;
      z-index: 999;
    }
    
    .div4 {
      position: fixed;
      background-color: #00f;
      top: 0;
      left: 300px;
      z-index: 2;
    }
  </style>
  <div class="div1"></div>
  <div class="div2">
    <div class="div3"></div>
  </div>
  <div class="div4"></div>

在线演示

在上面的例子中,可以看到,绝对定位(positon: absolute)已经有z-index: 999,比固定定位(positon: fixed)的z-index: 2大得多,但因为相对定位(position: relative)的z-index只有 0 ,因此绝对定位无法实现最顶覆盖。但如果相对定位(position:relative)不写z-index的话,结果又会是不一样的了,各位可自行测试。

五、position:relative和负margin都可以使元素位置发生偏移?二者有什么区别?

相对定位(postition: relative)的使用,不但使元素保持文档流,而且使用top、bottom、left、right位移也不会改变本身占据空间位置。而负margin是静态定位(position: static)位移的小技巧,是会让元素本身位置发生改变的,使用在相对定位上也有同样效果。看例子:

<style>
  body {
    margin: 0;
    padding-left: 100px;
  }
  .inline-block {
    display: inline-block;
    width: 200px;
    height: 200px;
    background-color: #333;
  }
  .div1 {
    position: relative;
    top: 0;
    left: -20px;
    /* margin-left: -20px; */
  }
  .div2 {
    margin-left: -20px;
  }
</style>
<div class="inline-block div1"></div>
<div class="inline-block"></div>
<div></div>
<div class="inline-block div2"></div>
<div class="inline-block"></div>

在线演示

记住,对相对元素使用负margin也是会使元素本身位置发生改变的,因为相对定位还是文档流。

六、BFC 是什么?如何生成 BFC ?BFC 有什么作用?举例说明

BFC(Block Formatting Context),译为块格式化上下文,说实话,这晦涩的翻译会让人更加困惑这个定义,且看我们怎么逐层分解!

1. 何为 BFC ?

首先要明白,BFC 指的是一个虚拟区域,一个块级盒布局区域,,可以说是一个环境每个区域间相互不受影响。当你使用了以下元素时,你就为这个元素开辟了一个 BFC 保护区,用来保护这个元素。 参考:块格式上下文 | MDN

特别地,当里面元素都是行内元素或者文本时,创建出来的 BFC 就是 IFC(Inline Formatting Context)。

2. 如何理解 BFC ?

CSS 的渲染是从上往下排列元素块的,最大的 BFC 就是 Document,在它里面的元素都要遵守他的规则。但 Document 里面允许创建新的 BFC,这些新的 BFC 会为自己内部建立新的规则,而且每个 BFC 之间不会相互干扰(就是基于这点解决外边距合并和清除浮动的)。形象的理解就是, Document 是国家;普通块元素是市(overflow: visible);新的 BFC 是省、直辖市(float、absolute、inline-block),他们允许有自己规则。

3. BFC 作用。

解决外边距合并和清除浮动。外边距合并下面说,现在说说清除浮动。

阻止浮动元素对其他元素的影响,可以为浮动元素新创建 BFC ,这样浮动元素就不会影响外部元素了,如下,通过overflow: hidden创建了 BFC(虽然本身float也创建了 BFC ,但因为它在父元素内部,不会影响父元素外部的元素),阻止其影响其他元素:

<style>
  .div0 {
    overflow: hidden;
  }
  
  .float {
    float: left;
    background: #333;
  }
  
  .float,.div1 {
    width: 200px;
    height: 200px;
  }
  
  .div1 {
    background: #f00;
  }
</style>
<div class="div0">
  <div class="float"></div>
  <div class="float"></div>
</div>
<div class="div1"></div>

在线演示

参考:
什么是 BFC | Div.IO
关于 BFC | 穆乙
CSS 布局 | winter

七、在什么场景下会出现外边距合并?如何合并?如何不让相邻元素外边距合并?给个父子外边距合并的范例

1. 何为外边距合并?

外边距合并(margin collapsing),准确来说,是外边距塌陷。指的是 BFC 中相邻的另个块盒子的左右边距和上下边距发送叠加,两者取最大值:

<style>
  div {
    width: 200px;
    height: 200px;
    background: #333;
    margin: 100px;
  }
</style>
<div></div>
<div></div>

在线预览

在上面例子中,两个<div>之间的间距只有100px,没有达到预想中的200px,这就是外边距合并。

2. 如何解决外边距合并?

a. 首先要明确,外边距合并只会发生在 BFC, 所以当前规则是 IFC 的话,就不会出现这种情况了,看例子:

<style>
  div {
    display: inline-block;
    width: 200px;
    height: 200px;
    background-color: #333;
    margin: 100px;
  }
</style>
<div></div>
<div></div>
<div></div>
<div></div>

b. 全部都是浮动元素不会出现外边距合并

  <style>
    div {
      float: left;
      width: 200px;
      height: 200px;
      background-color: #333;
      margin: 100px;
    }
  </style>
  <div></div>
  <div></div>
  <div></div>
  <div></div>

在线预览

c. 利用 BFC 来阻止合并

我们已经知道 BFC 之间不会相互影响,所以让外边距合并的元素各自创建一个 BFC ,就可以解决该问题

  <style>
    .div1 {
      width: 200px;
      height: 200px;
      margin: 100px;
      background-color: #333;
    }
    .div0 {
      overflow: hidden;
    }
  </style>
  <div class="div0">
    <div class="div1"></div>
  </div>
  <div class="div1"></div>

在线预览

在上面例子,我们只建立了一个 BFC ,overflow: hidden建立。因为这个 BFC 不会影响的外边的其他元素,所以效果就达到了。其实,在清除浮动的时候,在相邻的非浮动元素加上overflow: hidden达到清除浮动效果,也是这个原理,因为float脱离了文档流,但建立了新的 BFC,所以我们为受影响的元素创建 BFC 的话,根据 BFC 之间不会相互影响的规则,就可以达到清除浮动效果。如下例子:

  <style>
    body {
      margin: 0;
      padding: 1px;
    }
    div {
      width: 200px;
      height: 200px;
      background: #333;
      margin: 20px;
    }
    .float {
      float: left;
    }
    .normal {
      overflow: hidden;
    }
  </style>
  <div class="float"></div>
  <div class="normal"></div>

在线预览

d. 当容器没有paddingborder时,内部的margin会引发外边距合并(父子外边距合并)

这是一种很难发现的情况,但外边距合并是会被内边距padding阻止的,所以给父元素加1px的内边距可以解决问题。或者为这个子元素建立新的 BFC,即在父元素加overflow: hidden(其他也可以)。

  <style>
    .div0 {
      margin: 100px;
      background: red;
      padding: 1px;
      /* overflow: hidden; */
    }
      .div1 {
        width: 200px;
        height: 200px;
        background-color: #333;
        margin: 150px;
      }
  </style>
  <div class="div0">
    <div class="div1"></div>
  </div>

在线预览
参考:
谈外边距合并 | winter
外边距合并 | MDN

八、编程任务

任务十 | GitHub

上一篇 下一篇

猜你喜欢

热点阅读