Addaw, ir a inicio Donar

Técnica CSS WCAG 2.2

C43Usar scroll-padding para que los avisos fijos no tapen el foco

Nombre oficial en el W3C: Usar scroll-padding de CSS para desocultar el contenido

En pocas palabras

Muchas webs tienen elementos fijos en pantalla, como un aviso de cookies abajo o una cabecera que no se mueve. Al avanzar con el teclado, el elemento con el foco puede quedar escondido detrás. Las propiedades CSS scroll-padding y padding reservan ese hueco, y la página se desplaza para dejar el foco a la vista.

Por qué es importante

Quien navega con el teclado necesita ver dónde está en cada momento. El foco es la marca que indica qué enlace, botón o campo se activará al pulsar Intro.

Si un aviso de cookies fijo tapa el pie de página, la persona pulsa Tab y el foco desaparece bajo el aviso. No sabe dónde está ni qué va a activar. Le pasa a quien no usa ratón y a quien usa un teclado adaptado.

Las WCAG piden que el elemento con el foco no quede tapado del todo (criterio 2.4.11, nivel AA). En el nivel AAA (criterio 2.4.12) no puede quedar tapado ni en parte.

Cómo se hace

  1. Calcule la altura máxima del elemento fijo (aviso, cabecera o barra de chat). Guárdela en una variable CSS, por ejemplo --alto-aviso.
  2. En el elemento html, añada scroll-padding-bottom con esa altura más un pequeño margen. Si lo fijo está arriba, use scroll-padding-top.
  3. Añada también un padding-bottom igual a la altura del aviso. Así el final de la página puede subir por encima de él.
  4. En pantallas pequeñas o con mucha ampliación, deje de fijar el aviso dentro de una media query. Si no, puede ocupar casi toda la pantalla.
  5. Además, permita cerrar el aviso con el teclado. Una vez cerrado, ya no tapa nada.

Cómo comprobarlo

  1. Abra la página sin aceptar ni cerrar el aviso. Recórrala entera con Tab y Mayús+Tab.
  2. Fíjese sobre todo en los enlaces del pie y en los campos que quedan bajo una cabecera fija. Cada elemento con el foco debe verse; para el nivel AAA, entero.
  3. Repita la prueba con la ventana estrecha y con el zoom del navegador al 200 %.
  4. En las herramientas del navegador (F12), seleccione html. Compruebe que su scroll-padding es igual o mayor que la altura del elemento fijo.

Ejemplo

Aviso de cookies fijo en la parte inferior, con un hueco reservado para que el foco no quede debajo.

<style>
  :root { --alto-aviso: 8rem; }
  html {
    padding-bottom: var(--alto-aviso);
    scroll-padding-bottom: calc(var(--alto-aviso) + 1rem);
  }
  .aviso-cookies {
    position: fixed; bottom: 0; left: 0; right: 0;
    max-height: var(--alto-aviso); overflow: auto;
  }
</style>
<div class="aviso-cookies">Esta web usa cookies técnicas. <button>Aceptar</button></div>
Ver el texto completo del W3C (traducción al español)

Esta es una traducción no oficial al español de la técnica C43 de Techniques for WCAG 2.2, del W3C. Puede contener errores. El único documento oficial y normativo es la versión original en inglés, publicada en el sitio web del W3C.

Aplicabilidad

Todas las tecnologías compatibles con CSS.

Descripción

El objetivo de esta técnica es garantizar que los componentes de la interfaz de usuario (por ejemplo: enlaces, botones y campos de formulario) que inicialmente quedan completamente ocultos por un componente de posición fija sigan siendo accesibles para los usuarios. En este ejemplo, se consigue utilizando las propiedades CSS padding y scroll-padding para crear espacio debajo del pie de página del sitio y permitir que el enlace del pie se desplace hasta quedar visible cuando recibe el foco con el teclado.

Ejemplos

Usar scroll-padding de CSS para desocultar el contenido

Este ejemplo muestra una situación en la que hay un banner de posición fija en la parte inferior de la pantalla que tapa el pie de página del sitio, el cual contiene un enlace. Este tipo de banner de posición fija es un diseño habitual en los avisos de consentimiento de cookies.

