How to put the Terms and Conditions on a separate page of the pdf?

I recently migrated from V4 to V5 (hosted), but my settings did not migrate so well. My invoices now show the T&Cs just below the products/services and total/subtotal columns, whereas I would like them to appear on a separate page.

With V4, I was able to solve the issue by adding this piece of code through the Settings / Customize design page of the hosted app:

{
“pageBreak”: “after”,
“columns”: [
{

This does not work anymore, or is not possible.

Any idea on how to resolve the above when using Hosted V5?

Thank you.

Hi,

@david can you please advise?

I found this answer which seems to work: css - Google Chrome Printing Page Breaks - Stack Overflow

You’d want to add this code on the includes tab:

      div.page
      {
        page-break-after: always;
        page-break-inside: avoid;
      }

And then use the page class to force a break:

    <div class="page">
      <h1>This is Page 1</h1>
    </div>
    <div class="page">
      <h1>This is Page 2</h1>
    </div>
    <div class="page">
      <h1>This is Page 3</h1>
    </div>

Many thanks.

I must admit this goes beyond my programming skills…

Below is a copy of my includes tab. Would you mind at all showing me where, exactly, I ought to add the additional code?

Much appreciated.

<style id="style">
    @import url($font_url);

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

    html {
        width: 210mm;
        height: 200mm;     
    }

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

    @page {
        margin-left: $global_margin;
        margin-right: $global_margin;
        margin-top: 30;
        margin-bottom: 0;
        size: $page_size $page_layout;
    }


    p {
        margin: 0;
        padding: 0;
    }

    .header-container {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        gap: 20px;
    }

    .company-logo {
        max-width: 40%;
    }

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

    #company-details > p:first-child {
        color: var(--primary-color);
    }

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

    .entity-label {
        margin-top: 2.5rem;
        text-transform: uppercase;
        padding-left: 1rem;
        margin-bottom: 1rem;
        font-weight: bold;
        color: var(--primary-color);
    }

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

    #entity-details {
        text-align: left;
        margin-right: 20px;
    }

    #entity-details > tr,
    #entity-details th {
        font-weight: normal;
        padding-right: 15px;
        padding-top: 2.5px;
        padding-bottom: 2.5px;
    }

    #client-details {
        display: flex;
        flex-direction: column;
        line-height: var(--line-height);
    }

    #client-details > :first-child {
        font-weight: bold;
    }

    [data-ref="table"] {
        margin-top: 1rem;
        margin-bottom: 50px;
        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 {
        font-size: 1.1rem;
        padding-bottom: 1.5rem;
        padding-left: 1rem;
    }

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

    [data-ref="table"] > tbody > tr > td:first-child {
        color: var(--primary-color);
    }

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

    [data-ref="table"] > thead > tr > th:last-child {
        padding-right: 1rem;
    }

    [data-ref="table"] > tbody > tr:nth-child(odd) {
        background-color: #f5f5f5;
    }

    #table-totals {
        margin-top: 0rem;
        display: grid;
        grid-template-columns: 2fr 1fr;
        padding-top: .5rem;
        padding-right: 1rem;
        gap: 80px;
        page-break-inside:auto;
        overflow: visible !important;
    }

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

    #table-totals>.totals-table-right-side>*> :nth-child(1) {
        text-align: $dir_text_align;
        margin-top: .75rem;
    }

    #table-totals>.totals-table-right-side>*> :nth-child(2) {
        text-align: right;
    }

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

    #table-totals
    > *
    [data-element='product-table-balance-due-label'],
    #table-totals
    > *
    [data-element='product-table-balance-due'] {
        font-weight: bold;
    }

    #table-totals
    > *
    [data-element='product-table-balance-due'] {
        color: var(--primary-color);
    }

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

    #footer {
        margin-top: 14px;
       text-align: center;
       margin-bottom: 0;
    }

    /** Markdown-specific styles. **/
    #product-table h3,
    #task-table h3,
    #delivery-note-table h3 {
        font-size: 1rem;
        margin-bottom: 0;
    }

    .company-logo-container {
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
    }

    [data-ref="statement-totals"] {
        margin-top: 1rem;
        text-align: right;
        margin-right: .75rem;
    }
    
    [data-ref*=".line_total-td"] {
        white-space: nowrap;
    }

    /** .repeating-header,
    .repeating-header-space, **/
    .repeating-footer,
    .repeating-footer-space {
        height: 10px;
    }
    .repeating-header {
        position: fixed;
        top: 0;
    }
    .repeating-footer {
        position: fixed;
        bottom: 1;
    }

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

