网页打印出来不好看,写一份打印样式

举报
静水流深-云海 发表于 2026/10/14 11:29:53 2026/10/14
【摘要】 想让用户把页面打印成 PDF 或者纸质文件,直接 Ctrl+P 出来全是导航栏、按钮、背景色错乱。这篇讲 @media print 这套基本没人提的 CSS:怎么藏掉不该打印的元素、怎么让链接把网址也打出来、怎么控制分页别把表格从中间切断,以及背景色死活打不出来这件事。

打印样式这块基本没人聊,但真要用到,坑还不少。这篇讲 @media print 怎么用。

一、@media print 是什么

它是 CSS 的一种媒体查询,里面的样式只在打印时生效(包括"打印成 PDF"):

@media print {
  /* 这里的样式只影响打印输出 */
}

屏幕上的样式完全不受影响,等于给打印单独准备了一套皮肤。

调试的时候不用真的打印——Chrome 的开发者工具里按 Ctrl+Shift+P,输入 “Rendering”,在 Emulate CSS media type 那里选 print,就能直接预览打印效果了,比一遍遍按 Ctrl+P 快得多。

打印时常见的毛病和对应的解法,先摆个对照:

打印出来的问题 解决办法
导航栏、按钮、广告都在纸上 @media print 里 display: none
正文被挤到第二页 解开容器宽度限制
链接没法点,看不出指向哪 a[href^="http"]::after 补上网址
彩色标签、状态块全变白 print-color-adjust: exact + 用户勾选背景图形
表格从中间断成两截 break-inside: avoid
标题孤零零留在页尾 break-after: avoid

下面逐个说。

二、先把不该打印的藏掉

导航栏、侧边栏、按钮、广告、页脚的联系方式,这些在纸上没意义:

@media print {
  .navbar,
  .sidebar,
  .btn,
  .ad,
  .pagination,
  .comment-form {
    display: none !important;
  }
}

!important 在这里用得心安理得——因为很多组件的显示样式本身就带优先级,加上它最省事。

同时把正文区的限制解开,让内容铺满整张纸:

@media print {
  .container {
    max-width: none;
    width: auto;
    margin: 0;
    padding: 0;
  }
}

三、链接把网址也打出来

这是打印样式里最实用的一条。屏幕上链接点一下就跳转,但印在纸上没法点,不把网址写出来这链接就废了:

@media print {
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 10pt;
    color: #555;
  }
}

效果是在每个外部链接后面自动加上 (https://...)。

注意用 a[href^="http"] 限定外部链接——站内相对路径的锚点(比如 #section-1)打出来是一串没用的东西,不该加。

四、背景色打不出来

这是最常被问到的问题:打印时背景色和背景图默认不输出。 浏览器这么设计是为了省墨,但你要是做了彩色标签、进度条、状态块,打出来全变白了。

两个层面解决。

代码里告诉浏览器保留:

@media print {
  .badge,
  .status {
    -webkit-print-color-adjust: exact;   /* 兼容老版 Chrome/Safari */
    print-color-adjust: exact;           /* 标准属性 */
  }
}

用户那边也得在打印对话框里勾选"背景图形",不然浏览器还是按省墨模式走。这一点你控制不了,只能在页面打印按钮旁边加一句提示。

五、控制分页

表格从中间断开、标题孤零零留在页尾、图片被切成两半——这些都能避免:

@media print {
  table,
  figure,
  pre {
    break-inside: avoid;      /* 尽量别从中间断开 */
  }

  h1, h2, h3 {
    break-after: avoid;       /* 标题后面别立刻分页 */
  }

  .new-chapter {
    break-before: page;       /* 强制从新的一页开始 */
  }
}

现代写法是 break-inside,老的 page-break-inside 也还能用,两个都写上兼容性更好:

table {
  page-break-inside: avoid;
  break-inside: avoid;
}

要注意的是 avoid 是"尽量"不是"保证"——如果一个表格本身就超过一页,它该断还是得断。

六、单位换成 pt

屏幕用 px,纸张用 pt(磅)、cm、mm 这类物理单位更符合直觉:

@media print {
  body {
    font-size: 11pt;          /* 正文 11 磅,接近常规文档 */
    line-height: 1.5;
    color: #000;              /* 纯黑,省墨也清楚 */
  }

  h1 { font-size: 18pt; }
  h2 { font-size: 14pt; }

  @page {
    margin: 2cm;              /* 页边距 */
  }
}

@page 规则是专门控制纸张的,页边距、纸张方向(横竖)都在这儿设:

@page {
  size: A4 portrait;          /* A4 纵向 */
  margin: 2cm 1.5cm;
}

七、几个补充

  • 加个"打印"按钮方便用户:

    function printPage() {
      window.print()
    }
    

    简单粗暴,但比让用户自己找浏览器的打印菜单友好。

  • 打印前后可以做点事。有两个事件可以监听:

    window.addEventListener('beforeprint', () => {
      // 打印前,比如展开所有折叠的内容
    })
    window.addEventListener('afterprint', () => {
      // 打印后恢复
    })
    

    很适合用来"打印前把所有折叠面板展开",否则用户打印出来是折叠状态,内容不全。

  • 页眉页脚是浏览器的。URL、日期、页码那些由浏览器控制,CSS 改不了(@page 里加内容只有部分浏览器支持),跟用户说明一下就行。

  • 图片分辨率。屏幕上的图 72dpi 够了,打印会糊。正文里的图尽量用原始尺寸的。

  • 别指望跨浏览器一致。各家浏览器的打印实现差异不小,重要文档建议直接生成 PDF 而不是让用户打印。

总结

打印样式这块平时没人提,但真要做也就是一份 @media print 的事:藏掉导航和按钮、给链接补上网址、用 break-inside: avoid 防止表格断页、单位换成 pt。最麻烦的是背景色打印不出来——代码里加 print-color-adjust: exact,还得提醒用户在打印对话框里勾上"背景图形",两边都做到才有效。做完这些,页面印出来就正经多了。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。