Custom Print Format with fixed footer area

Hi, I am customizing a HTML Print format and the footer is somehow very big so that the page content does not reach the footer and makes a page break. Does anyone has a idea how to fix that?

Here a screenshot of the document area, in that case its a quotation with over 20 items, but at item 6 it makes a page-break without using the available space (marked yellow). That continues on every other page also:

This is the custom print format html used
when bottom margin is under 55mm then the footer is not shown completely

<style>
    .print-format {
        margin-left: 0mm;
        margin-right: 0mm;
        margin-top: 10mm;
        margin-bottom: 55mm;
        font-size: 10pt;
    }   
</style>

{% set company = frappe.get_doc("Company", doc.company) %}
{% set company_address_name = frappe.db.get_value("Dynamic Link", filters={"link_doctype": "Company", "link_name": doc.company, "parenttype": "Address"}, fieldname="parent") %}
{% set cmp_addr = frappe.get_doc("Address", company_address_name) if company_address_name else None %}
{% set pay_addr = frappe.get_doc("Address", doc.customer_address) %}

{% if doc.contact_person %}
    {% set contact = frappe.get_doc("Contact", doc.contact_person) %}
{% endif %}

<!-- HEAD -->
<div id="header">
    <div class="letter-head">
        {{ letter_head }}
    </div>
</div>

<div class="contact-row">
    <div id="address">
        <div id="sender">
            <p>{{ cmp_addr.address_title }} &#183; {{ cmp_addr.address_line1 }} &#183;
                {% if cmp_addr.address_line2 %}{{ cmp_addr.address_line2 }} <br>{% endif %}
                {{ cmp_addr.pincode }} {{ cmp_addr.city }}
            </p>
        </div>
        {{ doc.customer_name }}<br />
        {{ doc.address_display }}
    </div>

    <div id="contact">
    </br></br></br></br>
        <table>
            <tr></tr>
            <tr>
                <td>{{ _("Date") }}:</td>
                <td class="text-right">{{ frappe.utils.formatdate(doc.transaction_date, "dd. MMMM yyyy") }}</td>
            </tr>
            <tr>
                <td>{{ _("Valid Till") }}:</td>
                <td class="text-right">{{ frappe.utils.formatdate(doc.valid_till, "dd. MMMM yyyy") }}</td>
            </tr>
        </table>
    </div>
</div>

<div id="faltmarke-1" class="din-mark"></div>
<div id="lochmarke" class="din-mark"></div>
<div id="faltmarke-2" class="din-mark"></div>

