Skip to content

RODO: komunikat o ciasteczkach jako pasek u dołu zamiast modala blokującego stronę - #735

Merged
mpasternak merged 10 commits into
devfrom
fix-cookie-banner-pasek
Aug 9, 2026
Merged

RODO: komunikat o ciasteczkach jako pasek u dołu zamiast modala blokującego stronę#735
mpasternak merged 10 commits into
devfrom
fix-cookie-banner-pasek

Conversation

@mpasternak

Copy link
Copy Markdown
Member

Komunikat o ciasteczkach przestaje być pełnoekranowym oknem blokującym stronę, a staje się paskiem przy dolnej krawędzi okna.

Stan przed zmianą

#CookielawBanner był modalnym overlayem:

position: fixed !important;
width: 100vw !important;  height: 100vh !important;
background-color: rgba(0, 0, 0, 0.6) !important;
backdrop-filter: blur(10px) !important;
z-index: 9998 !important;

Przyciemniał i rozmywał całą stronę do czasu podjęcia decyzji o ciasteczkach. Nic pod spodem nie było ani czytelne, ani klikalne.

Dlaczego to zmieniamy

Treść. BPP to bibliografia publiczna — użytkownik zwykle trafia z wyszukiwarki prosto na rekord publikacji. Zasłonięcie go rozmytą płachtą przy pierwszym wejściu jest barierą dokładnie w tym momencie, w którym serwis ma pokazać, po co się na nim jest.

Prawo. RODO ani ePrivacy nie wymagają blokowania dostępu do treści. Konstrukcja „cookie wall" bywa kwestionowana, bo zgoda wymuszona brakiem alternatywy trudno uchodzi za dobrowolną. Pasek niemodalny jest bezpieczniejszy, nie tylko wygodniejszy.

Dostępność. Overlay o z-index: 9998 przykrywał wszystko: nawigację, wyszukiwarkę i stopkę. Dla użytkownika klawiatury i czytnika ekranu serwis był bezużyteczny do momentu kliknięcia. Problem wyszedł przy pracy nad zgodnością z WCAG — baner blokował dostęp do przełącznika skrótów klawiszowych w stopce.

Dlaczego dół, a nie góra ani bok

Góra zasłania nagłówek i wyszukiwarkę, czyli to, po co użytkownik przyszedł. Bok wymaga osobnego układu na wąskich ekranach i tak kończy jako pas. Dół jest konwencją i nie zabiera treści miejsca.

Szczegóły

  • max-height: 40vh z własnym suwakiem — rozbudowana klauzula nie urośnie na całe okno i nie odtworzy problemu.
  • z-index: 1000 — nad treścią, ale pod modalem wyszukiwarki globalnej.
  • scroll-padding-bottom: 8rem na html — realizuje WCAG 2.4.11 (Focus Not Obscured, nowe w 2.2). Bez tego pasek zasłaniałby element, na który przechodzi focus tabulacją przy dolnej krawędzi okna.
  • Znika backdrop-filter: blur(10px) z całego widoku — przeglądarka przeliczała go przy każdym przewinięciu.

Zmiana dotyczy wyłącznie SCSS. Szablon pakietu cookielaw i logika zapisu zgody pozostają nietknięte.

Weryfikacja

Testy nie były uruchamiane lokalnie — na życzenie, maszyna deweloperska jest obciążona równoległą pracą. Weryfikacja spada na CI oraz na wizualną ocenę recenzenta.

Warto obejrzeć: pierwszą wizytę bez zaakceptowanych ciasteczek (pasek u dołu, treść czytelna), zachowanie przy długiej klauzuli oraz przejście tabulacją przez stopkę przy widocznym pasku.

🤖 Generated with Claude Code

mpasternak and others added 10 commits August 7, 2026 15:15
#CookielawBanner byl pelnoekranowym overlayem: 100vw x 100vh, przyciemnienie
rgba(0,0,0,.6), backdrop-filter: blur(10px), z-index 9998. Zaslanial cala
strone do czasu podjecia decyzji o ciasteczkach.

Trzy powody zmiany, w kolejnosci wagi:

