为何伪元素未相对父元素<li>定位?轮播指示器样式异常
轮播指示器伪元素未相对父元素定位的问题
问题描述
我正在制作一款带有下方指示器的轮播组件,以下是我的代码:
<ul class="product-slick-dots"> <li aria-hidden="true" data-slick-index="0"></li> <li aria-hidden="true" data-slick-index="1"></li> <li aria-hidden="true" data-slick-index="2"></li> <li aria-hidden="true" data-slick-index="3"></li> </ul>
.product-slick-dots li { width: 8px; height: 8px; background: #00000042; border-radius: 100px; display:inline-block; vertical-align: middle; margin: 0 4px; cursor: pointer; } .product-slick-dots li::before { content: ''; position: absolute; top: 50%; left: 50%; margin-top: -6px; margin-left: -6px; width: 12px; height: 12px; background: #FFFFFFA6; border-radius: 150px; border: 1px solid #33333366; }
我期望指示器样式如图片左侧所示,但实际呈现为右侧效果,请问为何伪元素未相对其父元素<li>进行定位?
解决方案
这是个很常见的CSS定位问题——绝对定位的元素会相对于最近的、设置了非static定位的父元素来定位,而你的<li>元素默认的position值是static(浏览器的默认样式),所以伪元素会直接跳过它,去往上寻找有定位属性的父容器,甚至会相对于整个视口定位,自然就偏离了你想要的位置。
解决起来非常简单,只需要给<li>加上position: relative,把它变成伪元素的定位基准:
.product-slick-dots li { width: 8px; height: 8px; background: #00000042; border-radius: 100px; display:inline-block; vertical-align: middle; margin: 0 4px; cursor: pointer; /* 新增这一行,将li设为定位容器 */ position: relative; } .product-slick-dots li::before { content: ''; position: absolute; top: 50%; left: 50%; margin-top: -6px; margin-left: -6px; width: 12px; height: 12px; background: #FFFFFFA6; border-radius: 150px; border: 1px solid #33333366; }
另外给你个小优化建议:你现在用top:50% + margin-top:-6px的方式居中,虽然可行,但可以换成更灵活的transform: translate(-50%, -50%),这样不用手动计算margin值,不管伪元素尺寸怎么变,都能自动居中:
.product-slick-dots li::before { content: ''; position: absolute; top: 50%; left: 50%; /* 替换margin为transform,自动居中 */ transform: translate(-50%, -50%); width: 12px; height: 12px; background: #FFFFFFA6; border-radius: 150px; border: 1px solid #33333366; }
修改之后,伪元素就会精准地相对于每个<li>居中定位,完全符合你想要的左侧指示器效果啦!
内容的提问来源于stack exchange,提问作者hayley
相关产品推荐
相关产品推荐

