Entrada nativa de rango dual
(muffinman.io)@stanko/dual-range-inputcrea un slider de rango dual combinando dos inputs range nativos de HTML, aprovechando tal cual la interacción y accesibilidad predeterminadas del navegador- La implementación se centra en unos 50 líneas de JavaScript para sincronizar los valores de entrada y CSS, por lo que es más simple que los enfoques tradicionales que vuelven a crear manualmente el arrastre y la accesibilidad
- Los dos inputs actualizan su
min,maxy ancho según el punto medio de los valores seleccionados, y al hacer clic en la pista el thumb más cercano se mueve a ese valor - Como la pista del input range es más corta que el ancho real del input, se suma el ancho del thumb al cálculo y el padding del wrapper absorbe el ancho sobrante
- El tema puede ajustarse con variables CSS y gradients, lo que permite sobrescribir el color del rango seleccionado, el tamaño del thumb, el color de la pista y más
Slider dual hecho con range input nativo
@stanko/dual-range-inputimplementa una entrada de rango dual colocando dos inputs range de HTML uno junto al otro- Aquí “nativo” no significa un único control del navegador, sino que usa dos inputs range para conservar la interacción predeterminada del navegador y las funciones de accesibilidad
- La implementación consiste en unos 50 líneas de JavaScript que sincronizan los inputs y CSS para el acabado visual
- El punto de partida fue la necesidad de una UI para ajustar el valor mínimo y máximo de parámetros en una herramienta de dibujo generativo
- Había dos requisitos
- usar inputs range de HTML nativos
- al hacer clic en la pista, el thumb más cercano al punto pulsado debía moverse a ese valor
Sincronización de valores y manejo de clics
- Cuando cambia uno de los dos inputs, la librería calcula el punto medio entre los dos valores seleccionados
- configura los atributos
minymaxde cada input según ese punto medio - también actualiza el ancho de ambos inputs tomando como referencia el punto medio
- configura los atributos
- Como los inputs se redimensionan para encontrarse en el punto medio, al hacer clic entre ambos thumbs se mueve el thumb más cercano a la posición del clic
- si la cantidad de pasos entre ambos thumbs es impar, tiene prioridad el input usado más recientemente
Cálculos CSS y estilos
- La pista del input range es más corta que el ancho completo del input, y el navegador deja espacio a ambos lados para que el thumb no sobresalga
- si se divide el ancho del input simplemente en 25% y 75%, la proporción real de la pista no coincide
- la implementación suma
--dri-thumb-widthal ancho de cada input y agrega padding al wrapper para alojar el ancho extra
- El estilo usa las capacidades de CSS del navegador para personalizar los inputs range
- da estilo a la pista y al thumb, y evita que aparezca border radius en la parte central donde se unen ambas pistas
- El tema puede crearse con sobrescritura de variables CSS
- entre las variables principales están
--dri-height,--dri-thumb-width,--dri-thumb-color,--dri-track-color,--dri-track-filled-color,--dri-track-border-radiusy otras
- entre las variables principales están
- El rango seleccionado se pinta con un gradient de CSS
- la posición del gradient se define con la variable
--dri-gradient-position - el código actualiza también esta variable al modificar el ancho de los inputs
- la posición del gradient se define con la variable
- Esta implementación prioriza aprovechar elementos nativos siempre que sea posible, en lugar de reconstruir el arrastre y la accesibilidad con una librería personalizada
1 comentarios
Comentarios en Hacker News
Creo que este tipo de slider siempre debería permitir arrastrar también la zona central. O sea, si tomas el centro, ambos controles deberían moverse al mismo tiempo
Por cierto, Unity lo maneja así: https://docs.unity3d.com/StaticFiles/ScriptRefImages/EditorG...
“Siempre” quizá sea una palabra demasiado fuerte
Soy el autor. Qué gusto ver esto en HN
Vi que empezaron a dejar issues y reportes de bugs aquí, pero ya es tarde por este lado, así que lo revisaré mañana
Lo hice porque lo necesitaba para trabajo con imágenes generativas, y prefiero ver cómo cambia la imagen mientras arrastro un slider en lugar de meter números
Traté de mantenerlo lo más minimalista posible
Ahora mismo uso SwiftUI, donde casi es demasiado fácil crear tus propios componentes. Pero como explicó el autor, eso no siempre es lo mejor, y los componentes nativos muchas veces vienen bastante completos
También probé el post en Firefox para iOS, que es un navegador medio peculiar, y funcionó bien. Está muy bien hecho
Me topé con un bug apenas al probarlo. Si arrastras el slider a 100 - 100 y luego intentas dejarlo en 99 - 99, no se puede
Tampoco puedes llegar desde 99 - 100, ni desde 98 - 99. La única forma de llegar a 99 - 99 es bajar primero el límite inferior por debajo de 98
Si desde 98 - 99 bajas a 97 - 99, entonces sí puedes llegar a 99 - 99
Este bug puede pasar en cualquier parte; 99 - 99 solo fue el caso más fácil de reproducir por estar cerca del extremo del slider. En general, en cualquier estado X - X, si mueves un extremo un paso, no puedes arrastrar el otro extremo hacia ese hueco. Para cerrar esa distancia, antes tienes que alejar más el otro extremo
mousedown, sino hasta que ya empezó a mover el sliderGracias por el reporte, lo voy a corregir
En cambio, hay otro bug visual. Si empiezas en 23-25 y arrastras a 24-25, el tirador derecho que está en 25 se mueve unos cuantos píxeles. Si luego regresas el tirador izquierdo a 23, el derecho también vuelve a su lugar
¡Está genial! Siempre he pensado que al input HTML le hace falta una implementación de rango de dos valores, porque tiene bastante sentido
Por ejemplo, hay casos de uso como “quiero filtrar productos con al menos X widgets y como máximo Y widgets”
Pero encontré un bug en Firefox que quería señalar. Cada vez que haces clic en el control mínimo o máximo, el valor cambia un paso hacia arriba o hacia abajo
Si intentas hacer clic justo en el centro del tirador, el valor no cambia, pero si haces clic apenas a la izquierda, baja un paso, y si haces clic apenas a la derecha, sube
Lo esperable sería que el valor solo cambie cuando hagas una acción explícita de cambio, es decir, mover realmente el puntero del mouse mientras mantienes presionado el botón
Firefox interpreta ese clic como si hubieras hecho clic directamente en la pista. Esta librería no interviene en eso; simplemente es el comportamiento de Firefox
El hecho de que funcione con teclado es excelente. Funciona correctamente y hasta puedes retroceder manteniendo presionado Shift-Tab
Está realmente muy bien hecho, y aunque sea un detalle pequeño, se agradece que esa interacción esté implementada de forma correcta
En el sistema de diseño de nuestra empresa, un becario hizo una prueba de concepto parecida, colocando los controles uno al lado del otro, pero seguía apareciendo un efecto de saltos de píxeles en uno de los inputs y al final no logramos hacerlo bien
Así que un segundo becario propuso la solución de usar 2 input range superpuestos
Cada vez que necesitaba un input de rango usaba el slider de jQuery UI, y tenía que meter jQuery y jQuery UI a la página solo por ese slider. Esto está muy bien
Edit: ¿habría posibilidad de publicar también un archivo JS normal listo para usar, en vez de solo un módulo ESM?
"export default"https://cdn.jsdelivr.net/npm/@stanko/dual-range-input@0.9.8/...
Y no olvides el CSS
https://cdn.jsdelivr.net/npm/@stanko/dual-range-input@0.9.8/...
No sé si se pueden reportar bugs aquí. En los dos primeros ejemplos, los controles interceptan la interacción táctil y bloquean el scroll. Los tres ejemplos posteriores no hacen eso
Como efecto secundario, no puedes arrastrar hacia arriba para intentar ver la etiqueta debajo del dedo, y la página se desplaza haciendo que la etiqueta se quede debajo del dedo todo el tiempo
Me da curiosidad qué navegador y sistema operativo estás usando. Como esta librería usa inputs nativos, no hace nada relacionado con bloquear el scroll
En mi iPhone, todos los elementos
input[type=range], con o sin estilos, bloquean el scroll[1] https://github.com/Stanko/dual-range-input/issues
Lo de “nativo” es debatible. La librería usa dos range inputs HTML nativos, así que dicen que se conservan las interacciones nativas y las funciones de accesibilidad, pero para mí el criterio es claro
Si necesita JavaScript para funcionar como fue diseñado, entonces ya no es nativo
Aun así, entiendo lo que quería decir el autor. En vez de implementar a mano un montón de
divmovidos por JS, compuso sliders normales, así que se acerca mucho más a una solución nativa. Si no puedes reemplazar JavaScript con CSS ingenioso, probablemente sea lo más cercano posibleIndependientemente de si es nativo o no, este tipo de widget es muy útil cuando está disponible, y ese espacio ha tenido pocas implementaciones
Antes del atributo
popover, directamente no se podían abrir sin JavaScriptY también existen métodos nativos de JavaScript vanilla que vale la pena distinguir de librerías que ni siquiera usan las herramientas internas del navegador, como en la validación de formularios
Cuando hice https://spodj.intermer.net/, andaba buscando algo así
Terminé usando React de forma medio improvisada para conseguir la funcionalidad que necesitaba, porque no soy muy bueno en frontend