Проблема в input range, съезжает подсказка значения
Проблема в .range > output в свойстве left
Он двигает output в процентах от левого края.
Подскажите как можно решить эту проблему?
.container {
width: 300px;
margin: 60px auto 20px;
}
.range {
width: 100%;
--completed: calc((var(--value) - var(--min)) / (var(--max) - var(--min)) * 100);
display: inline-block;
position: relative;
z-index: 1;
margin: 22px 0 0 0;
}
.range__progress {
position: absolute;
left: 0;
top: 10px;
width: 100%;
height: 4px;
pointer-events: none;
z-index: -1;
border-radius: 20px;
background: linear-gradient(90deg, #BD3E8A 0%, #3F7446 90.48%);
}
.range__progress::after {
content: '';
display: block;
margin-left: auto;
margin-right: -1px;
width: calc((100% - var(--completed) * 1%) + (var(--completed) / 100) * 16px);
height: 100%;
background: #eee;
box-shadow: inherit;
border-radius: 0 20px 20px 0;
}
.range > input {
appearance: none;
-webkit-appearance: none;
width: 100%;
margin: 0;
cursor: -webkit-grab;
cursor: grab;
outline: none;
background: none;
}
.range > input::-webkit-slider-thumb {
appearance: none;
-webkit-appearance: none;
border-radius: 50%;
height: 24px;
width: 24px;
background: #84566B;
}
.range > input::-moz-slider-thumb {
appearance: none;
border-radius: 50%;
height: 24px;
width: 24px;
background: #84566B;
}
.range > input::-ms-thumb {
appearance: none;
border-radius: 50%;
height: 24px;
width: 24px;
background: #84566B;
}
.range > output {
pointer-events: none;
position: absolute;
z-index: 5;
background: #fff;
border-radius: 5px;
padding: 5px 0;
top: -30px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, .2);
left: calc(((var(--value) - var(--min)) / (var(--max) - var(--min))) * 100%);
font-weight: 500;
font-size: 12px;
width: 28px;
height: 14px;
text-align: center;
}
.range > output::after {
content: var(--text-value);
}
.range > output::before {
content: '';
position: absolute;
top: 100%;
left: 8px;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #fff;
}
<div class="container">
<div class="range" style='--min:1; --max:200; --value:38; --text-value:"38";'>
<input type="range" min="1" max="200" value="38" oninput="this.parentNode.style.setProperty('--value',this.value); this.parentNode.style.setProperty('--text-value', JSON.stringify(this.value))">
<output></output>
<div class='range__progress'></div>
</div>
</div>
Ответы (2 шт):
Автор решения: UserTest013
→ Ссылка
Я не знаю возможно ли сделать то, что вы хотите без js. Вот решение с использованием js
let range = document.querySelector('.range input');
let hint = document.querySelector('.range span');
hint.style.top = range.offsetHeight + 'px';
let thumbnWidth = 8;
let offset = range.clientWidth / (parseInt(range.max) - parseInt(range.min));
let updatePosition = () => {
hint.innerHTML = range.value;
hint.style.left = ((range.valueAsNumber - parseInt(range.min)) * offset - hint.offsetWidth / 2 - (range.valueAsNumber / parseInt(range.max) - parseInt(range.min) - 0.5) * thumbnWidth) + 'px';
};
updatePosition();
range.addEventListener('input', updatePosition);
.range {
position: relative;
margin: auto;
padding-top: 50px;
}
.range span {
position: absolute;
color: red;
border: 1px solid blue;
}
.range input {
margin: 0;
}
<div class="range">
<span></span>
<input type="range" max="1000" min="0">
</div>
Автор решения: Squeli47
→ Ссылка
Вроде получилось решить проблему
.container {
width: 300px;
margin: 60px auto 20px;
}
.range {
width: 100%;
--completed: calc((var(--value) - var(--min)) / (var(--max) - var(--min)) * 100);
display: inline-block;
position: relative;
z-index: 1;
margin: 22px 0 0 0;
}
.range__progress {
position: absolute;
left: 0;
top: 10px;
width: 100%;
height: 4px;
pointer-events: none;
z-index: -1;
border-radius: 20px;
background: linear-gradient(90deg, #BD3E8A 0%, #3F7446 90.48%);
}
.range__progress::after {
content: '';
display: block;
margin-left: auto;
margin-right: -1px;
width: calc((100% - var(--completed) * 1%) + (var(--completed) / 100) * 16px);
height: 100%;
background: #eee;
box-shadow: inherit;
border-radius: 0 20px 20px 0;
}
.range > input {
appearance: none;
-webkit-appearance: none;
width: 100%;
margin: 0;
cursor: -webkit-grab;
cursor: grab;
outline: none;
background: none;
}
.range > input::-webkit-slider-thumb {
appearance: none;
-webkit-appearance: none;
border-radius: 50%;
height: 24px;
width: 24px;
background: #84566B;
}
.range > input::-moz-slider-thumb {
appearance: none;
border-radius: 50%;
height: 24px;
width: 24px;
background: #84566B;
}
.range > input::-ms-thumb {
appearance: none;
border-radius: 50%;
height: 24px;
width: 24px;
background: #84566B;
}
.range__output {
width: calc(100% - 24px);
position: relative;
}
.range__output > output {
pointer-events: none;
position: absolute;
z-index: 5;
background: #fff;
border-radius: 5px;
padding: 5px 0;
top: -58px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, .2);
left: calc(((var(--value) - var(--min)) / (var(--max) - var(--min))) * 100%);
font-weight: 500;
font-size: 12px;
width: 28px;
height: 14px;
text-align: center;
}
.range__output > output::after {
content: var(--text-value);
}
.range__output > output::before {
content: '';
position: absolute;
top: 100%;
left: 8px;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #fff;
}
<div class="container">
<div class="range" style='--min:1; --max:200; --value:38; --text-value:"38";'>
<input type="range" min="1" max="200" value="38" oninput="this.parentNode.style.setProperty('--value',this.value); this.parentNode.style.setProperty('--text-value', JSON.stringify(this.value))">
<div class='range__output'><output></output></div>
<div class='range__progress'></div>
</div>
</div>