Introducción
Recientemente me he encontrado con la necesidad de elaborar proyectos web que puedan ser accesibles tanto con Javascript activado como sin el. Esta necesidad viene del progresivo auge de los dispositivos móviles en los que, en ocasiones, no podemos ejecutar scripts de forma nativa o simplemente los usuarios lo han desactivado por culpa de absurdas dañinas campañas virales.
Una solución interesante es adoptar el enfoque de grandes empresas como Yahoo!: siguiendo una idea que ya tratamos en su día con la biblioteca Modernizr.js, se trata de añadir determinadas clases a nuestro DOM indicando las capacidades que cumple un navegador. De esta forma, podemos mediante las hojas CSS reformatear el contenido según nos convenga.
Aunque Modernizr es capaz además de consultar el soporte CSS3 detectar si Javascript está activado (gracias @dzignus), podemos crear nuestra propia solución para no tener que recurrir a dependencias.
El script
La solución a este problema es muy simple desde un punto de vista técnico pero hay que contemplarla en fase de diseño para conseguir un resultado coherente y sólido.
El script sería como sigue:
// Versión jQuery $(document).ready( function(){ $('html:first').addClass('jsEnabled'); } ); |
o si se prefiere la versión Javascript pura:
document.getElementsByTagName('html')[0].className += ' jsEnabled'; |
Claves
- Aplicamos una clase jsEnabled al HTML en caso de que Javascript se encuentre activado.
- Atacamos al HTML en lugar del BODY para una mayor transparencia y cobertura.
- Utilizamos el filtro ‘:first’ en jQuery y el índice 0 (cero) en el ejemplo plano para prevenir la existencia de más de un elemento HTML en la página (útil en escenarios con múltiples frames).
- Añadimos un espacio al nombre de la clase en la versión Javascript plana para evitar que, en caso de que encontremos otras clases ya definidas, éstas no se concatenen.
Estilos
Una vez que tenemos identifacada la presencia o no de Javascript con una clase, podemos aplicar estilos a los elementos de nuestra página:
html.jsEnabled .tabs_content{ display: none; } |
Simple y limpio. Con esta sencilla técnica podemos preparar UIs complejas de tal modo que no queden capas ocultas o inaccesibles cuando un usuario accede con Javascript desactivado. Un escenario típico pueden ser las pestañas de una ventana, los menús de persianas o aquellos elementos que respondan a eventos desde Javascript.
¡Hola Carlos!,
no estoy del todo de acuerdo en hacerlo con jQuery, puesto que el navegador tiene que cargar la librería y luego aplicar el método ready (al igual que hacerlo con el evento load de JavaScript). El proceso de carga de la librería y/o de esperar a que se carge la página (evento load) puede provocar «parpadeos» en conexiones algo lentas, y se ve raro… por ejemplo, todo se muestra y luego todo se oculta de golpe.
Siempre he usado la segunda opción pero accediendo directamente al documentElement. Creo que es más limpio y más optimo ya que no tiene que llamar a ninguna función, ¿no? 🙂
¿Qué dices?
¡Saludos!
Hola;
yo personalmente también prefiero no utlizar jQuery para evitar tiempos de carga y ‘parpadeos’.
Hay que tener en cuenta que si estamos controlando que Javascript esté disponible es porque estamos tratando, o bien con un navegador muy antiguo (y lento), o bien con un dispositivo móvil (con conexiones también lentas). Por esto, prefiero una línea en código puro que no requiera de dependecias y se ejecute lo más rápidamente posible.
Sólo un apunte: en lugar de acceder al documento directamente, es más flexible hacerlo como indico en el ejemplo para evitar ‘comportamientos raros’ en iframes anidados. Ten en encuenta que puede haber varios ‘document’ y no nos interesa modificar las clases de todos ellos. 😉
Un saludo!!
Hola,
Quería agregar que Modernizr, además de la detección de características HTML5 y CSS3, detecta el soporte de JavaScript añadiendo la clase «js» en la etiqueta html.
Saludos
Cierto;
no sé si lo han añadido recientemente o siempre se me pasó por alto, pero no lo recordaba en las versiones anteriores. Actualizo el post.
Gracias Leandro!
@Carlos,
para evitar errores, en tu version de javascript pura, pon un espacio al nombre de la clase, no vaya a ser que ya tengas una clase CSS asociada y te las concatene 😉
document.getElementsByTagName('html')[0].className += ' jsEnabled';
Cierto; al reformatear el código para el editor me he comido el espacio.
Ya lo he actualizado a mano y añadido un punto nuevo a la lista explicando el porqué.
Gracias Javi!!
Ummm, pero estando dentro de un iframe y hacer el document.documentElement, te dará el documentElement del iframe, ¿no? y si lo haces en el parent document, pues te dará el documentElement del aprent ¿no? Así almenos lo entiendo yo.
Nunca habia pensado en los iframes para esto jejeje
Efectivamente, pero el escenario más típico sería que, desde dentro del iFrame, queramos llegar al Document del parent: «si un iFrame detecta que el padre no tiene el Javascript activado, actúa de esta u otra forma».
Aquí es interesante tener en cuenta que podemos estar programando algo que un tercero puede embeber en su aplicación. De ahí que queramos ‘escalar’ todo lo posible para evitar los errores.
Saludos!