Wideo w tle a dostępność WCAG – jak zrealizować to zgodnie z prawem?

Aleksandra Głaz
3 lipca, 2026

Efektowne wideo w tle sekcji hero to dziś standard w projektach dla instytucji, uczelni czy nowoczesnych marek. Problem w tym, że najprostsza implementacja – czyli włączenie wideo z poziomu ustawień Divi (i większości innych wizualnych narzędzi do budowania stron) – w praktyce łamie kilka wymagań WCAG 2.1 na poziomie AA. Dla firmy czy NGO, które podlegają Ustawie o dostępności cyfrowej lub Europejskiemu Aktowi o Dostępności (EAA), to nie jest kwestia estetyki, tylko realne ryzyko prawne.

W tym wpisie pokazuję, jak wygląda to zagadnienie od strony wykonawczej – na przykładzie autorskiego modułu Hero Video, który wdrażam u swoich klientów zamiast natywnego mechanizmu tła wideo w Divi.

Dlaczego natywne wideo w tle w Divi jest problemem

Standardowy mechanizm tła wideo w Divi ma trzy słabe punkty, które dotykają zarówno wydajności, jak i dostępności:

  • Brak realnej kontroli nad autoodtwarzaniem. WCAG 2.2.2 (Pause, Stop, Hide) wymaga, aby ruchoma, autoodtwarzana treść trwająca dłużej niż 5 sekund dała się zatrzymać przez użytkownika. Domyślny moduł Divi takiej kontrolki nie ma.
  • Ignorowanie preferencji systemowych. Część użytkowników – np. osoby z migreną, epilepsją światłoczułą czy zaburzeniami przedsionkowymi – włącza w systemie opcję „ogranicz ruch” (prefers-reduced-motion). Natywny mechanizm Divi tej preferencji nie odczytuje.
  • Wydajność i fallback. Domyślne tło wideo dokłada narzut skryptów Divi i słabo radzi sobie z obrazem zastępczym na wolniejszych łączach, co odbija się też na Core Web Vitals, a więc pośrednio na SEO.

Do tego dochodzi kwestia formalna: strony podmiotów publicznych i organizacji pozarządowych realizujących zadania publiczne podlegają w Polsce Ustawie o dostępności cyfrowej stron internetowych i aplikacji mobilnych (wdrażającej unijną dyrektywę 2016/2102) już od kilku lat. Firmy prywatne oferujące usługi konsumenckie online – w tym sklepy i wiele usług cyfrowych – od 28 czerwca 2025 r. podlegają dodatkowo <cite index=”4-1″>Europejskiemu Aktowi o Dostępności, którego polska implementacja wymaga zgodności z WCAG 2.1 na poziomie AA</cite>. Mikroprzedsiębiorstwa (poniżej 10 osób i 2 mln euro obrotu) mają pewne zwolnienia, ale <cite index=”5-1″>to nie oznacza, że ich strona może być całkowicie niedostępna</cite> – a instytucje i NGO zwykle w ogóle nie łapią się na ten wyjątek.

Innymi słowy: jeśli robisz stronę dla instytucji, uczelni, fundacji albo świadomej firmy, wideo w tle „na domyślnych ustawieniach Divi” to gotowy powód do skargi lub uwagi w audycie dostępności.

Rozwiązanie: autorski moduł Hero Video zamiast natywnego tła

Zamiast polegać na wbudowanym mechanizmie, buduję sekcję hero od zera – czystym HTML, CSS i JavaScriptem, osadzonym w Divi jako Moduł Kodu. Takie podejście daje pełną kontrolę nad trzema rzeczami, których natywny Divi nie oferuje:

  1. Przyciskiem play/pause widocznym cały czas, z poprawnymi atrybutami aria-label i aria-pressed, które aktualizują się dynamicznie wraz ze stanem odtwarzacza.
  2. Automatycznym wykrywaniem prefers-reduced-motion – jeśli użytkownik ma w systemie włączoną redukcję ruchu, wideo w ogóle się nie odtwarza, a widoczny jest bezpieczny obraz zastępczy.
  3. Blokadą Picture-in-Picture i brakiem dźwięku – wideo jest zawsze wyciszone (muted), więc nie narusza WCAG 1.4.2 (Audio Control), a dodatkowa blokada PiP (CSS + JS) eliminuje niepożądane, pływające okienko wideo, które potrafi rozwalić layout na urządzeniach mobilnych.

Do tego dochodzi warstwa czysto techniczna: obraz poster i tag <img> jako fallback ładują się błyskawicznie, a atrybut preload="auto" sprawia, że przeglądarka priorytetyzuje pobieranie wideo bez narzutu skryptów page buildera.

Demo – zobacz działanie w praktyce

Poniżej uproszczone demo pokazujące dokładnie ten mechanizm: przycisk zatrzymuje animację w tle, a etykieta i aria-pressed zmieniają się razem ze stanem odtwarzacza. W finalnej wersji tło stanowi realne wideo klienta – tutaj, żeby demo działało od razu w artykule bez dodatkowych plików, zastąpiłam wideo animowanym gradientem obrazującym ten sam mechanizm sterowania.

