HTML页脚与未知页数的页码(动态生成的数据)

前端开发 2026-07-09

我正在把Crystal Reports转换成HTML,但在页脚上遇到了问题。

我无法将页脚固定在每一页生成或打印的底部。布局(例如表格)将由后端C#动态填充。它们有时会错位(在我的情况下是A4尺寸)或只是随着内容漂浮。

我的目标是在每一页的底部显示干净的页脚(包含页码),且不让页面内容溢出到页脚。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>dEMO</title>

<style>

*{
    box-sizing:border-box;
}

body{
    margin:0;
    padding:8px;
    background:#f4f4f4;
    font-family:Arial,sans-serif;
    font-size:12px;
}

/* =========================
   A4 PAGE
========================== */

@page{
    size:A4;
    margin:10mm;
}

.page{
    width:210mm;
    min-height:297mm;

    margin:0 auto;

    background:#fff;

    border:1px solid #dcdcdc;

    padding:10mm;

    /* reserve space for footer */
    padding-bottom:30mm;

    position:relative;
}

@media print{

    body{
        background:white;
        padding:0;
        margin:0;
    }

    .page{
        border:none;
        margin:0 auto;
    }

    table{
        page-break-inside:auto;
    }

    tr{
        page-break-inside:avoid;
        page-break-after:auto;
    }

    thead{
        display:table-header-group;
    }

    tfoot{
        display:table-footer-group;
    }
}
/* =========================
    HEADER
========================== */

caption{
    text-align: center;
    margin-bottom:8px;
}
caption a{
    text-decoration:none;
    color:#4CAF50;
    font-size:0.9em;
}
.header{
    display:flex;
    justify-content:space-between;
    margin-bottom:8px;
}

.company-section{
    display:flex;
    gap:15px;
}

.company-logo{
    width:60px;
    height:60px;
    object-fit:contain;
}

.company-details{
    line-height:18px;
}

.company-name{
    font-weight:bold;
    font-size:22px;
}

.right-header{
    width:300px;
}

.report-title{
    text-align:right;
    font-size:22px;
    font-weight:bold;
    color:#8b0000;
    border-bottom:1px solid purple;
    margin-bottom:10px;
    padding-bottom:2px;
}

.info-table{
    width:100%;
    border-collapse:collapse;
}

.info-table td{
    padding:3px 0;
}

.info-label{
    width:120px;
}

.info-colon{
    width:15px;
}

.info-value{
    text-align:right;
}

.info-value-code{
    text-align:right;
    font-weight:bold;
    color:#8b0000;
}



/* =========================
    CUSTOMER DETAILS
========================== */

.customer-section{
    margin-top:5px;
    margin-bottom:5px;
    line-height:18px;
}

.customer-row{
    display:flex;
}

.customer-label{
    width:70px;
}

/* =========================
   MAIN TABLE
========================== */

.bbs-table{
    width:100%;
    border-collapse:collapse;
    table-layout:fixed;
}

.bbs-table th{
    background-color:#8d8d8d;
    color:white;
    padding:6px 4px;
    font-size:12px;
    font-weight:bold;
    border:1px solid #8d8d8d;
}

.bbs-table td{
    border:1px solid #c0c0c0;
    padding:4px;
    text-align:center;
    vertical-align:middle;
}

.sub-text{
    display:block;
    font-size:10px;
    color:#eaeaea;
}

.weight-row td{

       background-color:#8d8d8d;

       color:white;

       font-weight:bold;

       padding:4px;

       border-top:4px solid #f3f3f3;
}

.shape-cell{
    width:140px;
    text-align:center;
    vertical-align:middle;
}

.shape-image{

    width:120px;

    height:auto;

    object-fit:contain;

    display:block;

    margin:auto;
}

/* =========================
   PRODUCT TABLE
========================== */

.product-table{
    width:100%;
    border-collapse:collapse;
    margin-top:2px;
}

.product-table th{
    background:#8d8d8d;
    color:white;
    padding:5px;
    text-align:left;
}

.product-table td{
    padding:4px 6px;
    border:none;
}

.right{
    text-align:right;
}

.muted{
    display:block;
    font-size:10px;
    color:#777;
}

.summary-row td{
    background:#8a8a8a;
    color:white;
    font-weight:bold;
    text-align:center;
    padding:4px;
}

.total-weight{
    text-align:center;
}

.grand-total-section{
    margin-top:2px;
}

