Multipage issue with invoice template Calm

Good day, dear fellow Invoice Ninja users and programmers,

first of all I hope you’ll come along with my English. I’m from Germany and lost some of my English language flow. So I hope that I can make myself and my issue clear.

So let’s go.

I use the template Calm as basis for my own invoice template. In Germany it’s kind of state of the art to write an invoice like a business letter. We also have a DIN for that (that’s like an ISO).

However the template Calm – and so my customized template does – creates a blank page in front and sometimes another blank page at the end if there are too many articles in the invoice (or offer). Seems that other templates are working correctly. But I did not test that, yet, because some templates are very compact. So I had to create too many dummy articles.

Does anyone use template calm, too? Has someone customized it so the template works perfectly?

Or has someone a nice template fitting for Germany he or she would share? That would be great!

Thank you and have a great day or night

Schmitti

Hi,

@david any thoughts?

@Schmitti

I am not able to recreate the multi page issue from my testing. Have you modified the design , or are you able to share a screenshot of the current design

Hello David and hillel,

thanks a lot for your fast reply! Yes, I customized Calm.

It’s weird, as I made a second offer today, multipage pdf works “well”. And when I say “well”, I mean it’s okay, but not perfect. However there are some screenshots I made.

Offer #1 is the problem I told about.
Offer #2 is a new offering today created.
Offer #3 is again the first one with one further article added, to reproduce the blank last page.

I hope that helps.

I cannot say what’s different now. But “at least” the first one is still wrong.

However, as you can see, the header on further pages overlaps the body of the offering. But I guess, my bad html- and css-knowings are causing this.

Greetz

Schmitti

What did you customize?

Hello, David,

I’ll try to paste the code.

  1. The Body
<div id="body">
<table style="min-width: 100%">
   <thead>
      <tr>
         <td>
            <div class="repeating-header-space">&#xA0;</div>
         </td>
      </tr>
   </thead>

   <tbody>
      <tr>
         <td>
            <div id="">
                    <div class="header-wrapper">
                    </div>
                **<div class="absender">$company.name | $company.address1 | $company.postal_code $company.city</div>**
                <div class="header-wrapper2">
                    <div id="client-details"></div>
                    <div id="vendor-details"></div>
                    <div id="shipping-details"></div>
                    <div>
                        <p class="entity-label" style="font-size:32px; font-weight: bold; color:$primary_color;">$entity_label</p>
                        <table id="entity-details" cellspacing="0" cellpadding="0" dir="ltr"></table>
                    </div>
                </div>

**<div id="middle-space"></div>**

               <table id="product-table" cellspacing="0" data-ref="table"></table>
               <table id="task-table" cellspacing="0" data-ref="table"></table>
               <table id="delivery-note-table" cellspacing="0" data-ref="table"></table>
               <table id="statement-invoice-table" cellspacing="0" data-ref="table"></table>
               <div id="statement-invoice-table-totals" data-ref="statement-totals"></div>
               <table id="statement-payment-table" cellspacing="0" data-ref="table"></table>
               <div id="statement-payment-table-totals" data-ref="statement-totals"></div>
               <table id="statement-aging-table" cellspacing="0" data-ref="table"></table>
               <div id="statement-aging-table-totals" data-ref="statement-totals"></div>
               <div id="table-totals" cellspacing="0">$status_logo</div>
            </div>
         </td>
      </tr>
   </tbody>
   <tfoot>
      <tr>
         <td>
            <div class="repeating-footer-space">&#xA0;</div>
         </td>
      </tr>
   </tfoot>
</table>
</div>
  1. The Header
<div class="repeating-header" id="header">

<!--        <div class="logo-container"> -->
            <img class="company-logo" src="$company.logo" alt="$company.name – Logo">
<!--        </div> -->

</div>
  1. The Footer
