×

CSS position 属性 定位

解析 position 属性的奥秘(探寻定位的神奇之处)

元智汇电子 元智汇电子 发表于2023-12-01 11:34:28 浏览534 评论0

抢沙发发表评论

📔前言

在Web开发中,掌握CSS布局对于提高页面开发效率至关重要。随着Web技术的不断演进,实现各种布局的方法层出不穷。

最近,我利用零散时间花费了半个月整理了一系列文章。本系列总结了CSS中各种布局以及实现方式及常用技巧,通过阅读这些文章,你将对CSS布局有全新的认识。


📔position 属性简介

position 属性是CSS布局中的一个关键属性,用于定义元素在文档中的定位方式。通过 top、right、bottom 和 left 属性,可以确定元素最终的位置。

该属性包含以下五个取值:

  1. static: 默认值,表示正常布局行为,此时设置 top、right、bottom、left 和 z-index 属性均无效。

  2. relative: 将元素设置为相对定位元素,不会脱离文档流。

  3. absolute: 将元素设置为绝对定位元素,使其相对于最近的非 static 定位祖先元素进行定位。

  4. fixed: 将元素设置为固定定位元素,相对于视窗进行定位。

  5. sticky: 将元素设置为粘性定位元素,一开始不脱离文档流,当到达某个位置时,相对于视口进行定位。

🍚absolute 属性值

基本性质

与 float 属性类似,具有相似的包裹性和破坏性特征:

  • 包裹性: 元素的宽度会自动调整为与内容一致。

  • 破坏性: 导致父元素的高度塌陷。


🍚脱离文档流

当将 position 属性设置为 absolute 时,元素会脱离文档流。

文档流是将窗体从上至下分成行,并按从左至右的顺序排列元素的布局方式,也被称为文档流或普通流。

脱离文档流意味着元素不再占据文档流中的位置,而是处于浮动状态(可以理解为浮在文档流的上方)。脱离文档流的元素定位基于正常的文档流。一旦元素脱离文档流,其他在文档流中的元素将忽略该元素,并填充其原先的空间。

以下是示例代码:

image.png

不脱离文档流的效果如下图所示:

image.png

脱离文档流的效果如下图所示:

image.png

从中可以观察到 <div> 元素已经漂浮在图片的上方。


🍚与 margin 结合运用

当 absolute 属性值与 margin 结合使用时,可以实现一些出色的布局效果。例如,实现一个搜索框的下拉提示效果。以下是示例代码:

