A4 page height is not considered when generating dynamic page number using javascript during print event

I’m generating A4 invoice using HTML, CSS and JS. The invoice is getting generated as expected during print preview. However page number is not aligned and extra empty pages are generated automatically.

Here is my code snippet:

<html>

<head>
    <script>function setPrintStyles(pagesize, standardSize) {
            var documentHeight = standardSize ? '' : (document.getElementsByTagName('html')[0].offsetHeight / 2) + 100 + 'px';
            var bodySize = standardSize ? '' : 'body { width: ' + pagesize + '; }';
            var css = `@media print { @page { size: ${pagesize} ${documentHeight}; } ${bodySize} }`,
                head = document.head || document.getElementsByTagName('head')[0],
                style = document.createElement('style');
            head.appendChild(style);
            style.type = 'text/css';
            style.appendChild(document.createTextNode(css));
        }</script>
    <style type="text/css">
        @media print {
            #section-to-print {
                position: absolute;
                left: 0;
                top: 0;
            }

            body {
                font-family: Calibri, monospace;
                font-size: 0.8rem;
                margin: 1rem;
                border: 1px solid;
            }

            body ol {
                list-style: none;
                padding-left: 0;
                margin: 0.5rem 0;
            }

            table {
                width: 100%;
                height: 100%;
                border-collapse: collapse;
                page-break-inside: auto;
            }

            td section div {
                page-break-inside: avoid;
            }

            thead {
                display: table-header-group;
            }

            tfoot {
                display: table-footer-group;
            }

            header {
                display: flex;
                flex-direction: column;
                font-weight: normal;
            }

            #brand {
                border-bottom: 1px solid;
                padding: 0.25rem 0.5rem;
                text-transform: uppercase;
                font-weight: bold;
            }

            #invoicedetails {
                display: grid;
                grid: "shop customer invoice";
                grid-template-columns: repeat(3, 1fr);
                padding: 0 0.5rem;
                border-bottom: 1px solid;
            }

            #shop {
                text-align: left;
            }

            #customer {
                border: 1px solid;
                border-top: 0;
                border-bottom: 0;
                padding-left: 0.5rem;
                text-align: center;
            }

            #invoice {
                text-align: right;
            }

            table tbody td {
                height: 100%;
                display: flex;
                flex-direction: column;
                justify-content: space-between;
            }

            main {
                display: block;
                height: 100%;
            }

            #invoiceitems {
                display: block;
                height: 100%;
                text-transform: uppercase;
            }

            #itemscontent {
                height: 100%;
                display: grid;
                grid: "sno isbnno title price quantity amount";
                /*Below line is added as inline style in A4 invoice component*/
                /*grid-template-rows: repeat(2, minmax(1rem, max-content)) auto repeat(2, minmax(1rem, max-content));*/
                /*grid-template-columns: minmax(min-content, max-content) minmax(min-content, auto) max-content max-content max-content max-content max-content max-content;*/
                grid-auto-rows: minmax(1rem, max-content);
                grid-column-gap: 1px;
                align-items: center;
            }

            #itemscontent>div {
                display: flex;
                align-items: center;
                border: 1px solid;
                height: 100%;
                border-top: 0;
                border-right: 0;
                padding: 0 0.25rem;
            }

            .border-left-0 {
                border-left: 0 !important;
            }

            .border-bottom-0 {
                border-bottom: 0 !important;
            }

            .span-4 {
                grid-column-start: span 4;
            }

            .flex-end {
                justify-content: flex-end;
            }

            footer {
                display: flex;
                flex-direction: column;
            }

            #itemsfooter {
                display: flex;
                justify-content: space-between;
                align-items: center;
                text-transform: uppercase;
                border-top: 1px solid;
            }

            #itemsfooter>div {
                align-self: stretch;
                display: flex;
                align-items: center;
                padding: 0 0.5rem;
            }

            #amountinwords {
                flex: 75%;
            }

            #totalamount {
                flex: 25%;
                text-align: right;
                border-left: 1px solid black;
            }

            #totalamount ol {
                width: 100%;
            }

            #totalamount ol li:last-child {
                font-size: x-large;
            }

            #invoiceinformation {
                display: flex;
                justify-content: end;
                padding: 0 0.5rem;
                border-top: 1px solid;
                border-bottom: 1px solid;
            }

            #signature {
                padding-left: 0.5rem;
            }

            #message {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 0 0.5rem;
            }
        }
    </style>
    <style type="text/css">
        @media print {
            @page {
                size: A4;
            }
        }
    </style>
    <style>
        html {
            height: 297mm !important;
            overflow-y: scroll;
        }
    </style>