You’d want to add the code after the opening style tag

Just to follow on,

after you have made the page break, just use the variable $terms and the terms will be injected.

Many thanks.

I tried all this, but it won’t work regrettably.

The variable $terms is built within the invoice’s “totals-table” code, which makes it impossible to split Terms, through a page break, from the rest of the table that shows the invoice’s total. As a result, the T&Cs are displayed as a column, on the page’s left-hand-side, which does not look right. Here is a screen capture:

I should perhaps consider not adding my T&Cs at all on my invoices, or having these sent to my clients as a separate attachment.

Previously, when using V4 (hosted), I was able to split the T&Cs from the remainder of the invoice. Below is an ectract of the code I used at the time.

I used " “pageBreak”: “after”,
“columns”:

and instered “$notesAndTerms” further down.

  {
    "style": "invoiceLineItemsTable",
    "table": {
      "headerRows": 1,
      "widths": [
        "55%",
        "15%",
        "15%",
        "15%"
      ],
      "body": "$invoiceLineItems"
    },
    "layout": {
      "hLineWidth": "$notFirst:.5",
      "vLineWidth": "$none",
      "hLineColor": "#D8D8D8",
      "paddingLeft": "$amount:8",
      "paddingRight": "$amount:8",
      "paddingTop": "$amount:14",
      "paddingBottom": "$amount:14"
    }
  },
  {
    "columns": [],
    "margin": [
      40,
      -20,
      40,
      10
    ]
  },
  {
    "pageBreak": "after",
    "columns": [
      {
        "table": {
          "widths": [
            "*",
            "40%"
          ],
          "body": "$subtotals"
        },
        "layout": {
          "hLineWidth": "$none",
          "vLineWidth": "$none",
          "paddingLeft": "$amount:34",
          "paddingRight": "$amount:8",
          "paddingTop": "$amount:6",
          "paddingBottom": "$amount:4"
        }
      }
    ]
  },
  "$notesAndTerms",
  "$signature",
  {
    "stack": [
      "$invoiceDocuments"
    ],
    "style": "invoiceDocuments"
  }
]

which resulted in the Terms being on a separate page, as shown on this screen capture.

@Zeidroc Have you found a solution? I’m having the same issue

I haven’t solved the issue so far, so am stuck with invoices which display my T&Cs in a column on the first page’s left-hand side. That’s messy and does not look much professional.

It was easy to fix with V4 and I hope someone will come around with a solution for V5 too!

Hi,

I am afraid that none of the suggestions I was kindly given actually work.

So, I’ve given up trying to put my T&Cs on a separate page and have now reverted back to V4!

That’s too bad, I’m not sure why this solution above isn’t working for you. If you want to share your v5 design we can review it for you.

just in case you still want to do this…

My start template is “Plain”

In the INCLUDES tab, add following code:

/** START terms and conditions on a new page **/
/**  **/
/**  SOURCE - https://forum.invoiceninja.com/t/how-to-put-the-terms-and-conditions-on-a-separate-page-of-the-pdf/11553/5**/
      div.termspage
      {
        page-break-after: always;
        page-break-inside: avoid;
      }

 [data-ref="total_table-terms"] { display: none }

/** END terms and conditions on a new page **/
How it looks in my code


This text will be hidden

Then in the Body add following code before last </div>

 <div class="termspage">$terms</div>

This is not perfect, it will cause the Body div to stretch to the new page, and shift footer below it. Not sure how to fight that yet.

Make it pretty to your taste.

Full template code