- Tresc. BPP to bibliografia publiczna; uzytkownik zwykle trafia
  z wyszukiwarki prosto na rekord publikacji. Zaslonienie go rozmyta plachta
  przy pierwszym wejsciu jest bariera dokladnie tam, gdzie serwis ma pokazac,
  po co sie na nim jest.
- Prawo. RODO ani ePrivacy nie wymagaja blokowania dostepu do tresci.
  Konstrukcja "cookie wall" bywa kwestionowana, bo zgoda wymuszona brakiem
  alternatywy trudno uchodzi za dobrowolna.
- Dostepnosc. Overlay o z-index 9998 przykrywal wszystko: nawigacje, stopke
  i tresc. Do czasu klikniecia serwis byl bezuzyteczny takze dla uzytkownika
  klawiatury i czytnika ekranu.

Dol, a nie gora ani bok: gora zaslania naglowek i wyszukiwarke, czyli to, po
co uzytkownik przyszedl; bok wymaga osobnego ukladu na waskich ekranach i tak
konczy jako pas.

Pasek dostaje max-height 40vh z wlasnym suwakiem, zeby rozbudowana klauzula
nie urosla na cale okno i nie odtworzyla problemu. Dodane
scroll-padding-bottom na html realizuje WCAG 2.4.11 (Focus Not Obscured,
nowe w 2.2) — bez tego pasek zaslanialby element, na ktory przechodzi focus
tabulacja przy dolnej krawedzi okna.

Zmiana wylacznie w SCSS, bez ingerencji w szablon pakietu cookielaw ani
w logike zapisu zgody.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
Uklad poziomy: tresc po lewej, przyciski po prawej, ktore nie kurcza sie
przy dlugim tekscie (flex-shrink: 0), wiec zawsze sa w tym samym miejscu.
Ponizej 640 px pasek przechodzi w kolumne, a przyciski dziela szerokosc po
polowie. Pasek jest wyrazenie nizszy: znika naglowek <h3>, akapit skrocony
do jednego zdania, ikona z 24 na 18 px, max-height z 40 na 30vh.

Tresc. Naglowek "Informacja o ciasteczkach (tych internetowych, nie tych
slodkich i chrupiacych...)" oraz czteroliniowy akapit zastapione jednym
zdaniem, ktore zachowuje sedno dotychczasowego zartu — paradoks odmowy
wymagajacej ciasteczka — bez rozwlekania: "Uzywamy ich, zeby zapamietac
Twoje ustawienia i policzyc odwiedziny. Odmowa tez zostawia ciasteczko —
bez niego nie zapamietalibysmy Twojej decyzji."

Linki. Wszystkie piec sprawdzone (HTTP 200). Adres dla Edge zawieral
niezakodowane polskie znaki w sciezce i dzialal wylacznie przez
przekierowanie — podmieniony na kanoniczny. Dolozona Opera: dotad wpadala
w galaz Chrome, bo jej user agent zawiera "chrome". Kolejnosc detekcji
poprawiona, bo Edge i Opera podaja sie takze za Chrome i musza byc
sprawdzane wczesniej.

Dostepnosc. Przyciski zgody byly <a href="javascript:...">, czyli linkami,
ktore nigdzie nie prowadza — czesc czytnikow ekranu ich nie udostepnia,
a rola elementu klamie (WCAG 4.1.2). Sa teraz <button type="button">.
Pasek dostal role="region" i aria-label, bez ktorych czytnik oglasza samo
"grupa". Cel dotykowy przyciskow to min. 2.25rem (WCAG 2.5.8). Wstawianie
linku przegladarki przez createElement/textContent zamiast innerHTML.

Sprzatniete przy okazji: martwe klasy .privacy-icon i .cookie-info-links,
nieuzywane w zadnym szablonie. Ta druga byla jedynym miejscem w pliku
siegajacym po zmienna Foundation $primary-color, wiec arkusz kompiluje sie
teraz samodzielnie.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
…tralne

Wysokosc. Przyciski przenieslismy z osobnej kolumny do wiersza z odnosnikami,
wiec pasek ma teraz dwie linie tekstu zamiast wysokosci najwyzszego z dwoch
blokow. Do tego mniejsze przyciski (min-height 1.9rem zamiast 2.25),
drobniejszy tekst (0.85/0.78rem), cianszy padding (0.45rem) i max-height
zbity z 30 na 25vh.

