Search code examples
htmlcsscss-selectorspdf-generationbrowsershot

HTML to PDF: Elements overlapping fixed footer


I would like to render HTML to PDF. To get this working, I make use of Browsershot, which uses a headless Chrome to render the HTML and CSS.

This is my additional style to fit A4-format:

<head>
    <meta charset="utf-8">
    <meta content="IE=edge" http-equiv="X-UA-Compatible">
    <meta content="width=device-width,initial-scale=1.0" name="viewport">
    <!-- Styles -->
    <link href="{{ asset(('/css/app.css')) }}" rel="stylesheet">

    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link
        href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap"
        rel="stylesheet">

    <style>
        @page {
            size: A4;
            margin: 11mm 17mm 6mm 17mm;
        }

        @media print {
            #footer {
                position: fixed;
                bottom: 0;
            }

            .unbreak-element {
                page-break-inside: avoid;
                page-break-after: avoid;
            }

           /* html, body {
                 height: 297mm;
            }*/
        }

    </style>
</head>

This is my footer, which is included:

<div class="grid grid-cols-3" id="footer">
    <address class="text-muted not-italic text-xs text-gray-900 font-extralight">
        Text <br/>
        Text <br/>
        Text <br/>
        Text <br/>
     </address>
    <div class="text-muted not-italic text-xs text-gray-900 font-extralight">
        Text <br/>
        Text <br/>
        Text <br/>
        Text <br/>
    </div>
    <div class="text-muted not-italic text-xs text-gray-900 font-extralight">
        Text <br/>
        Text <br/>
        Text <br/>
        Text <br/>
    </div>
</div>

My problem is: Very large elements are now overlapping the footer-section like this:

enter image description here

My question: How can I avoid overlapping and break the table to the next page?


Solution

  • There is an answer that answers a similar question that references an article that might help you along.

    The gist of it is that you need tables to get space reserved at to bottom for a fixed footer:

    .main-footer .inner {
      bottom: 0;
      position: fixed;
    }
    <table>
      <tbody>
        <tr>
          <td>
            <header>
              <h1>Page Title</h1>
            </header>
            
            <p>Lorem ipsum...</p>
          </td>
        </tr>
      </tbody>
      
      <tfoot>
        <tr>
          <td>
            <footer class="main-footer">
              <div class="inner">
                <small>© YEAR AUTHOR</small>
              </div>
            </footer>
          </td>
        </tr>
      </tfoot>
    </table>

    This is not ideal since these are not semantic tables. I managed to get CSS tables to work in firefox like so:

    body {
      display: table;
    }
    
    .main-header,
    .main-body {
      display: table-row-group;
    }
    
    .main-footer {
      display: table-footer-group;
    }
    <header class="main-header">
      <h1>Page Title</h1>
    </header>
    
    <div class="main-body">
      <p>Lorem ipsum...</p>
    </div>
    
    <footer class="main-footer">
      <small>© YEAR AUTHOR</small>
    </footer>

    However once I tried to fix the footer to the bottom position with

    <footer class="main-footer">
      <div class="inner">
        <!-- footer content -->
      </div>
    </div>
    
    .main-footer {
      display: table-footer-group;
    }
    
    .main-footer::after {
      content: "";
      display: block;
      height: 2em;
    }
    
    .main-footer .inner {
      bottom: 0;
      display: block;
      position: fixed;
    }
    

    ...firefox the footer is painted twice (with a slight offset). I believe this is a browser bug.

    All the while CSS tables won’t work in chrome at all (I also believe this is a bug).