frecuente
¿Es posible hacer un control deslizante HTML5 con dos valores de entrada, por ejemplo, para seleccionar un rango de precios? Si es así, ¿cómo se puede hacer esto?
Gary
He estado buscando un control deslizante dual liviano y libre de dependencias durante algún tiempo (parecía una locura importar jQuery solo para esto) y no parece haber muchos por ahí. terminé modificando Código de @Wildhoney un poco y realmente me gusta.
function getVals(){
// Get slider values
var parent = this.parentNode;
var slides = parent.getElementsByTagName("input");
var slide1 = parseFloat( slides[0].value );
var slide2 = parseFloat( slides[1].value );
// Neither slider will clip the other, so make sure we determine which is larger
if( slide1 > slide2 ){ var tmp = slide2; slide2 = slide1; slide1 = tmp; }
var displayElement = parent.getElementsByClassName("rangeValues")[0];
displayElement.innerHTML = slide1 + " - " + slide2;
}
window.onload = function(){
// Initialize Sliders
var sliderSections = document.getElementsByClassName("range-slider");
for( var x = 0; x < sliderSections.length; x++ ){
var sliders = sliderSections[x].getElementsByTagName("input");
for( var y = 0; y < sliders.length; y++ ){
if( sliders[y].type ==="range" ){
sliders[y].oninput = getVals;
// Manually trigger event first time to display values
sliders[y].oninput();
}
}
}
}
section.range-slider {
position: relative;
width: 200px;
height: 35px;
text-align: center;
}
section.range-slider input {
pointer-events: none;
position: absolute;
overflow: hidden;
left: 0;
top: 15px;
width: 200px;
outline: none;
height: 18px;
margin: 0;
padding: 0;
}
section.range-slider input::-webkit-slider-thumb {
pointer-events: all;
position: relative;
z-index: 1;
outline: 0;
}
section.range-slider input::-moz-range-thumb {
pointer-events: all;
position: relative;
z-index: 10;
-moz-appearance: none;
width: 9px;
}
section.range-slider input::-moz-range-track {
position: relative;
z-index: -1;
background-color: rgba(0, 0, 0, 1);
border: 0;
}
section.range-slider input:last-of-type::-moz-range-track {
-moz-appearance: none;
background: none transparent;
border: 0;
}
section.range-slider input[type=range]::-moz-focus-outer {
border: 0;
}
<!-- This block can be reused as many times as needed -->
<section class="range-slider">
<span class="rangeValues"></span>
<input value="5" min="0" max="15" step="0.5" type="range">
<input value="10" min="0" max="15" step="0.5" type="range">
</section>
-
Lamentablemente, no funciona con el navegador Android 4.0.4 Mobile Safari 4.0. 🙁
– Erik
14/08/2015 a las 19:28
-
@erik Realmente no tengo una buena manera de probar esas versiones, pero me funciona en Android 5.0 con la última versión de Safari (que Google Play dice que es 1.2, así que estoy confundido acerca de su 4.0). Si lo averiguas, me encantaría saberlo.
– Gary
7 sep 2015 a las 16:18
-
¡Eso es realmente inteligente! Me pregunto cómo no está marcado como la respuesta correcta, ya que resuelve el problema con gracia sin ningún tipo de dependencia. Agregar jQuery solo para hacer eso es obviamente una exageración.
– zanona
30 de abril de 2016 a las 10:53
-
@zanona Gracias, pero la respuesta correcta se marcó 4 años antes, por lo que no creo que al OP le importara mucho otra solución.
– Gary
30 de abril de 2016 a las 14:20
-
Realmente me gusta su enfoque y traté de adaptarlo a mi caso de uso, pero tuve que renunciar cuando me di cuenta de que algunas de las especificaciones de diseño que tenía (por ejemplo, colorear la parte “activa” del rango de manera diferente al resto de la pista ) no son posibles de implementar con esto. Así que busqué otra solución y encontré este proyecto realmente genial: freshless.com/nouislider Es libre de dependencias, tiene una API agradable y limpia, es compatible con AMD y ofrece muchas opciones. Hasta ahora estoy bastante contento con él.
– Félix Wienberg
12 mayo 2016 a las 16:55
Martín Buberl
no, el Entrada de rango HTML5 solo acepta una entrada. Te recomendaría usar algo como el Control deslizante de rango de jQuery UI para esa tarea.
-
Gracias por el enlace y la información. Tengo que comprobar si puedo hacer que esto se ejecute en dispositivos móviles.
– frecuente
21 de enero de 2011 a las 8:11
-
Hace algún tiempo… pero me las arreglé para “falsificar” un control deslizante doble colocando dos controles deslizantes exactamente uno encima del otro. Uno que comienza en el valor mínimo y el otro que comienza en el valor máximo. Supongo que eso es hacer trampa, pero… funciona para mí.
– frecuente
23 de julio de 2011 a las 7:43
-
WhatWG al menos está discutiendo su implementación: html.spec.whatwg.org/multipage/…
– kunambi
26 de febrero de 2015 a las 13:32
-
Me gusta ionRangeSlider un poco mejor que el control deslizante jQuery UI: ionden.com/a/plugins/ion.rangeSlider/en.html
– Carlota
18 mayo 2016 a las 14:45
-
Otro enfoque es “falsificar” el control deslizante doble con controles de entrada uno al lado del otro: simple.gy/blog/range-slider-two-handles
– SimplGy
26 de noviembre de 2018 a las 7:38
dario_ramos
llega tarde, pero noUiSlider evita tener una dependencia de jQuery-ui, que la respuesta aceptada no tiene. Su única “advertencia” es que el soporte de IE es para IE9 y más reciente, si IE heredado es un factor decisivo para usted.
También es gratuito, de código abierto y se puede utilizar en proyectos comerciales sin restricciones.
Instalación: descargue noUiSlider, extraiga el archivo CSS y JS en algún lugar del sistema de archivos de su sitio y luego vincule al CSS desde la cabeza y al JS desde el cuerpo:
<!-- In <head> -->
<link href="https://stackoverflow.com/questions/4753946/nouislider.min.css" rel="stylesheet">
<!-- In <body> -->
<script src="nouislider.min.js"></script>
Ejemplo de uso: crea un control deslizante que va de 0 a 100 y comienza a configurarse en 20-80.
HTML:
<div id="slider">
</div>
JS:
var slider = document.getElementById('slider');
noUiSlider.create(slider, {
start: [20, 80],
connect: true,
range: {
'min': 0,
'max': 100
}
});
-
¡¡Fantástico!! ¡Esto es exactamente lo que necesitábamos y está maravillosamente desarrollado! SIN jQuery
– David Taubmann
26 de marzo de 2017 a las 0:51
-
Sin embargo, debería ser bastante fácil agregarlo usted mismo y enviar una solicitud de extracción al proyecto.
– dario_ramos
25 mayo 2018 a las 19:38
-
No profundicé en eso, pero podría usar el control deslizante con el teclado, así que creo que ahora está implementado @ptrin 🙂
–Edu Ruiz
30 sep 2019 a las 14:45
-
Muchas gracias por esta maravillosa respuesta. Nada es tarde, solo comparte tu respuesta cuando la encontraste.
– dhiraj
22 de diciembre de 2020 a las 4:41
-
@ChrisDixon (Lo siento, acabo de ver el comentario) Eso debería ser suficiente, tal vez intente depurar la información sobre herramientas y confirme que están rotas. Si puede solucionarlos, puede enviar un PR al proyecto;)
– dario_ramos
31 de mayo de 2021 a las 4:20
usuario1532132
Claro, puede simplemente usar dos controles deslizantes superpuestos y agregar un poco de javascript (en realidad, no más de 5 líneas) para que los selectores no excedan los valores mínimos / máximos (como en @Garys) solución.
Adjunto encontrará un breve fragmento adaptado de un proyecto actual que incluye algunos estilos CSS3 para mostrar lo que puede hacer (solo webkit). También agregué algunas etiquetas para mostrar los valores seleccionados.
Utiliza JQuery, pero una versión vanillajs no es mágica.
@Actualizar: El siguiente código fue solo una prueba de concepto. Debido a muchas solicitudes, he agregado una posible solución para Mozilla Firefox (sin cambiar el código original). Es posible que desee refractor el código a continuación antes de usarlo.
(function() {
function addSeparator(nStr) {
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + '.' + '$2');
}
return x1 + x2;
}
function rangeInputChangeEventHandler(e){
var rangeGroup = $(this).attr('name'),
minBtn = $(this).parent().children('.min'),
maxBtn = $(this).parent().children('.max'),
range_min = $(this).parent().children('.range_min'),
range_max = $(this).parent().children('.range_max'),
minVal = parseInt($(minBtn).val()),
maxVal = parseInt($(maxBtn).val()),
origin = $(this).context.className;
if(origin === 'min' && minVal > maxVal-5){
$(minBtn).val(maxVal-5);
}
var minVal = parseInt($(minBtn).val());
$(range_min).html(addSeparator(minVal*1000) + ' €');
if(origin === 'max' && maxVal-5 < minVal){
$(maxBtn).val(5+ minVal);
}
var maxVal = parseInt($(maxBtn).val());
$(range_max).html(addSeparator(maxVal*1000) + ' €');
}
$('input[type="range"]').on( 'input', rangeInputChangeEventHandler);
})();
body{
font-family: sans-serif;
font-size:14px;
}
input[type="range"] {
width: 210px;
height: 30px;
overflow: hidden;
cursor: pointer;
outline: none;
}
input[type="range"],
input[type="range"]::-webkit-slider-runnable-track,
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
background: none;
}
input[type="range"]::-webkit-slider-runnable-track {
width: 200px;
height: 1px;
background: #003D7C;
}
input[type="range"]:nth-child(2)::-webkit-slider-runnable-track{
background: none;
}
input[type="range"]::-webkit-slider-thumb {
position: relative;
height: 15px;
width: 15px;
margin-top: -7px;
background: #fff;
border: 1px solid #003D7C;
border-radius: 25px;
z-index: 1;
}
input[type="range"]:nth-child(1)::-webkit-slider-thumb{
z-index: 2;
}
.rangeslider{
position: relative;
height: 60px;
width: 210px;
display: inline-block;
margin-top: -5px;
margin-left: 20px;
}
.rangeslider input{
position: absolute;
}
.rangeslider{
position: absolute;
}
.rangeslider span{
position: absolute;
margin-top: 30px;
left: 0;
}
.rangeslider .right{
position: relative;
float: right;
margin-right: -5px;
}
/* Proof of concept for Firefox */
@-moz-document url-prefix() {
.rangeslider::before{
content:'';
width:100%;
height:2px;
background: #003D7C;
display:block;
position: relative;
top:16px;
}
input[type="range"]:nth-child(1){
position:absolute;
top:35px !important;
overflow:visible !important;
height:0;
}
input[type="range"]:nth-child(2){
position:absolute;
top:35px !important;
overflow:visible !important;
height:0;
}
input[type="range"]::-moz-range-thumb {
position: relative;
height: 15px;
width: 15px;
margin-top: -7px;
background: #fff;
border: 1px solid #003D7C;
border-radius: 25px;
z-index: 1;
}
input[type="range"]:nth-child(1)::-moz-range-thumb {
transform: translateY(-20px);
}
input[type="range"]:nth-child(2)::-moz-range-thumb {
transform: translateY(-20px);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div class="rangeslider">
<input class="min" name="range_1" type="range" min="1" max="100" value="10" />
<input class="max" name="range_1" type="range" min="1" max="100" value="90" />
<span class="range_min light left">10.000 €</span>
<span class="range_max light right">90.000 €</span>
</div>
En realidad, usé mi script en html directamente. Pero en javascript, cuando agrega un detector de eventos de entrada para este evento, proporciona los datos automáticamente. Solo necesita asignar el valor según sus requisitos.
[slider] {
width: 300px;
position: relative;
height: 5px;
margin: 45px 0 10px 0;
}
[slider] > div {
position: absolute;
left: 13px;
right: 15px;
height: 5px;
}
[slider] > div > [inverse-left] {
position: absolute;
left: 0;
height: 5px;
border-radius: 10px;
background-color: #CCC;
margin: 0 7px;
}
[slider] > div > [inverse-right] {
position: absolute;
right: 0;
height: 5px;
border-radius: 10px;
background-color: #CCC;
margin: 0 7px;
}
[slider] > div > [range] {
position: absolute;
left: 0;
height: 5px;
border-radius: 14px;
background-color: #d02128;
}
[slider] > div > [thumb] {
position: absolute;
top: -7px;
z-index: 2;
height: 20px;
width: 20px;
text-align: left;
margin-left: -11px;
cursor: pointer;
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4);
background-color: #FFF;
border-radius: 50%;
outline: none;
}
[slider] > input[type=range] {
position: absolute;
pointer-events: none;
-webkit-appearance: none;
z-index: 3;
height: 14px;
top: -2px;
width: 100%;
opacity: 0;
}
div[slider] > input[type=range]:focus::-webkit-slider-runnable-track {
background: transparent;
border: transparent;
}
div[slider] > input[type=range]:focus {
outline: none;
}
div[slider] > input[type=range]::-webkit-slider-thumb {
pointer-events: all;
width: 28px;
height: 28px;
border-radius: 0px;
border: 0 none;
background: red;
-webkit-appearance: none;
}
div[slider] > input[type=range]::-ms-fill-lower {
background: transparent;
border: 0 none;
}
div[slider] > input[type=range]::-ms-fill-upper {
background: transparent;
border: 0 none;
}
div[slider] > input[type=range]::-ms-tooltip {
display: none;
}
[slider] > div > [sign] {
opacity: 0;
position: absolute;
margin-left: -11px;
top: -39px;
z-index:3;
background-color: #d02128;
color: #fff;
width: 28px;
height: 28px;
border-radius: 28px;
-webkit-border-radius: 28px;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
text-align: center;
}
[slider] > div > [sign]:after {
position: absolute;
content: '';
left: 0;
border-radius: 16px;
top: 19px;
border-left: 14px solid transparent;
border-right: 14px solid transparent;
border-top-width: 16px;
border-top-style: solid;
border-top-color: #d02128;
}
[slider] > div > [sign] > span {
font-size: 12px;
font-weight: 700;
line-height: 28px;
}
[slider]:hover > div > [sign] {
opacity: 1;
}
<div slider id="slider-distance">
<div>
<div inverse-left style="width:70%;"></div>
<div inverse-right style="width:70%;"></div>
<div range style="left:0%;right:0%;"></div>
<span thumb style="left:0%;"></span>
<span thumb style="left:100%;"></span>
<div sign style="left:0%;">
<span id="value">0</span>
</div>
<div sign style="left:100%;">
<span id="value">100</span>
</div>
</div>
<input type="range" value="0" max="100" min="0" step="1" oninput="
this.value=Math.min(this.value,this.parentNode.childNodes[5].value-1);
let value = (this.value/parseInt(this.max))*100
var children = this.parentNode.childNodes[1].childNodes;
children[1].style.width=value+'%';
children[5].style.left=value+'%';
children[7].style.left=value+'%';children[11].style.left=value+'%';
children[11].childNodes[1].innerHTML=this.value;" />
<input type="range" value="100" max="100" min="0" step="1" oninput="
this.value=Math.max(this.value,this.parentNode.childNodes[3].value-(-1));
let value = (this.value/parseInt(this.max))*100
var children = this.parentNode.childNodes[1].childNodes;
children[3].style.width=(100-value)+'%';
children[5].style.right=(100-value)+'%';
children[9].style.left=value+'%';children[13].style.left=value+'%';
children[13].childNodes[1].innerHTML=this.value;" />
</div>
-
¡Eres un genio! Esta es una idea increíble y tu estilo también es genial.
– Puspam
25 oct 2020 a las 20:48
-
He estado buscando durante días, ¡esta es una excelente solución! ¡¡Gracias por compartir!!
– dmboucher
19 de junio de 2021 a las 20:57
-
Ahí va mi 10, pero no sé por qué tengo problemas para arrastrar en mozilla, si agregamos entrada[type=range]::-moz-range-thumb entonces hay problemas con el borde, ¿alguna idea?
–Braian Mellor
10 mayo 2022 a las 22:14
La pregunta era: “¿Es posible hacer un control deslizante HTML5 con dos valores de entrada, por ejemplo, para seleccionar un rango de precios? Si es así, ¿cómo se puede hacer?”
En 2020 es posible crear un Deslizador HTML5 totalmente accesible, nativo, sin jquery con dos pulgares por rangos de precios. Si encontré esto publicado después de haber creado esta solución y pensé que sería bueno compartir mi implementación aquí.
Esta implementación ha sido probada en dispositivos móviles Chrome y Firefox (Android) y Chrome y Firefox (Linux). No estoy seguro acerca de otras plataformas, pero debería ser bastante bueno. Me encantaría recibir sus comentarios y mejorar esta solución.
Esta solución permite instancias múltiples en una página y consta de solo dos entradas (cada una) con etiquetas descriptivas para lectores de pantalla. Puede establecer el tamaño del pulgar en la cantidad de etiquetas de cuadrícula. Además, puede usar el tacto, el teclado y el mouse para interactuar con el control deslizante. El valor se actualiza durante el ajuste, debido al detector de eventos ‘en entrada’.
Mi primer enfoque fue superponer los controles deslizantes y recortarlos. Sin embargo, eso resultó en un código complejo con muchas dependencias del navegador. Luego recreé la solución con dos controles deslizantes que estaban ‘en línea’. Esta es la solución que encontrarás a continuación.
var thumbsize = 14;
function draw(slider,splitvalue) {
/* set function vars */
var min = slider.querySelector('.min');
var max = slider.querySelector('.max');
var lower = slider.querySelector('.lower');
var upper = slider.querySelector('.upper');
var legend = slider.querySelector('.legend');
var thumbsize = parseInt(slider.getAttribute('data-thumbsize'));
var rangewidth = parseInt(slider.getAttribute('data-rangewidth'));
var rangemin = parseInt(slider.getAttribute('data-rangemin'));
var rangemax = parseInt(slider.getAttribute('data-rangemax'));
/* set min and max attributes */
min.setAttribute('max',splitvalue);
max.setAttribute('min',splitvalue);
/* set css */
min.style.width = parseInt(thumbsize + ((splitvalue - rangemin)/(rangemax - rangemin))*(rangewidth - (2*thumbsize)))+'px';
max.style.width = parseInt(thumbsize + ((rangemax - splitvalue)/(rangemax - rangemin))*(rangewidth - (2*thumbsize)))+'px';
min.style.left="0px";
max.style.left = parseInt(min.style.width)+'px';
min.style.top = lower.offsetHeight+'px';
max.style.top = lower.offsetHeight+'px';
legend.style.marginTop = min.offsetHeight+'px';
slider.style.height = (lower.offsetHeight + min.offsetHeight + legend.offsetHeight)+'px';
/* correct for 1 off at the end */
if(max.value>(rangemax - 1)) max.setAttribute('data-value',rangemax);
/* write value and labels */
max.value = max.getAttribute('data-value');
min.value = min.getAttribute('data-value');
lower.innerHTML = min.getAttribute('data-value');
upper.innerHTML = max.getAttribute('data-value');
}
function init(slider) {
/* set function vars */
var min = slider.querySelector('.min');
var max = slider.querySelector('.max');
var rangemin = parseInt(min.getAttribute('min'));
var rangemax = parseInt(max.getAttribute('max'));
var avgvalue = (rangemin + rangemax)/2;
var legendnum = slider.getAttribute('data-legendnum');
/* set data-values */
min.setAttribute('data-value',rangemin);
max.setAttribute('data-value',rangemax);
/* set data vars */
slider.setAttribute('data-rangemin',rangemin);
slider.setAttribute('data-rangemax',rangemax);
slider.setAttribute('data-thumbsize',thumbsize);
slider.setAttribute('data-rangewidth',slider.offsetWidth);
/* write labels */
var lower = document.createElement('span');
var upper = document.createElement('span');
lower.classList.add('lower','value');
upper.classList.add('upper','value');
lower.appendChild(document.createTextNode(rangemin));
upper.appendChild(document.createTextNode(rangemax));
slider.insertBefore(lower,min.previousElementSibling);
slider.insertBefore(upper,min.previousElementSibling);
/* write legend */
var legend = document.createElement('div');
legend.classList.add('legend');
var legendvalues = [];
for (var i = 0; i < legendnum; i++) {
legendvalues[i] = document.createElement('div');
var val = Math.round(rangemin+(i/(legendnum-1))*(rangemax - rangemin));
legendvalues[i].appendChild(document.createTextNode(val));
legend.appendChild(legendvalues[i]);
}
slider.appendChild(legend);
/* draw */
draw(slider,avgvalue);
/* events */
min.addEventListener("input", function() {update(min);});
max.addEventListener("input", function() {update(max);});
}
function update(el){
/* set function vars */
var slider = el.parentElement;
var min = slider.querySelector('#min');
var max = slider.querySelector('#max');
var minvalue = Math.floor(min.value);
var maxvalue = Math.floor(max.value);
/* set inactive values before draw */
min.setAttribute('data-value',minvalue);
max.setAttribute('data-value',maxvalue);
var avgvalue = (minvalue + maxvalue)/2;
/* draw */
draw(slider,avgvalue);
}
var sliders = document.querySelectorAll('.min-max-slider');
sliders.forEach( function(slider) {
init(slider);
});
* {padding: 0; margin: 0;}
body {padding: 40px;}
.min-max-slider {position: relative; width: 200px; text-align: center; margin-bottom: 50px;}
.min-max-slider > label {display: none;}
span.value {height: 1.7em; font-weight: bold; display: inline-block;}
span.value.lower::before {content: "€"; display: inline-block;}
span.value.upper::before {content: "- €"; display: inline-block; margin-left: 0.4em;}
.min-max-slider > .legend {display: flex; justify-content: space-between;}
.min-max-slider > .legend > * {font-size: small; opacity: 0.25;}
.min-max-slider > input {cursor: pointer; position: absolute;}
/* webkit specific styling */
.min-max-slider > input {
-webkit-appearance: none;
outline: none!important;
background: transparent;
background-image: linear-gradient(to bottom, transparent 0%, transparent 30%, silver 30%, silver 60%, transparent 60%, transparent 100%);
}
.min-max-slider > input::-webkit-slider-thumb {
-webkit-appearance: none; /* Override default look */
appearance: none;
width: 14px; /* Set a specific slider handle width */
height: 14px; /* Slider handle height */
background: #eee; /* Green background */
cursor: pointer; /* Cursor on hover */
border: 1px solid gray;
border-radius: 100%;
}
.min-max-slider > input::-webkit-slider-runnable-track {cursor: pointer;}
<div class="min-max-slider" data-legendnum="2">
<label for="min">Minimum price</label>
<input id="min" class="min" name="min" type="range" step="1" min="0" max="3000" />
<label for="max">Maximum price</label>
<input id="max" class="max" name="max" type="range" step="1" min="0" max="3000" />
</div>
Tenga en cuenta que debe mantener el tamaño de paso en 1 para evitar que los valores cambien debido a redibujados/errores de redibujado.
Ver en línea en: https://codepen.io/joosts/pen/rNLdxvK
-
¡Eres un genio! Esta es una idea increíble y tu estilo también es genial.
– Puspam
25 oct 2020 a las 20:48
-
He estado buscando durante días, ¡esta es una excelente solución! ¡¡Gracias por compartir!!
– dmboucher
19 de junio de 2021 a las 20:57
-
Ahí va mi 10, pero no sé por qué tengo problemas para arrastrar en mozilla, si agregamos entrada[type=range]::-moz-range-thumb entonces hay problemas con el borde, ¿alguna idea?
–Braian Mellor
10 mayo 2022 a las 22:14
2022 – Solución accesible – Solución de 30 segundos para implementar
Esta solución se basa en esta respuesta de @JoostS. La accesibilidad es algo en lo que ninguna de las respuestas se ha centrado y eso es un problema, por lo que me basé en la respuesta anterior haciéndola más accesible y extensible ya que tenía algunas fallas.
El uso es muy simple:
- Utilizar el CDN o aloja el script localmente:
https://cdn.jsdelivr.net/gh/maxshuty/accessible-web-components/dist/simpleRange.min.js
- Agregue este elemento a su plantilla o HTML:
<range-selector min-range="0" max-range="1000" />
- Engánchate escuchando el
range-changed
evento (o lo que seaevent-name-to-emit-on-change
pasas adentro)
Eso es. Ver la demostración completa aquí. Puede personalizarlo fácilmente simplemente aplicando atributos como inputs-for-labels
utilizar entradas en lugar de etiquetas, slider-color
para ajustar el color, ¡y mucho más!
Aquí hay un violín:
window.addEventListener('range-changed', (e) => {console.log(`Range changed for: ${e.detail.sliderId}. Min/Max range values are available in this object too`)})
<script src="https://cdn.jsdelivr.net/gh/maxshuty/accessible-web-components@latest/dist/simpleRange.min.js"></script>
<div>
<range-selector
id="rangeSelector1"
min-label="Minimum"
max-label="Maximum"
min-range="1000"
max-range="2022"
number-of-legend-items-to-show="6"
/>
</div>
<div>
<range-selector
id="rangeSelector1"
min-label="Minimum"
max-label="Maximum"
min-range="1"
max-range="500"
number-of-legend-items-to-show="3"
inputs-for-labels
/>
</div>
<div>
<range-selector
id="rangeSelector2"
min-label="Minimum"
max-label="Maximum"
min-range="1000"
max-range="2022"
number-of-legend-items-to-show="3"
slider-color="#6b5b95"
/>
</div>
<div>
<range-selector
id="rangeSelector3"
min-label="Minimum"
max-label="Maximum"
min-range="1000"
max-range="2022"
hide-label
hide-legend
/>
</div>
Decidí abordar los problemas de la respuesta vinculada como las etiquetas usando display: none
(malo para a11y), sin enfoque visual en el control deslizante, etc., y mejore el código limpiando los detectores de eventos y haciéndolo mucho más dinámico y extensible.
creé esto diminuto biblioteca con muchas opciones para personalizar colores, nombres de eventos, conectarse fácilmente, hacer que las etiquetas accesibles sean compatibles con i18n y mucho más. Aquí está en un violín si quieres jugar.
Puede personalizar fácilmente la cantidad de elementos de la leyenda que muestra, ocultar o mostrar las etiquetas y la leyenda, y personalizar los colores de todo, incluido el color de enfoque como este.
Ejemplo usando varios de los accesorios:
<range-selector
min-label="i18n Minimum Range"
max-label="i18n Maximum Range"
min-range="5"
max-range="555"
number-of-legend-items-to-show="6"
event-name-to-emit-on-change="my-custom-range-changed-event"
slider-color="orange"
circle-color="#f7cac9"
circle-border-color="#083535"
circle-focus-border-color="#3ec400"
/>
Luego en tu script:
window.addEventListener('my-custom-range-changed-event', (e) => { const data = e.detail; });
Finalmente, si ve que falta algo que necesita, lo hice muy fácil de personalizar esta biblioteca.
Simplemente copie Este archivo y en la parte superior se puede ver cssHelpers
y constants
objetos que contienen la mayoría de las variables que probablemente desee personalizar aún más.
Desde que construí esto con un Componente web nativo he aprovechado disconnectedCallback
y otros ganchos para limpiar los detectores de eventos y configurar las cosas.
Hice un componente basado en CSS para esto: Demostración de código abierto
– vsync
25 de junio de 2021 a las 11:48
Hasta ahora, de todas estas respuestas, creo que solo una es accesible y otra es un poco accesible aunque he comentado esa respuesta con sus problemas de accesibilidad. Si está leyendo esto, entonces ya es al menos 2022 y le imploro que encuentre una solución totalmente accesible (
ctrl+f
“accesibilidad”)– maxshuty
3 de enero de 2022 a las 3:37
Agregando a los ejemplos más recientes de cómo se puede hacer esto: Deslizador de rango dual nativo
– SketchyTech
19 de agosto de 2022 a las 9:13