</head>

<body><!--!-->
    <table>
        <thead>
            <tr>
                <th>
                    <header>
                        <section id="brand"></section><!--!-->
                        <section id="invoicedetails">
                            <section id="shop">
                                <ol>
                                    <li>From</li><!--!-->
                                    <li><b>ABC</b></li><!--!-->
                                    <li>Address:</li><!--!-->
                                    <li>Phone:</li><!--!-->
                                    <li>Mobile:</li>
                                </ol>
                            </section><!--!-->
                            <section id="customer">
                                <ol>
                                    <li>To</li><!--!-->
                                    <li><b>DEF </b></li><!--!-->
                                    <li>Mobile: </li>
                                </ol>
                            </section><!--!-->
                            <section id="invoice">
                                <ol id="invoice-details"><!--!-->
                                    <li>Invoice Details</li>
                                    <li>Invoice No: <b>18/2023-24</b></li><!--!-->
                                    <li>Invoice Date: <b>17 Nov 2023</b></li><!--!-->
                                    <li>Payment Mode: <b>Cash</b></li><!--!-->
                                    <li>Payment Status: Paid</li><!--!-->
                                    <li id="page-number"><br/></li>
                                </ol>
                            </section>
                        </section>
                    </header>
                </th>
            </tr>
        </thead><!--!-->
        <tbody>
            <tr>
                <td>
                    <main>
                        <section id="invoiceitems">
                            <section id="itemscontent"
                                style="grid-template-rows: repeat(5, minmax(1rem, max-content)) auto repeat(2, minmax(1rem, max-content)); grid-template-columns: minmax(min-content, max-content) minmax(min-content, max-content) minmax(min-content, auto) max-content max-content max-content">
                                <!--!-->
                                <div class="border-left-0">S.No</div>
                                <!--!-->
                                <div>ISBN No</div>
                                <!--!-->
                                <div>Title</div>
                                <!--!-->
                                <div>Price</div>
                                <!--!-->
                                <div>Quantity</div>
                                <!--!-->
                                <div>Amount</div>
                                <div class="border-left-0 border-bottom-0">1</div><!--!-->
                                <div class="border-bottom-0"></div><!--!-->
                                <div class="border-bottom-0">Another Test</div><!--!-->
                                <div class="flex-end border-bottom-0">10.00</div><!--!-->
                                <div class="flex-end border-bottom-0">1</div><!--!-->
                                <div class="flex-end border-bottom-0">10.00</div>
                                <div class="border-left-0 border-bottom-0">2</div><!--!-->
                                <div class="border-bottom-0"></div><!--!-->
                                <div class="border-bottom-0">Another Test</div><!--!-->
                                <div class="flex-end border-bottom-0">10.00</div><!--!-->
                                <div class="flex-end border-bottom-0">1</div><!--!-->
                                <div class="flex-end border-bottom-0">10.00</div>
                                <div class="border-left-0 border-bottom-0">3</div><!--!-->
                                <div class="border-bottom-0"></div><!--!-->
                                <div class="border-bottom-0">Another Test</div><!--!-->
                                <div class="flex-end border-bottom-0">10.00</div><!--!-->
                                <div class="flex-end border-bottom-0">1</div><!--!-->
                                <div class="flex-end border-bottom-0">10.00</div>
                                <div class="border-left-0 border-bottom-0">4</div><!--!-->
                                <div class="border-bottom-0"></div><!--!-->
                                <div class="border-bottom-0">Another Test</div><!--!-->
                                <div class="flex-end border-bottom-0">10.00</div><!--!-->
                                <div class="flex-end border-bottom-0">1</div><!--!-->
                                <div class="flex-end border-bottom-0">10.00</div><!--!-->
                                <div class="border-left-0"></div>
                                <div></div>
                                <div></div>
                                <div></div>
                                <div></div>
                                <div></div>

                                <!--!-->
                                <div class="border-left-0 flex-end span-4">Sub Total</div>
                                <div class="flex-end">4</div><!--!-->
                                <div class="flex-end">40.00</div>
                                <div class="border-left-0 flex-end span-4">Discount (10.00%)</div><!--!-->
                                <div></div>
                                <div class="flex-end">-3.00</div>
                            </section>
                        </section>
                    </main><!--!-->
                    <footer>
                        <section id="itemsfooter">
                            <div id="amountinwords">
                                <ol>
                                    <li><small>Total Amount in Words (INR)</small></li><!--!-->
                                    <li><b>thirty seven ONLY</b></li>
                                </ol>
                            </div><!--!-->
                            <div id="totalamount">
                                <ol><!--!-->
                                    <li><small>Total Amount</small></li>
                                    <li><b>₹37.00</b></li>
                                </ol>
                            </div>
                        </section><!--!-->
                        <section id="invoiceinformation">
                            <div id="signature"><text>for <!--!--><br><br><br>Authorized
                                    Signatory</text></div>
                        </section><!--!-->
                        <!--!-->
                        <section id="message">
                            <div><small>THANK YOU FOR THE BUSINESS</small></div>
                            <div><small>THIS IS A COMPUTER GENERATED INVOICE</small></div>
                        </section>
                    </footer>
                </td>
            </tr>
        </tbody>
    </table>
    <div id="dpi" style="height: 1in; left: -100%; position: absolute; top: -100%; width: 1in;"></div>
    <script>window.print();</script>
    <script>window.onbeforeprint = addPageNumbers;
        window.onafterprint = removePageNumbers;
        function removePageNumbers() {
            document.querySelectorAll('.dynamic-page-number').forEach(function (li) {
                li.remove();
            });
        }
        function addPageNumbers() {
            var dpi = document.getElementById("dpi").offsetHeight;
            console.log(dpi);
            var sheetHeightInMM = 297;
            var mmPerInch = 25.4;
            var pixels = (sheetHeightInMM * dpi) / mmPerInch;
            var bodyHeight = document.getElementsByTagName('body')[0].scrollHeight;
            console.log(bodyHeight);
            var totalPages = Math.ceil(bodyHeight / pixels);
            console.log(totalPages);
            for (var i = 1; i <= totalPages; i++) {
                var pageNumberLi = document.createElement("li");
                var pageNumber = document.createTextNode("Page " + i + " of " + totalPages);
                pageNumberLi.classList.add('dynamic-page-number');
                pageNumberLi.style.paddingTop = '5px'; // added to adjust spacing between previous li element in dom
                pageNumberLi.style.position = "absolute";
                var offsetTop = document.getElementById("page-number").offsetTop + "px";
                console.log(offsetTop);
                pageNumberLi.style.top = `calc((${i - 1} * ${sheetHeightInMM}mm) + ${offsetTop} - ${i * 1}rem)`;
                pageNumberLi.style.right = '1.5rem'; // 1rem body right margin + 0.5rem header right padding
                pageNumberLi.appendChild(pageNumber);
                document.getElementById("invoice-details").appendChild(pageNumberLi);
            }
        }</script>
