網頁列印時想要每頁固定頁首/頁尾、控制分頁位置?CSS @media print 搭配 HTML Table 架構,即可在瀏覽器端純前端實現,無需後端產生 PDF。本文詳細說明架構邏輯、關鍵 CSS 屬性與 JavaScript 動態插入分頁流程。
<div id="header" class="hdrftr">頁首內容(Logo、標題、日期)</div>
<div id="footer" class="hdrftr">頁尾內容(頁碼、機密等級、公司名)</div>
<table id="tbl" style="width:6.5in; border-collapse:collapse;">
<tr class="datarow"><td>資料列 1</td></tr>
<tr class="datarow"><td>資料列 2</td></tr>
...
</table>
@media print {
.hdrftr { display: block; width: 6.5in; height: 1in; overflow: hidden; position: relative; }
.datarow { page-break-inside: avoid; } /* 避免資料列跨頁斷裂 */
tr.page-break { page-break-after: always; } /* 強制分頁 */
@page { margin: 0.25in 1in; size: portrait; } /* 上下 0.25in、左右 1in、直式 */
}
window.onload = function() {
const rows = document.querySelectorAll('#tbl .datarow');
const pageH = 11 * screen.deviceYDPI; // 頁面高度 (dots)
const headerH = 1 * screen.deviceYDPI; // 頁首高度
const footerH = 1 * screen.deviceYDPI; // 頁尾高度
const marginV = 0.25 * screen.deviceYDPI * 2; // 上下邊距
const availH = pageH - headerH - footerH - marginV; // 可用高度
let accumulated = 0;
let pageCount = 1;
// 插入第一頁頁首
const firstHeader = document.getElementById('header').cloneNode(true);
firstHeader.style.display = 'table-row';
firstHeader.style.height = '1in';
rows[0].parentNode.insertBefore(firstHeader, rows[0]);
rows.forEach((row, i) => {
const rowH = row.offsetHeight;
if (accumulated + rowH + footerH > availH) {
// 超過可用高度 → 前一列加分頁、插入頁尾+下一頁頁首
rows[i-1].classList.add('page-break');
insertFooterHeaderAfter(rows[i-1], pageCount);
accumulated = rowH;
pageCount++;
} else {
accumulated += rowH;
}
});
// 最後一頁加頁尾
insertFooterHeaderAfter(rows[rows.length-1], pageCount);
};
function insertFooterHeaderAfter(refRow, pageNum) {
const footer = document.getElementById('footer').cloneNode(true);
footer.style.display = 'table-row'; footer.style.height = '1in';
const nextHeader = document.getElementById('header').cloneNode(true);
nextHeader.style.display = 'table-row'; nextHeader.style.height = '1in';
// 插入順序:頁尾 → 頁首
refRow.parentNode.insertBefore(footer, refRow.nextSibling);
refRow.parentNode.insertBefore(nextHeader, footer.nextSibling);
}
page-break-inside: avoid 防止單列被切斷position: relative + 固定高度,配合 overflow: hidden 避免內容外溢@media print 偽類純前端實現列印分頁、頁首頁尾,零後端依賴、零外掛套件。掌握 @media print、page-break-after、@page 三大 CSS 關鍵字,配合 JS 動態計算高度插入分頁列,即可滿足報表、發票、合約等商務列印需求。