Odnosnik zewnetrzny NASK dostal strzalke. Sam znak jest dekoracja
(aria-hidden), a informacje dla czytnika ekranu niesie sasiedni tekst
"Otwiera sie w nowej karcie" w .show-for-sr — inaczej uzytkownik czytnika
dowiaduje sie o zmianie kontekstu dopiero po fakcie.

Kolory przyciskow. Oba sa teraz neutralnie szare, zamiast zielonego obok
czerwonego. Trzy powody: czerwien znaczy blad albo destrukcje, a odmowa
zgody nie jest ani jednym, ani drugim; RODO wymaga, zeby odmowa byla rownie
latwa jak zgoda, a przycisk wyrozniony kolorem obok wyszarzonego to wzorzec
kwestionowany przez organy ochrony danych jako naciskanie na zgode; przy
rownej wadze wizualnej decyzje podejmuje tresc etykiety, nie kolor.

Zachowany focus-visible z widocznym pierscieniem (WCAG 2.4.7) i cel dotykowy
powyzej progu 24 px (2.5.8).

Sprzatniete: osierocona regula .cookie-info-links a:hover, ktora przetrwala
poprzednie usuniecie samej klasy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
…onowo

Uklad. Po lewej zdanie, pod nim odnosniki jeden pod drugim; po prawej
przyciski wysrodkowane pionowo wzgledem tej kolumny. Ponizej 640 px pasek
przechodzi w pion: zdanie, odnosniki po polowie szerokosci, przyciski
rowniez po polowie.

Font wrocil do poprzedniego rozmiaru — 0.9rem dla zdania i 0.8rem dla
odnosnikow zamiast 0.85/0.78. Przyciski 0.85rem przy min-height 2rem,
nadal powyzej progu 24 px z WCAG 2.5.8.

Odnosniki ukladaja sie pionowo przez `display: block`. Wstawiany przez JS
link przegladarki mieszka w opakowujacym spanie, ktory dostal
`display: contents` — bez tego nie dalby sie ulozyc ani blokowo na szerokim
ekranie, ani po polowie na waskim, bo span zostawal miedzy kontenerem
a odnosnikiem. Zniknal tez separator " · ", zbedny przy ukladzie pionowym.

Link przegladarki dostal taka sama strzalke zewnetrzna i taki sam ukryty
tekst "Otwiera sie w nowej karcie" jak odnosnik NASK — wczesniej mial go
tylko ten drugi, choc oba wychodza poza serwis.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
Przyciski. "Zgadzam sie", a pod nim "Nie zgadzam sie" — pionowo, po prawej
stronie tekstu. Ponizej 640 px wracaja obok siebie i dziela szerokosc po
polowie, bo w kolumnie zajelyby dwa razy wiecej wysokosci na ekranie,
na ktorym jest jej najmniej.

Rozmiar tekstu. Zdanie, odnosniki i przyciski nie maja juz wlasnego
font-size — dziedzicza rozmiar po reszcie strony. Pomniejszanie komunikatu
o zgodzie jest wzorcem, ktory organy ochrony danych traktuja jak ukrywanie
informacji: zgoda ma byc rownie czytelna jak tresc, na ktora sie zgadzamy.
Zniknelo tez przygaszenie odnosnikow (opacity .85), z tego samego powodu
i dla kontrastu.

Strzalka odnosnika zewnetrznego. U+2197 ma w wiekszosci krojow bardzo niska
pozycje wzgledem linii pisma i ladowala pod tekstem. vertical-align: middle
wyrownuje ja do srodka x-height, a line-height: 1 odcina od interlinii, zeby
nie rozpychala wiersza w pionie.

