Search code examples
javascriptcssgoogle-chrome-extension

Slider "before" bar overlaps on top of thumb in HTML/CSS/JS


I am making a web audio player with a slider control bar. I used the <input type="slider"> tag to display the slider, and I've got it to work 90% of the way. The only issue now is that the "before" bar, implemented with ".slider:before" in CSS, overlaps on top of the thumb button (especially as you move the thumb toward the end). Here is what it looks like:

current UI

I would like to see how to make it so that the darker "before" bar hides under the thumb

Here is my code

const seekSlider = document.getElementById('slider');
    
const showRangeProgress = (rangeInput) => {
  seekSlider.style.setProperty('--seek-before-width', `${rangeInput.value}%`);
}

seekSlider.addEventListener('input', (e) => {
    showRangeProgress(e.target);
})
input[type="range"] {
      width: 185px;
    }
    
    .slider {
      position: relative;
      margin-left: 10px;
      cursor: pointer;
      -webkit-appearance: none;
      height: 10px;
      outline: none;
      margin-top: 7px;
      margin-bottom: -3px;
      opacity: 0.7;
      transition: 0.3s;
    }
    
    .slider::-webkit-slider-runnable-track {
      height: 3px;
      background: rgba(66, 64, 70, 0.15);
    }
    
    .slider::before {
      position: absolute;
      content: "";
      width: var(--seek-before-width);
      height: 3px;
      margin-top: 4px;
      background-color: rgba(203, 195, 227, 0.8);
    }
    
    .slider::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 8px;
      height: 8px;
      background: #a8a3b3;
      border-radius: 50%;
      margin-top: -2px;
    }
<div id="controls" class="controls">
  <input id="slider" type="range" value="0" max="100" class="slider">
  <p id="time" class="time">0:00</p>
  <p class="endtime">3:25</p>
</div>

Here is kind of what I would like to achieve:

enter image description here

Any help would be greatly appreciated :)


Solution

  • Adding z-index:-1; property to your .slider::before class will do the job.

    Try the following snippet

    const seekSlider = document.getElementById('slider');
            
    const showRangeProgress = (rangeInput) => {
      seekSlider.style.setProperty('--seek-before-width', `${rangeInput.value}%`);
    }
    
    seekSlider.addEventListener('input', (e) => {
        showRangeProgress(e.target);
    })
    input[type="range"] {
              width: 185px;
            }
            
            .slider {
              position: relative;
              margin: 10px;
              cursor: pointer;
              height: 9px;
              outline: none;
              opacity: 0.7;
              transition: 0.3s;
            }
            
            .slider::-webkit-slider-runnable-track {
              height: 3px;
              background: rgba(66, 64, 70, 0.15);
            }
            
            .slider::before {
              position: absolute;
              content: "";
              width: var(--seek-before-width);
              height: 3px;
              margin-top: 4px;
              z-index:-1;
            }
            
            .slider::-webkit-slider-thumb {
              width: 9px;
              height: 9px;
              margin-top:-6px;
              background: #a8a3b3;
              border-radius: 50%;
              background-color:grey;
            }
    <input id="slider" type="range" value="0" max="100" class="slider">

    Definition and Usage: the z-index property specifies the stack order of an element. An element with greater stack order is always in front of an element with a lower stack order.

    Note: z-index only works on positioned elements (position: absolute, position: relative, position: fixed, or position: sticky) and flex items (elements that are direct children of display:flex elements).