语义化html结构组织行程单:用包裹单日行程,标记时间,区分模块;打印时用@media print隐藏无关元素、避免分页截断、重置字体;移动端通过viewport和clamp适配;localstorage存备注需json序列化并按日期区分key;导出pdf须内联中文字体、禁用@import、设置@page页边距。

用语义化 HTML 结构组织行程单内容
行程单本质是时间线 + 信息卡片的组合,别一上来就套 <div> 堆砌。用 <code><article></article> 包裹单日行程,用 <time></time> 标记出发/到达时间,用 <section></section> 区分交通、住宿、景点等模块——这样既利于屏幕阅读器识别,也方便后续用 CSS 的 display: grid 或 flex 做响应式排列。
常见错误是把所有文字塞进一个 <p></p> 里加 <br> 换行,结果打印时断行错乱、手机上缩成一团。正确做法是每个关键信息点独立成标签,比如:
<article><h2>Day 1:北京 → 西安</h2>
<time datetime="2024-06-01T08:30">08:30</time><strong>首都机场T3</strong> 出发(航班 CA1201)<br><time datetime="2024-06-01T11:20">11:20</time><strong>西安咸阳机场</strong> 抵达<br><section><h3>住宿</h3>
<p><strong>西安威斯汀大酒店</strong>|钟楼店|含早</p>
</section></article>
CSS 控制打印样式和移动端适配
电子行程单大概率要打印或发给客户看 PDF,所以必须写 @media print 规则。重点做三件事:隐藏无关元素(如导航栏、广告)、强制分页(用 page-break-inside: avoid 防止行程块被截断)、重置字体大小(打印时 14px 在 A4 上才清晰)。
移动端适配不用复杂框架,只靠两行 CSS 就够:
-
meta标签必须带<meta name="viewport" content="width=device-width, initial-scale=1"> - 对
<article></article>设置margin: 1rem 0,再加font-size: clamp(1rem, 4vw, 1.2rem),让文字在小屏不挤、大屏不虚
别忽略 color: #333 和 background: #fff —— 很多用户直接“另存为 PDF”,深色背景+浅灰字会变成糊成一片的黑块。
用 localStorage 保存用户编辑的行程备注
如果行程单支持客户手写备注(比如“孩子要坐靠窗位”“酒店需无烟房”),别每次刷新都丢掉。用 localStorage.setItem('itinerary-notes', JSON.stringify(notes)) 存,页面加载时用 JSON.parse(localStorage.getItem('itinerary-notes')) 读回来填进 <textarea></textarea>。
注意两个坑:
-
localStorage只存字符串,对象必须JSON.stringify,否则存进去是[object Object] - 不同日期的行程用唯一 key 区分,比如
itinerary-notes-day2,不然 Day 1 的备注会覆盖 Day 3 的 - 别在
input事件里高频存——改一个字就写一次磁盘,卡顿且损耗 Flash。用blur或change事件更稳妥
导出 PDF 时避免中文乱码和布局错位
直接用浏览器“打印 → 另存为 PDF”最稳,但前提是字体得内联。别依赖系统字体,把常用中文字体(如 “PingFang SC”, “Microsoft YaHei”, “Noto Sans CJK SC”)全写进 font-family,并确保 CSS 里没用 @import 引入外部字体文件——那些在 PDF 导出时大概率失效。
如果非要用 JS 库(如 jsPDF + html2canvas),记住:html2canvas 对 transform、position: fixed 和跨域图片极其敏感,行程单里带地图截图或二维码时,优先用 <img src="data:image/png;base64,..."> 内嵌,而不是外链。
真正容易被忽略的是页边距和分页逻辑——PDF 导出时,height: 100vh 会撑满整个视口,但一页 A4 实际只有约 842px 高。用 @page { size: A4; margin: 0.5in; } 显式声明,比靠 JS 算高度靠谱得多。