<!-- CONTENT -->
<div id="text">
	<div id="subject">
		<strong><h3>{{ _(doc.doctype) }}: {{ doc.name }}</h3></strong>
    </div>

    <table class="w-100 text-small">
        <thead class="black-border">
        <tr>  <p style="font-size: 8pt">
            <th style="width: 5%"><p style="font-size: 8pt">{{ _("Sr") }}</p></th>
            <th style="width: 45%">
            <p style="font-size: 8pt">{{ _("Description") }}</p></th>
            <th style="width: 12%"><p style="font-size: 8pt">{{ _("Unit") if not print_settings.print_uom_after_quantity else '&nbsp;'}}</p></th>
            <th style="width: 8%" class:"text-right"><p style="font-size: 8pt; text-align:right">{{ _("Qty") }}</p></th>
            <th style="width: 15%"><p style="font-size: 8pt; text-align:right">{{ _("Price") }}</p></th>
            <!-- <th style="width: 15%"><p style="font-size: 8pt">{{ _("Discount") }}</p></th> -->
            <th style="width: 15%" class="text-right"><p style="font-size: 8pt">{{ _("Amount") }}</p></th>
        </tr>
        </thead>

        <tbody class="black-border">
            {% for n in doc.items %}
            <tr>
                <td>{{ loop.index }}</td>
                <td><b>{{ _(n.item_name) }}</b><br>
                <p style="font-size: 9pt">{{ _(n.description) }}</p></td>
                <td><p style="font-size: 8pt">{{ _(n.uom) if not print_settings.print_uom_after_quantity else '&nbsp;'}}</p></th></td>
                <td>
                      <p style="text-align: right">{{ n.get_formatted("qty") }}</p>
                    {% if print_settings.print_uom_after_quantity %}
                        <p style="text-align: right">{{ _(n.uom) }}</p>
                    {% endif %}
                </td>
                <td><p style="text-align: right">{{ n.get_formatted("rate") }}</p></td>
                <!-- <td><p style="text-align: right">{{ n.get_formatted("discount_amount") }}</p></td> -->
                <td class="text-right"><p style="text-align: right">{{ n.get_formatted("amount") }}</p></td>
            </tr>
            {% endfor %}
        </tbody>

        <tfoot class="black-border" style="display:table-row-group;">
            {% if doc.additional_discount_percentage %}
                <tr>
                    <td></td>
                    <td>{{ _("Total") }}</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td class="text-right">{{ doc.get_formatted("total") }}</td>
                </tr>
                <tr>
                    <td></td>
                    <td>{{ _("Discount") }}</td>
                    <td></td>
                    <td></td>
                    <td>
                        {{ doc.get_formatted("additional_discount_percentage") }} &percnt;
                    </td>
                    <td class="text-right">
                        {{ doc.get_formatted("discount_amount") }}
                    </td>
                </tr>
            {% endif %}
            <tr>
                <td></td>
                <td>{{ _("Net Total") }}</td>
                <td></td>
                <td></td>
                <td></td>
                <td class="text-right">{{ doc.get_formatted("net_total") }}</td>
            </tr>
            {% if doc.tax_category == "Reverse Charge" -%}
                <tr>
                    <td></td>
                    <td>Steuerschuldnerschaft des Leistungsempfängers.</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td class="text-right"></td>
                </tr>
            {% else %}
                {% for tax_row in doc.taxes -%}
                    {% if tax_row.tax_amount or print_settings.print_taxes_with_zero_amount %}
                        <tr>
                            <td></td>
                            <td>
                            {{ tax_row.description }}
                            </td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td class="text-right">
                                {{ tax_row.get_formatted("tax_amount") }}
                            </td>
                        </tr>
                    {% endif %}
                {%- endfor %}
            {%- endif %}
            <tr>
                <td></td>
                <td>
                    <strong>{{ _("Grand Total") }}</strong>
                </td>
                <td></td>
                <td></td>
                <td></td>
                <td class="text-right"><strong>{{ doc.get_formatted("grand_total") }}</strong>
                </td>
            </tr>
        </tfoot>
    </table>



