如何让 :before & :after 伪元素填充剩余宽度?

How to make :before & :after pseudo-elements fill remaining width?

所以我想在页面上编辑这个现有的小部件。我无权编辑源代码,所以希望能够完全在 CSS 中完成,理想情况下。与其试图解释,我认为更容易粘贴所需行为的图像 - 即有一个左侧部分(:之前)和右侧部分(:之后) - 随着拆分器的移动,然后是每个伪元素的宽度应相应更改。

desired result

这是小部件 code/structure

的基本版本的 JSFiddle

https://jsfiddle.net/o0zgyut3/

HTML

<div id='wrapper'>
  <div id='splitter' style='left: 50%'></div>
</div>
<input id='slider' type='range' min='0' max='100' value='50'/>

CSS

body, html{
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  background: #222;
}

input{
  margin-top: 10px;
}

#wrapper{
  width: 500px;
  height: 50px;
  background: #444;
  position: relative;
  display: flex;
}

/*left*/
#wrapper::before{
  content:'';
  width: 50px;
  height: 50px;
  background: linear-gradient(0deg,#00be1abf,#5fed00b3);
  position: absolute;
  left: 0px;
}

/*right*/
#wrapper::after{
  content:'';
  width: 50px;
  height: 50px;
  background: linear-gradient(0deg,#9f0000ff,#f10000ff);
  position: absolute;
  right: 0px;
}

#splitter{
  position: relative;
  transform: translateX(-50%);
  background: #ddd;
  height: 50px;
  width: 10px;
  z-index: 99;
}

JS(请注意,我无法访问真实站点中的 JS - 下面这个示例中的滑块只是为了允许在调试时轻松更改拆分器位置(无需添加拖动功能)

document.getElementById("slider").addEventListener("change", function(){
  document.getElementById("splitter").style.left = this.value + "%";
})

我已经尝试过各种方法(使用 flex、inline、grid、floats、margins 等)并且可以得到我想要的一半的行为,但从来没有完全正确。另请注意,如果它更容易,则实际宽度不必准确 - 它是一个纯粹的视觉小部件,因此可以例如使右侧部分为 100% 宽度,然后只有左侧部分是动态的,并通过给它更高的 z-index 将其定位在右侧上方,如果这样更容易——即如果右侧部分被硬编码为 100% 宽度,并且left 从 css 派生出 80% 的宽度,它会产生 80:20 拆分的错觉(即使从技术上讲它是 80:100),这很好

无论如何,我怀疑我遗漏了一些相当明显的东西,所以如果有人能够让它工作,那就太棒了。谢谢

您不可能直接使用 JS 访问伪元素,因为当页面加载时它们不是 DOM 的一部分。

但是,您可以像这样创建一个新的 style 元素,该元素将为您的 wrapper

创建新的 CSS

运行 下面的代码片段以查看它是否正常工作。

document.getElementById("slider").addEventListener("change", function() {
  document.getElementById("splitter").style.left = this.value + "%";
  var sytleElement = document.head.appendChild(document.createElement("style"));
  sytleElement.innerHTML = "#wrapper:before {width: " + this.value + '%' + "  }";
})
body,
html {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  background: #222;
}

input {
  margin-top: 10px;
}

#wrapper {
  width: 500px;
  height: 50px;
  background: #444;
  position: relative;
  display: flex;
}


/*left*/

#wrapper::before {
  content: '';
  width: 10%;
  height: 50px;
  background: linear-gradient(0deg, #00be1abf, #5fed00b3);
  position: absolute;
  left: 0px;
}


/*right*/

#wrapper::after {
  content: '';
  width: 50px;
  height: 50px;
  background: linear-gradient(0deg, #9f0000ff, #f10000ff);
  position: absolute;
  right: 0px;
}

#splitter {
  position: relative;
  transform: translateX(-50%);
  background: #ddd;
  height: 50px;
  width: 10px;
  z-index: 99;
}
<div id='wrapper'>
  <div id='splitter' style='left: 10%'></div>
</div>
<input id='slider' type='range' min='0' max='100' value='10' />