HTML文档流规则

486 阅读10分钟

什么是文档流

文档流(normal flow)是浏览器在渲染显示网页内容时默认采用的一套排版规则,规定了应该以何种方式排列元素。及标签默认的排版方式。也就是我们通常所说的普通文本流。

什么是文本流

从字面意思可以看出,文本流就是元素内部的一系列的字符的排列规则。

文档流分为哪几种

文档流主要分为以下两种:

  1. 标准文档流:就是html文档元素在计算排版过程中,所有处于文档流的元素自动从左到右(行内元素),从上到下(块级元素)的排列顺序。也称之为标准流,普通流
  2. 脱离正常文本流:相对于正常文档流而言的。指的是元素脱离正常元素的布局排版顺序,其他处于文档流中的盒子计算布局排版时,会自动无视已脱离文档流的元素来进行定位。元素不是按照默认的排列顺序排列的,而是通过一些css样式改变元素原来的排序顺序。

HTML中的定位方式

元素在平时开发排版中主要分为以下三种

  1. 标准文档流:块级格式化的块级盒子,行内格式化的行内盒子。还有相对定位的块级盒子和行内盒子也是标准文档流排版。

标准文档流相对来说比较简单,而且我们很熟悉,我们不过多介绍,我们重点介绍一下下面的浮动和绝对定位。

  1. 浮动 我们先来看一个我们平时会做的案例,图片和文本内容环绕排列。 首先我们使用行内盒子,也就是标准文档流的方式实现:
<div class="parent-wrap">
  <div class="image-wrap">
    <img src="../assets/logo.png" alt="">
  </div>
  <div class="text-wrap">这是一段很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长的文本</div>
</div>
.test-wrap {
  .parent-wrap {
    .image-wrap {
      display: inline;
    }
    .text-wrap {
      display: inline;
    }
  }
}

效果展示:

图文排列.png

从效果图上可以看出,虽然可以实现环绕的效果,但是会有缝隙,如果文本一行展示不下的话会另起一行展示。显然达不到我们想要实现的效果

现在我们使用浮动的方式来实现。

<div class="parent-wrap">
  <div class="image-wrap">
    <img src="../assets/logo.png" alt="">
  </div>
  <div class="text-wrap">这是一段很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长的文本</div>
</div>
.test-wrap {
  .parent-wrap {
    .image-wrap {
      float: left;
    }
    .text-wrap {
      // display: inline;
    }
  }
}

????上面这个例子中为什么不能同时设置左边元素左浮动,右边元素右浮动 ---- 因为设置浮动会让我们的元素脱离文档流,不会保留原先的位置。浮动的元素会在一行内显示并且根据元素顶部对齐,浮动的元素相互贴靠在一起(没有缝隙), 如果父元素的宽度装不下这些浮动的盒子,多出的盒子会另起一行对齐;浮动的元素会具有行内块元素的特性。

下面再来看一个例子:

<div class="parent-wrap">
  <div class="text1-wrap">
    这是第一段很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长的文本
  </div>
  <div class="tip1">Normal Flow</div>
  <div class="tip2">Normal Flow</div>
  <div class="text2-wrap">这是第二段很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长的文本</div>
</div>

.test-wrap {
  .parent-wrap {
    .text1-wrap {
      background: gray;
      width: 200px; 
      float: left;
    }
    .tip1 {
      background: black;
      color: white;
    }
    .tip2 {
      background: yellow;
    }
    .text2-wrap {
      background: lightblue;
    }
  }
}

通过f12打开控制台,我们可以看出来这几个元素的样式,我们会发现第一个元素设置了浮动之后,后面几个元素会无视浮动元素,自动从body元素的左边开始排列,但是它们的文本并不会无视浮动元素。 也就是说明:给元素设置浮动会脱离文档流,但不会脱离文本流。这个也特别注意,这也是我们上面例子中文本环绕图片的原因。

浮动的应用

我们在实际开发过程,浮动用的最多的地方就是

  • 图片和文本内容一起时,文本环绕图片
  • 将块级元素一行内排列显示
  • 设置元素的左右对齐
浮动的影响

前面我们已经了解了浮动的作用,下面来看一下浮动的影响 这里我们主要从两点来看影响

  • 浮动对父元素的影响 如果父元素不设置高度,子元素设置浮动,那么父元素的高度不会被撑开,这就是常说的父元素高度塌陷
<div class="parent-wrap">
  <div class="son-wrap"></div>
</div>
.parent-wrap {
  border: 1px solid lightblue;
  .son-wrap {
    width: 200px;
    height: 200px;
    float: left;
    background: yellow;
  }
}

效果展示:

高度塌陷.png

  • 浮动对兄弟元素的影响 如果某个元素设置浮动,会影响到它后面的兄弟元素
<div class="parent-wrap">
  <div class="son-wrap"></div>
  <div class="son2-wrap"></div>