{
  "header": "<div class=\"repeating-header\" id=\"header\"></div>",
  "body": "<div id=\"body\">\n                    <div class=\"header-wrapper\">\n                        <div id=\"company-details\"></div>\n                        <div id=\"company-address\"></div>\n                        <div>\n                            <img class=\"company-logo\" src=\"$company.logo\" alt=\"$company.name logo\">                            \n                        </div>\n                    </div>\n                    <div class=\"client-wrapper\">\n                        <div id=\"client-details\"></div>\n                        <div id=\"vendor-details\"></div>\n                        <div id=\"shipping-details\"></div>\n                        <div>\n                            <table id=\"entity-details\" cellspacing=\"0\" cellpadding=\"0\" dir=\"$dir\"></table>\n                        </div>\n                    </div>\n                    <table id=\"product-table\" cellspacing=\"0\" data-ref=\"table\"></table>\n                    <table id=\"task-table\" cellspacing=\"0\" data-ref=\"table\"></table>\n                    <table id=\"delivery-note-table\" cellspacing=\"0\" data-ref=\"table\"></table>\n                    <table id=\"statement-invoice-table\" cellspacing=\"0\" data-ref=\"table\"></table>\n                    <div id=\"statement-invoice-table-totals\" data-ref=\"statement-totals\"></div>\n                    <table id=\"statement-payment-table\" cellspacing=\"0\" data-ref=\"table\"></table>\n                    <div id=\"statement-payment-table-totals\" data-ref=\"statement-totals\"></div>\n                    <table id=\"statement-credit-table\" cellspacing=\"0\" data-ref=\"table\"></table>\n                    <div id=\"statement-credit-table-totals\" data-ref=\"statement-totals\"></div>\n                    <table id=\"statement-aging-table\" cellspacing=\"0\" data-ref=\"table\"></table>\n                    <div id=\"statement-aging-table-totals\" data-ref=\"statement-totals\"></div>\n                    <div id=\"table-totals\" cellspacing=\"0\">$status_logo</div>\n                   d following\n <div class=\"termspage\">$terms</div>\n                </div>",
  "footer": "<div class=\"repeating-footerx\" id=\"footer\">\n    <p data-ref=\"total_table-footer\">$entity_footer</p>\n\n    <script>\n        // Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.\n        document.addEventListener('DOMContentLoaded', () => {\n            let tables = [\n                'product-table', 'task-table', 'delivery-note-table',\n                'statement-invoice-table', 'statement-payment-table', 'statement-aging-table-totals',\n                'statement-invoice-table-totals', 'statement-payment-table-totals', 'statement-aging-table',\n                'client-details', 'vendor-details', 'swiss-qr', 'shipping-details', 'statement-credit-table', 'statement-credit-table-totals',\n            ];\n\n            tables.forEach((tableIdentifier) => {\n                document.getElementById(tableIdentifier).childElementCount === 0\n                    ? document.getElementById(tableIdentifier).style.display = 'none'\n                    : '';\n            });\n        });\n    </script>\n</div>",
  "includes": "<style id=\"style\">\n    @import url($font_url);\n\n    :root {\n        --primary-color: $primary_color;\n        --secondary-color: $secondary_color;\n        --line-height: 1.6;\n    }\n\n    body {\n        -webkit-font-smoothing: antialiased;\n        -moz-osx-font-smoothing: grayscale;\n        font-family: $font_name, Helvetica, sans-serif;\n        font-size: $font_size !important;\n        zoom: 80%;\n    }\n\n    table tr td,\n    table tr,\n    th {\n        font-size: $font_size !important;\n    }\n\n    html {\n        width: 210mm;\n        height: 200mm;\n    }\n\n    @page {\n        margin-left: $global_margin;\n        margin-right: $global_margin;\n        margin-top: 0;\n        margin-bottom: 0;\n        size: $page_size $page_layout;\n\n    }\n\n    p {\n        margin: 0;\n        padding: 0;\n    }\n\n    .header-wrapper {\n        display: grid;\n        grid-template-columns: 1fr 1fr 1fr;\n        line-height: var(--line-height);\n        margin-bottom:10px;\n    }\n\n    .client-wrapper{\n        display: grid;\n        gap: 10px;\n        grid-template-columns: 1fr 1fr 1fr;\n        grid-template-areas: \"a b c \";\n        grid-auto-columns: minmax(0, 1fr);\n        grid-auto-flow: column;\n        justify-content:left;\n        line-height: var(--line-height);\n\n    }\n\n    .company-logo {\n        max-width: $company_logo_size;\n    }\n\n    .header-wrapper #company-address {\n        display: flex;\n        flex-direction: column;\n        line-height: var(--line-height);\n    }\n\n     #entity-details {\n        text-align: left;\n        width: 100%;\n        line-height: var(--line-height) !important;\n        white-space: nowrap;\n    }\n\n    #entity-details>tr,\n    #entity-details th {\n        font-weight: normal;\n        padding-right: 3rem;\n        line-height: var(--line-height) !important;\n    }\n\n    .header-wrapper #entity-details [data-element='entity-balance-due-label'],\n    .header-wrapper #entity-details [data-element='entity-balance-due'] {\n        background-color: #e6e6e6;\n    }\n\n    #client-details {\n        display: flex;\n        flex-direction: column;\n        line-height: var(--line-height);\n        white-space: nowrap;\n    }\n\n    #shipping-details {\n        opacity: $show_shipping_address_visibility;\n        flex-direction: column;\n        line-height: var(--line-height);\n        white-space: nowrap;\n    }\n\n    [data-ref=\"table\"] {\n        margin-top: 1rem;\n        min-width: 100%;\n        table-layout: fixed;\n        overflow-wrap: break-word;\n        margin-bottom: 5px;\n    }\n\n    .task-time-details {\n        display: block;\n        margin-top: 5px;\n        color: grey;\n    }\n\n    [data-ref=\"table\"]>thead {\n        text-align: left;\n    }\n\n    [data-ref=\"table\"]>thead>tr>th {\n        padding: 0.5rem;\n        background-color: #e6e6e6;\n    }\n\n    [data-ref=\"table\"]>thead>tr>th:last-child {\n        text-align: right;\n    }\n\n    [data-ref=\"table\"]>tbody>tr>td {\n        border-bottom: 1px solid #e6e6e6;\n        padding: 0.75rem;\n    }\n\n    [data-ref=\"table\"]>tbody>tr>td:last-child {\n        text-align: right;\n    }\n\n    #table-totals {\n        margin-top: 0rem;\n        display: grid;\n        grid-template-columns: 2fr 1fr;\n        padding-top: .5rem;\n        padding-left: .5rem;\n        margin-right: .75rem;\n        gap: 80px;\n        page-break-inside: auto;\n        overflow: visible !important;\n    }\n\n    #table-totals .totals-table-right-side>* {\n        display: grid;\n        grid-template-columns: 1fr 1fr;\n    }\n\n    #table-totals>.totals-table-right-side>*> :nth-child(1) {\n        text-align: $dir_text_align;\n        margin-top: .25rem;\n        padding-left: 7px;\n    }\n\n    #table-totals>.totals-table-right-side>*> :not([hidden])~ :not([hidden]) {\n        --tw-space-y-reverse: 0;\n        margin-top: calc(.25rem * calc(1 - var(--tw-space-y-reverse)));\n        margin-bottom: calc(.25rem * var(--tw-space-y-reverse));\n    }\n\n    #table-totals>.totals-table-right-side>*> :nth-child(2) {\n        text-align: right;\n        padding-right: 0px;\n    }\n\n    #table-totals>* [data-element='total-table-balance-due-label'],\n    #table-totals>* [data-element='total-table-balance-due'] {\n        font-weight: bold;\n    }\n\n    #table-totals>*> :last-child {\n        text-align: right;\n        padding-right: 1rem;\n    }\n\n    [data-ref=\"total_table-footer\"] {\n        padding-left: 1rem\n    }\n\n    #footer {\n        margin-top: 30px;\n    }\n\n    [data-ref=\"totals_table-outstanding\"] {\n        color: var(--primary-color)\n    }\n\n    /** Markdown-specific styles. **/\n    [data-ref=\"table\"] h3 {\n        font-size: 1rem;\n        margin-bottom: 0;\n    }\n\n    [data-ref=\"totals_table-outstanding-label\"],\n    [data-ref=\"totals_table-outstanding\"] {\n        background-color: #e6e6e6;\n        color: black;\n        padding-top: 7px;\n        padding-bottom: 7px;\n        padding-right: 7px;\n    }\n\n    [data-ref=\"statement-totals\"] {\n        margin-top: 1rem;\n        text-align: right;\n        margin-right: .75rem;\n    }\n\n    [data-ref*=\".line_total-td\"] {\n        white-space: nowrap;\n    }\n\n    /** .repeating-header,\n    .repeating-header-space, **/\n    .repeating-footer,\n    .repeating-footer-space {\n        height: 10px;\n    }\n\n    .repeating-header {\n        position: fixed;\n        top: 0;\n    }\n\n    .repeating-footer {\n        position: fixed;\n        bottom: 0;\n    }\n\n    [data-element='product_table-product.description-td'],\n    td {\n        min-width: 100%;\n        max-width: 300px;\n        overflow-wrap: break-word;\n    }\n\n    .stamp {\n        transform: rotate(12deg);\n        color: #555;\n        font-size: 3rem;\n        font-weight: 700;\n        border: 0.25rem solid #555;\n        display: inline-block;\n        padding: 0.25rem 1rem;\n        text-transform: uppercase;\n        border-radius: 1rem;\n        font-family: 'Courier';\n        mix-blend-mode: multiply;\n        z-index: 200 !important;\n        position: fixed;\n        text-align: center;\n    }\n\n    .is-paid {\n        color: #D23;\n        border: 1rem double #D23;\n        transform: rotate(-5deg);\n        font-size: 6rem;\n        font-family: \"Open sans\", Helvetica, Arial, sans-serif;\n        border-radius: 0;\n        padding: 0.5rem;\n        opacity: 0.2;\n        z-index: 200 !important;\n        position: fixed;\n        display: $show_paid_stamp;\n    }\n\n    .project-header {\n        font-size: 1.2em;\n        margin-top: 0.1em;\n        margin-bottom: 0;\n        padding-bottom: 0;\n        margin-left: 0;\n        margin-right: 0;\n        font-weight: bold;\n        color: #505050;\n    }\n\n    .pqrcode {}\n\n/** START terms and conditions on a new page **/\n/**  **/\n/**  SOURCE - https://forum.invoiceninja.com/t/how-to-put-the-terms-and-conditions-on-a-separate-page-of-the-pdf/11553/5**/\n      div.termspage\n      {\n        page-break-after: always;\n        page-break-inside: avoid;\n      }\n\n [data-ref=\"total_table-terms\"] { display: none }\n\n/** END terms and conditions on a new page **/\n\n\n    /** Useful snippets, uncomment to enable. **/\n\n    /** Hide company logo **/\n    /* .company-logo { display: none } */\n\n    /* Hide company details */\n    /* #company-details > * { display: none } */\n\n    /* Hide company address */\n    /* #company-address > * { display: none } */\n\n    /* Hide public notes */\n    /* [data-ref=\"total_table-public_notes\"] { display: none } */\n\n    /* Hide terms label */\n   [data-ref=\"total_table-terms-label\"] { display: none }\n\n    /* Hide totals table */\n    /* #table-totals { display: none } */\n\n    /* Hide totals table left side */\n    /* #table-totals div:first-child > * { display: none !important } */\n\n    /* Hide totals table right side */\n    /* .totals-table-right-side { display: none } */\n\n    /** For more info, please check our docs: https://invoiceninja.github.io **/\n    /** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/\n</style>"
}

Also, Split Terms and Public notes to dedicated pages - #24 by checkitsedo
has a better solution.

Still have to figure out how to repeat the footer…

1 Like

I got an answer from ChatGPT for the template. Seems it has learnt well Invoice Ninja as well :slight_smile:

did it actually help?