.grand-total-line{
    border-top:1px solid #8d8d8d;
    margin-bottom:4px;
}

.grand-total-row{
    display:grid;
    grid-template-columns:15% 45% 15% 25%;
    align-items:center;
    font-weight:bold;
    font-size:12px;
}

.grand-total-label{
    padding-left:6px;
}

.grand-total-pcs{
    text-align:center;
}

.grand-total-wgt{
    text-align:right;
    padding-right:6px;
}

/* =========================
    FOOTER
========================== */

.report-footer{
    position:absolute;

    bottom:10mm;
    left:10mm;
    right:10mm;

    font-size:11px;
    color:#444;
}

.footer-line{
    border-top:1px solid #8d8d8d;
    margin-bottom:6px;
}

.footer-content{
    display:flex;
    justify-content:space-between;
    align-items:center;
}

.footer-item{
    min-width:180px;
}

.footer-label{
    font-weight:bold;
}

</style>
</head>

<body>  
<div class="page">
    <table summary="Total Weight" style="width: 100%;">
        <caption>
                 <a href="http://bendplus.com">
                   DEMO
                </a>
        </caption>

        <tbody>
            <tr>   
            </tr>
        </tbody>
    </table>

    <!-- =========================
         HEADER
    ========================== -->

    <div class="header">

        <!-- LEFT -->
        <div class="company-section">

            <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTb11uhYlc60nFSkWl4pY1SHfEJXB2gdIwtTA&s" class="company-logo">

             <div class="company-details">

                <div class="company-name">
                    xxCompanyName
                </div>
                <div>
                    xxCompanyAddress
                </div>
                <div>
                    xxCompanyMail
                </div>
                <div>
                    xxCompanyWeb
                </div>

            </div>

        </div>

        <!-- RIGHT -->
        <div class="right-header">

            <div class="report-title">
                DEMO
            </div>

           <table class="info-table">
                <tr>
                    <td class="info-label">DEMO</td>
                    <td class="info-colon">:</td>
                    <td class="info-value-code">xxCtrlCode</td>
                </tr>

                <tr>
                    <td class="info-label">DEMO</td>
                    <td class="info-colon">:</td>
                    <td class="info-value">xxProjectCode</td>
                </tr>
                <tr>
                    <td class="info-label">DEMO</td>
                    <td class="info-colon">:</td>
                    <td class="info-value">xxDeliveryDate</td>
                </tr>

                <tr>
                    <td class="info-label">DEMO</td>
                    <td class="info-colon">:</td>
                    <td class="info-value">xxDwgRef</td>
                </tr>

                <tr>
                    <td class="info-label">DEMO</td>
                    <td class="info-colon">:</td>
                    <td class="info-value">xxDwgNo</td>
                </tr>
                <tr>
                    <td class="info-label">Description</td>
                    <td class="info-colon">:</td>
                    <td class="info-value">xxDescription</td>
                </tr>
            </table>

        </div>

    </div>

    <!-- =========================
         CUSTOMER
    ========================== -->

    <div class="customer-section">

        <div class="customer-row">
            <div class="customer-label">Customer</div>
            <div>: xxCustName</div>
        </div>

        <div class="customer-row">
            <div class="customer-label">Project</div>
            <div>: xxProject</div>
        </div>

    </div>

    <!-- =========================
         MAIN TABLE
    ========================== -->

    <table class="bbs-table">

        <thead>

            <tr>
                <th>DEMO</th>
                <th>DEMO</th>
                <th>
                   DEMO
                    <span class="sub-text">MM</span>
                </th>
                <th>Qty</th>
                <th>DEMO</th>
                <th>Length</th>
                <th>
                   DEMO
                    <span class="sub-text">MM</span>
                </th>
                <th>
                    DEMO
                    <span class="sub-text">Kgs</span>
                </th>
                <th>
                    DEMO
                    <span class="sub-text">Kgs</span>
                </th>
                <th style="width: 18%;">Shape</th>
            </tr>

        </thead>
        <tbody id="DEMO">

             <tr>
                <td colspan="10">###Notes</td>
            </tr>
            <tr>
                <td>###SEQ</td>
                <td>###DEMO</td>
                <td>###DEMO</td>
                <td>###Qty</td>
                <td>###DEMO</td>
                <td>###Length</td>
                <td>###DEMO</td>
                <td>###DEMO</td>
                <td>###DEMO</td>
                <td rowspan="2">###DEMO</td>
            </tr>
             <tr>
                <td colspan="6" style="color: #8b0000;text-align: left;">###Remarks</td>
                <td colspan="3" style="color: blue;text-align: right;">###SurchargeGrp</td>
            </tr>

        </tbody>
    </table>

    <!-- =========================
         PRODUCT TABLE
    ========================== -->

    <table class="product-table">

        <thead>

            <tr>
                <th style="width:10%">DEMO</th>
                <th style="width:35%">DEMO</th>
                <th style="width:35%">DEMO</th>
                <th style="width:10%">DEMO</th>
                <th style="width:10%" class="right">DEMO</th>
            </tr>

        </thead>

            <tbody id="bbsSummaryTemplate">
                <tr style="background-color: cornsilk;">
                    <td style="width: 50%;color: #8b0000;text-align: left;">###DEMO</td>
                    <td style="color: fuchsia;">SubTotal : </td>
                    <td colspan="2" style="color:#8b0000;font-weight: bold;">###DEMO</td>
                    <td style="color: #8b0000;font-weight: bold;">###DEMOt</td>
                </tr>
            <tr>
                <td>###DEMO</td>
                <td>###DEMO  
                    <span class="muted" style="display: block;">###DEMO</span>
                </td>
                <!-- <td>###DEMO</td> -->
                <!--<td>###DEMO</td>-->
                <td>###DEMO</td>
                <td>DEMO</td>
                <td>###DEMO</td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td style="text-align: left;">###DEMO</td>
            </tr>
        </tbody>
    </table>

    <!-- GRAND TOTAL -->