</div>
.parent-wrap {
  border: 1px solid lightblue;
  .son-wrap {
    width: 200px;
    height: 200px;
    float: left;
    background: yellow;
  }
  .son2-wrap {
    width: 300px;
    height: 100px;
    background: pink;
  }
}

元素设置浮动,会遮盖它后面的兄弟元素

<div class="parent-wrap">
  <div class="son-wrap"></div>
  <div class="son2-wrap"></div>
</div>
.parent-wrap {
  border: 1px solid lightblue;
  .son-wrap {
    width: 200px;
    height: 200px;
    background: yellow;
    display: inline-block;
  }
  .son2-wrap {
    width: 300px;
    height: 100px;
    float: left;
    background: pink;
  }
}

若非第一个元素浮动,则该之前的元素也需要跟随其后,否则会影响页面布局。

如何清除浮动

清除浮动主要是清除前面的元素设置浮动对后面的元素造成的影响。 主要方法有下面这几种

  • 额外标签法(不推荐使用)
<div class="parent-wrap">
  <div class="son-wrap"></div>
  <div style="clear:both;"></div>
</div>

这样就消除了父元素高度塌陷的问题,但是如果在一个很复杂的HTML中,这样写就会增加元素所以不推荐。

  • 给浮动元素的父元素添加overflow属性方法
.parent-wrap {
  border: 1px solid lightblue;
  overflow: hidden;
  .son-wrap {
    width: 200px;
    height: 200px;
    float: left;
    background: yellow;
  }
}
  • after伪元素清除浮动(推荐) 给浮动元素的父元素设置after伪类
<div class="parent-wrap clearfix">
  <div class="son-wrap"></div>
  <div class="son2-wrap"></div>
  <!-- <div style="clear:both;"></div> -->
</div>
.clearfix:after {
  /* 使用伪元素必须添加content属性 */
  content: "";
  /* 因为伪元素是行内元素,所以需要转换成块元素 */
  display: block;
  /* 兼容 */
  height: 0;
  clear: both;
  visibility: hidden;
}
.clearfix {
  /* IE6、7 专有  */
  *zoom: 1;
}
  • 双伪元素清除浮动(推荐) 给设置浮动的父元素设置双伪类
.clearfix::before,
.clearfix::after {
  /* 要想使用伪元素,必须写上content属性 */
  content: "";
  /* 这里写成block也是没有问题的,为什么使用table,这是老的写法,兼容老版本浏览器 */
  display: table;
} 
.clearfix::after {
  clear: both;
} 
.clearfix {
  *zoom: 1;
}
  1. 定位 相对定位是相对于自己原来的位置定位。当元素位置发生改变的时候,改变之前的位置还在,不会被其他元素占据。
<div class="parent-wrap">
  <div class="son-wrap">
    这是一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文本
  </div>
  <div class="son2-wrap"></div>
</div>
.parent-wrap {
  border: 1px solid lightblue;
  position: relative;
  .son-wrap {
    width: 200px;
    background: yellow;
    position: relative;
    left: 300px;
  }
  .son2-wrap {
    width: 300px;
    height: 100px;
    background: pink;
  }
}

效果:

浮动定位.png

从上面可以看出,元素并没有脱离文本流。

绝对定位是指相对于某个元素而言的,父级是非static元素(static是标准文档流,不会脱离普通文档流)。如果它的上级一直是static元素,那么它的父级元素就是body元素。改变位置后,之前的位置已经不存在,会被其他的元素占据。

<div class="parent-wrap">
  <div class="son-wrap">
    这是一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文本
  </div>
  <div class="son2-wrap">
    这是另外一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    的文本
  </div>
</div>
.parent-wrap {
  border: 1px solid lightblue;
  position: relative;
  .son-wrap {
    width: 200px;
    background: yellow;
    position: absolute;
    left: 200px;
  }
  .son2-wrap {
    width: 300px;
    height: 100px;
    background: pink;
  }
}

效果:

绝对定位.png

从上述代码可以看出,绝对定位会脱离文档流,而且也脱离了文本流,因为元素和文本都会被遮挡。

固定定位是指相对于浏览器定位(也就是相对与窗口来进行定位的)

<div class="parent-wrap">
  <div class="son-wrap">
    这是一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文本
  </div>
  <div class="son2-wrap">
    这是另外一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长
    的文本
  </div>
</div>
.parent-wrap {
  border: 1px solid lightblue;
  .son-wrap {
    width: 200px;
    background: yellow;
    position: fixed;
    top: 200px;
    left: 200px;
  }
  .son2-wrap {
    width: 300px;
    height: 100px;
    background: pink;
  }
}

效果:

固定定位.png

固定定位也是一种特殊的绝对定位,所以它也会脱离文档流,也会脱离文本流

浮动和绝对定位的比较

相同点

都是脱离文档流的排列

不同点

浮动虽然脱离了文档流,但是没有脱离文本流 绝对定位既脱离了文档流,也脱离了文本流