<div id="footer" style="margin-bottom: 1.5em;">
    <div style="width: 100%;">
        <p data-ref="total_table-footer">$entity_footer</p>
        <script>
            // Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
            document.addEventListener('DOMContentLoaded', () => {
                let tables = [
                    'product-table', 'task-table', 'delivery-note-table',
                    'statement-invoice-table', 'statement-payment-table', 'statement-aging-table-totals',
                    'statement-invoice-table-totals', 'statement-payment-table-totals', 'statement-aging-table',
                    'vendor-details', 'client-details'
                ];

                tables.forEach((tableIdentifier) => {
                    console.log(document.getElementById(tableIdentifier));
                    document.getElementById(tableIdentifier)?.childElementCount === 0
                        ? document.getElementById(tableIdentifier).style.setProperty('display', 'none', 'important')
                        : '';
                });
            });
        </script>
    </div>

    **<!-- Hier kommt rein, was unter den Strich soll --> (This means: Put in here what's coming under the line)**
**    <table style="min-width: 100%;">**
**        <tr style="vertical-align: top;">**
**            <td style="width: 32%; padding-left: 1pt; padding-right: 5em;">**
**                <div id="company-details"></div>**
**            </td>**

**            <td style="width: 11%; border-left: 1px solid #000; padding-left: 5pt; padding-right: 5pt">**
**                Tel.**
**                <br>Fax**
**                <br>E-Mail**
**                <br>Steuernr.**
**            </td>**

**            <td style="width: 22%; <!-- text-align:right-->; padding-right: 5pt">**
**                <div id="company-address"></div>**
**            </td>**

**            <td style="width: 33%; border-left: 1px solid #000; padding-left: 5pt; padding-right: 5pt">**
**                My bank name**
**                <br>(some further bank information)**
**                <br>IBAN**
**                <br>Swift/BIC**
**            </td>**
**    </tr>**

</div>
  1. The Includes
<style id="style">
    @import url($font_url);

    :root {
        --primary-color: $primary_color;
        --secondary-color: $secondary_color;
        --line-height: 1.25;
    }

    body {
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        font-family: $font_name, Helvetica, sans-serif;
        font-size: $font_size !important;
        zoom: 80%;
    }


    table tr td, table tr, th {
        font-size: $font_size !important;
    }
    
    html {
        margin: 0;
        padding-top: 1rem;
        padding-left: 4rem;
	       padding-right: 4rem; 
    }

    @page {
        margin: 0 !important;
        size: $page_size $page_layout;
    }

    p {
        margin: 0;
        padding: 0;
    }

   **#middle-space {**
**      padding-top: 2rem;**
**   }**

    .header-wrapper {
        display: grid;
        margin-top: 2rem;
        gap: 20px;
        grid-template-columns: 2.44fr 1fr 1fr;
        grid-template-areas: "a b c";
        grid-auto-columns: minmax(0, 5fr);
        grid-auto-flow: column;
        justify-content: left;
    }

    **.absender {**
**    margin-top: 4rem;**
**    padding-top: 3rem;**
**    font-size: 8.5pt;**
**    }**

    .header-wrapper2 {
        display: grid;
        margin-top: 3rem;
        gap: 20px;
        grid-template-columns: 2fr 2fr auto;
        grid-template-areas: "a b c";
        grid-auto-columns: minmax(0, 5fr);
        grid-auto-flow: column;
        justify-content: left;
    }
    
    .company-logo {
        max-width: 42%;
        /*max-width: $company_logo_size*/;
    }

    .logo-container {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .company-container {
        display: flex;
        flex-direction: column;
        margin-top: 1rem;
    }
    .client-and-entity-wrapper {
        display: flex;
        padding: 1rem;
        border-top: 1px solid #d8d8d8;
        border-bottom: 1px solid #d8d8d8;
    }

    .header-wrapper #company-address {
        display: flex;
        flex-direction: column;
        line-height: var(--line-height);
    }

    .header-wrapper #company-details {
        display: flex;
        flex-direction: column;
        line-height: var(--line-height);
    }

    .header-wrapper #entity-details {
        padding-right: 0.5rem;
        text-align: left;
        line-height: var(--line-height);
        width: 100%;
    }

    .header-wrapper #entity-details > tr,
    .header-wrapper #entity-details th {
        font-weight: normal;
        white-space: nowrap;
    }
	
    .header-wrapper
    #entity-details
    [data-element='entity-balance-due-label'],
    .header-wrapper
    #entity-details
    [data-element='entity-balance-due'] {
        background-color: #e6e6e6;
    }

	#entity-details {
        **padding-left: 0.22rem; /* Überschrift "Rechnung" leicht nach links versetzen */**
        text-align: left;
        width: 100%;
	}
	
	#entity-details th {
        font-weight:normal;
        line-height: 1.5rem;
        padding-right: 2rem;
	}
	
    #client-details {
        display: flex;
        flex-direction: column;
        line-height: var(--line-height);