</body>

</html>

Issue I’m facing:

the above code will generate single page A4 invoice. But this generates two pages in print preview. The page number can also be seen in invoice.

Page 1:

enter image description here

Page 2:

enter image description here

Script used for page number generation:

function addPageNumbers() {
    var dpi = document.getElementById("dpi").offsetHeight;
    console.log(dpi);
    var sheetHeightInMM = 297;
    var mmPerInch = 25.4;
    var pixels = (sheetHeightInMM * dpi) / mmPerInch;
    var bodyHeight = document.getElementsByTagName('body')[0].scrollHeight;
    console.log(bodyHeight);
    var totalPages = Math.ceil(bodyHeight / pixels);
    console.log(totalPages);
    for (var i = 1; i <= totalPages; i++) {
        var pageNumberLi = document.createElement("li");
        var pageNumber = document.createTextNode("Page " + i + " of " + totalPages);
        pageNumberLi.classList.add('dynamic-page-number');
        pageNumberLi.style.paddingTop = '5px'; // added to adjust spacing between previous li element in dom
        pageNumberLi.style.position = "absolute";
        var offsetTop = document.getElementById("page-number").offsetTop + "px";
        console.log(offsetTop);
        pageNumberLi.style.top = `calc((${i - 1} * ${sheetHeightInMM}mm) + ${offsetTop} - ${i * 1}rem)`;
        pageNumberLi.style.right = '1.5rem'; // 1rem body right margin + 0.5rem header right padding
        pageNumberLi.appendChild(pageNumber);
        document.getElementById("invoice-details").appendChild(pageNumberLi);
    }
}

Expected Behavior:
Page should be generated properly considering the height set in html which is 297mm (height of A4 page).

Please try saving the code snippet as html file and open in browser. The above code snippet execution gives different output.