Nagłówek i stopka dla wydruku w CSS

HTML i CSS są bardzo wygodnymi językami do przygotowywania raportów. Generowanie kodu jest o wiele prostszym zadaniem niż generowanie plików .docx czy .xlsx. I choć powstały one pierwotnie do opisu dokumentów i są w pewnym stopniu przystosowane do formatowania wydruku, potrafią one w niektórych okolicznościach wciąż przysporzyć dużo kłopotów. Jednym z nich jest możliwość przygotowania nagłówka i stopki dla każdej strony wydruku.

Nie udało mi się odnaleźć rozwiązania dedykowanego; w Internecie krążą fragmenty kodu pokroju position: running(header);, ale – mówiąc najprościej – po prostu nie działają. Konieczne jest więc – niestety – zastosowanie kilku sztuczek.

Po pierwsze, potrzebujemy wstawić na stronę element, który będzie powtarzany na każdej stronie. Okazuje się jednak, że wystarczy w tym celu ustawić mu parametr position na fixed. Przykładowy nagłówek i stopka mogą więc wyglądać tak:

div.header {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    width: 100%;
    height: 15mm;
    background-image: url(/img/header.png);
    background-repeat: no-repeat;
    background-size: 180pt;
    background-position: right top;
}

div.footer {
    position: fixed;
    left: 0;
    bottom: 0;
    right: 0;
    width: 100%;
    height: 15mm;
    background-image: url(/img/footer.png);
    background-repeat: no-repeat;
    background-size: 250pt;
    background-position: right bottom;
}
<div class="header"></div>
<div class="footer"></div>

To rozwiązuje wyświetlanie nagłówka i stopki na każdej stronie wydruku. Niestety jednak pojawia się kolejny problem, ponieważ position: fixed; wyjmuje je z normalnego layoutu, co z kolei powoduje, że zlewają się one z zawartością strony.

Oczywiście moglibyśmy rozwiązać problem przy pomocy bloku z ustawionym marginesem, tylko znów wracamy do punktu wyjścia: margines ów musielibyśmy przecież również powtórzyć na każdej stronie. I tu pojawia się druga sztuczka: na każdej stronie domyślnie powtarzany jest bowiem nagłówek i stopka tabeli.

Wprowadzamy więc dwa dodatkowe style dla bloków, które staną się naszymi marginesami, a następnie ubieramy całą zawartość strony w tabelę z odpowiednio skonstruowanym nagłówkiem i stopką.

div.header-spacer {
    height: 15mm;
}

div.footer-spacer {
    height: 15mm;
}
<table>
    <thead>
        <tr>
            <td><div class="header-spacer"></div></td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                
                <!-- HERE GOES PAGE CONTENT -->
                
            </td>
        </tr>
    </tbody>

    <tfoot>
        <tr>
            <td>
                <div class="footer-spacer"></div>
            </td>
        </tr>
    </tfoot>
</table>

Nie jest to oczywiście rozwiązanie idealne, ale przynajmniej działa i nie powoduje zbyt wielu problemów z formatowaniem zawartości strony.