<div class="grand-total-section">

    <div class="grand-total-line"></div>

    <div class="grand-total-row">

        <div></div>

        <div class="grand-total-label">

        </div>

        <div>GRAND TOTAL  : </div>

        <div class="grand-total-wgt">
            ###GrandTotalWgt
        </div>

    </div>

</div>

    <!-- =========================
         FOOTER
    ========================== -->
    <div class="report-footer">
        <div class="footer-line"></div>

        <div class="footer-content">

            <div class="footer-item">
                <span class="footer-label">B+ Code :</span>
                <span>xxCtrlCode</span>
            </div>
            <div class="footer-item">
                <span class="footer-label">Release :</span>
                <span>xxReleaseNo</span>
            </div>
            <div class="footer-item">
                <span class="footer-label">Page Wgt :</span>
                <span>xxPageWgt</span>
            </div>
        </div>
    </div>

</div>
</body>
</html>

解决方案

Your current footer uses:

.report-footer {
  position: absolute;
  bottom: 10mm;
}

这只对一个 .page div 有效。当浏览器将内容分割时,它不会在每个打印页面上自动重复。HTML/CSS打印不像Crystal Reports那样分页。

要在每一页打印时显示页脚,请在 @media print 内使用 position: fixed

@media print {
  @page {
    size: A4;
    margin: 15mm 10mm 25mm 10mm;
  }

  body {
    margin: 0;
    padding: 0;
    background: white;
  }

  .page {
    width: auto;
    min-height: auto;
    border: none;
    margin: 0;
    padding: 0;
    padding-bottom: 25mm;
  }

  .report-footer {
    position: fixed;
    bottom: 8mm;
    left: 10mm;
    right: 10mm;
    height: 15mm;
    background: white;
  }

  table {
    page-break-inside: auto;
  }

  tr {
    page-break-inside: avoid;
    page-break-after: auto;
  }

  thead {
    display: table-header-group;
  }
}

要添加页码,请使用以下内容:

.report-footer::after {
  content: "Page " counter(page);
  float: right;
}

重要提示:在Chrome/Edge中对 counter(page) 的浏览器支持并不可靠。如果你需要“准确的页码和保证的页脚定位”,请使用服务器端的HTML-to-PDF引擎生成PDF,例如 wkhtmltopdfDinkToPdfQuestPDFRotativa,或 Puppeteer

另外,在打印时请移除 .page 的固定A4大小。这部分会造成大量的对齐问题:

.page {
  width: 210mm;
  min-height: 297mm;
}

让浏览器通过 @page 来处理打印时的页面大小,而不是通过固定的 .page 容器。你当前的结构使用一个 .page 包裹,并且页脚是绝对定位的,因此无法在生成的每一页上自然重复页脚。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章