Ejemplo práctico: Usar scroll-padding de CSS para desocultar el contenido.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>Using CSS scroll-padding to un-obscure content</title>
  <style>
    ...
    :root{
      --height-dialog: 400px;
      --breathing-room: 20px;
      --scroll-padding: calc(var(--height-dialog) + var(--breathing-room));      
    }
    .wrapper {
      display:grid;
      gap:1rem;
      grid-template-columns:repeat(9, 1fr);
      grid-template-rows:8rem auto minmax(10rem, max-content);
      min-block-size: 100vh;
    }
    .wrapper > * {
      border:1px solid var(--black);
      padding:1rem;
    }
    header {
      grid-column:1 / -1;
      grid-row:1;
    }
    main {
      grid-column:1 / 8;
    }
    aside {
      grid-column:8 / 10;
    }
    footer {
      grid-column:1 / -1;
    }
    @media (max-width:50rem) {
      main {
       grid-column:1 / -1;
      }
      aside {
        grid-column:1 / -1;
      }
    }
    .fixed-position-banner {
      background:var(--banner-background);
      border:3px solid var(--banner-border);
      margin-block-end:0.5rem;
      padding:1rem 1rem 5rem;
      position:relative;
      width:calc(100vw - 1rem);
    }
    @media (min-width: 50rem) {
      html {
        padding-bottom:var(--height-dialog);
        scroll-padding-bottom:var(--scroll-padding);
      }
     .fixed-position-banner {
        margin-block-end:0;
        position:fixed;
        inset:auto 0 0 0;
      }
    } 
    ...
  </style>
</head>
<body>
  <dialog class="fixed-position-banner">
    <h2 tabindex="-1">Fixed-Position Banner</h2>
    <button aria-label="close fixed-position banner" class="close-banner" type="button">
      ...
    </button>
  </dialog>
  <div class="wrapper">
    <header>
      <p>Header Content</p>
    </header>
    <main>
      <h1>Main Content</h1>
    </main>
    <aside>
      <h2>Sidebar Content</h2>
      <p><a href="https://example.com">Here's an example link in the sidebar</a>.</p>
    </aside>
    <footer>
      <h2>Footer Content</h2>
      <p><a href="https://example.com">Here's an example link in the footer</a>.</p>
    </footer>
  </div>
  <script>
    window.addEventListener('DOMContentLoaded', () => {
      const elFixedBanner = document.querySelector('dialog');
      const elCloseBannerBtn = document.querySelector(".close-banner");
      elFixedBanner.show();
      const getDialogHeight = () => {
        const height = elFixedBanner.offsetHeight;
        document.documentElement.style.setProperty('--height-dialog', `${height}px`);
        document.documentElement.style.setProperty('--breathing-room', `${height ? 20 : 0}px`);
      }
      const observer = new ResizeObserver(getDialogHeight);
      observer.observe(elFixedBanner);
      elCloseBannerBtn.addEventListener("click", function(e){
        elFixedBanner.close();
      }, false);
    });
  </script>	
</body>
</html>

Pruebas

Procedimiento

Para cada componente de la interfaz de usuario que puede recibir el foco del teclado:

  1. Comprobar que el componente de la interfaz de usuario no queda completamente oculto cuando recibe el foco del teclado.
  2. Comprobar que ninguna parte del componente de la interfaz de usuario queda oculta cuando recibe el foco del teclado.

Resultados esperados

  • La comprobación n.º 1 es verdadera.
  • Para el criterio de conformidad 2.4.12 Foco No Oscurecido (Mejorado) (nivel AAA), la comprobación n.º 2 también es verdadera.

Recursos

  1. W3C - CSS padding.
  2. W3C - CSS: la propiedad scroll-padding.

Cómo lo comprobamos en ADDAW

En cada auditoría de ADDAW revisamos esta técnica página a página y le entregamos los errores con capturas y la forma de corregirlos.

Solicitar una auditoría

Basado en la técnica C43 del W3C (WCAG 2.2). Explicación y ejemplos: ADDAW. Traducción no oficial del texto del W3C © W3C, licencia de documentos del W3C. ¿Ha visto un error? Escríbanos.