pin_drop当前位置:知识文库 ❯ 图文
高级技巧:HTML打印样式 - 详细教程与实战指南
一、教程简介
虽然 Web 页面主要在屏幕上浏览,但用户仍然有打印网页的需求,如打印文章、报表、发票等。默认情况下,浏览器打印网页的效果往往不理想——导航栏、广告、背景色等都会被打印出来,而链接地址和表格边框却丢失了。本教程将系统讲解 HTML 打印样式技术,包括@media print、打印专用 CSS、分页控制、打印隐藏元素、打印链接 URL、@page 规则、打印预览和打印事件处理。
二、核心概念
打印与屏幕的差异
纸张尺寸
三、语法与用法
@media print
代码示例
/* 打印专用样式 */
@media print {
/* 隐藏不需要打印的元素 */
nav, .sidebar, .footer, .ads, .social-share {
display: none !important;
}
/* 确保内容占满打印页面 */
body {
font-size: 12pt;
line-height: 1.5;
color: #000;
background: #fff;
}
/* 移除背景色和图片 */
* {
background: transparent !important;
color: #000 !important;
box-shadow: none !important;
text-shadow: none !important;
}
/* 链接显示 URL */
a[href]::after {
content: " (" attr(href) ")";
font-size: 0.875em;
color: #666;
}
/* 内部链接不显示 URL */
a[href^="#"]::after,
a[href^="javascript:"]::after {
content: "";
}
/* 确保图片不超出页面 */
img {
max-width: 100% !important;
page-break-inside: avoid;
}
/* 表格样式 */
table {
border-collapse: collapse;
}
th, td {
border: 1px solid #999;
padding: 4px 8px;
}
}分页控制
代码示例
/* page-break-before:元素前分页 */
.page-break-before {
page-break-before: always;
}
/* page-break-after:元素后分页 */
.page-break-after {
page-break-after: always;
}
/* page-break-inside:元素内不分页 */
.no-page-break {
page-break-inside: avoid;
}
/* 现代属性:break-before/break-after/break-inside */
.break-before {
break-before: page;
}
.break-after {
break-after: page;
}
.no-break {
break-inside: avoid;
}分页属性值
@page 规则
代码示例
/* 设置页面大小和边距 */
@page {
size: A4 portrait; /* 纵向 */
margin: 2cm;
}
@page {
size: A4 landscape; /* 横向 */
margin: 1cm 2cm;
}
@page {
size: 210mm 297mm; /* 自定义尺寸 */
margin: 25mm 20mm;
}
/* 命名页面 */
@page cover {
margin: 0;
}
@page content {
margin: 2cm;
}
/* 首页特殊边距 */
@page :first {
margin-top: 4cm;
}
/* 左右页不同边距(双面打印) */
@page :left {
margin-left: 3cm;
margin-right: 2cm;
}
@page :right {
margin-left: 2cm;
margin-right: 3cm;
}打印链接 URL
代码示例
/* 显示所有外部链接的 URL */
a[href^="http"]::after {
content: " (" attr(href) ")";
font-size: 0.875em;
color: #666;
word-break: break-all;
}
/* 使用 abbr 显示链接标题 */
abbr[title]::after {
content: " (" attr(title) ")";
}
/* 锚点链接不显示 URL */
a[href^="#"]::after {
content: none;
}打印事件
代码示例
// 打印前事件
window.addEventListener('beforeprint', function() {
// 添加打印专用类
document.body.classList.add('printing');
// 展开折叠内容
document.querySelectorAll('.collapsed').forEach(el => {
el.classList.remove('collapsed');
el.dataset.wasCollapsed = 'true';
});
});
// 打印后事件
window.addEventListener('afterprint', function() {
// 移除打印专用类
document.body.classList.remove('printing');
// 恢复折叠状态
document.querySelectorAll('[data-was-collapsed]').forEach(el => {
el.classList.add('collapsed');
delete el.dataset.wasCollapsed;
});
});
// 触发打印
function printPage() {
window.print();
}四、代码示例
示例 1:完整的打印样式页面
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>打印样式示例</title>
<style>
/* 屏幕样式 */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
line-height: 1.6;
color: #333;
margin: 0;
}
.page-header {
background: #2c3e50;
color: white;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.page-header nav a {
color: white;
text-decoration: none;
margin-left: 1rem;
}
.sidebar {
width: 250px;
background: #f5f5f5;
padding: 1.5rem;
position: fixed;
top: 60px;
right: 0;
bottom: 0;
}
.content {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.ads {
background: #fff3cd;
padding: 1rem;
margin: 1rem 0;
border: 1px solid #ffc107;
border-radius: 4px;
}
.social-share {
display: flex;
gap: 0.5rem;
margin: 1rem 0;
}
.social-share button {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
color: white;
}
.btn-print {
background: #4A90D9;
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
}
.article {
margin: 2rem 0;
}
.article h1 {
color: #2c3e50;
border-bottom: 2px solid #4A90D9;
padding-bottom: 0.5rem;
}
.article img {
max-width: 100%;
border-radius: 8px;
}
.data-table {
width: 100%;
border-collapse: collapse;
margin: 1rem 0;
}
.data-table th, .data-table td {
padding: 0.75rem;
text-align: left;
border-bottom: 1px solid #eee;
}
.data-table th {
background: #4A90D9;
color: white;
}
.data-table tr:nth-child(even) {
background: #f9f9f9;
}
.page-footer {
background: #ecf0f1;
padding: 1rem 2rem;
text-align: center;
color: #666;
}
/* ========== 打印样式 ========== */
@media print {
/* 隐藏不需要打印的元素 */
.page-header nav,
.sidebar,
.ads,
.social-share,
.btn-print,
.page-footer {
display: none !important;
}
/* 重置布局 */
.page-header {
background: none !important;
color: #000 !important;
border-bottom: 2px solid #000;
padding: 0 0 0.5rem 0;
position: static;
}
.content {
max-width: 100%;
padding: 0;
margin: 0;
}
body {
font-size: 12pt;
line-height: 1.5;
color: #000;
}
/* 移除背景 */
* {
background: transparent !important;
color: #000 !important;
box-shadow: none !important;
text-shadow: none !important;
}
/* 显示链接 URL */
a[href^="http"]::after {
content: " (" attr(href) ")";
font-size: 0.875em;
color: #666 !important;
}
a[href^="#"]::after {
content: none;
}
/* 表格添加边框 */
.data-table {
border-collapse: collapse;
}
.data-table th, .data-table td {
border: 1px solid #999 !important;
padding: 4px 8px;
}
.data-table th {
background: #eee !important;
color: #000 !important;
font-weight: bold;
}
/* 图片不分页 */
.article img {
page-break-inside: avoid;
max-width: 100%;
}
/* 标题后不分页 */
h1, h2, h3 {
page-break-after: avoid;
}
/* 段落不在页面底部开始 */
p {
orphans: 3; /* 页底至少 3 行 */
widows: 3; /* 页首至少 3 行 */
}
/* 页面设置 */
@page {
size: A4;
margin: 2cm;
}
}
</style>
</head>
<body>
<header class="page-header">
<h1>技术博客</h1>
<nav>
<a href="#">首页</a>
<a href="#">文章</a>
<a href="#">关于</a>
<button class="btn-print" onclick="window.print()">打印此页</button>
</nav>
</header>
<aside class="sidebar">
<h3>相关文章</h3>
<ul>
<li><a href="#">CSS Grid 布局指南</a></li>
<li><a href="#">JavaScript 异步编程</a></li>
<li><a href="#">Web 性能优化技巧</a></li>
</ul>
</aside>
<main class="content">
<article class="article">
<h1>HTML 打印样式完全指南</h1>
<p>本文详细介绍了如何为网页添加打印样式,确保用户打印时获得理想的输出效果。</p>
<img src="https://picsum.photos/seed/print1/800/400.jpg"
alt="打印样式示意图"
loading="lazy">
<h2>为什么需要打印样式</h2>
<p>默认情况下,浏览器打印网页的效果往往不理想。导航栏、广告、背景色等都会被打印出来,而链接地址和表格边框却丢失了。通过添加打印专用 CSS,我们可以控制哪些内容被打印,以及打印的样式。</p>
<p>了解更多信息,请访问 <a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/@media">MDN CSS @media 文档</a>。</p>
<div class="ads">
<strong>广告:</strong>这是一条广告,打印时会被隐藏。
</div>
<h2>销售数据报表</h2>
<table class="data-table">
<thead>
<tr>
<th>季度</th>
<th>销售额</th>
<th>同比增长</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr>
<td>Q1</td>
<td>¥1,200,000</td>
<td>+15%</td>
<td>春节促销</td>
</tr>
<tr>
<td>Q2</td>
<td>¥980,000</td>
<td>+8%</td>
<td>正常销售</td>
</tr>
<tr>
<td>Q3</td>
<td>¥1,500,000</td>
<td>+22%</td>
<td>618 大促</td>
</tr>
<tr>
<td>Q4</td>
<td>¥2,100,000</td>
<td>+30%</td>
<td>双 11 活动</td>
</tr>
</tbody>
</table>
<div class="social-share">
<button style="background:#1DA1F2;">分享到 Twitter</button>
<button style="background:#4267B2;">分享到 Facebook</button>
<button style="background:#07C160;">分享到微信</button>
</div>
</article>
</main>
<footer class="page-footer">
<p>© 2024 技术博客。保留所有权利.</p>
</footer>
</body>
</html>示例 2:发票打印模板
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>发票打印模板</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
line-height: 1.6;
color: #333;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.print-btn {
background: #4A90D9;
color: white;
border: none;
padding: 0.75rem 2rem;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
margin-bottom: 2rem;
}
.invoice {
border: 1px solid #ddd;
border-radius: 8px;
padding: 2rem;
}
.invoice-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 2px solid #4A90D9;
}
.invoice-header .company h2 {
margin: 0;
color: #4A90D9;
}
.invoice-header .invoice-info {
text-align: right;
}
.invoice-header .invoice-info .invoice-number {
font-size: 1.5rem;
font-weight: 700;
color: #2c3e50;
}
.invoice-parties {
display: flex;
justify-content: space-between;
margin: 2rem 0;
gap: 2rem;
}
.invoice-parties .party {
flex: 1;
}
.invoice-parties .party h4 {
margin: 0 0 0.5rem 0;
color: #4A90D9;
font-size: 0.875rem;
text-transform: uppercase;
}
.invoice-table {
width: 100%;
border-collapse: collapse;
margin: 1.5rem 0;
}
.invoice-table th {
background: #4A90D9;
color: white;
padding: 0.75rem;
text-align: left;
font-size: 0.875rem;
}
.invoice-table td {
padding: 0.75rem;
border-bottom: 1px solid #eee;
}
.invoice-table .text-right {
text-align: right;
}
.invoice-totals {
margin-left: auto;
width: 300px;
}
.invoice-totals .row {
display: flex;
justify-content: space-between;
padding: 0.5rem 0;
}
.invoice-totals .total {
font-size: 1.25rem;
font-weight: 700;
border-top: 2px solid #333;
padding-top: 0.75rem;
}
.invoice-footer {
margin-top: 2rem;
padding-top: 1rem;
border-top: 1px solid #ddd;
font-size: 0.875rem;
color: #666;
}
/* 打印样式 */
@media print {
.print-btn {
display: none !important;
}
body {
padding: 0;
max-width: none;
}
.invoice {
border: none;
padding: 0;
}
.invoice-header {
border-bottom: 2px solid #000;
}
* {
background: transparent !important;
color: #000 !important;
}
.invoice-table th {
background: #eee !important;
color: #000 !important;
border: 1px solid #999;
}
.invoice-table td {
border: 1px solid #ccc;
}
.invoice-totals .total {
border-top: 2px solid #000;
}
@page {
size: A4;
margin: 1.5cm;
}
}
</style>
</head>
<body>
<button class="print-btn" onclick="window.print()">打印发票</button>
<div class="invoice">
<div class="invoice-header">
<div class="company">
<h2>示例科技有限公司</h2>
<p>北京市朝阳区科技路 100 号</p>
<p>电话:010-12345678</p>
<p>邮箱:billing@example.com</p>
</div>
<div class="invoice-info">
<div class="invoice-number">发票 #INV-2024-001</div>
<p>日期:2024 年 1 月 15 日</p>
<p>到期日:2024 年 2 月 15 日</p>
</div>
</div>
<div class="invoice-parties">
<div class="party">
<h4>开票方</h4>
<p><strong>示例科技有限公司</strong></p>
<p>统一社会信用代码:91110000XXXXXXXX</p>
<p>开户行:中国银行北京分行</p>
<p>账号:6217 0000 0000 0000</p>
</div>
<div class="party">
<h4>收票方</h4>
<p><strong>客户公司名称</strong></p>
<p>上海市浦东新区商业路 200 号</p>
<p>联系人:张经理</p>
<p>电话:021-87654321</p>
</div>
</div>
<table class="invoice-table">
<thead>
<tr>
<th>项目</th>
<th>描述</th>
<th class="text-right">数量</th>
<th class="text-right">单价</th>
<th class="text-right">金额</th>
</tr>
</thead>
<tbody>
<tr>
<td>网站开发</td>
<td>企业官网设计与开发</td>
<td class="text-right">1</td>
<td class="text-right">¥50,000.00</td>
<td class="text-right">¥50,000.00</td>
</tr>
<tr>
<td>UI 设计</td>
<td>移动端 UI 设计(10 个页面)</td>
<td class="text-right">10</td>
<td class="text-right">¥2,000.00</td>
<td class="text-right">¥20,000.00</td>
</tr>
<tr>
<td>服务器部署</td>
<td>云服务器配置与部署</td>
<td class="text-right">1</td>
<td class="text-right">¥5,000.00</td>
<td class="text-right">¥5,000.00</td>
</tr>
</tbody>
</table>
<div class="invoice-totals">
<div class="row">
<span>小计:</span>
<span>¥75,000.00</span>
</div>
<div class="row">
<span>税费(6%):</span>
<span>¥4,500.00</span>
</div>
<div class="row total">
<span>合计:</span>
<span>¥79,500.00</span>
</div>
</div>
<div class="invoice-footer">
<p>备注:请在到期日前付款。逾期将收取每日 0.05% 的滞纳金。</p>
<p>银行转账请备注发票号:INV-2024-001</p>
</div>
</div>
</body>
</html>示例 3:打印事件与动态处理
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>打印事件与动态处理</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
line-height: 1.6;
color: #333;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.demo-section {
border: 1px solid #ddd;
border-radius: 8px;
padding: 1.5rem;
margin: 1.5rem 0;
}
.demo-section h3 {
margin-top: 0;
color: #4A90D9;
}
.collapsible-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s;
}
.collapsible-content.expanded {
max-height: 500px;
}
.toggle-btn {
background: #4A90D9;
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
}
.print-btn {
background: #27ae60;
color: white;
border: none;
padding: 0.75rem 2rem;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
}
.qr-code {
display: none;
text-align: center;
margin: 1rem 0;
}
.timestamp {
display: none;
text-align: center;
font-size: 0.875rem;
color: #666;
margin-top: 1rem;
}
@media print {
.toggle-btn, .print-btn {
display: none !important;
}
.collapsible-content {
max-height: none !important;
overflow: visible !important;
}
.qr-code, .timestamp {
display: block !important;
}
.demo-section {
border: none;
padding: 0;
}
@page {
size: A4;
margin: 2cm;
}
}
</style>
</head>
<body>
<h1>打印事件与动态处理</h1>
<button class="print-btn" onclick="window.print()">打印此页</button>
<div class="demo-section">
<h3>折叠内容(打印时自动展开)</h3>
<button class="toggle-btn" onclick="toggleContent()">展开/折叠</button>
<div class="collapsible-content" id="collapsible">
<p>这段内容在屏幕上默认折叠,但打印时会自动展开显示。这是通过 beforeprint 事件实现的。</p>
<p>使用场景:FAQ 页面、详细说明、技术文档等,屏幕上折叠以节省空间,打印时展开以获取完整信息。</p>
</div>
</div>
<div class="demo-section">
<h3>打印专用内容</h3>
<p>以下内容只在打印时显示:</p>
<div class="qr-code">
<p>[二维码占位 - 扫码访问此页面]</p>
<p style="font-size:2rem;">▦▦▦▦</p>
</div>
<div class="timestamp" id="printTimestamp"></div>
</div>
<div class="demo-section">
<h3>beforeprint/afterprint 事件</h3>
<p>浏览器在打印前后触发事件,可以用来动态调整页面内容:</p>
<ul>
<li><strong>beforeprint</strong>:打印对话框打开前触发</li>
<li><strong>afterprint</strong>:打印对话框关闭后触发</li>
</ul>
</div>
<script>
function toggleContent() {
document.getElementById('collapsible').classList.toggle('expanded');
}
// 打印前处理
window.addEventListener('beforeprint', function() {
// 展开所有折叠内容
document.querySelectorAll('.collapsible-content').forEach(el => {
el.classList.add('expanded');
el.dataset.wasCollapsed = 'true';
});
// 添加打印时间戳
const now = new Date();
document.getElementById('printTimestamp').textContent =
'打印时间:' + now.toLocaleString('zh-CN');
});
// 打印后处理
window.addEventListener('afterprint', function() {
// 恢复折叠状态
document.querySelectorAll('[data-was-collapsed]').forEach(el => {
el.classList.remove('expanded');
delete el.dataset.wasCollapsed;
});
});
</script>
</body>
</html>五、浏览器兼容性
六、注意事项与最佳实践
-
始终添加打印样式:即使只是简单的@media print 块,也能显著改善打印效果
-
隐藏非内容元素:导航、侧边栏、广告、分享按钮等不需要打印
-
移除背景色和图片:大多数浏览器默认不打印背景,但应显式设置
-
显示链接 URL:打印后链接不可点击,应显示 URL 供参考
-
为表格添加边框:屏幕上的 CSS 边框在打印时可能消失
-
控制分页:避免表格行、图片、代码块被分页截断
-
使用 pt 单位:打印样式使用 pt(点)而非 px(像素)
-
设置合理的页面边距:使用@page 规则设置适当的边距
-
测试打印效果:使用浏览器的打印预览功能测试,不必真的打印
-
考虑黑白打印:大多数用户使用黑白打印,确保颜色不是唯一的信息传达方式
七、代码规范示例
代码示例
/* 规范:打印样式模板 */
@media print {
/* 1. 隐藏非内容元素 */
nav, .sidebar, .ads, .social,
.comments, .footer, .print-hide {
display: none !important;
}
/* 2. 重置样式 */
* {
background: transparent !important;
color: #000 !important;
box-shadow: none !important;
text-shadow: none !important;
}
body {
font-size: 12pt;
line-height: 1.5;
}
/* 3. 显示链接 URL */
a[href^="http"]::after {
content: " (" attr(href) ")";
font-size: 0.875em;
}
/* 4. 表格边框 */
table { border-collapse: collapse; }
th, td { border: 1px solid #999; }
/* 5. 分页控制 */
h1, h2, h3 { page-break-after: avoid; }
img, table, pre { page-break-inside: avoid; }
p { orphans: 3; widows: 3; }
/* 6. 页面设置 */
@page {
size: A4;
margin: 2cm;
}
}八、常见问题与解决方案
问题 1:背景色不打印
解决方案:浏览器默认不打印背景,可以在打印设置中勾选"打印背景图形",或在 CSS 中使用-webkit-print-color-adjust。
代码示例
@media print {
* {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
}问题 2:表格跨页截断
解决方案:使用page-break-inside: avoid。
代码示例
@media print {
table {
page-break-inside: avoid;
}
thead {
display: table-header-group; /* 每页重复表头 */
}
tfoot {
display: table-footer-group; /* 每页重复表尾 */
}
}问题 3:打印内容太小或太大
解决方案:使用 pt 单位设置打印字体大小,调整@page 边距。
代码示例
@media print {
body {
font-size: 12pt; /* 打印推荐 12pt */
}
@page {
margin: 2cm; /* 适当的边距 */
}
}九、总结
打印样式是 Web 开发中容易被忽视但非常重要的环节。通过本教程的学习,你应该掌握了:
-
@media print:编写打印专用 CSS 样式
-
分页控制:page-break-before/after/inside 和 break-*属性
-
@page 规则:设置页面大小和边距
-
打印隐藏:隐藏不需要打印的导航、广告等元素
-
打印链接 URL:使用 CSS 伪元素显示链接地址
-
打印事件:beforeprint/afterprint 事件处理
-
发票模板:实际打印模板的开发实践
为每个面向内容的项目添加打印样式,确保用户在需要打印时能获得良好的输出效果。
常见问题
为什么浏览器默认打印效果不理想?
浏览器默认会打印页面上的所有可见元素,包括导航栏、侧边栏、广告等不需要打印的内容。同时,屏幕上的背景色、阴影等效果在打印时会被忽略,链接地址也不会显示。通过添加@media print 样式,可以控制哪些内容被打印以及如何打印。
如何让链接在打印时显示 URL?
使用 CSS 伪元素::after 和 attr() 函数:a[href^="http"]::after { content: " (" attr(href) ")"; }。这样可以在链接文本后显示完整的 URL。注意要排除锚点链接(href^="#")和 JavaScript 链接(href^="javascript:")。
page-break-inside: avoid 有什么作用?
page-break-inside: avoid 用于防止元素内部被分页截断。常用于表格、图片、代码块等需要保持完整的内容。现代 CSS 推荐使用 break-inside: avoid,但为了兼容性可以同时使用两个属性。
@page 规则可以设置哪些属性?
@page 规则主要可以设置:size(页面尺寸,如 A4、Letter)、margin(页面边距)。还可以使用伪类:first(首页)、:left(左侧页)、:right(右侧页)为不同页面设置不同的边距。注意@page 规则的浏览器兼容性,特别是 size 属性在 Firefox 和 Safari 中支持有限。
beforeprint 和 afterprint 事件有什么用途?
beforeprint 事件在打印对话框打开前触发,可以用来展开折叠内容、添加打印时间戳等。afterprint 事件在打印对话框关闭后触发,可以用来恢复页面状态。这两个事件在 Chrome 63+、Firefox 和 Edge 中支持,但 Safari 不支持。
打印样式应该使用什么单位?
打印样式推荐使用 pt(点)作为字体大小单位,因为 pt 是印刷行业的标准单位(1pt = 1/72 英寸)。页面边距可以使用 cm(厘米)或 mm(毫米)。避免使用 px(像素),因为像素在打印时没有明确的物理尺寸对应关系。
本文涉及AI创作
内容由AI创作,请仔细甄别