/*        font-size: 13pt; */
    }

    #shipping-details {
        visibility: $show_shipping_address_visibility;
        flex-direction: column;
        line-height: var(--line-height);
    }

    [data-ref="table"] {
        margin-top: 2rem;
        min-width: 100%;
        table-layout: fixed;
        overflow-wrap: break-word;
    }

    .task-time-details {
        display: block;
        margin-top: 5px;
        color: grey;
    }

    [data-ref="table"] > thead {
        text-align: left;
    }

    [data-ref="table"] > thead > tr > th {
        padding: 1rem;
        background-color: #f5f5f5;
    }

    [data-ref="table"] > thead > tr > th:last-child {
        text-align: right;
    }

    [data-ref="table"] > tbody > tr > td {
        border-bottom: 1px solid #e6e6e6;
        padding: 0.75rem;
        vertical-align: top;
    }

    [data-ref="table"] > tbody > tr > td:last-child {
        text-align: right;
        vertical-align: top;
    }

    [data-ref="table"] > tbody > tr:nth-child(even) {
        background-color: #f5f5f5;
    }
    
    #table-totals {
        margin-top: 0.5rem;
        display: grid;
        grid-template-columns: 1.5fr 1fr;
        padding-top: .5rem;
        gap: 80px;
        page-break-inside:auto;
        overflow: visible !important;
        font-weight: bold;
        line-height: var(--line-height);

    }

    #table-totals .totals-table-right-side>* {
        display: grid;
        grid-template-columns: 1fr 1fr;
    }

    #table-totals>.totals-table-right-side>*> :nth-child(1) {
        text-align: left;
        margin-top: .25rem;
        padding-left: 7px;
    }

    #table-totals>.totals-table-right-side> * > :not([hidden]) ~ :not([hidden]) {
        --tw-space-y-reverse: 0;
        margin-top: calc(.25rem * calc(1 - var(--tw-space-y-reverse)));
        margin-bottom: calc(.25rem * var(--tw-space-y-reverse));
    }

    #table-totals>.totals-table-right-side>*> :nth-child(2) {
        text-align: right;
        padding-right: 0.72rem;
    }
	
    #table-totals
    > *
    [data-element='total-table-balance-due-label'],
    #table-totals
    > *
    [data-element='total-table-balance-due'] {
        font-weight: bold;
    }

    #table-totals > * > :last-child {
        text-align: right;
        padding-right: 1rem;
    }

    [data-ref="total_table-footer"] {
        padding-left: 1rem;
        padding-right: 1rem;
    }

    [data-ref="totals_table-outstanding"] {
        color: var(--primary-color)
    }

    /** Markdown-specific styles. **/
    [data-ref="table"] h3 {
        font-size: 1rem;
        margin-bottom: 0;
    }

    [data-ref="totals_table-outstanding-label"],
    [data-ref="totals_table-outstanding"] {
        background-color: #e6e6e6;
        color: black;
        padding-top: 7px;
        padding-bottom: 7px;
        padding-right: 7px;
    }

    [data-ref="statement-totals"] {
        margin-top: 1rem;
        text-align: right;
        margin-right: .75rem;
    }

    [data-ref*=".line_total-td"] {
        white-space: nowrap;
    }

    .repeating-footer,
    .repeating-footer-space {
        height: 150px;
    }

    .repeating-header {
        position: fixed;
        top: 3em;
    }

    .repeating-footer {
        position: fixed;
        bottom: 0;

    }

    #header {
        position: fixed;
        top: 4em;
    }

    #footer {
        position: fixed;
        bottom: 00;
        border-top: 1px solid #000;
        width: 82%;
        min-height:100px;
        padding-top: 0.3rem;
        margin-top: 40px;
    }

    [data-element='product_table-product.description-td'], td {
        min-width:100%;
        max-width: 300px;
        overflow-wrap: break-word; 
    }

    [data-ref="total_table-public_notes"] { font-weight: normal; } 
    [data-ref="total_table-terms"] { font-weight: normal; } 

    /* [data-ref="shipping_address-label"] {
        display: none;
    } */

    .stamp {
      transform: rotate(12deg);
        color: #555;
        font-size: 3rem;
        font-weight: 700;
        border: 0.25rem solid #555;
        display: inline-block;
        padding: 0.25rem 1rem;
        text-transform: uppercase;
        border-radius: 1rem;
        font-family: 'Courier';
        mix-blend-mode: multiply;
        z-index:200 !important;
        position:  fixed;
        text-align: center;
    }

    .is-paid {
        color:  #D23;
        border: 1rem double  #D23;
        transform: rotate(-5deg);
        font-size: 6rem;
        font-family: "Open sans", Helvetica, Arial, sans-serif;
        border-radius: 0;
        padding: 0.5rem;
        opacity: 0.2;
        z-index:200 !important;
        position:  fixed;
        display: $show_paid_stamp;
    } 

    .project-header {
        font-size: 1.2em;
        margin-top: 0.1em;
        margin-bottom: 0;
        padding-bottom: 0;
        margin-left: 0;
        margin-right: 0;
        font-weight: bold;
        color: #505050;
    } 
    
    .pqrcode {
        
    }
    
    /** Useful snippets, uncomment to enable. **/

    /** Hide company logo **/
    /* .company-logo { display: none } */

    /* Hide company details */
    /* # > * { display: none } */

    /* Hide company address */
    /* #company-address > * { display: none } */

    /* Hide terms label */
    /* [data-ref="total_table-terms-label"] { display: none } */

    /* Hide totals table */
    /* #table-totals { display: none } */

    /* Hide totals table left side */
    /* #table-totals div:first-child > * { display: none !important } */

    /* Hide totals table right side */
    /* .totals-table-right-side { display: none } */

    /** For more info, please check our docs: https://invoiceninja.github.io **/
    /** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
</style>

I marked the lines I added as bold text. But I also deleted some lines. I hope, this is not too much debugging pain for you.

PS: Is it right, that customized text will not appear until the Docker-container has been restarted?