Pixiv - KiraraShss
1459 字
7 分钟
12.3号学习内容
欢迎来到我的博客!
这是我的第 3 篇文章,使用 Markdown 格式编写。
今天学到了什么
- 3D悬停相册
代码比较简单,但是在自己写的过程中,总能发现一些小问题
疑问1
<style> .box ul:has(.item:nth-child(1):hover) { grid-template-columns: 2fr 1fr 1fr 1fr; } .item:nth-child(1):hover ul { grid-template-columns: 2fr 1fr 1fr 1fr; }</style>第二种写法是:
.item:nth-child(1):hover ul :用于当某个 item 被 hover 时,改变 该 item 内部的 <ul> 元素 的样式。如果 item 内部没有 <ul> ,则无效。(本质应该是一个后代选择器)
感觉冒号后面更多的是形容词,主体还是item
疑问2
刚写到最后一行的时候我就有疑问了
我明明没有设置z-index=1,但是,被鼠标选中的元素 不会 被后面的元素遮住
<style> .box { display: flex; justify-content: center; align-items: center; margin: 200px auto; gap: 2px; }
.box .item { width: 120px; height: 120px; transition: all 0.6s ease; }
.box .item img { width: 100%; height: 100%; border-radius: 8px; }
.box .item:hover { transform: scale(1.2); }</style>写到这里我还没有深究,直到我快写完这个案例的时候
<style> .box .item { width: 120px; height: 120px; transition: all 0.6s ease; -webkit-box-reflect: below 1px linear-gradient(transparent, #0002); /* 写到这里的时候我就发现不对劲了,经过我慢慢探索,发现了。。。 */ }/* 鼠标经过某个盒子,其余的子盒子都变形,当前盒子保持不变 */ .box:hover .item:not(:hover) { transform: perspective(500px) rotateY(45deg); margin: 0 -20px; }</style>我发现,我加了倒影之后,后面的图片就会压在 鼠标经过的图片 的上面,我不加倒影,就不会这样
这背后的原因就是 CSS 堆叠上下文 (Stacking Context) 。
堆叠上下文 (Stacking Context) 是什么?
堆叠上下文是 HTML 元素的一个三维概念,它沿着 Z 轴(垂直于屏幕的轴)对元素进行分层。每个堆叠上下文都有自己的 Z 轴,并且其子元素在其中进行堆叠。
哪些属性会创建新的堆叠上下文?
有很多 CSS 属性可以创建新的堆叠上下文,其中最常见和与你情况相关的就是:
-
position 属性 :
- 当一个元素的 position 属性值为 absolute 或 relative ,并且设置了 z-index 属性(即使 z-index 的值是 auto 或 0 ,只要不是 static 且设置了 z-index 就会创建)。
- 注意 : position: fixed 和 position: sticky 也会创建堆叠上下文。
-
transform 属性 :
- 当一个元素设置了 transform 属性,并且其值不是 none 时,它会创建一个新的堆叠上下文。
- 这就是你遇到的情况!
-
opacity 属性 :
- 当一个元素的 opacity 属性值小于 1 时,它会创建一个新的堆叠上下文。
-
filter 属性 :
- 当一个元素的 filter 属性值不是 none 时,它会创建一个新的堆叠上下文。
-
will-change 属性 :
- 如果 will-change 属性的值是 transform 、 opacity 、 filter 或 perspective ,它会创建一个新的堆叠上下文。 还有其他一些属性,比如 perspective 、 clip-path 、 mask 等,也会创建堆叠上下文。
问题的核心: -webkit-box-reflect 也创建了堆叠上下文
-webkit-box-reflect 这个属性,同样会为元素创建一个新的堆叠上下文。
详细解释:
-
不加倒影时(没有 -webkit-box-reflect ) :
- 只有当你鼠标滑过某个 .item 元素时,它才会被应用 transform: scale(1.2); 。
- 此时, 只有被滑过的那个 .item 元素创建了新的堆叠上下文 。
- 其他未被滑过的 .item 元素没有 transform 属性,也没有 -webkit-box-reflect ,所以它们 没有创建新的堆叠上下文 。
- 根据堆叠上下文的规则,一个创建了堆叠上下文的元素,会堆叠在没有创建堆叠上下文的兄弟元素之上。所以,被滑过的图片自然就浮在了最上面。
-
加了倒影之后(所有 .item 都应用了 -webkit-box-reflect ) :
- 当你给所有的 .item 元素都加上 -webkit-box-reflect 之后, 所有的 .item 元素都创建了各自的堆叠上下文 。
- 现在,所有的 .item 元素都在同一个父堆叠上下文(通常是 body 或 html )中,并且它们都创建了自己的子堆叠上下文。
- 在这种情况下,它们的堆叠顺序不再是“有堆叠上下文的在上面,没有的在下面”那么简单了。而是要根据它们各自的 z-index 值来决定。
- 如果所有 .item 的 z-index 都是默认的 auto 或 0 ,那么它们的堆叠顺序将由它们在 HTML 中的 文档流顺序 决定。 也就是说,HTML 中写在后面的元素会覆盖写在前面的元素。
- 当你滑过一个图片时,它会应用 transform: scale(1.2); ,并且你的代码中通常会同时设置 z-index: 1; 。
- 关键在于: 如果你 没有 在 .item
中设置 z-index: 1; ,那么即使它被 transform: scale(1.2); 放大,它的 z-index 仍然是默认值。由于所有元素都创建了堆叠上下文,并且 z-index 相同,那么文档流顺序就会生效,导致后面的图片覆盖前面的图片。
结束:完整代码演示
最终我也是把照片换成了她的照片❤️
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><style> * { margin: 0; padding: 0; box-sizing: border-box; }
body { background-color: #1A252C; }
.box { display: flex; justify-content: center; align-items: center; margin: 200px auto; gap: 2px; }
.box .item { width: 120px; height: 120px; transition: all 0.6s ease; -webkit-box-reflect: below 1px linear-gradient(transparent, #0002); }
.box .item img { width: 100%; height: 100%; border-radius: 8px; }
.box .item:hover { transform: scale(1.2); z-index: 1; }
/* 鼠标经过某个盒子,其余的子盒子都变形,当前盒子保持不变 */ .box:hover .item:not(:hover) { transform: perspective(500px) rotateY(45deg); margin: 0 -20px; }
.box .item:hover~.item { transform: perspective(500px) rotateY(-45deg); }</style>
<body> <div class="box"> <div class="item"><img src="../代码/img/1.png"></div> <div class="item"><img src="../代码/img/2.png"></div> <div class="item"><img src="../代码/img/3.png"></div> <div class="item"><img src="../代码/img/4.png"></div> <div class="item"><img src="../代码/img/5.png"></div> </div></body>
</html>很高兴与你分享这些知识!
赞助支持
如果这篇文章对你有帮助,欢迎赞助支持!
最后更新于 2025-12-03