Bloquear enlaces: la búsqueda de una solución perfecta
Estaba leyendo este artículo de Chris donde habla de que bloquear enlaces (ya sabes, como envolver un elemento completo de una tarjeta dentro de un ancla) es una mala idea. Es una mala accesibilidad debido a cómo afecta a los lectores de pantalla. Y es una mala experiencia de usuario porque impide tareas simples del usuario, como seleccionar texto.
Pero tal vez haya algo más en juego. Quizás sea menos un problema con el patrón que con su implementación. Eso me llevó a creer que este es el momento de escribir un artículo de seguimiento para ver si podemos abordar algunos de los problemas que señaló Chris.
A lo largo de esta publicación, usaré el término “tarjeta” para describir un componente que usa el patrón de enlace de bloque. Esto es lo que queremos decir con eso.
Veamos cómo queremos que funcionen nuestros Componentes de Tarjeta:
- Todo debe estar vinculado y se puede hacer clic en él.
- Debería poder contener más de un enlace.
- El contenido debe ser semántico para que la tecnología de asistencia pueda entenderlo.
- El texto debe poder seleccionarse, como los enlaces normales.
- Cosas como el clic derecho y los atajos de teclado deben funcionar con él.
- Sus elementos deben poder enfocarse al tabular.
¡Esa es una lista larga! Y como no tenemos ningún widget de tarjeta estándar proporcionado por el navegador, no tenemos pautas estándar para crearlo.
Como la mayoría de las cosas en la web, hay más de una forma de crear un componente de tarjeta. Sin embargo, no he encontrado nada que verifique todos los requisitos que acabamos de cubrir. En este artículo, intentaremos abordarlos todos. ¡Eso es lo que vamos a hacer ahora!
Método 1: envolver todo ya
Esta es la forma más común y sencilla de crear una tarjeta vinculada. Tome el HTML de la tarjeta y envuélvalo todo en una etiqueta de anclaje.
a href="/" !-- Card markup --/a
Esto es lo que eso nos da:
- Se puede hacer clic.
- Funciona con clic derecho y atajos de teclado.
Bueno, no genial. Todavía no podemos:
- Pon otro enlace dentro de la tarjeta porque todo es un solo enlace.
- Úselo con un lector de pantalla: el contenido no es semántico, por lo que la tecnología de asistencia anunciará todo lo que hay dentro de la tarjeta, comenzando por la marca de tiempo.
- elegir texto
Eso es suficiente para que probablemente no deberíamos usarlo. Pasemos a la siguiente técnica.
Método 2: simplemente vincule lo que necesita vincularse
Este es un buen compromiso que sacrifica un poco de UX para mejorar la accesibilidad.
Con este patrón conseguimos la mayoría de nuestros objetivos:
- Podemos poner tantos enlaces como queramos.
- El contenido es semántico.
- Podemos seleccionar el texto de Card.
- El clic derecho y los atajos del teclado funcionan.
- El enfoque está en el orden correcto al tabular.
Pero le falta la característica principal que queremos en una tarjeta: ¡se debe poder hacer clic en todo! Parece que tenemos que intentarlo de otra manera.
Método 3: El viejo pseudoelemento ::antes
En este, agregamos un elemento : :before
o : :after
, lo colocamos encima de la tarjeta con posicionamiento absoluto y lo estiramos por todo el ancho y alto de la tarjeta para que se pueda hacer clic.
Pero ahora:
- Todavía no podemos agregar más de un enlace porque cualquier otra cosa que esté vinculada está debajo de la capa de pseudoelemento. Podemos intentar poner todo el texto encima del pseudoelemento, pero el enlace de la tarjeta en sí no funcionará al hacer clic encima del texto.
- Todavía no podemos seleccionar el texto. Nuevamente, podríamos intercambiar capas, pero luego volvemos al problema del enlace en el que se puede hacer clic.
Intentemos marcar todas las casillas aquí en nuestra técnica final.
Método 4: agregar JavaScript en el segundo método
Desarrollemos el segundo método. Recuerde que ahí es donde vinculamos todo lo que queremos que sea un vínculo:
article time datetime="2020-03-20"Mar 20, 2020/time h2a href="https://css-tricks.com/a-complete-guide-to-calc-in-css/"A Complete Guide to calc() in CSS/a/h2 p In this guide, let’s cover just about everything there is to know about this very useful function. /p a href="https://css-tricks.com/author/chriscoyier/" target="_blank"Chris Coyier/a div a href="https://css-tricks.com/tag/calc/" calc/a /div/article
Entonces, ¿cómo hacemos para que se pueda hacer clic en toda la tarjeta? Podríamos usar JavaScript como una mejora progresiva para hacer eso. Comenzaremos agregando un click
detector de eventos a la tarjeta y activaremos el clic en el enlace principal cuando esté activo.
const card = document.querySelector(".card")const mainLink = document.querySelector('.main-link')
card.addEventListener("click", handleClick)
function handleClick(event) { mainLink.click();}
Temporalmente, esto introduce el problema de que no podemos seleccionar el texto, que hemos estado intentando solucionar todo este tiempo. Aquí está el truco: usaremos la API web relativamente menos conocida window.getSelection
. De MDN:
El
Window.getSelection()
método devuelve unSelection
objeto que representa el rango de texto seleccionado por el usuario o la posición actual del cursor.
Aunque este método devuelve un objeto, podemos convertirlo en una cadena con toString()
.
const isTextSelected = window.getSelection().toString()
Con una línea y sin complicados trucos de kung-fu con detectores de eventos, sabemos si el usuario ha seleccionado texto. Usemos eso en nuestra handleClick
función.
const card = document.querySelector(".card")const mainLink = document.querySelector('.main-link')
card.addEventListener("click", handleClick)
function handleClick(event) { const isTextSelected = window.getSelection().toString(); if (!isTextSelected) { mainLink.click(); }}
De esta manera, se puede hacer clic en el enlace principal cuando no se selecciona ningún texto, y todo lo que se necesita son unas pocas líneas de JavaScript. Esto satisface nuestros requisitos:
- Todo está vinculado y se puede hacer clic.
- Puede contener más de un enlace.
- Este contenido es semántico para que la tecnología de asistencia pueda entenderlo.
- El texto debe poder seleccionarse, como los enlaces normales.
- Cosas como el clic derecho y los atajos de teclado deben funcionar con él.
- Sus elementos deben poder enfocarse al tabular.
Hemos cumplido con todos los requisitos, pero todavía hay algunos problemas, como la activación de eventos dobles en elementos en los que se puede hacer clic, como enlaces y botones en la tarjeta. Podemos solucionar este problema agregando un detector de eventos de clic en todos ellos y deteniendo la propagación del evento.
// You might want to add common class like 'clickable' on all elements and use that for the query selector.const clickableElements = Array.from(card.querySelectorAll("a"));clickableElements.forEach((ele) = ele.addEventListener("click", (e) = e.stopPropagation()));
Aquí está la demostración final con todo el código JavaScript que hemos agregado:
¡Creo que lo hemos logrado! Ahora ya sabes cómo crear un componente de tarjeta perfecta en el que se pueda hacer clic.
¿Qué pasa con otros patrones? Por ejemplo, ¿qué pasa si la tarjeta contiene el extracto de una publicación de blog seguida de un enlace “Leer más”? ¿A dónde debería ir eso? ¿Se convierte ese en el vínculo “principal”? ¿Qué pasa con la imagen?
Para esas preguntas y más, aquí hay más lecturas sobre el tema:
- Tarjetas de Heydon Pickering
- Bloquear enlaces, tarjetas, regiones en las que se puede hacer clic, filas, etc. por Adrian Roselli
- Los enlaces de bloqueo son una molestia (y tal vez simplemente una mala idea) por Chris Coyier
- Errores de las interfaces de usuario de tarjetas por Dave Rupert
Deja un comentario