Introducción
En muchos temas de WordPress el cursor cambia a pointer (la mano) en todo el sitio, aunque no todos los elementos sean realmente clicables. Esto genera confusión al usuario y reduce la percepción de calidad de la interfaz. Este tutorial explica, con todo detalle y ejemplos prácticos, cómo aplicar cursor: pointer únicamente a los elementos que verdaderamente son interactivos, usando CSS y complementándolo opcionalmente con pequeñas ayudas en JavaScript y con instrucciones para integrarlo correctamente en WordPress.
Concepto y buenas prácticas
El cursor de puntero indica interactividad. Debe aplicarse sólo a elementos que ejecutan una acción al hacer clic: enlaces (a con href), botones, inputs tipo submit/button, elementos con rol=button, elementos con manejadores onclick, o bloques que activan navegación. Aplicarlo en exceso provoca expectativas falsas.
Buenas prácticas:
- Usar selectores específicos para elementos realmente interactivos.
- Respetar la accesibilidad: no sustituir pistas visuales que benefician a usuarios de teclado/lectores de pantalla.
- Preferir soluciones CSS puras usar JavaScript sólo cuando el HTML no refleja la interactividad (por ejemplo componentes dinámicos).
Selector CSS básico para elementos interactivos
Un conjunto de selectores que cubre la mayoría de los casos comunes sería:
/ Aplicar puntero sólo a elementos que habitualmente responden a clic /
a[href],
button,
input[type=button],
input[type=submit],
input[type=reset],
label[for],
summary,
[role=button],
[onclick] {
cursor: pointer
}
Explicación breve de cada selector:
- a[href]: enlaces con atributo href (evita marcadores o anchors sin destino).
- button: botones nativos.
- input[type=…]: inputs que actúan como botones.
- label[for]: etiquetas que activan un input al hacer clic.
- summary: usado por elementos details/summary.
- [role=button]: elementos ARIA declarados como botón.
- [onclick]: elementos con atributo onclick inline.
Evitar falsas positivas y elementos deshabilitados
Si un enlace o botón está deshabilitado (atributo disabled, clase .disabled o aria-disabled=true), no debería mostrar el puntero. Podemos excluir esos casos con :not() y atributos:
/ Excluir elementos deshabilitados /
a[href]:not([aria-disabled=true]):not(.disabled),
button:not([disabled]):not([aria-disabled=true]):not(.disabled),
input[type=button]:not([disabled]),
input[type=submit]:not([disabled]),
[role=button]:not([aria-disabled=true]):not(.disabled),
[onclick]:not([aria-disabled=true]):not(.disabled) {
cursor: pointer
}
Selector específico para bloques y componentes de WordPress
WordPress (Gutenberg y temas) suele añadir clases a botones y bloques. Algunos ejemplos prácticos para temas comunes:
/ Botón de bloque de Gutenberg /
.wp-block-button a,
.wp-block-button__link,
.button, / clases comunes en temas /
.entry-title a, / títulos que son enlaces /
.menu-item a {
cursor: pointer
}
/ Evitar aplicar globalmente al o al /
html.pointer-all, body.pointer-all { / ejemplo de mal uso que debemos evitar / }
Integración en WordPress: dónde poner el CSS
- Apariencia > Personalizar > CSS adicional: método rápido y seguro para probar pequeños fragmentos.
- Child theme (style.css): para cambios permanentes y versionables en tu tema hijo.
- Enqueue desde functions.php: ideal si vas a empaquetar el CSS junto con scripts del tema/plugin.
Ejemplo de cómo añadir una hoja de estilos desde functions.php (child theme) para que el CSS quede cargado correctamente:
/ functions.php del tema hijo /
function mi_tema_child_enqueue_styles() {
wp_enqueue_style( mi-ajuste-cursor, get_stylesheet_directory_uri() . /css/ajuste-cursor.css, array(), 1.0 )
}
add_action( wp_enqueue_scripts, mi_tema_child_enqueue_styles )
En el archivo css/ajuste-cursor.css colocarías los selectores que hemos visto arriba.
Casos complejos: elementos dinámicos o marcados por scripts
Algunos componentes crean interactividad mediante JavaScript sin reflejarlo en atributos HTML (ni role ni onclick). En esos casos puedes añadir una pequeña rutina que detecte elementos con listeners o con clases conocidas y les añada una clase utilitaria, por ejemplo .is-clickable. Luego el CSS apuntará a esa clase.
/ Añadir clase .is-clickable a elementos que probablemente son interactivos /
(function(){
// selectores heurísticos
var selectors = [
a[href],
button,
input[type=button],
input[type=submit],
[role=button],
[onclick],
.js-toggle, // ejemplo de clases JS comunes
.carousel-control, // ejemplo
.swipe-item[data-action] // ejemplo de componente personalizado
]
var els = document.querySelectorAll(selectors.join(,))
els.forEach(function(el){
// evitar elementos inactivos
if (el.closest([aria-disabled=true], .disabled)) return
el.classList.add(is-clickable)
})
})()
CSS correspondiente:
.is-clickable {
cursor: pointer
}
Enqueue del script en WordPress (opcional)
Si decides usar el script anterior, añádelo mediante functions.php para que cargue correctamente:
function mi_tema_enqueue_clickable_script() {
wp_enqueue_script( mi-clickable-js, get_stylesheet_directory_uri() . /js/clickable-detect.js, array(), 1.0, true )
}
add_action( wp_enqueue_scripts, mi_tema_enqueue_clickable_script )
Compatibilidad y testing
- Prueba en distintos navegadores (Chrome, Firefox, Safari, Edge) y en dispositivos táctiles. En móviles el cursor no se muestra, pero la lógica de visibilidad y estado sigue siendo importante para consistencia.
- Verifica componentes del tema y plugins (megamenús, sliders, formularios) para no romper interacciones al cambiar reglas CSS globales.
- Revisa estados de foco (keyboard navigation). No elimines outlines por CSS sin una alternativa visible.
Problemas comunes y cómo solucionarlos
- El cursor sigue siendo mano en todo: busca reglas globales como { cursor: pointer } o html, body { cursor: pointer } y sobreescríbelas con reglas más específicas o elimina la regla culpable.
- El puntero no aparece en componentes JS: añade la clase .is-clickable con JavaScript o ajusta el HTML del componente para incluir role=button o un href cuando proceda.
- Conflictos con plugins: localiza la hoja CSS del plugin que define cursor global y anula con tu hoja cargada después (mayor especificidad o !important como último recurso, evitando abusar de !important).
Ejemplos prácticos completos
Ejemplo 1 — Regla compacta para la mayoría de sitios:
/ Aplicar puntero sólo a elementos realmente interactivos y no deshabilitados /
a[href]:not([aria-disabled=true]):not(.disabled),
button:not([disabled]):not(.disabled),
input[type=button]:not([disabled]),
input[type=submit]:not([disabled]),
[role=button]:not([aria-disabled=true]) {
cursor: pointer
}
Ejemplo 2 — Detectar con JS y aplicar clase (para elementos creados por scripts):
/ clickable-detect.js /
document.addEventListener(DOMContentLoaded, function() {
var guess = [
a[href],
[data-action],
[role=button],
[onclick],
.js-action, // añade tus propias clases según tu tema/plugins
]
document.querySelectorAll(guess.join(,)).forEach(function(el) {
if (!el.closest([aria-disabled=true], .disabled)) el.classList.add(is-clickable)
})
})
CSS asociado:
.is-clickable {
cursor: pointer
}
Accesibilidad (A11Y)
- Asegúrate de que los elementos interactivos sean accesibles por teclado (tabindex donde corresponda) y tengan roles ARIA adecuados si no son botones nativos.
- No ocultes indicadores de foco: si personalizas outline, proporciona una alternativa visible.
- Usa aria-disabled en lugar de solo clases visuales para indicar elementos no interactivos.
Resumen final
Aplicar cursor de puntero sólo en elementos clicables mejora la usabilidad y la percepción de calidad de un sitio WordPress. La solución ideal combina selectores CSS específicos (a[href], button, inputs, [role=button], [onclick], etc.) y, si es necesario, un pequeño script que marque elementos creados dinámicamente. Integra las reglas en un child theme, en el área de CSS adicional o mediante el enqueuing apropiado. Prueba en distintos navegadores y dispositivos, y cuida la accesibilidad para todos los usuarios.
Leave a Reply