Demo sekcji hero z animowanym tłem i przyciskiem zatrzymania animacji zgodnym z WCAG

Kliknij przycisk, żeby zobaczyć zachowanie zgodne z WCAG 2.2.2 – animacja zatrzymuje się, pokazuje się fallback, a aria-pressed i etykieta się aktualizują.

Gotowy kod do wklejenia w Moduł Kodu Divi

<!-- ========================================== -->
<!-- 1. STRUKTURA HTML -->
<!-- ========================================== -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">

<div id="premium-hero-wrapper">
    <!-- OBRAZ FALLBACK -->
    <img id="hero-fallback-img"
         src="TUTAJ_WKLEJ_LINK_DO_OBRAZU_FALLBACK.jpg"
         alt="Tło sekcji przedstawiające [wpisz dokładny opis]" />

    <!-- WIDEO PREMIUM -->
    <video id="hero-premium-video"
           autoplay muted playsinline disablepictureinpicture
           preload="auto"
           poster="TUTAJ_WKLEJ_LINK_DO_OBRAZU_FALLBACK.jpg"
           aria-label="Krótkie wideo w tle pokazujące [wpisz opis]">
        <source src="TUTAJ_WKLEJ_LINK_DO_WIDEO.mp4" type="video/mp4">
        Twoja przeglądarka nie obsługuje odtwarzacza wideo.
    </video>

    <!-- PRZYCISK STERUJĄCY -->
    <div id="hero-controls-container">
        <button id="bg-video-toggle" class="bg-video-toggle" aria-label="Zatrzymaj animację w tle" aria-pressed="false">
            <i class="fa-solid fa-pause" aria-hidden="true"></i>
            <span class="label">Zatrzymaj tło</span>
        </button>
    </div>
</div>

<!-- ========================================== -->
<!-- 2. STYLE CSS -->
<!-- ========================================== -->
<style>
    #premium-hero-wrapper {
        position: absolute;
        top: 0;
        left: 50%;
        transform: translateX(-50%);
        width: 100vw;
        height: 100%;
        min-height: 65vh;
        background-color: #1a1a1a;
        overflow: hidden;
        z-index: 0;
    }
    #hero-fallback-img {
        position: absolute; top: 0; left: 0;
        width: 100%; height: 100%;
        object-fit: cover; z-index: 1;
    }
    #hero-premium-video {
        position: absolute; top: 0; left: 0;
        width: 100%; height: 100%;
        object-fit: cover; z-index: 2;
        opacity: 1;
        transition: opacity 0.6s ease-in-out;
        pointer-events: none; /* blokada interakcji myszy, np. ikony PiP */
    }
    #hero-premium-video.is-hidden { opacity: 0; }
    #hero-controls-container {
        position: absolute; bottom: 30px; right: 30px; z-index: 9999;
    }
    .bg-video-toggle {
        background: rgba(0, 0, 0, 0.65);
        color: #fff;
        padding: 12px 18px;
        border-radius: 8px;
        font-size: 17px;
        border: 2px solid #fff;
        cursor: pointer;
        display: inline-flex;
        align-items: center;
        gap: 10px;
        transition: all 0.3s ease;
    }
    .bg-video-toggle:focus-visible {
        outline: 3px solid #c29c43;
        outline-offset: 4px;
    }
    .bg-video-toggle:hover { background: rgba(0, 0, 0, 0.85); }

    @media (max-width: 980px) {
        #premium-hero-wrapper { min-height: 50vh; }
        #hero-controls-container { bottom: 25px; right: 25px; }
    }
    @media (max-width: 767px) {
        #premium-hero-wrapper { min-height: 40vh; }
        .bg-video-toggle .label { display: none; }
        #hero-controls-container { bottom: 20px; right: 20px; }
    }
</style>

<!-- ========================================== -->
<!-- 3. SKRYPT JAVASCRIPT -->
<!-- ========================================== -->
<script>
document.addEventListener("DOMContentLoaded", function () {
    const video = document.getElementById('hero-premium-video');
    const toggleBtn = document.getElementById('bg-video-toggle');
    const icon = toggleBtn.querySelector('i');
    const label = toggleBtn.querySelector('.label');

    function pauseVideoAndShowFallback() {
        video.pause();
        video.classList.add('is-hidden');
        icon.classList.remove('fa-pause');
        icon.classList.add('fa-play');
        label.textContent = "Odtwórz tło";
        toggleBtn.setAttribute('aria-label', "Odtwórz animację w tle");
        toggleBtn.setAttribute('aria-pressed', "true");
    }

    function playVideo() {
        video.play();
        video.classList.remove('is-hidden');
        icon.classList.remove('fa-play');
        icon.classList.add('fa-pause');
        label.textContent = "Zatrzymaj tło";
        toggleBtn.setAttribute('aria-label', "Zatrzymaj animację w tle");
        toggleBtn.setAttribute('aria-pressed', "false");
    }

    if (video && toggleBtn) {
        video.disablePictureInPicture = true;
        video.setAttribute('controlsList', 'nodownload noplaybackrate nofullscreen');

        toggleBtn.addEventListener('click', function () {
            if (video.paused) { playVideo(); } else { pauseVideoAndShowFallback(); }
        });

        video.addEventListener('ended', pauseVideoAndShowFallback);

        // A11Y: redukcja ruchu
        const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
        if (prefersReducedMotion.matches) { pauseVideoAndShowFallback(); }

        // Zabezpieczenie przed błędem autoplay
        let playPromise = video.play();
        if (playPromise !== undefined) {
            playPromise.catch(() => { pauseVideoAndShowFallback(); });
        }
    }
});
</script>

