You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动父滑块时让轮播项相对祖父元素定位的CSS方案咨询

补充说明: 我已经实现了一个JS方案——通过获取祖父元素宽度来设置轮播项宽度,这样轮播项和滑块容器都能设为绝对定位,但还是想知道有没有纯CSS的实现方式。


原始问题

我正在制作一个图片轮播,将轮播项(.slide)设置为相对于祖父元素(白色的.dummy-page)绝对定位,以此保证能显示正确数量的轮播项及边距,效果如下:
轮播图效果

问题在于,若要移动包含轮播项的父滑块容器(带红色边框的.slider),需将其设置为绝对定位,但这会破坏轮播项的尺寸——原本轮播项宽度为.dummy-page的30%,现在变成了.slider的30%。

我曾尝试使用transform(无需将父元素设为绝对定位),但问题依旧(取消JS中第9行代码注释可查看效果)。

我认为当前方法存在根本性缺陷,希望获取其他轮播项定位/尺寸设置思路,感谢!

代码示例

JavaScript

const moveLeft = () => {
  const slider = document.querySelector('.slider');
  const slide = document.querySelector('.slide');
  const slideWidth = slide.offsetWidth;
  const slideLeft = parseFloat(getComputedStyle(slide).left);
  const offset = slideWidth + slideLeft;
  
  // addStyle(slider, {'left': `${offset}px`});  
  // slider.style.transform = `translateX(${30}px)`;
}

const addStyle = (element, style) => {
    for (const property in style) element.style[property] = style[property];
}

moveLeft();

CSS

* {
  margin: 0;
  padding: 0;
}

:root {
  --slide-width: 30%;
  --slide-height: 15rem;
  --num-slides: 5;
  --visible-slides: 3;
  --slide-margin: calc( (100% - var(--visible-slides) * var(--slide-width)) / (var(--visible-slides) + 1) );
}

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100vh;
  background-color: grey;
}

.dummy-page {
  position: relative;
  width: 60%;
  height: 90%;
  background-color: white;
}

.slider {
  display: inline-flex;

  /*   Each slide has width and a margin-right, + 1 LHS margin */
  width: calc(var(--num-slides) * (var(--slide-width) + var(--slide-margin)) + var(--slide-margin));
  height: var(--slide-height);

  margin-top: 2rem;

  border: 1px solid red;
}

.slide {
  position: absolute;
  height: var(--slide-height);
  width: var(--slide-width);
  background-color: lightgrey;
  border: 1px solid grey;
}

.slide-1 {
  left: var(--slide-margin);
}
.slide-2 {
  left: calc(var(--slide-margin) * 2 + var(--slide-width))
}
.slide-3 {
  left: calc(var(--slide-margin) * 3 + var(--slide-width) * 2);
}

.slide-4 {
  left: calc(var(--slide-margin) * 4 + var(--slide-width) * 3);
}

.slide-5 {
  left: calc(var(--slide-margin) * 5 + var(--slide-width) * 4);
}

.btn-container { 
  display: flex;
  justify-content: center;
  width: 100%;
}
.btn {
  display: inline-flex;
  margin: .5rem;
  padding: .8rem 1.5rem;
  border: 1px solid lightgrey;
}

HTML

<div class="container">
  <div class="dummy-page">
    <div class="slider">
      <div class="slide slide-1"></div>
      <div class="slide slide-2"></div>
      <div class="slide slide-3"></div>
      <div class="slide slide-4"></div>
      <div class="slide slide-5"></div>
    </div>
    
    <div class="btn-container">
      <div class="btn left">Left</div>
      <div class="btn right">Right</div>
    </div>
  </div>
</div>

JS(接近可行)解决方案

我新增了一个额外的滑块容器,通过JS获取祖父元素的宽度(遗憾存在10px误差),再设置轮播项宽度,这样轮播项和滑块容器均可设置为绝对定位。

代码示例

const initSlider = () => {
  const pageWidth = document.querySelector('.slider-container').offsetWidth;
  
  const numSlides = parseInt(getCssVariable('--num-slides'));
  const slideWidth = pageWidth / numSlides;

  setCssVariable('--slide-width', `${slideWidth}px`);
 
}

const getCssVariable = (name) => {
  return getComputedStyle(document.documentElement).getPropertyValue(name);
}

const setCssVariable = (name, value) => {
  document.documentElement.style.setProperty(name, value);
}

window.addEventListener('DOMContentLoaded', initSlider());

内容的提问来源于stack exchange,提问作者NickW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 06:30:59