Skip to content

Style wydruku (@media print) dla front-endu i panelu administracyjnego - #801

Open
mpasternak wants to merge 3 commits into
devfrom
worktree-print-styles
Open

Style wydruku (@media print) dla front-endu i panelu administracyjnego#801
mpasternak wants to merge 3 commits into
devfrom
worktree-print-styles

Conversation

@mpasternak

Copy link
Copy Markdown
Member

Po co

Wydruk stron BPP był w praktyce nieużywalny: szare tło, drukująca się
nawigacja i stopka, nagłówki wielkości plakatu, a wydruk z admina zaczynał
się całą czarną stroną z menu modeli. Ten PR porządkuje @media print
osobno dla serwisu publicznego i osobno dla admina.

Efekt (realny wydruk, headless Chrome, A4, dump produkcyjny)

przed po
Strona główna 7 stron, szare tło, menu + baner cookies + widget WCAG 4 strony, białe tło, sama treść
Lista zmian w adminie 15 stron, pierwsza cała czarna, 6,5 MB 5 stron, tabela od str. 1, 190 KB
Formularz w adminie 11 stron, pomoce kontekstowe i przyciski 10 stron, same wartości pól
Tekst / h1 9 pt / 24 pt 10,5 pt / 16 pt

Co się zmienia

Front-end — przepisany src/bpp/static/scss/_print.scss: białe tło,
ukryte chrome i widgety zewnętrzne, skala typografii sprowadzona do
rozmiarów dokumentu.

Admin — nowy src/bpp/static/bpp/scss/admin-print.scss. Osobny plik,
bo admin-style.css, admin-menu.css i admin-themes.css są linkowane
z media="screen" — reguły @media print dopisane do któregokolwiek
z nich przeglądarka pobierze, ale nigdy nie zastosuje.

Błędy naprawione przy okazji

Nie były w pierwotnym zakresie, ale każdy sam w sobie psuł wydruk:

  1. hide-on-print nigdy nie istniała w CSS — 0 wystąpień w każdym
    skompilowanym arkuszu. Polegały na niej cztery szablony BPP oraz
    zewnętrzny pakiet django-countdown. Dlatego klasa została
    zdefiniowana, a nie zamieniona w szablonach na hide-for-print
    pakietu z venv i tak nie poprawimy.

  2. Marginesy strony z django-constance (WYDRUK_MARGINES_*) były
    ignorowane.
    @page nie ma specyficzności ani !important
    rozstrzyga wyłącznie kolejność, a blok <style> stał przed
    arkuszem, w którym Foundation emituje @page { margin: .5cm }.
    Przeniesiony za arkusze.

  3. #grp-content { padding-bottom: 50vh } w Grappellim. Pomiar
    w trybie print dał 80px 20px 360px — pół pustej kartki doklejone
    do każdego wydruku z admina.

  4. .grp-changelist-results { float: left } — wysoki float nie dzieli
    się między strony, więc szedł w całości na stronę drugą, zostawiając
    pierwszą pustą.

  5. @import "print" stał w kaskadzie PRZED blokiem @media print
    Foundation
    (bo common.scss wchodzi przed foundation-includes).
    Przeniesiony na koniec każdego app-*.scss.

Weryfikacja

  • Brak regresji na ekranie — dowód wprost: po wycięciu z buildów sprzed
    i po zmianie wszystkich bloków @media print reszta CSS-u jest bajt
    w bajt identyczna (230 886 B dla app-green, 232 126 B dla app-blue).
    Ekran nie mógł się zmienić.
  • Testy lokalne: pytest -m "not playwright" — 9438 przeszło,
    0 błędów, 4 pominięte. (W pierwszym przebiegu jeden flake
    test_strona_rekordu_naprawde_sie_cachuje — kolizja cache'a między
    workerami xdist; przy powtórzeniu pełnej suity nie wystąpił, izolowanie
    i przy -n 4 przechodzi.)
  • Wizualnie: wydruki do PDF dla strony głównej, opisu publikacji,
    strony autora, listy zmian i formularza w adminie.
  • npx grunt build i pre-commit przechodzą.

Czego nie zweryfikowano twardo

Marginesy @page potwierdzone strukturalnie (blok stoi za arkuszami,
Foundation faktycznie emituje konkurencyjne @page), ale nie zmierzone
w milimetrach na papierze — Playwright page.pdf() narzuca własny rozmiar
strony, więc nie byłby to uczciwy dowód. Warto kliknąć podgląd wydruku
w Chrome z podkręconą wartością w constance.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YDWJPTz55i4uM2A9pFM4Qn

mpasternak and others added 3 commits September 6, 2026 08:11
Przepisany `_print.scss`. Trzy problemy, każdy z inną przyczyną:

1. TŁO. Foundation robi `* { background: transparent !important }`, ale
   selektor `*` przegrywa specyficznością z `html { background-color:
   #e6e6e6 !important }` z `_layout.scss` (0,0,1 vs 0,0,0) i w ogóle nie
   matchuje pseudo-elementów, więc gradient z `.gradient-background::before`
   — na dodatek `position: fixed` — szedł na papier jako szara plama.