<!-- FOOTER -->
<div id="footer-html" class="visible-pdf">
<p style="font-size: 8pt; text-align:right" id="pagenum">
    {{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
</p>
    <div class="print-format-footer">
        {{ footer }}
    </div>
</div>

This is the Print Style CSS used:

.print-format{padding:0;position:relative}

.print-format #header{width:100%;height:35mm;margin-top:-10mm;overflow:hidden;position:relative;margin-left:25mm;margin-right:20mm}

.print-format .contact-row{position:relative;overflow:hidden;left:20mm;height:45mm;width:170mm}

.print-format #sender{position:relative;font-size:75%;height:17.7mm}

.print-format #sender p{position:absolute;width:85mm;bottom:0}

.print-format #address{float:left;width:85mm;padding-left:5mm}

.print-format #contact{float:right;width:75mm;margin-top:5mm}

.print-format #contact>table{width:100%}

.print-format #contact td{padding:1.5px !important}

.print-format #subject{margin-bottom:2em;height:5mm;font-weight:bold}

.print-format .din-mark{height:1pt;background-color:#000;position:absolute}

.print-format #faltmarke-1{top:95mm;width:12mm}

.print-format #lochmarke{top:138.5mm;width:7mm}

.print-format #faltmarke-2{top:200mm;width:12mm}

.print-format #text{margin-top:8.46mm;margin-left:25mm;margin-right:20mm}

.print-format .text-right{text-align:right}

.print-format .text-small{font-size:10pt}

.print-format .black-border{border-top:solid #000 1px;border-bottom:solid #000 1px}

.print-format .w-100{width:100%}

.print-format table{page-break-inside:auto;table-layout:fixed}

.print-format table tr{page-break-inside:avoid;page-break-after:auto}

.print-format table thead{display:table-header-group}

.print-format table tfoot{display:table-row-group}

.print-format .epilogue{text-align:justify}

.print-format .epilogue .salutation{page-break-inside:avoid}

.print-format .ql-editor{line-height:unset;font-family:unset;overflow:hidden}

.print-format .ql-editor p{margin:unset}

.print-format-footer{margin-left:25mm;padding-right:20mm}#pagenum{text-align:right;margin-right:20mm;margin-top:4.23mm;margin-bottom:4.23mm}body,html{padding:0;margin:0;width:100%;height:100%}/*# sourceMappingURL=print_style.css.map */



.print-format th {
    font-weight: 400;
    color: black !important; 
    border-bottom : 1px #888888 !important; 
    border-top : hidden !important; 
    border-right : hidden !important; 
    border-left : hidden !important;
}

.print-format .table-bordered td, .print-format .table-bordered th {
    border-bottom : 1px #888888 !important;
}

.print-format .table-bordered {
    border-bottom : 1px #888888 !important;

}

.print-format td, .print-format th {
    padding: 6px !important;
    background-color: #ffffff !important; 
    color: black !important; 
    border-bottom : 1px #888888 !important; 
    border-t : 1px #888888 !important; 
    border-left : hidden !important ; 
    border-right : hidden !important;
}

.print-format .primary.compact-item {
    font-weight: normal;
}

.print-format table td .value {
    font-size: 12px;
    line-height: 1.5;
}

This is the Letterhead Footer with just a simple html code for a image:

<img src="/files/footer.png" style="max-width: 100%;" vspace="8">

I already tried multiple print formats and researched about that CSS problem, sadly without better results. Hopefully there is a way. Thank you.

<style>
    #footer {
         display: block;
         position: fixed;
         bottom: 0;
         width: 100%;
         padding: 0 20px;
         text-align:right;
         left:0px;
    }
</style>
					
<div id="footer" width="100%">
<hr>
   <img alt= height="0.0" src="/files/footer.png" style="text-align: right; height: 70.0px;">
</div>

@pronext - you can try this, you may have to edit padding in style tag to match your requirements, also align=right you can adjust for your requirement accordingly.
This above HTML keeps the footer fixed in the bottom.
NOTE: This works perfect when you click on ‘Print’ button and after that you can also save as pdf, directly view as PDF and View full page may not work as required.

1 Like

I tried that, but then the footer does not repeat. And when using

its the same problem like described before.

Found a solution after experimenting a long time.

Print Style:

.letter-head-footer{margin-left:25mm;margin-right:20mm;position: absolute; bottom: 9mm}
.page-number{position: absolute; bottom: 5mm; left: 100mm; overflow: visible}

Custom Print Format Footer

<!-- FOOTER -->
{% if print_settings.repeat_header_footer %}
<div id="footer-html" class="visible-pdf">
  {% if not no_letterhead and footer %}
  <div class="letter-head-footer">
    {{ footer }}
  </div>
  {% endif %}
  <p class="text-center small page-number visible-pdf">
    {{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
  </p>
</div>
{% endif %}

Custom Print Format Inline Style:

<style>
    .print-format {
        margin-left: 0mm;
        margin-right: 0mm;
        margin-top: 10mm;
        margin-bottom: 25mm;
        font-size: 10pt;
    }
</style>

Hope thats helpful for others too.

1 Like

In my case, there is footer overflow contained and not repeated on every page. And also page number does not show only the Page of display.