1135 字
6 分钟

display:flex与绝对定位

欢迎来到我的博客!#

使用 Markdown 格式编写。

今天学到了什么#

  • 炫彩工具箱案例

父盒子设置了 display: flex;对设置了绝对定位的子盒子还生效吗#

这是一个非常经典且容易混淆的问题。

结论: display: flex 对绝对定位(position: absolute)的子元素只有部分影响,大部分 Flex 布局特性会失效。

具体来说:

  1. 脱离文档流: 一旦子元素设置了 position: absolute,它就脱离了文档流。这意味着它不再参与 Flex 容器的自动空间分配(比如 flex-grow, flex-shrink 等属性对它无效)。

  2. justify-contentalign-items 的影响

    • 如果子元素没有设置偏移量(top/left/right/bottom): Flex 容器的对齐属性(justify-contentalign-items依然会影响这个绝对定位子元素的初始位置
      • 在你的代码中,.menu 设置了 justify-content: center; align-items: center;,且 .btn 没有设置 top/left 等。
      • 结果.btn 会乖乖地待在 .menu 的正中心。
    • 如果子元素设置了偏移量(比如 top: 0; left: 0;: 偏移量的优先级高于 Flex 对齐。子元素会直接飞到 top: 0; left: 0 的位置,完全无视 Flex 的居中设置。
  3. 父级定位基准: 你注释掉了 .menuposition: relative;

    • 如果 .menu 没有定位属性,.btnposition: absolute 会向上寻找最近的已定位祖先元素作为参考点。
    • 如果找不到,它就会相对于 body(或者说初始包含块)进行定位。
    • 但在你的例子中,因为 .btn 没有写 top/left,它默认就停留在它在文档流中“本该在”的位置(也就是被 Flex 居中的位置)。

总结建议: 虽然 Flex 对齐能影响无偏移的绝对定位元素,但为了代码的健壮性,通常建议:

  1. 给父元素 .menu 加上 position: relative;
  2. 如果你想让子元素居中,既然已经用了 absolute,也可以直接用 top: 50%; left: 50%; transform: translate(-50%, -50%); 来强制居中,这样就不依赖父级的 Flex 属性了。或者保留现在的写法利用 Flex 居中也是一种常见的技巧。

设置绝对定位后,如果不设置top,元素会停在原先的位置#

是的,你的理解完全正确。这是一个非常实用但经常被忽略的 CSS 特性。

原理解析#

当一个元素设置了 position: absolute,它确实会脱离文档流(不再占据空间),但是:

  1. 如果没有设置偏移量top, left, right, bottom): 浏览器会把它渲染在它原本在普通文档流中应该出现的位置。这被称为元素的**“静态位置” (Static Position)**。

  2. 结合你的代码

    • 你的父盒子 .menu 设置了 Flex 布局居中:
      display: flex;
      justify-content: center;
      align-items: center;
    • 这意味着,如果子元素 .btnspan 不是绝对定位的话,它们本来就会被 Flex 挤到正中间。
    • 当你加上 position: absolute不写 top/left 时,它们就乖乖地停留在那个“本该在的正中间位置”,只是不再占据物理空间了(所以它们会重叠在一起)。

总结: 利用这个特性配合 Flex 布局,是让绝对定位元素快速居中的一个非常巧妙的技巧!总结: 利用这个特性配合 Flex 布局,是让绝对定位元素快速居中的一个非常巧妙的技巧!

案例完整代码#

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>炫彩工具箱.html</title>
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_4090357_z2qpnic06um.css">
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #303640;
}
.menu {
position: relative;
width: 200px;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
.menu .btn {
position: absolute;
z-index: 1000;
width: 60px;
height: 60px;
background-color: #303640;
color: #fff;
border: 2px solid #fff;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
transition: all 1.25s;
}
.menu .btn i {
font-size: 32px;
}
.menu:hover .btn {
transform: rotate(315deg);
}
.menu span {
position: absolute;
border: 2px solid var(--clr);
border-radius: 50%;
/* 分开写两个过渡 */
transition: all 0.5s calc(var(--i) * 0.1s);
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
color: var(--clr);
}
.menu span i {
font-size: 24px;
/* color: var(--clr); */
}
.menu:hover span {
transform: rotate(calc(360deg / 8 * var(--i))) translateX(80px);
}
.menu:hover span i {
transform: rotate(calc(-360deg / 8 * var(--i)));
}
.menu span:hover {
box-shadow:
0 0 10px var(--clr),
0 0 30px var(--clr),
0 0 50px var(--clr);
background-color: var(--clr);
color: #333;
/* 想要阴影立马显示,所以去掉过渡 */
transition: all 0s;
}
</style>
</head>
<body>
<div class="menu">
<div class="btn"><i class="iconfont icon-add"></i></div>
<span style="--i:0;--clr: #ff2972;">
<i class="iconfont icon-home"></i>
</span>
<span style="--i:1;--clr: #fee800;">
<i class="iconfont icon-more"></i>
</span>
<span style="--i:2;--clr: #04fc43;">
<i class="iconfont icon-gift"></i>
</span>
<span style="--i:3;--clr: #fe00f1;">
<i class="iconfont icon-setting"></i>
</span>
<span style="--i:4;--clr: #00b0fe;">
<i class="iconfont icon-message"></i>
</span>
<span style="--i:5;--clr: #fea600;">
<i class="iconfont icon-cart"></i>
</span>
<span style="--i:6;--clr: #a529ff;">
<i class="iconfont icon-money"></i>
</span>
<span style="--i:7;--clr: #01bdab;">
<i class="iconfont icon-star"></i>
</span>
</div>
</body>
</html>

赞助支持

如果这篇文章对你有帮助,欢迎赞助支持!

赞助
最后更新于 2026-01-03,距今已过 1 天

部分内容可能已过时

目录