揭秘css中定位

225 阅读5分钟

Snipaste_2024-08-26_13-46-43.png

定位在我们的布局中常常会用,巧妙的利用定位,会在部分业务中帮助我们实现很多功能。通俗来讲,定位是脱离文档流,不占用父级高度,且会存在层级关系。

本文主要会从以下几点认识定位

  • relative,absolute,fixed,sticky,static的应用理解
  • 如何理解relative,absolute,一个元素中设置absolute,它是绝对定位,相对于谁?
  • fixed失效问题
  • sticky吸顶

相对定位

首先我们问自己一个问题,relative是相对哪个元素定位,相对自身?还是相对父级?,还是相对相邻元素?

我们先看一段简单的代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      h1 {
        font-size:50px;
      }
      .app {
        position: relative;
        top: 100px;
        left: 100px;
      }
    
    </style>
  </head>
  <body>
    <div class="app">
      <h1 class="text">Web技术学苑</h1>
    </div>
  </body>
</html>

从结果来看如果一个元素设置相对定位,那么它的参照是相对父级元素body

1.png

如果我们在app上方再加一个相邻元素

 <body>
	  <h1>Hello</h1>
    <div class="app">
      <h1 class="text">Web技术学苑</h1>
    </div>
  </body>

2.png

我们会发现app元素相对定位与顶部最初位置的Y轴偏距多了50px,offsetTop= 150(加上了文字的高度)

我们继续给.text设置相对定位试试

 .text {
  position: relative;
  top: 100px;
  left: 100px;
}

3.png

我们发现text文本元素相对原有位置xy方向分别偏移了100个像素

我们再来看一段代码,假设app不设置相对定位,相对定位只作用在text元素中呢

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      .text {
        position: relative;
        top: 100px;
        left: 100px;
      }
    </style>
  </head>
  <body>
    <h1>Hello</h1>
    <div class="app">
      <h1 class="text">Web技术学院</h1>
    </div>
  </body>
</html>

5.png

所以我们可以确定,当一个元素设置相对定位,这个元素是相对它父级最近的一个元素,父元素本身的高度由子元素决定,offetTop会作用在父级元素上,如果父级有设置relative,那么子元素的offsetTop就是当前定位的偏移值,如果父级元素没有设置relative,那么offetTop会包含元素自身高度

绝对定位

当一个元素我设置绝对定位时,这个元素到底是相对于谁?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>absolute</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }

      .text {
        position: absolute;
        top: 100px;
        left: 100px;
      }
      .app {
        background: red;
      }
    </style>
  </head>
  <body>
    <h1>Hello</h1>
    <div class="app">
      <h1 class="text">Web技术学院</h1>
    </div>
  </body>
</html>

6.png

我们发现text元素是相对body的

如果我们在.app设置relative,那么这个text元素就是相对.app

absolute相对谁?

如果我在.app中设置absolute,那么子元素text也是设置absolute,那么text元素会怎么样

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>absolute</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }

      .app {
        background: red;
        width: 100px;
        height: 100px;
        position: absolute;
        top: 100px;
        left: 100px;
      }
      .text {
        position: absolute;
        top: 100px;
        left: 100px;
      }

    </style>
  </head>
  <body>
    <h1>Hello</h1>
    <div class="app">
      <h1 class="text">Web技术学院</h1>
    </div>
  </body>
</html>

7.png

你发现.text的absolute是相对最近的父级元素,而父级设置的absolute是相对它本身最近的父级元素。

如果一个absolute元素设置的外边距会怎么样

.text {
  position: absolute;
  top: 100px;
  left: 100px;
  margin-top: 100px;
 }

8.png

从以上现象来看,外边距会相对它父级元素偏移,并且边距并不会被合并

fixed

当我们对一个元素设置fixed时,该元素是相对视图窗口的。当我们在它父元素上添加transformperspectivefilterbackdrop-filter会导致fixed失效,主要是因为fixed产生了层叠上下文

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>fixed</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      .text {
        width: 100px;
        height: 100px;
        background-color: red;
        position: fixed;
        top: 100px;
        left: 100px;
      }
      .app {
        backdrop-filter: blur(10px);
      }
    </style>
  </head>
  <body>
    <div class="app">
      <div class="text">Web技术学苑</div>
    </div>
    <div style="height: 3000px; background-color: yellow">Maic</div>
  </body>
</html>

sticky

粘性定位,可以理解成相对定位与固定定位的混合,元素在特定阀值就是相对定位,之后为固定定位

比如我给一个元素加上sticky之后

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>sticky</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      .header {
        position: sticky;
        top: 10px;
        width: 100%;
        height: 50px;
        background-color: red;
      }
      .main {
        height: 2000px;
      }
    </style>
  </head>
  <body>
    <div class="app">
      <div class="header">header</div>
      <div class="main"></div>
    </div>
  </body>
</html>

在可视区域范围内,header距离顶部10px,但是超过可视区域后,header就固定在10px位置了

当我们对一个元素使用fixed时,有时会失效,为什么?

fixed失效

由于我们对一个元素使用了fixed,此时会产生层叠上下文,当我们它的父元素上添加transfromperspectivefilterbackdrop-filter属性会导致fixed失效。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>fixed</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      .header {
        position: fixed;
        top: 10px;
        width: 100%;
        height: 50px;
        background-color: red;
      }
      .main {
        height: 2000px;
      }
      .app {
        filter: blur(5px);
      }
    </style>
  </head>
  <body>
    <div class="app">
      <div class="header">header</div>
      <div class="main"></div>
    </div>
  </body>
</html>

static

当我们对一个元素使用static时,此时这个元素就相当于一个普通文档流,top,right,bottom,left,以及zIndex就会失效。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>static</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      h1 {
        position: static;
        top: 100px;
        left: 100px;
      }
    </style>
  </head>
  <body>
    <div class="app">
      <h1>公众号: Web技术学苑</h1>
    </div>
  </body>
</html>

总结

  • 当我们对元素设置relative,absolute,fixed时,该元素会脱离文档流

  • 定位的元素不会占用父级高度,当一个元素设置absolute,width与height会相对父级

  • 当一个元素设置relative时,它相对的是它的父级元素,如果父级没有设置relative,当前元素的offestTop会包含父级本身的高度,offetTop = Y + parentHeight,如果父级设置了relative,此时offsetTop = Y

  • 当我们在一个多级结构,多层定位,比如一个父级元素加了absolute绝对定位,它的子元素继续绝对定位,那么该子元素设置的绝对定位只会相对它最近的父级元素

  • sticky是吸顶定位,是相对定位与固定定位的结合体,当一个元素在可视区域时,它是相对的,当内容区域超过可视区域时,它就变成了固定定位

  • fixed是相对可视窗口的,fixed会产生css层级堆叠上下文,如果在该元素的父级设置transfrom,filter,backdrop-filter,perspective,那么fixed就会失效

  • static设置会导致left,right,top,bottom,zIndex失效

  • [code example] github.com/maicFir/les…