从 parent 的开始到结束平滑地移动 object,没有重叠

Move object smoothly from start to end of parent without overlap

我想使用 CSS 模拟滑块。 This code pen 显示了一个最小的工作示例。

滑块的 left 属性 可以使用 javascript 设置,或者像在代码笔示例中那样,通过将 CSS 变量设置为 0 到 100 .

在 0% 时,滑块应位于其 parent 的左侧。在 100% 时,滑块应与右侧齐平。

parent 是一个 flex child,其宽度由 flex-grow 设置,它与另一个 flex child.

共享行

在下图中,滑块的 parent 是黄色的,滑块本身是蓝绿色的。相邻的 flex child 显示为橙色:

当 CSS 变量(或 Javascript 变量)达到 100% 时,滑块的 right-hand 边缘应与黄色框的 right-hand 边缘齐平,但目前它是这样移动的:

我想我可以使用类似的东西计算 left 属性:

calc((100% - 40px) / 100%)

但是as MDN states,除法的right-hand边必须是数字

我是不是遗漏了什么明显的东西?

.full {
  display: flex;
  height: 50px;
  max-width: 600px;
}

.full p {
  float: left;
  padding-left: 10px;
}

.left {
  flex-grow: 8;
  background-color: yellow;
  padding: 5px 0;
}

.right {
  flex-grow: 2;
  background-color: orange;
}

.slider {
  height: 100%;
  width: 40px;
  background-color: steelblue;
  opacity: 0.9;
}

.slider {
  position: relative;
  --complete: 100%;
  left: calc(var(--complete));
}
<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>

多亏了 Temani Afif about using translateX as well as left 的有用提示,我已经设法组合了一个不漂亮但有效的解决方案。

我仍然愿意接受更多 'attractive' 解决方案。

.slider {
  position: relative;
  --complete: 100;
  left: calc(1% * var(--complete));
  transform: translateX(calc(-40px * var(--complete) / 100));
}

您可以调整计算并从 --complete 中删除百分比:

--complete:80;
left: calc( var(--complete) * 1% - var(--complete) * (40px/100));

完整代码:

.full {
  display: flex;
  height: 50px;
  max-width: 600px;
}

.full p {
  float: left;
  padding-left: 10px;
}

.left {
  flex-grow: 8;
  background-color: yellow;
  padding: 5px 0;
}

.right {
  flex-grow: 2;
  background-color: orange;
}

.slider {
  height: 100%;
  width: 40px;
  background-color: steelblue;
  opacity: 0.9;
}

.slider {
  position: relative;
  --complete:80;
  left: calc( var(--complete) * 1% - var(--complete) * (40px/100));
}
<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>
<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider" style="--complete:100">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>

<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider" style="--complete:0">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>

<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider" style="--complete:50">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>

<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider" style="--complete:20">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>

或者将它与transform结合使用,像这样:

--complete: 80%;
left: calc(var(--complete)); 
transform: translateX(calc(-1 * var(--complete)));

.full {
  display: flex;
  height: 50px;
  max-width: 600px;
}

.full p {
  float: left;
  padding-left: 10px;
}

.left {
  flex-grow: 8;
  background-color: yellow;
  padding: 5px 0;
}

.right {
  flex-grow: 2;
  background-color: orange;
}

.slider {
  height: 100%;
  width: 40px;
  background-color: steelblue;
  opacity: 0.9;
}

.slider {
  position: relative;
  --complete: 80%;
  left: calc(var(--complete));
  transform: translateX(calc(-1 * var(--complete)));
}
<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>
<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider" style="--complete:100%">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>

<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider" style="--complete:0%">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>

<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider" style="--complete:50%">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>

<div class="full">
  <div class="left">
    <p>flex-grow: 8</p>
    <div class="slider" style="--complete:20%">
    </div>
  </div>
  <div class="right">
    <p>flex-grow: 2</p>
  </div>
</div>