Podría crear un elemento que iría encima del control deslizante de rango. Tengo un ejemplo en el que el elemento .range-text tiene el mismo tamaño que el control deslizante, por lo que se siente igual que la entrada normal al moverlo, y el texto/posición se actualiza a través de JS. Esperemos que le dé una idea de cómo puede crear algo para resolver sus necesidades.
const rangeInput = document.querySelector('input[type="range"]'); const rangeText = document.querySelector('.range-text'); rangeInput.addEventListener('change', (e) => { let newVal = e.target.value; let negNewVal = -1 * newVal; rangeText.style.left = (newVal + '%'); //Set range left position rangeText.style.transform = 'translate(' + negNewVal + '%, 2px)'; //Set range translate to correct rangeText.innerHTML = newVal; //Set range text equal to input position }) .input-container { position: relative; display: flex; background: black; width: 100%; padding: 0; } input[type="range"] { appearance: none; background-color: white; width: 100%; height: 20px; padding: 0; } input[type="range"]::-webkit-slider-thumb { -moz-appearance: none !important; appearance: none !important; position: relative; height: 20px; width: 100px; background: transparent; cursor: pointer; z-index: 2; } input[type="range"]::-moz-range-thumb { -moz-appearance: none !important; appearance: none !important; position: relative; height: 20px; width: 100px; background: transparent; cursor: pointer; z-index: 2; } .range-text { position: absolute; top: 0; left: 0; display: flex; justify-content: center; align-items: center; background: skyblue; text-align: center; line-height: 1; height: 20px; width: 100px; transform: translate(0, 2px); } <div class="input-container"> <input type="range" min="0" max="100" value="0" step='25'> <div class="range-text">0</div> </div>