Jak to wdrożyć w Divi krok po kroku

  1. Sekcja. Nowa sekcja bez tła (zdjęcia, wideo, kolorów), marginesy i paddingi górny/dolny na 0px, w zakładce Zaawansowane → Pozycja ustaw Względna.
  2. Moduł Kodu. Wstaw Moduł Kodu do sekcji, w Zaawansowane → Pozycja ustaw Absolutna, zakotwicz w lewym górnym rogu, z-index: 0. Wklej cały kod powyżej.
  3. Podmiana danych. Zamień TUTAJ_WKLEJ_LINK_DO_OBRAZU_FALLBACK.jpg (2 wystąpienia) i TUTAJ_WKLEJ_LINK_DO_WIDEO.mp4 (1 wystąpienie) na realne adresy z biblioteki mediów. Uzupełnij alt i aria-label konkretnym opisem tego, co dzieje się na wideo.
  4. Wysokość sekcji. W Ustawieniach Sekcji → Projekt → Rozmiary → Min. wysokość ustaw wartości responsywne: 65vh (pulpit), 50vh (tablet), 40vh (telefon) – zgodnie z CSS w module.

Checklista dostępności do tego typu sekcji

  • Wideo jest wyciszone (muted) – brak autoodtwarzania dźwięku (WCAG 1.4.2).
  • Widoczny przycisk zatrzymania animacji trwającej dłużej niż 5 s (WCAG 2.2.2).
  • Skrypt reaguje na prefers-reduced-motion i domyślnie zatrzymuje wideo dla osób, które włączyły tę preferencję w systemie.
  • Przycisk ma poprawny kontrast i widoczny obrys przy nawigacji klawiaturą (:focus-visible).
  • aria-label i aria-pressed przycisku aktualizują się razem ze stanem odtwarzacza.
  • Obraz fallback ma sensowny, opisowy atrybut alt.
  • Wideo nie zawiera efektów migotania ani szybkich błysków (WCAG 2.3.1).

Dlaczego to się opłaca nie tylko instytucjom

Publiczne strony i te realizujące zadania publiczne od dawna muszą spełniać krajową ustawę o dostępności cyfrowej. Firmy prywatne i NGO prowadzące sprzedaż lub usługi online dołączyły do tego obowiązku wraz z wejściem w życie EAA 28 czerwca 2025 r., kiedy wszystkie nowo oferowane produkty i usługi cyfrowe muszą już spełniać wymogi dostępności. Dla stron istniejących wcześniej przewidziano okres przejściowy, ale nowo wdrażane treści i funkcje – takie jak świeżo dodana sekcja hero – powinny być zgodne od razu.

Niezależnie od tego, czy dany podmiot formalnie podlega pod EAA, dostępna sekcja hero to też: lepszy wynik Core Web Vitals (bo rezygnujemy z ciężkiego mechanizmu Divi), mniej reklamacji od użytkowników z czytnikami ekranu i realny argument sprzedażowy, gdy klient pyta „czy to będzie zgodne z WCAG?”.

FAQ

Czy wideo w tle strony musi mieć napisy?

Jeśli wideo pełni czysto dekoracyjną rolę i nie zawiera treści informacyjnej ani ścieżki dźwiękowej, napisy nie są wymagane – kluczowe jest jednak wyciszenie i możliwość zatrzymania animacji.

Czy wystarczy sam atrybut muted, żeby spełnić WCAG?

Nie. Sam brak dźwięku nie zwalnia z obowiązku dania użytkownikowi kontroli nad ruchomą treścią (WCAG 2.2.2) ani z uwzględnienia preferencji prefers-reduced-motion.

Czy natywny moduł wideo w tle Divi da się „doszlifować” do WCAG bez pisania własnego kodu?

Częściowo – da się dodać przycisk pauzy nakładką CSS, ale bez własnego skryptu nie ma kontroli nad prefers-reduced-motion, blokadą PiP ani realnym priorytetem ładowania pliku.

Kogo dotyczy obowiązek dostępności cyfrowej stron w Polsce?

Podmiotów publicznych i realizujących zadania publiczne – od lat, na mocy ustawy z 2019 r. Od 28 czerwca 2025 r. dołączyły do nich firmy prywatne oferujące określone usługi i produkty konsumenckie online, na mocy Europejskiego Aktu o Dostępności, z pewnymi wyłączeniami dla mikroprzedsiębiorstw.


Potrzebujesz wdrożyć taką sekcję u siebie albo sprawdzić, czy Twoja strona spełnia wymogi WCAG? Napisz do mnie i umów konsultację – przygotuję audyt i wdrożę rozwiązanie dopasowane do Twojej instytucji.