2. ROZMIARY. Cały projekt wymiarowany jest w `rem`, a przeglądarka nie
   przelicza rem-ów na jednostki papierowe: `h1` Foundation (3rem) wychodził
   ~33 pt, a na stronie autora 24 pt. Teraz rem-base jest zakotwiczony w `pt`
   (deterministyczny wydruk niezależny od domyślnej czcionki przeglądarki),
   a tekst i nagłówki mają jawne rozmiary. `!important` na nagłówkach jest
   konieczne — komponenty mają własne, bardziej specyficzne reguły w rem.

   Usunięty też `div { font-size: 9pt }` z poprzedniej wersji: rozmiar
   wpisany na KAŻDY div zabija dziedziczenie.

3. CHROME. Ukryte: sticky-nav, title-bar, okruszki, stopka, menu boczne,
   baner cookies, baner serwera testowego, komunikaty flash oraz widgety
   wstrzykiwane JS-em (UserWay, Freshworks), których nie da się oznaczyć
   klasą w szablonie.

Poza tym:

- `.hide-on-print` NIGDY nie miała definicji w CSS (0 wystąpień w każdym
  skompilowanym arkuszu). Polegały na niej cztery szablony BPP ORAZ
  zewnętrzny `django-countdown`, więc definiujemy klasę zamiast przepisywać
  szablony na `hide-for-print` — pakietu z venv i tak nie poprawimy.

- `@import "print"` przeniesiony z `common.scss` na koniec każdego
  `app-*.scss`: `common` wchodzi PRZED `foundation-includes`, więc dotąd
  nasz blok `@media print` stał w kaskadzie przed blokiem Foundation.

- `@page` z django-constance (WYDRUK_MARGINES_*) w `bare.html` przeniesione
  ZA arkusze stylów. `@page` nie ma specyficzności ani `!important` —
  decyduje wyłącznie kolejność, a Foundation emituje własne
  `@page { margin: .5cm }`, które dotąd po cichu wygrywało. Ustawienia
  marginesów uczelni nie miały żadnego efektu.

- Usunięty `div.grid-x { display: block }`: przy `display: block` komórki
  tracą kontekst flex, ale ZACHOWUJĄ `max-width` z klas `medium-*`, więc
  kafelki strony głównej drukowały się jako wąski słupek na kilka stron.

Zweryfikowane realnym wydrukiem (headless Chrome, A4, dump produkcyjny):
strona główna 7 -> 4 strony. Po wycięciu z obu buildów wszystkich bloków
`@media print` reszta CSS-u jest bajt w bajt identyczna, więc wygląd na
ekranie nie mógł się zmienić.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YDWJPTz55i4uM2A9pFM4Qn
Nowy entrypoint `admin-print.scss` -> `bpp/css/admin-print.css`, wpięty
w Gruntfile (`sass:adminprint` + `concurrent:themes`) i linkowany
w `admin/base_site.html`.

DLACZEGO OSOBNY PLIK, a nie sekcja w admin-themes.scss: admin-style.css,
admin-menu.css i admin-themes.css są linkowane z `media="screen"`.
Reguły `@media print` dopisane do któregokolwiek z nich przeglądarka
pobierze, ale NIGDY nie zastosuje. Nowy arkusz idzie bez `media`,
a jego treść siedzi w `@media print`, więc na ekranie nie zmienia niczego.

Trzy pułapki Grappelliego, wszystkie zmierzone na prawdziwej instalacji:

1. `#grp-content { padding: 80px 20px 50vh }`. Na ekranie `50vh` rezerwuje
   miejsce pod przyklejoną stopkę z przyciskami. Na wydruku 1vh to 1%
   wysokości PUDEŁKA STRONY — pomiar w trybie print dał
   `80px 20px 360px`, czyli pół pustej kartki doklejone do każdego wydruku.

2. `.grp-changelist-results { float: left }`. Wysoki float NIE dzieli się
   między strony — przeglądarka przepycha go w całości na następną.
   Pierwsza kartka zawierała sam tytuł i była poza tym pusta.

3. `#grp-header { position: fixed }` i `.grp-fixed-footer` — elementy fixed
   lądują przy druku na pierwszej stronie NA treści.

Poza tym ukryte: nagłówek admina z pełnym menu modeli (drukował się jako
CAŁA CZARNA PIERWSZA STRONA), breadcrumbs, panel filtrów Grappelliego
i BPP, wyszukiwarka, paginacja, kolumna checkboxów akcji, przyciski
i teksty pomocy w formularzu. Tabele: powtarzany nagłówek na kolejnych
kartkach, ramki zamiast zebry, czarny tekst na białym.

Skala typografii ujednolicona z frontem (`_print.scss`).

Zweryfikowane realnym wydrukiem (headless Chrome, A4, dump produkcyjny):
lista zmian 15 -> 5 stron i 6,5 MB -> 190 KB, formularz 11 -> 10 stron.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YDWJPTz55i4uM2A9pFM4Qn
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YDWJPTz55i4uM2A9pFM4Qn
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