Introducción — por qué estilizar bloques de código largos
En blogs técnicos en WordPress es habitual pegar fragmentos de código que exceden el ancho del contenedor y rompen el diseño o hacen la lectura incómoda. La solución visual más elegante y usable es permitir scroll horizontal sutil en los bloques de código: que el lector pueda desplazarse cuando haga falta, que la pista de que hay más contenido sea discreta (sombras/fades) y que la experiencia sea accesible y funcione tanto en escritorio como en móvil.
Objetivos de este tutorial
- Ofrecer CSS para activar scroll horizontal controlado y visualmente sutil.
- Proveer mejoras visuales (barras finas, degradados o sombras en los bordes) para indicar contenido oculto sin ser intrusivo.
- Agregar un pequeño script que detecte cuándo hay overflow y active clases para cambiar el aspecto (mejora progresiva).
- Mostrar cómo integrar esto en un tema o plugin de WordPress (enqueue para frontend y editor).
- Tener en cuenta accesibilidad, rendimiento y compatibilidad.
Principio básico
El punto de partida es convertir el contenedor de código en un elemento con overflow-x: auto y white-space: pre (o el valor que use el resaltador), y luego añadir detalles: scrollbars finas, suavizado para iOS (-webkit-overflow-scrolling), y un indicativo visual (degradado/mask o pseudo-elementos) para sugerir que hay más contenido a la derecha/izquierda.
CSS base recomendado
Este bloque CSS crea un contenedor con scroll horizontal, scrollbars discretas y un fondo neutro. Pégalo en tu hoja de estilos del tema o en un archivo específico que enqueues para el frontend.
/ CSS base para bloques de código con scroll sutil /
.EnlighterJSRAW {
position: relative / necesario si usamos pseudo-elementos /
display: block
max-width: 100%
overflow-x: auto / permite scroll horizontal /
-webkit-overflow-scrolling: touch / smooth scrolling en iOS /
white-space: pre / mantiene el formato del código /
padding: 1rem / espacio interior /
margin: 1rem 0
border-radius: 8px
background: linear-gradient(180deg, #0f1720, #0b1216) / tono oscuro neutro /
color: #e6edf3
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Roboto Mono, monospace
font-size: 0.95rem
line-height: 1.5
box-shadow: 0 1px 0 rgba(255,255,255,0.02) inset
outline: none / el foco lo manejamos por accesibilidad abajo /
}
/ Scrollbars finas - WebKit /
.EnlighterJSRAW::-webkit-scrollbar {
height: 8px
}
.EnlighterJSRAW::-webkit-scrollbar-track {
background: transparent
}
.EnlighterJSRAW::-webkit-scrollbar-thumb {
background: rgba(255,255,255,0.06)
border-radius: 999px
}
/ Compatibilidad con Firefox /
.EnlighterJSRAW {
scrollbar-width: thin
scrollbar-color: rgba(255,255,255,0.06) transparent
}
/ Indicador visual sutil por borde (fallback) /
.EnlighterJSRAW:focus {
box-shadow: 0 0 0 3px rgba(100,150,255,0.12)
}
Degradado / máscara para indicar contenido oculto
Una solución moderna y muy elegante es usar mask-image (y -webkit-mask-image) para crear un fade en los bordes. Pero queremos que el fade desaparezca cuando no haya overflow o cambie según el scroll. Para eso combinamos una máscara por defecto y un script que añade clases cuando hay contenido oculto a la izquierda/derecha.
/ Por defecto: sutil fade a ambos lados /
.EnlighterJSRAW {
-webkit-mask-image: linear-gradient(90deg, transparent 0px, black 24px, black calc(100% - 24px), transparent 100%)
mask-image: linear-gradient(90deg, transparent 0px, black 24px, black calc(100% - 24px), transparent 100%)
transition: -webkit-mask-image 200ms linear
transition: mask-image 200ms linear
}
/ Si no hay overflow: eliminamos el fade para mejor contraste /
.EnlighterJSRAW.no-overflow {
-webkit-mask-image: none
mask-image: none
}
/ Si hay overflow sólo a la derecha: mostramos fade en la derecha /
.EnlighterJSRAW.can-scroll-right:not(.can-scroll-left) {
-webkit-mask-image: linear-gradient(90deg, black 0%, black calc(100% - 24px), transparent 100%)
mask-image: linear-gradient(90deg, black 0%, black calc(100% - 24px), transparent 100%)
}
/ Si hay overflow sólo a la izquierda: fade en la izquierda /
.EnlighterJSRAW.can-scroll-left:not(.can-scroll-right) {
-webkit-mask-image: linear-gradient(90deg, transparent 0%, black 24px, black 100%)
mask-image: linear-gradient(90deg, transparent 0%, black 24px, black 100%)
}
JavaScript ligero para detectar overflow y scroll
Este pequeño script añade o quita clases .no-overflow, .can-scroll-left y .can-scroll-right en cada bloque. Usa ResizeObserver para reaccionar a cambios de tamaño (ventana o contenedor) y escucha el evento scroll. Envíalo en un archivo JS y enquéuelo en el frontend.
/ script: code-scroll.js /
(function () {
var items = [].slice.call(document.querySelectorAll(.EnlighterJSRAW))
if (!items.length) return
function update(el) {
var scrollLeft = el.scrollLeft
var clientW = el.clientWidth
var scrollW = el.scrollWidth
el.classList.toggle(no-overflow, scrollW <= clientW 1)
el.classList.toggle(can-scroll-left, scrollLeft > 0)
el.classList.toggle(can-scroll-right, scrollLeft clientW < scrollW - 1)
}
items.forEach(function (el) {
// primera evaluación
update(el)
// al hacer scroll
el.addEventListener(scroll, function () { update(el) }, { passive: true })
// si el tamaño del contenedor cambia
if (window.ResizeObserver) {
var ro = new ResizeObserver(function () { update(el) })
ro.observe(el)
} else {
// fallback: escucha resize de ventana
window.addEventListener(resize, function () { update(el) })
}
})
})()
Markup de ejemplo (cómo debe aparecer el pre en tu HTML)
Si insertas código manualmente, añade tabindex=0 para que usuarios de teclado puedan desplazarse y para que el foco visual sea claro. En bloques generados por plugins de resaltado (Enlighter, Prism, Highlight.js, etc.) probablemente ya tengan un wrapper adapta las selectores si es necesario.
/ Tu código aquí / .example { width: 1200px background: red }Integración en WordPress: enqueue de CSS y JS
Coloca el CSS y JS anteriores en los archivos de tu tema (por ejemplo /css/code-scroll.css y /js/code-scroll.js) y regístralos/enquéualos desde functions.php.
/ functions.php / function theme_enqueue_code_scroll() { wp_enqueue_style(theme-code-scroll, get_stylesheet_directory_uri() . /css/code-scroll.css, array(), 1.0) wp_enqueue_script(theme-code-scroll, get_stylesheet_directory_uri() . /js/code-scroll.js, array(), 1.0, true) } add_action(wp_enqueue_scripts, theme_enqueue_code_scroll) / Encolar también para el editor de bloques (Gutenberg) para ver el mismo estilo al editar / function theme_enqueue_block_editor_assets_code_scroll() { wp_enqueue_style(theme-code-scroll-editor, get_stylesheet_directory_uri() . /css/code-scroll-editor.css, array(wp-edit-blocks), 1.0) } add_action(enqueue_block_editor_assets, theme_enqueue_block_editor_assets_code_scroll)Soporte para el editor (Gutenberg / Classic)
1) Gutenberg: encolando una hoja de estilos para el editor (como en el ejemplo anterior) aseguras que los bloques de código dentro del editor reciban las mismas reglas visuales.
2) Classic editor: si tu plugin de resaltado imprime pre con la clase EnlighterJSRAW en el contenido, el CSS del frontend actuará igual. Si no, ajusta las selectores al HTML que genera tu plugin.
Accesibilidad y buenas prácticas
- Teclado: asegúrate de que los bloques sean enfocables con tabindex=0 si no lo son por defecto. Al estar el foco, añade outline visible con CSS para indicar foco.
- Screen readers: el código debe conservar su semántica (pre y code). No uses roles innecesarios que puedan confundir a lectores de pantalla.
- Scroll suave en móviles: -webkit-overflow-scrolling: touch mejora la experiencia en iOS.
- Evitar reflow pesado: el script propuesto es mínimo y usa ResizeObserver si está disponible, evitando cálculos frecuentes.
Compatibilidad y fallback
mask-image no funciona en navegadores antiguos. Por eso el CSS inicial funciona sin mask (simple scroll) y las reglas con mask-image son una mejora progresiva. Como fallback visual puedes usar pseudo-elementos con gradientes (antes de mask) si necesitas soporte más amplio.
Ejemplo de fallback con pseudo-elementos
/ Fallback: pseudo-elementos para crear fades si mask no está soportado /
.EnlighterJSRAW {
position: relative
overflow: auto
}
/ gradiente izquierdo /
.EnlighterJSRAW::before,
.EnlighterJSRAW::after {
content:
pointer-events: none
position: absolute
top: 0
height: 100%
width: 32px
transition: opacity 160ms linear
opacity: 0 / visible sólo cuando corresponda /
}
/ izquierdo /
.EnlighterJSRAW::before {
left: 0
background: linear-gradient(90deg, rgba(11,17,22,1), rgba(11,17,22,0))
}
/ derecho /
.EnlighterJSRAW::after {
right: 0
background: linear-gradient(270deg, rgba(11,17,22,1), rgba(11,17,22,0))
}
/ se muestran según clases gestionadas por JS /
.EnlighterJSRAW.can-scroll-left::before { opacity: 1 }
.EnlighterJSRAW.can-scroll-right::after { opacity: 1 }
Tabla rápida de soporte y recomendaciones
| Funcionalidad | Soporte / nota |
| overflow-x:auto | Universal — todos los navegadores modernos |
| scrollbar styling (::-webkit-scrollbar) | WebKit/Blink (Chrome, Safari). Firefox usa scrollbar-width/scrollbar-color. |
| mask-image / -webkit-mask-image | Chrome, Safari en Firefox la propiedad funciona pero con prefijos distintos usar pseudo-elementos como fallback. |
| ResizeObserver | Soporte moderno si no está usar window.resize como fallback. |
Buenas prácticas de publicación
- Minimiza el CSS/JS que enqueues: agrupa en archivos y minifica para mantener velocidad.
- Si usas plugins de resaltado (Enlighter, Prism, etc.), aplica tus reglas al wrapper que generan o añade una clase extra para no afectar otros elementos.
- Prueba en móvil: comprueba que el scroll horizontal no interfiera con el scroll vertical general y que iOS desliza sin problemas.
- Controla contraste: si tu fondo de código es oscuro, asegúrate de que las sombras/degradados no reduzcan demasiado la legibilidad.
Notas finales
Con combinar overflow-x: auto, scrollbars finas, una máscara o pseudo-elementos para el fade y un JS ligero para detectar overflow se obtiene una solución elegante, accesible y compatible. Integra el CSS y el JS en tu tema o plugin y registra también la hoja de estilos en el editor para mantener consistencia entre edición y publicación.
Leave a Reply