css - position

3,021 阅读9分钟

前置回顾

先回顾前面的文章:

css 视觉格式化模型 (visual formatting model )  

  • 盒模型的尺寸和类型
  • 定位方案【正常文档流,浮动和绝对定位】
  • 文档树内部元素之间的关系
  • 外部信息(视口大小,图片的固有尺寸等)

总结,visual formatting model决定浏览器如何显示如何处理文档树。盒子类型和定位方案决定元素盒子如何在文档树中显示和放置。

如何理解BFC的应用
可能我们的页面是很复杂的页面,但是初始我们的页面书写都是基于上面的结构。此时整个文档流只有一个BFC环境,那就是html。所以内部的元素存在盒子塌陷,浮动等问题,是根据规则来的。所以我们在内部创建了新的BFC根据上面规则第三条。就可以解决相关的问题。

本篇学习一下定位方案中的position


普通文档流

正常的文档流布局是将元素放置在浏览器视口内的系统。

  • 块级元素在视口中垂直布局——每个都将显示在上一个元素下面的新行上,并且它们的外边距将分隔开它们。
  • 内联元素表现不一样——它们不会出现在新行上;相反,它们互相之间以及任何相邻(或被包裹)的文本内容位于同一行上,只要在父块级元素的宽度内有空间可以这样做。如果没有空间,那么溢流的文本或元素将向下移动到新行。
  • 如果两个相邻元素都在其上设置外边距,并且两个外边距接触,则两个外边距中的较大者保留,较小的一个消失——这叫外边距折叠, 我们之前也遇到过。

基本定义

定义和用法position 属性规定元素的定位类型。定位允许从正常的文档流布局中取出元素,并使它们具有不同的行为,例如放在另一个元素的上面,或者始终保持在浏览器视窗内的同一位置。

说明
这个属性定义建立元素布局所用的定位机制。任何元素都可以定位,不过绝对或固定元素会生成一个块级框,而不论该元素本身是什么类型。相对定位元素会相对于它在正常流中的默认位置偏移。

描述归属文档流
static默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。常规文档流
relative参照自身在常规流中的位置通过top,right,bottom,left这4个定位偏移属性进行偏移时不会影响常规流中的任何元素常规文档流
absolute生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。

偏移属性参照的是离自身最近的定位祖先元素,如果没有定位的祖先元素,则一直回溯到body元素。盒子的偏移位置不影响常规流中的任何元素,其margin不与其他任何margin折叠
脱离文档流
fixed生成绝对定位的元素,相对于浏览器窗口进行定位。
元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。

与absolute一致,但偏移定位是以窗口为参考。当出现滚动条时,对象不会随着滚动
脱离文档流
inherit规定应该从父元素继承 position 属性的值。



属性值

静态定位 static

HTML 元素默认情况下的定位方式为 static(静态)。
静态定位的元素不受 top、bottom、left 和 right 属性的影响。
position: static; 的元素不会以任何特殊方式定位;它始终根据页面的正常流进行定位:

.positioned {
  position: static;
  background: yellow;
}

相对定位 relative

position: relative; 的元素相对于其正常位置进行定位。
设置相对定位的元素的 top、right、bottom 和 left 属性将导致其偏离其正常位置进行调整。不会对其余内容进行调整来适应元素留下的任何空间。

元素的positnion的值是relative和static,包含块则由最近的块级框表单元格或行内快的内容边界构成

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Static positioning</title>

    <style>
      .block {
          width: 400px;
          height: 200px;
          background-color: #669966;
          border: 5px solid #3333FF; 
      }
       
      .relative {
          width: 100px;
          height: 50px;
          background-color: #484848;
          border: 5px solid #990066; 
          position: relative;
          top: 10px;
      }
       
      .inline {
          background-color: #00CC00;
          border: 5px solid #990066; 
      }
       
      table td {
          background-color: #00CC00;
      }
       
      strong {
          position: relative;
          top: 10px;
      }
    </style>
  </head>
  <body>
    <div class="block">
        <div class="relative">
            relative text
        </div>
    </div>
    <table>
        <tr>
            <th>Name</th>
        </tr>
        <tr>
            <td>
                <div class="relative">
                    relative text
                </div>
            </td>
        </tr>
    </table>
    <br /><br />
    <span class="inline">
        Test inline text 
        <strong>this is strong text</strong>
    </span>
  </body>
</html>

image.png
当然这个例子和包含块没有多大关系,毕竟这里的元素偏移是偏移自身原先位置的。


绝对定位 absolute

前置回顾:包含块

css 视觉格式化模型 (visual formatting model )

  1. 根元素所在的包含块称之为初始包含块。
  2. 如果元素的position属性值为releative或者static。包含块则是最近的块级盒子或者建立格式上下文祖先元素
  3. 如果元素的position属性值为fixed。连续媒体,包含块为视口。多页媒体,包含块为页面区域。
  4. 如果元素的position属性值为absolute。则包含块由具有position属性值为 'absolute', 'relative' or 'fixed'最近祖先元素建立。
    1. 如果祖先元素为内联元素,则包含块是当前内联元素创建的第一个内联元素和最后一个内联元素填充框周围的边界框
    2. 其他情况下,包含块为祖先的填充边缘组成。
  5. 如果没有上述的父元素,则包含块为初始包含块。

绝对定位,定位元素规则