Zaslanianie dolu strony. Pasek jest position: fixed, wiec nie zajmuje miejsca
w przeplywie i przykrywal stopke na stale — nie dalo sie przewinac do konca.
Skrypt rezerwuje na body padding-bottom rowny zmierzonej wysokosci paska
i aktualizuje go przez ResizeObserver, bo wysokosc zalezy od dlugosci tekstu,
szerokosci okna i ustawien czcionki uzytkownika. Ten sam zapas trafia do
scroll-padding-bottom (WCAG 2.4.11), a po decyzji o ciasteczkach oba sa
zerowane.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
Uklad tresci. Odnosniki plyna teraz w tym samym akapicie co zdanie,
rozdzielone kropka srodkowa, zamiast stac jeden pod drugim. Pasek robi sie
przez to nizszy o dwa wiersze na szerokim ekranie.

Ikona odnosnika zewnetrznego. Znak U+2197 zastapiony malym SVG (kwadrat
z wychodzaca strzalka). Powod: U+2197 siedzi w wiekszosci krojow daleko
ponizej linii pisma i nie da sie tego wyrownac przenosnie — kazdy krój ma
inna metryke, wiec `vertical-align: middle` poprawialo sytuacje w jednym
foncie i psulo w drugim. SVG ma wlasne pudelko o znanej wysokosci
(0.75em), wiec wyrownanie dziala tak samo wszedzie.

Ikone rysujemy raz w szablonie, a link przegladarki dostaje jej klon przez
cloneNode — jedno zrodlo ksztaltu zamiast dwoch kopii sciezek SVG.

Separatory i sama ikona maja aria-hidden: czytnik ekranu odczytalby je jako
"kropka srodkowa" i opis grafiki, co nic nie wnosi. Informacje o wyjsciu
poza serwis niesie ukryty tekst "Otwiera sie w nowej karcie" przy kazdym
z odnosnikow.

Sprzatniete: martwa regula w media query, ktora odwolywala sie do
usunietego kontenera .cookie-pasek__linki.

Zbudowane statyki (grunt build) — poprzednie commity zmienialy sam SCSS,
wiec efekt nie byl widoczny bez przebudowy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
Ikona odnosnika zewnetrznego rozpychala wysokosc wiersza. Miala
`vertical-align: 0.02em`, czyli dodatnia wartosc, ktora podnosi cale pudelko
ikony ponad linie pisma — a to zwieksza wysokosc wiersza i sprawia, ze tekst
obok wyglada, jakby mial wyzsza linie bazowa i inny rozmiar. Stad wrazenie,
ze odnosniki sa mniejsza czcionka; w rzeczywistosci dziedzicza ten sam
rozmiar co reszta paska. Pozycje poprawiamy teraz przez `position: relative`
+ `top`, ktore jest czysto wizualne i nie dotyka ukladu wiersza. Odstep od
tekstu zwiekszony z 0.3 na 0.45em.

Przyciski wracaja obok siebie. Ustawione pionowo zajmowaly wiecej wysokosci
niz sam tekst paska, przez co nad zdaniem i pod nim robilo sie duzo pustego
miejsca — pasek mial byc niski, a rosl przez uklad przyciskow.

Odcienie. "Zgadzam sie" dostaje stonowana zielen, "Nie zgadzam sie" zostaje
neutralnie szary. Czerwieni nadal nie uzywamy: odmowa nie jest bledem ani
operacja destrukcyjna, a czerwony sugerowalby jedno albo drugie. Oba
przyciski maja te sama wage wizualna — identyczny rozmiar, ta sama grubosc
ramki, porownywalny kontrast — wiec rozni je odcien, nie donosnosc. RODO
wymaga, zeby odmowa byla rownie latwa jak zgoda.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
Ikona byla elementem inline, wiec zachowywala sie jak pierwszy znak
akapitu: drugi i kolejne wiersze zaczynaly sie od lewej krawedzi, podplywajac
pod nia. Teraz jest pozycjonowana absolutnie wzgledem akapitu (ktory dostal
position: relative), a tekst ma padding-left na jej szerokosc z odstepem.
Wszystkie wiersze zaczynaja sie w tej samej kolumnie.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8RjSZWMR6L7fuRDJJZW4L
@mpasternak
mpasternak merged commit c495d0d into dev Aug 9, 2026
22 checks passed
@mpasternak
mpasternak deleted the fix-cookie-banner-pasek branch August 9, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant