No necesitas JavaScript para eso
(htmhell.dev)- Al implementar funcionalidades web, conviene revisar primero las tecnologías menos potentes en el orden HTML, CSS y JavaScript, ya que eso ayuda a reducir fallas de carga y problemas de accesibilidad
- JavaScript puede controlar directamente el comportamiento del navegador, pero por los recursos adicionales que requiere y la posibilidad de errores, es fácil que los usuarios de teclado y de tecnologías de asistencia queden excluidos
- Funciones que antes requerían JavaScript, como interruptores con checkbox,
datalist,input type="color",details/summaryydialog, ahora en gran parte ya pueden lograrse con funcionalidades nativas de HTML/CSS - Las capacidades declarativas de HTML y CSS permiten que el navegador se encargue del comportamiento nativo, las preferencias del usuario y la accesibilidad, ofreciendo mejores valores predeterminados
- Aunque una implementación conocida en JavaScript siga funcionando, conviene revisar periódicamente las alternativas modernas en HTML/CSS y, al hacer cambios, acompañarlos con pruebas de accesibilidad
La regla del menor poder
- La regla del menor poder es un principio de desarrollo web que indica elegir el lenguaje menos potente capaz de cumplir el objetivo
- En la web, normalmente se aplica considerando primero HTML antes que CSS, y CSS antes que JavaScript
- JavaScript es la más versátil de las tres tecnologías, pero también la más pesada
- Puede romperse
- Puede fallar al cargar
- Requiere recursos adicionales para descargarse, analizarse y ejecutarse
- Es fácil excluir a usuarios de teclado y a usuarios de tecnologías de asistencia
- HTML y CSS funcionan de forma declarativa, a diferencia del JavaScript imperativo
- El desarrollador le dice al navegador qué quiere, y el navegador decide cómo implementarlo
- El navegador puede elegir una forma de procesamiento más eficiente
- Cuando el navegador se encarga de las funciones de HTML/CSS, puede haber ventajas en rendimiento, comportamiento nativo, respuesta a las preferencias del usuario y accesibilidad
- Aun así, la accesibilidad no siempre queda garantizada automáticamente
Funciones que antes requerían JavaScript
- Los fabricantes de navegadores y quienes escriben las especificaciones han ido trasladando a CSS y HTML funciones que hasta hace unos años requerían JavaScript
- Como la web mantiene la compatibilidad hacia atrás, una forma de implementación que aprendiste una vez suele quedarse en tu caja de herramientas y reutilizarse una y otra vez
- Aunque creas que cierta función necesita JavaScript, vale la pena comprobar de vez en cuando si todavía es así, porque eso puede ayudarte a crear sitios web mejores
Interruptores personalizados con checkbox
- Un interruptor personalizado puede implementarse con un checkbox nativo y CSS, en lugar de usar un
div, un controladoronclicky estado interno - Si colocas un
<input type="checkbox">dentro de un<label>, el navegador conecta ambos- Hacer clic en cualquier parte de la etiqueta activa o desactiva el checkbox
- No hace falta un controlador
onclickaparte
appearance: nonedetiene el renderizado predeterminado de los controles de formulario del navegador y permite estilizarlo manualmente- El propio
inputpuede decorarse como fondo del interruptor ::beforepuede usarse como el punto interno que se mueve al alternar
- El propio
- La pseudoclase
:checkedpermite cambiar el color de fondo y la posición de::beforesegún el estado marcado - Para usuarios de teclado, hace falta un indicador de foco
- No es buena idea ocultar el foco con
outline: none :focus-visiblepermite mostrar un anillo de foco agradable solo durante la interacción con tecladooutline-offsetpermite ajustar el contorno de foco hacia afuera o hacia adentro del elemento
- No es buena idea ocultar el foco con
input:focus { outline-color: transparent; }hace transparente el contorno en condiciones normales, pero en modo de alto contraste puede volver a mostrarse con el color elegido por el usuario- Puedes ver más sobre el modo de colores forzados en forced colors explained
Autocompletado nativo con datalist
datalistes una función de sugerencias automáticas integrada en el navegador que muestra una lista de opciones mientras el usuario escribe- La estructura es simple
- Se coloca un
idy variosoptiondentro del elementodatalist - Se conecta con el atributo
listdelinput
- Se coloca un
- Cuando el usuario escribe, el navegador muestra un menú desplegable y filtra automáticamente las opciones según el contenido ingresado
- Como sigue siendo un campo de entrada normal, también se puede escribir directamente un valor que no esté en la lista
- Después de seleccionar el campo, se puede recorrer la lista con las teclas de flecha o hacer clic en el ícono desplegable que agrega el navegador para ver todas las opciones
Selector de color nativo con input type="color"
- Con una sola línea,
<input type="color">permite usar el selector de color nativo del navegador - Puede reemplazar muchas interfaces en canvas y sliders hechas con JavaScript
- En navegadores Chromium, el selector de color nativo permite elegir colores no solo dentro del sitio, sino en cualquier parte de la pantalla
- Como no todos los usuarios pueden usar el selector de color del navegador, conviene ofrecer también otra forma de elegir el color, por ejemplo mediante una entrada de texto común
Acordeones con details y summary
- Los elementos
detailsysummaryofrecen un acordeón nativo del navegador para contraer y expandir contenido - El comportamiento básico es simple
- El contenido dentro de
details, exceptosummary, queda oculto - Cuando el usuario hace clic en
summary, se muestra el resto del contenido
- El contenido dentro de
- El atributo
opendefine el estado inicialmente abierto- No es un valor fijo después de la interacción; si el usuario abre o cierra, el estado cambia
summary::markerpermite estilizar el marcador triangular predeterminado- Su contenido puede cambiarse por emoji u otros elementos
- Se pueden ajustar el color de fondo, la imagen de fondo, el tamaño de fuente, etc.
- Muchas propiedades CSS no funcionan, y hay limitaciones para estilos como colocarlo en una posición completamente distinta
- En Safari se necesita el pseudoelemento
::-webkit-details-marker - Cambiar el contenido del marcador puede afectar la forma en que las tecnologías de asistencia anuncian el acordeón, así que puedes consultar details/summary inconsistencies
summaryes clicable, pero por defecto no muestra un cursor tipo puntero como un enlace ni parece un botón, por lo que conviene agregar estados hover y focus para dejar claro que se puede pulsar
Modales con dialog
alert(),prompt()yconfirm()permiten avisar algo al usuario o pedir confirmación, pero bloquean el hilo principal y son difíciles de estilizar para ajustarlos al diseño- Si construyes tu propio diálogo, manejar la accesibilidad se vuelve complejo
- Hay que mantener el foco dentro del diálogo
- Hay que indicar que es modal
- Hay que evitar que el usuario salga accidentalmente
- Puede entrar en conflicto con widgets que usan un
z-indexmuy alto
- El elemento
dialogdel navegador ofrece diálogos nativos - Actualmente todavía se necesita JavaScript para abrir un diálogo
- Se está trabajando en cambios para abrirlo sin JavaScript, pero todavía no están completamente especificados ni implementados
- Se puede abrir con la función
showModal()
dialogse abre en la top layer- La top layer es una capa nueva separada del HTML
- Los elementos en esta capa siempre se muestran por encima, sin importar el
z-indexni el anidamiento de contextos de apilamiento - Para entender el concepto, puedes consultar Top layer en MDN
dialogno ofrece una interfaz de cierre predeterminada, así que hay que agregarla manualmente- Si se envía un
form method="dialog", el navegador cierra el diálogo - Si a dos botones de envío se les da un
valuedistinto, puede usarse como un diálogo de confirmación - En el evento
close, puedes leerdialog.returnValuepara saber qué botón pulsó el usuario - Los datos adicionales del formulario pueden leerse con FormData
- Si se envía un
dialog::backdropes la capa entre el diálogo y el resto de la página- Puedes oscurecer o desenfocar el fondo para dirigir la atención del usuario al diálogo
- Como el navegador se encarga de su colocación, no hace falta gestionar manualmente el scroll, los elementos fijos ni los cambios de tamaño de la ventana
Funciones posibles con menos JavaScript
- Hay más funciones en las que se puede reducir el uso de JavaScript
- Scroll suave nativo con
scroll-behavior: smooth- con la condición de usarlo solo cuando
prefers-reduced-motion: no preferencese cumpla
- con la condición de usarlo solo cuando
- Carruseles nativos con
scroll-snap - Elementos “in-view” con
position: sticky - Container queries
- Scroll suave nativo con
- También hay funciones que llegarán más adelante
- Animaciones basadas en scroll
- Diseños Masonry con
grid-template-rows: masonrysinmasonry.js - Un
selectcompletamente estilizable mediante el nuevo elementoselectlist - El selector
:has(), que puede reducir una categoría de código de selección en JavaScript
- Puedes ver más sobre esto en la charla Stop Using JavaScript for That: Moving Features from JS to CSS and HTML.
- Al cambiar una implementación ya probada por una forma nueva, especialmente, hay que probar la accesibilidad para no dejar a nadie fuera
1 comentarios
Comentarios de Hacker News
Lo que falta en este artículo es que la razón para usar JavaScript en estos casos es que ofrece mejor compatibilidad.
El JavaScript nuevo se puede transpilar, pero hacer polyfill de funciones faltantes de CSS o HTML es mucho más difícil y, en algunos casos, imposible. Además, esos polyfills al final también usan JavaScript.
Incluso en MDN hay muchas advertencias de probar a fondo
appearance, inclusoappearance: none. Si solo das soporte a navegadores modernos puede importar menos, pero las versiones antiguas de Safari siguen circulando más tiempo de lo que uno cree.datalistno hace absolutamente nada en Firefox Android, y para mí solo aparece como un campo de entrada sin siquiera sugerencias.El selector de color es genial, pero extremadamente no estándar, lo cual es fatal para la mayoría de los negocios. No es solo que los diseñadores se quejen: soporte al cliente también tiene más dificultades para ayudar a los usuarios. Chromium incluso permite tomar un color de la página o elegir uno arbitrario, pero Firefox Android solo ofrece algo como arcoíris, gris, blanco y negro.
El propio artículo también reconoce las inconsistencias de
detailsydialog. Ojalá algún día dejen de usarse los navegadores que no soportan estas funciones, o que no las soportan de forma consistente entre sí, pero por ahora creo que estos elementos solo se usarán en proyectos personales donde se pueda controlar por completo qué navegadores se soportan.En iPhone, al tocar el botón aparece el selector de color nativo real del sistema. Es el mismo control que proporciona el OS y que se ve en varias apps, y lo prefiero muchísimo más que uno hecho a medida.
Prefiero muchísimo más la web sin JavaScript, y además afecta la batería de la laptop por horas. Algunos sitios no son compatibles con esto y solo renderizan una página en blanco, o se quejan de que necesitan JavaScript para mostrar texto.
En cambio Amazon incluso tiene una réplica de su sitio de e-commerce sin JavaScript, lo que demuestra que algo así de enorme es posible sin JavaScript.
dialogya tiene una cobertura de soporte bastante amplia, y los polyfills para ese pequeño porcentaje de usuarios que usan Firefox o Safari de 2021 también son bastante aceptables.Si vas a crear un modal, lo recomiendo mucho; las mejoras de accesibilidad son excelentes.
En mi trabajo anterior discutimos activamente este problema y decidimos usar una implementación en JS en lugar de cosas como
datalist. En particular probamosdatalist, pero los resultados eran tan inconsistentes que tuvimos que descartarlo.Al final, por las inconsistencias entre navegadores, incluso terminamos dejando de dar soporte a todo lo que no fuera Chrome.
Los ejemplos en HTML pueden verse mal en navegadores antiguos, pero el contenido real sigue ahí. Con JS simplemente no hay nada. Rompe por completo la accesibilidad.
Con HTML, un lector de pantalla al menos puede leerlo, pero el contenido generado con JS lo impide. Cuando JS no puede ejecutar JS, ningún polyfill ni otro JS puede rescatar a JS. Tiene que “funcionar” desde el principio para ser aceptable en accesibilidad, y en ese caso el argumento original deja de tener sentido.
No conocía
Datalist, pero al menos en Chrome Android no parece funcionar correctamente.Las opciones sí aparecen en el área del teclado donde salen las sugerencias de autocompletado: https://imgur.com/a/Ecb4503
Es la primera vez que veo algo así en un control de formulario de una UI web móvil, y no lo había visto salvo cuando una app de autocompletado de contraseñas usa el mismo espacio.
No está mal. Es mucho mejor que desplazarse torpemente por un dropdown personalizado en JS hecho a medias, pero no estoy seguro de que un usuario común vaya a descubrir cómo usarlo. Por eso creo que en móvil, en la práctica, no tiene mucho futuro.
En Firefox Android ni siquiera está soportado: https://caniuse.com/?search=datalist
datalist?Referencia: https://adrianroselli.com/2023/06/under-engineered-comboboxe...
JavaScript está bastante bien estandarizado, pero HTML y CSS lo están menos en comparación.
autocomplete="off"al elementoinputcambia el comportamiento.De todos modos, es necesario para usar
datalistcorrectamente. Si no, el historial de selección de valores se añade a la lista desplegable. Lo observé en Chromium.Además, en algunas situaciones, como cuando hay un valor predeterminado establecido,
datalisttodavía necesita JS. Dejé documentados workarounds y notas de comportamientos particulares por navegador en el código del nuevo sitio web de LibreOffice: https://git.libreoffice.org/infra/libreofficeorg/+/835a5cc59...La buena noticia es que un desarrollador de Firefox planea revisar mejoras al comportamiento de
datalist, así que quizá sea posible mostrar la lista con un solo clic.En mi caso, las opciones aparecen en el área sobre el teclado donde normalmente se muestran sugerencias de palabras.
datalistaparezcan dentro del teclado es un cambio de los últimos meses.Antes era “normal”, pero parece que alguien quiso cambiarlo solo por cambiarlo.
Usar desplazamiento suave nativo con
scroll-behavior: smoothdebería hacerse, por favor, solo de forma limitadaEn más casos de los que uno cree no es una buena idea, y suele tener efectos secundarios no deseados
Dicen que se puede crear un carrusel nativo con
scroll-snap, pero los carruseles siguen siendo una mala idea, así que el ámbito legítimo de uso descroll-snapes extremadamente limitadoLas páginas que usan animaciones basadas en el scroll por lo general mejoran si se les quita eso
El desplazamiento suave es un buen ejemplo. La API nativa permite que el usuario lo interrumpa cuando quiera. La mayoría de las implementaciones en JS se traban horriblemente y hacen sufrir al usuario
Puedes criticar todo lo que quieras las decisiones de diseño, pero si no presentas razones reales para decir que “los carruseles siguen siendo malos”, es difícil esperar que te hagan caso
Pero la página de inicio de Amazon usa carruseles de forma muy visible, y tengo entendido que Amazon prueba sin piedad variantes de su página de inicio con A/B testing. Entonces es posible que los carruseles hayan salido bien en las pruebas, y es ambiguo decir que realmente son “malos” en algún sentido universal u objetivo
Normalmente, justo después de implementar anclas al estilo de una tabla de contenidos, al menos suelo agregarlo
Sorprende que en 2023 todavía estemos peleando por los formularios y la UX general donde el usuario ingresa datos
Basta ver los comentarios sobre
datalisty los selectores de color; no entiendo por qué esto todavía no es un área resueltaAntes hubo un intento de resolverlo de una vez con XForms, pero no se implementó en los navegadores
En cambio, casi todos los frameworks de componentes CSS/JS ofrecen cada uno su propio conjunto limitado de elementos de formulario con semánticas distintas
Parece que nos pasaremos la vida implementando a mano controles básicos de UI
Que “no está resuelto” solo parece así porque algunas personas, por su extraña obsesión con evitar JavaScript, intentan encajar a la fuerza alternativas a medio cocinar
Si te quedas con tecnología aburrida y básica, ya están resueltos. Pero si insistes en resolverlos otra vez con React, luego otra vez con React hooks, y así infinitamente, entonces pasan a no estar resueltos
La intención no es algo que pueda determinarse programáticamente, así que en ciertas situaciones no podemos tener funciones elegantes
En el último formulario complejo en el que trabajé, tuve que hacer que un evento de clic provocara el envío del formulario de forma bastante directa para que el navegador lo permitiera
Nunca pedí una forma de enviar colores a través de una página web
Si usas
detailsen lugar de JavaScript, Ctrl+F puede buscar dentro y abrirloUn acordeón hecho con JavaScript no puede abrirse así
hidden="until-found"eso también es posible en acordeones basados en JS u otro contenido oculto, pero lamentablemente por ahora solo está en navegadores basados en Chromium: https://developer.chrome.com/articles/hidden-until-found/Estoy de acuerdo con la mayoría, pero no he usado lo suficiente
dialogcomo para opinar, y creo quedatalistno es una opción válida si no es para herramientas internasEs feo, tiene capacidades limitadas y no se le puede aplicar estilo. Ese es el problema de la mayoría de los argumentos de “simplemente usa lo incorporado”. Lo mismo pasa con el
date pickerNo solo los valores predeterminados son malos, sino que tampoco puedes cambiarlos aunque quieras. Si te topas con una de las muchas paredes al cambiar el estilo o el comportamiento, por ejemplo querer que la semana empiece en lunes, no puedes. Entonces la opción suele ser una biblioteca de reemplazo completa usando JS
Estoy a favor de usar opciones más ligeras y coincido con la jerarquía HTML > CSS > JS, pero para tener una UI agradable y todas las funciones que quieres, a veces JS es la única respuesta
datalistpodría servirFuncionaba bien hasta el momento en que quise mostrar opciones que no empezaran estrictamente con lo escrito. Por ejemplo, si hay un error tipográfico en la entrada, no se muestra ninguna opción
Como no había forma de forzar que se mostraran todos los elementos, terminé eligiendo una lista ordenada
Cuando empecé en desarrollo web, los cambios tardaban hasta 10 años. IE6 también nos tenía atrapados a todos, pero el w3c de entonces tampoco tenía mucho poder. Ahora los cambios son rápidos
El año que viene, tal vez sea posible dar estilo a
datalistsin prefijos en los tres navegadores principales, pero si estás atado a una solución JS personalizada, el negocio no pagará el costo de reconstruirlaSi extiendes funciones nativas con JS, cuando el soporte sea suficiente podrás quitar el JS a bajo costo. Usa ahora los controles nativos donde sean aceptables y aplica JS como si fuera un polyfill
input[type=date]es mejor que no estén bajo control del desarrolladorEl calendario apropiado que se muestra debería depender del locale. La plataforma del usuario ya tiene la capacidad de configurarlo y mostrarlo de la forma que es más probable que el usuario pueda usar eficazmente
El selector de fecha de la plataforma es mejor que alguna cosa rara hecha a mano
Ese botón de alternar está buenísimo
Parece que los desarrolladores frontend de memes se están enojando con este artículo, pero el punto central es correcto. ¿Por qué se hacen tantos sitios absurdos con JS? Si la gente siguiera un solo estándar como HTML, todo podría ser consistente, y cosas como la accesibilidad o la traducción también serían fáciles de ajustar
Hoy en día entras a un sitio y, como cargan todo dinámicamente en una sola página, ni siquiera funciona el botón de atrás
Y sigue existiendo el problema de “esperar a que la gente actualice”, en el que pueden pasar años desde que se introduce una función nueva hasta que tenga soporte lo bastante amplio como para ser útil
En general estoy de acuerdo en que hay muchas implementaciones malas y artilugios complejos en JavaScript. Hay bastantes soluciones estandarizadas para mantener la función de volver atrás incluso con contenido dinámico, y tengo entendido que los frameworks web populares las soportan por defecto
Leí los comentarios principales, pero no veo mucho que pueda llamarse enojo; solo veo gente planteando puntos válidos sobre el soporte de los navegadores
Es un paso en la dirección correcta, pero CSS también es otra herramienta que los “artistes” de los que hablaba Philip Greenspun usan indebidamente para crear páginas difíciles de leer
No soy partidario de Gemini, pero básicamente todos los aspectos del layout y la tipografía deberían volver al navegador y quedar bajo control del usuario. Los diseñadores han demostrado una y otra vez que no se puede confiar en ellos para eso
Me gusta la intención, el switch está genial y
summary/detailstambién son útiles a vecesPero el elemento
datalistcasi nunca es una opción realista para algo que vaya más allá de un juguete o prototipoMis cosas favoritas de “CSS alcanza sin JS” son los drawers de barra lateral y los carruseles
La biblioteca de componentes TailwindCSS llamada DaisyUI también tiene componentes listos para usar
https://daisyui.com/components/drawer/
https://daisyui.com/components/carousel/
El drawer y el resto del contenido que aparece en la página deben anunciarse, y junto al control debería estar el estado
aria-expandedSigue siendo una pregunta real. Tal vez haya una forma, o tal vez los desarrolladores colectivamente piensen que no es importante. Aunque los auditores no estarían de acuerdo
Creo que los autores de estos frameworks subestiman muchísimo cuántas pruebas hacen falta para que realmente funcionen en todos los navegadores
Con tantos componentes y, además, la posibilidad de usar temas, tampoco es seguro que se puedan corregir sin romper temas y aplicaciones existentes
components/carousel/¿Qué diablos es snap y cómo funciona? Mi pantalla no responde a clics con el dedo
No creo que un modo de interacción desconocido sea una buena base para recomendar una biblioteca de elementos de UI