<!DOCTYPE html><html>    <head>        <meta charset="utf-8" />        <title>巧妙运用 absolute 和 margin 实现下拉框</title>        <style>            body {                margin: 0;                background-color: #edeff0;            }            /* 容器样式 */            .container {                margin-top: 120px;                margin-left: 240px;                overflow: hidden;            }            /* 输入框样式 */            .input {                width: 240px;                line-height: 18px;                padding: 10px;                margin: 0;                border: 0 none;            }            .input:focus {                outline: 0 none;            }            .list {                /* 默认不显示,通过js控制显示 */                /* display: none; */                position: absolute;                width: 260px;                /* 通过 margin 控制显示位置 */                margin: 39px 0 0 -1px;                padding-left: 0;                list-style-type: none;                border: 1px solid #e6e8e9;                background-color: #fff;                box-shadow: 0px 1px 2px #d5d7d8;                font-size: 12px;            }            /* 列表项样式及悬停样式 */            .list > li {                line-height: 30px;                padding-left: 12px;            }            .list > li:hover {                background-color: #f9f9f9;            }            .list a {                display: block;                color: #5e5e5e;                text-decoration: none;            }            .list a:hover {                color: #000;            }        </style>    </head>    <body>        <div class="container">            <ul class="list">                <li>                    <a>玩转CSS布局之 Grid 布局</a>                </li>                <li>                    <a>玩转CSS布局之 Flex 布局</a>                </li>                <li>                    <a>玩转CSS布局之深入理解 position 定位</a>                </li>                <li>                    <a>玩转CSS布局之深入理解 z-index 定位</a>                </li>            </ul>            <input class="input" placeholder="请输入内容" />        </div>    </body></html>

执行结果如下图所示:

image.png

此时,可以通过 JavaScript 控制提示内容的显示与隐藏。这种结合运用的方式使得页面布局更加灵活多样。


🍚left、right、top、bottom 的应用技巧

一旦开启定位,我们便能通过这四个属性来灵活控制元素的偏移,这些属性可以接受像素值、百分比(相对于元素包含块的宽度或高度)等参数。尽管基础的使用比较简单,这里分享一些在实际开发中的小技巧。

全屏自适应效果(无需宽度和高度声明)

示例代码如下:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>全屏自适应效果</title>        <style>            .overlay {                position: absolute;                /* 拉满整个页面 */                left: 0;                top: 0;                right: 0;                bottom: 0;                background-color: #000;                opacity: 0.5;            }        </style>    </head>    <body>        <div class="overlay"></div>    </body></html>

水平居中(使用 left、right 和 width)

示例代码如下:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>水平居中</title>        <style>            img {                position: absolute;                right: 0;                left: 0;                width: 800px;                /* 开启定位后,margin: auto 无法实现水平居中,需结合 left、right 和 width 使用 */                margin: auto;            }        </style>    </head>    <body>        <img src="../image/img.jpg" />    </body></html>

实现效果如下:

image.png


值得注意的是,absolute 属性值不能与 float 共同使用,当二者共存时,float 将失效。


🍚定位与 z-index 的关联

对于绝对定位的元素,我们可以通过 z-index 属性来控制它们的层级显示关系。然而,在实际开发中,我们更注重代码结构的清晰性,因此并非必须在所有情况下都使用 z-index。以下是一些使用准则:

  • 单个绝对定位元素: 如果只有一个绝对定位的元素,它自然会覆盖普通元素,此时无需通过 z-index 控制层级显示。

  • 两个绝对定位元素: 当存在两个绝对定位的元素时,通过控制它们在 DOM 流中的前后顺序即可达到覆盖效果,无需额外使用 z-index 属性。

  • 多个绝对定位元素: 在极少见的情况下,如果有多个绝对定位元素相互交错,可以通过 DOM 流的顺序和设置 z-index: 1 等较小的值来实现层级控制。

  • 非弹框类元素: 对于非弹框类的绝对定位元素,如果需要设置 z-index,建议将值设为大于2的数值。然而,注意在许多情况下,使用 z-index 的冗余性可能会使代码变得复杂,可以考虑优化代码结构。

通过遵循这些准则,我们能够在确保页面效果的同时,保持代码的简洁和可维护性。


🍚relative 属性值

relative 对 absolute 的限制

🍉1. 使用 relative 定位的父元素对其子元素的 absolute 定位具有一些限制作用,主要体现在以下方面:

位置限制: 当父元素开启 relative 定位后,其子元素如果使用 absolute 定位,那么子元素的 left、right、top、bottom 属性值将受到限制,永远不会超出父元素的边界。示例代码如下:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>relative 对 absolute 的限制</title>        <style>            .container {                /* 父级元素开启 relative 定位 */                position: relative;                height: 400px;                width: 600px;                margin: 0 auto;                background-color: #9c27b0;            }            .item {                /* 子元素开启 absolute 定位 */                position: absolute;                background-color: #4caf50;                height: 200px;                width: 300px;                /* 子元素的 top left right bottom 会被限制在父级容器中 */                right: 0;                bottom: 0;            }        </style>    </head>    <body>        <div class="container">            <div class="item"></div>        </div>    </body></html>

执行结果如下:

image.png

🍉2. z-index 层级限制: 当存在两个父元素都开启 relative 定位,并通过 z-index 限制层级时,z-index 较大的父元素的子元素将始终覆盖 z-index 较小的父元素的子元素。这是因为在同一层级中,z-index 更大的元素具有更高的堆叠顺序。示例代码如下:

image.png

在这种情况下,parent-1 下面的子元素无论其 z-index 的值多大,都不会覆盖 parent-2 下面的子元素。

🍉3. overflow:hidden 限制: 如果父元素未开启 relative 定位,其 overflow: hidden; 的限制对 absolute 定位的子元素并没有任何限制。只有父元素开启 relative 定位后,才会对 absolute 定位的子元素施加位置和溢出限制。示例代码如下:

image.png

当父元素未开启 relative 定位时:

image.png

当父元素开启 relative 定位后:

image.png

通过了解这些相对定位对绝对定位的限制,我们能更好地利用它们来实现页面布局。


🍚自定义偏移属性的使用

在元素开启 relative 定位后,我们可以使用 left、right、top、bottom 这些自定义偏移属性来实现相对于其原始位置的偏移,而不会对其他元素产生侵入性影响。简而言之,这些偏移属性是相对于元素自身进行调整,不会影响其他元素的布局。

以下是一个示例代码:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>自定义偏移属性的使用</title>        <style>            .container {                /* 父级元素开启 relative 定位 */                position: relative;                height: 400px;                width: 600px;                background-color: #9c27b0;                left: 100px;                top: 100px;            }        </style>    </head>    <body>        <div class="container"></div>    </body></html>

执行结果如下:

image.png

通过调整 left 和 top 属性的值,我们可以使元素相对于其原始位置进行水平和垂直方向的偏移。这种方式非常灵活,可以用于微调元素的布局,而不会对其他元素的排列产生干扰。


🍚相对定位的最小化影响原则

相对定位的最小化影响原则旨在尽量减少 relative 属性对其他元素或布局的潜在影响,体现在两个方面的考虑:

🍉1. 优先使用 margin 实现 absolute 定位的偏移,而不是依赖 relative 属性值。

示例代码如下:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>相对定位的最小化影响原则</title>        <style>            .container {                height: 400px;                width: 600px;                background-color: #9c27b0;                margin: 0 auto;            }            .item {                height: 100px;                width: 50px;                background-color: #ff7043;                line-height: 100px;                font-size: 30px;                text-align: center;            }            .absolute-item {                position: absolute;                right: 0;            }        </style>    </head>    <body>        <div class="container">            <div class="item absolute-item">1</div>            <div class="item">2</div>        </div>    </body></html>

这样的设计避免了相对定位对后续元素布局的干扰。

🍉2. 当必须使用相对定位时,为相对定位的子元素创建单独的父元素,并在该父元素上开启相对定位。

示例代码如下:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>相对定位的最小化影响原则</title>        <style>            .container {                height: 400px;                width: 600px;                background-color: #9c27b0;                margin: 0 auto;            }            .item {                height: 100px;                width: 50px;                background-color: #ff7043;                line-height: 100px;                font-size: 30px;                text-align: center;            }            .relative-parent {                position: relative;            }            .absolute-item {                position: absolute;                right: 0;            }        </style>    </head>    <body>        <div class="container">            <!-- 单独创建一个 开启 relative 定位的 父元素-->            <div class="relative-parent">                <!-- 这样不会影响后面元素的定位 -->                <div class="item absolute-item">1</div>            </div>            <div class="item">2</div>        </div>    </body>

</html>

这种方式有效地隔离了相对定位,减少了其对其他元素的潜在影响。

image.png

通过以上设计原则,我们能够更好地利用相对定位,同时最小化其可能带来的布局影响。


🍚fixed 定位的特性

在CSS中,当 position 属性值设置为 fixed 时,元素会相对于浏览器窗口进行偏移,即定位的基准点是整个浏览器窗口。这使得该元素的位置不会随着页面的滚动而变化,它就像是固定在页面上一样。

fixed 属性值可以与 top、bottom、left、right 这四个属性一起使用,用于确定元素的初始位置,这些值是相对于视口计算的。如果不使用这四个属性,元素将出现在其默认位置。

以下是示例代码:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>fixed 定位的特性</title>        <style>            body {                margin: 0;                height: 2000px;            }            .container {                /* 使用 fixed 定位 */                position: fixed;                height: 400px;                background: #2c80c5;                /* 实现居中 */                left: 0;                right: 0;                width: 500px;                margin: auto;            }        </style>    </head>    <body>        <div class="container"></div>    </body></html>

无论页面如何滚动,该元素始终保持在浏览器窗口的顶部。

这种布局方式的效果如下图所示。

image.png



🍚sticky 定位的独特特性

在CSS中,sticky 定位值与其他属性不同,它呈现出一种动态效果,可用于实现吸顶效果。

这个值的行为就像是 relative 和 fixed 的结合。在某些情况下,它是相对定位(基准点是元素自身的默认位置),而在其他情况下,它会自动变成固定定位(基准点是视口)。

sticky 属性值必须与 top、bottom、left、right 这四个属性一起使用,不能省略,否则效果等同于 relative 定位,不会产生动态吸附的效果。

这个属性值的定位规则是:当页面滚动时,父元素开始脱离视口(即部分不可见),只要与 sticky 元素的距离达到生效门槛,relative 定位自动切换为 fixed 定位;等到父元素完全脱离视口时(即完全不可见),fixed 定位自动切换回 relative 定位。

以下是示例代码:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>sticky 定位的独特特性</title>        <style>            .container {                background: #eee;                width: 600px;                height: 1000px;                margin: 0 auto;            }            .title {                /* 兼容 Safari 浏览器 */                position: -webkit-sticky;                position: sticky;                height: 60px;                background: #ff7300;                top: 0px;                font-size: 30px;                text-align: center;                color: #fff;                line-height: 60px;            }            img {                width: 100%;                display: block;            }        </style>    </head>    <body>        <div class="container">            <div>                <div class="title">内容1</div>                <img src="../image/img.jpg" />            </div>            <div>                <div class="title">内容2</div>                <img src="../image/img.jpg" />            </div>            <div>                <div class="title">内容3</div>                <img src="../image/img.jpg" />            </div>            <div>                <div class="title">内容4</div>                <img src="../image/img.jpg" />                <img src="../image/img.jpg" />            </div>        </div>    </body></html>

当页面滚动时,只要视口的顶部与 .title 的距离 >= 0,.title 就会自动变为 fixed 定位,保持与视口顶部 0px 的距离。页面继续向下滚动,父元素彻底离开视口,.title 恢复成 relative 定位。这种效果如下图所示。



🍚position:sticky 的生效规则需要满足以下条件:

🍉1. 指定 top、right、bottom 或 left 阈值: 在使用 position:sticky 时,必须指定 top、right、bottom 或 left 四个阈值中的至少一个,以使粘性定位生效。如果没有指定这些阈值,其行为将与相对定位相同。

  • 如果同时设置 top 和 bottom,top 的优先级较高。

  • 如果同时设置 left 和 right,left 的优先级较高。

🍉2. 父节点的 overflow 属性设置为 visible: position:sticky 元素的任意父节点的 overflow 属性必须是 visible,否则 position:sticky 不会生效。这是因为:

  • 如果 position:sticky 元素的任意父节点的 overflow 设置为 hidden,则父容器无法进行滚动,导致 position:sticky 元素无法在滚动时固定。

  • 如果 position:sticky 元素的任意父节点的 overflow 设置为 position:relative、absolute 或 fixed,则元素会相对于父元素进行定位,而不是相对于视口。

🍉3. 达到设定的阈值: position:sticky 元素会在滚动时相对于其包含块(nearest block ancestor)进行定位,直到达到设定的 top、right、bottom 或 left 阈值。元素达到设定的阈值后,其表现为 fixed 定位,保持在视口的相应位置。

考虑以上规则,以下是一个示例代码:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8" />        <meta http-equiv="X-UA-Compatible" content="IE=edge" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>position:sticky 生效规则</title>        <style>            .container {                background: #eee;                width: 600px;                height: 1000px;                margin: 0 auto;                overflow: visible; /* 必须设置 overflow 为 visible */            }            .sticky-element {                position: -webkit-sticky;                position: sticky;                top: 20px; /* 达到设定的阈值 */                height: 60px;                background: #ff7300;                font-size: 18px;                text-align: center;                line-height: 60px;            }            img {                width: 100%;                display: block;            }        </style>    </head>    <body>        <div class="container">            <div class="sticky-element">Sticky Element</div>            <img src="../image/img.jpg" />        </div>    </body></html>

这个示例满足了 position:sticky 的生效条件,包括指定了 top 阈值、父节点的 overflow 属性为 visible,以及达到设定的阈值。


群贤毕至

访客