元素的position值是absolute,包含块设置为最近的position值不是static的祖先元素

  1. 如果这个祖先是块级元素包含块则设置为该元素内的内边距边界,换句话说,就是由边框界定的区域,参考上面4.b
  2. 如果祖先元素是行内元素,包含块则设置为该祖先元素内的内容边界参考上面4.a
  3. 如果没有找到祖先元素,则以根元素为基准。
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Static positioning</title>

    <style>
      .block {
          width: 400px;
          height: 200px;
          background-color: #669966;
          border: 5px solid #3333FF; 
      }
       
      .absolute {
          width: 100px;
          height: 50px;
          background-color: #484848;
          border: 5px solid #990066; 
          position: absolute;
          top: 10px;
      }
       
      .inline {
          background-color: #00CC00;
          border: 5px solid #990066; 
      }
       
      table td {
          background-color: #00CC00;
      }
       
      strong {
          position: absolute;
          top: 10px;
      }
    </style>
  </head>
  <body>
    <div class="block">
        <div class="absolute">
            absolute text
        </div>
    </div>
    <table>
        <tr>
            <th>Name</th>
        </tr>
        <tr>
            <td>
                <div class="absolute">
                    absolute text
                </div>
            </td>
        </tr>
    </table>
    <br /><br />
    <span class="inline">
        Test inline text 
        <strong>this is strong text</strong>
    </span>
  </body>
</html>


效果如图,当前由于都没有找到可参照的祖先元素,所以两个div和一个strong元素都以body作为参照物。
image.png

然后我们将父级元素设置为relative.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Static positioning</title>

    <style>
      .block {
          width: 400px;
          height: 200px;
          background-color: #669966;
          border: 5px solid #3333FF;
          position: relative;
      }
       
      .absolute {
          width: 100px;
          height: 50px;
          background-color: #484848;
          border: 5px solid #990066; 
          position: absolute;
          top: 10px;
      }
       
      .inline {
          background-color: #00CC00;
          border: 5px solid #990066; 
      }
       
      table td {
          background-color: #00CC00;
          position: relative;
      }

      span {
        position: relative;
      }
       
      strong {
          position: absolute;
          top: 10px;
      }
      }
    </style>
  </head>
  <body>
    <div class="block">
        <div class="absolute">
            absolute text
        </div>
    </div>
    <table>
        <tr>
            <th>Name</th>
        </tr>
        <tr>
            <td>
                <div class="absolute">
                    absolute text
                </div>
            </td>
        </tr>
    </table>
    <br /><br />
    <span class="inline">
        Test inline text 
        <strong>this is strong text</strong>
    </span>
  </body>
</html>

image.png


说一下现象:

  • .absolute元素找到各自元素相对块级父元素,然后相对块级父级【position属性为relative】元素乡下偏移10px。
  • strong元素,默认会在原先的相对位置上下进行偏移。这里我们没有设置left偏移量,所以这里会在当前位置,并且向下偏移10px,此时是有默认的left偏移量的

我们将strong的left设置为0px

strong {
	position: absolute;
	top: 10px;
	left: 0PX;
}

image.png
我们可以看到这里this is strong text已经,改变了位置,这里因为我们已经将left设置了0。这里为什么text文本会跑到下面来。还是因为包含块的原因,参考上面包含块的4.a


固定定位 fixed

position: fixed; 的元素是相对于视口定位的,这意味着即使滚动页面,它也始终位于同一位置。 top、right、bottom 和 left 属性用于定位此元素。
固定定位的元素不会在页面中通常应放置的位置上留出空隙。

.positioned {
  position: fixed;
  background: yellow;
}

sticky 定位

position: sticky; 的元素根据用户的滚动位置进行定位。
粘性元素根据滚动位置在相对(relative)和固定(fixed)之间切换。起先它会被相对定位,直到在视口中遇到给定的偏移位置为止 - 然后将其“粘贴”在适当的位置(比如 position:fixed)。

div.sticky {
  position: -webkit-sticky; /* Safari */
  position: sticky;
  top: 0;
  background-color: green;
  border: 2px solid #4CAF50;
}

注意:Internet Explorer、Edge 15 以及更早的版本不支持粘性定位。 Safari 需要 -webkit- 前缀。您还必须至少指定 top、right、bottom 或 left 之一,以便粘性定位起作用。


z-index

在对元素进行定位时,它们可以与其他元素重叠。z-index 属性指定元素的堆栈顺序(哪个元素应放置在其他元素的前面或后面)。当然这个和层叠上下文,层叠等级有关系,后续学习层叠上下文。

z-index: auto |<integer>

  • auto:元素在当前层叠上下文中的层叠级别是0。元素不会创建新的局部层叠上下文,除非它是根元素。
  • <integer>:用整数值来定义堆叠级别。可以为负值。

利用z-index,可以改变元素相互覆盖的顺序。这个属性的名字有坐标系统而来,其中从左向右是x轴,从上到下是y轴。第三个轴则是z轴,则是面向文档流的方向。
image.png

div {
    position: absolute;
}
 
.first {
    width: 400px;
    height: 400px;
    background-color: red;
}
 
.second {
    width: 200px;
    height: 200px;
    background-color: gray;
}
 
.third {
    width: 100px;
    height: 100px;
    background-color: blue;
}
<div class="first">      
</div>
<div class="second">      
</div>
<div class="third">      
</div>

image.png

如图此时,没有设置z-index的情况下,三个div按照文档加载的方式布局排列,此时我们将第三个div的z-index设置为0,此时没有变化。说明z-index默认为0,当我将z-inde设置为-1的时候,当前div就会被前面两个div覆盖。


  • z-index的比较基本是在同一层级,也就是拥有同一个父元素。如果是不同层级的比较,则需要依靠z-index的比重大小决定,和层叠上下文有关系。
  • z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面

  • 注释:元素可拥有负的 z-index 属性值。
  • 注释:Z-index 仅能在定位元素上奏效(position属性值设置除默认值static以外的元素,包括relative,absolute,fixed样式)