@page 的 content 仅支持静态字符串、内置计数器(如 counter(page))和极少数未实现的 string(),不支持 attr()、HTML、JS 或 CSS 变量;主流浏览器中仅 Chromium ≥120 部分支持 @top/@bottom,且 counter(pages) 在 PDF 导出时可能失效;推荐用 DOM 元素 + @media print 模拟页眉页脚,并通过 fixed/absolute 定位与 JS 动态注入实现跨浏览器兼容。
浏览器对 @page 规则的支持非常有限,无法用它实现动态、个性化或含 DOM 元素的页眉页脚——这是硬性限制,不是写法问题。
@page 里的 content 只能用静态字符串或简单计数器CSS Paged Media 模块规定 @page 中的 content 属性仅允许以下值:
string() 函数(但仅支持来自 element() 的极少数上下文,且所有主流浏览器均未实现)counter(page)、counter(pages) 等内置计数器"Report v2.1",不解析 HTML、不执行 JS、不读取属性attr()、url()、变量、伪元素内容等常见 CSS 功能这意味着你不能通过 @page :first { @top-center { content: "Hello " attr(data-title); } } 这类写法注入页面标题——attr() 在 @page 中完全无效。
目前仅 Chromium 内核(Chrome ≥ 120、Edge ≥ 120)部分支持 @page 的 @top/@bottom 区域,且仅限基础内容:
@page { size: A4; margin: 0;}@page :first { @top-center { content: "CONFIDENTIAL"; font-size: 10px; color: #999; }}@page { @bottom-right { content: "Page " counter(page) " of " counter(pages); font-size: 9px; }}
注意:counter(pages) 仅在打印预览中正确渲染,PDF 导出时可能显示为 NaN;@top-left 等位置在 Firefox 和 Safari 中完全被忽略。
真正可控的方式是放弃 @page,改用固定定位 + 分页控制:
page-break-after: always 或 break-after: page
<header class="print-header"> 和 <footer class="print-footer">
@media print 控制它们的显示/尺寸/位置,例如:.print-header { position: fixed; top: 0; width: 100%; height: 20mm; }
header 元素,再触发重排这种方案兼容所有浏览器,支持 HTML、图标、响应式字体,但需确保内容不与正文重叠——必须显式设置 margin-top 避开页眉高度。
最常被忽略的一点:即使用了 DOM 模拟,Chrome 打印时仍可能把固定定位元素重复渲染到每一页顶部。解决方法是只对第一页加 position: fixed,其余页用 position: absolute + top: 0 并配合 transform: translateY(-20mm) 微调。这没有标准解法,得靠反复打印预览调试。