🪪

HTML + Chromeで名刺を作ってみよう

2022/01/05に公開

名刺のオンデマンド印刷に使うPDFデータをHTMLとChromeで作ってみたので、その際の備忘録です。

japanese.png

基本的なツール

  • Google Chrome -- レンダリングの確認、PDFへの変換に利用する

技術的なポイント

  1. CSS に @media print { @page { size: 97mm 61mm; } } などのように @page によるページサイズ指定があると、Chrome の Save as PDF 機能はページサイズとしてこの値を使用するようです。

    オンデマンド印刷の名刺データ入稿の際に3mmのマージン(断ち切り領域)が必要な場合が多いので、今回の実験では一般的な名刺サイズである 91x55mm に両側3mmのマージンを取ったサイズ(97x61mm)をページサイズとして指定します。

  2. 上記の状態で Chrome の Save as PDF (PDFに保存) の操作を行うと、期待したサイズのPDFが生成できます。

  3. バッチファイルなどで一気に変換したい場合は、Google Chromeをコマンドラインから呼び出し、オプションで --print-to-pdf および --headless を与えることで所望の処理が可能です。
    この際、背景画像などの読み込みが間に合わない場合は --virtual-title-budget=1000 などの遅延オプションをつけるようにしてください(単位はミリ秒です)。

    実験で利用したスクリプト では Google Developersの記事 などに従い、--disable-gpu オプションも指定していますが、このオプションは暫定的なのとされているので、最新の Chrome でも必須なのかは未確認です。

長所

  1. Chromeの場合、自動的にフォントは全部埋め込もうとするので、電子入稿の際にフォントの問題が発生しづらい。
  2. CSSの知識があれば比較的簡単にレイアウトが管理できる。
  3. Outputはブラウザで確認しながら進められる。
  4. 自動化に向いている。社内の名刺発注の自動化などのベースとして使える。

短所

  1. フォントのレイアウトをPixel単位で調整しようとすると、ブラウザの細かい挙動はあまり文書化されていないので難しく、ある程度の諦めが必要。
    たとえば、Font Familyで日本語、英語を別フォントにした場合と、日本語のみの場合ではベースラインが変わってしまうなど謎の挙動がある。

レイアウトする際のTips

  • 全体を囲うBOX要素を一つ作って、それに対して背景指定をするとロゴなどの配置がやりやすい。
  • 配置を細かく指定したい場合は、CSSの position: absolute を活用して箱の位置を厳密に決めるとレイアウトが崩れにくい。
  • レイアウトをディスプレイで確認している場合には印刷領域をBorderで表示して、PDFに変換するときはBorderを消すように @media print を活用してCSSを書くと便利。

例:

.page_container {
  /* page size */
  width: 91mm;
  height: 55mm;
  /* margin and border (total: 3mm) */
  margin: 2.9mm;
  margin-bottom: 0mm;
  border: solid gray 0.1mm;
}
@media print {
  @page {
    margin: 0;
    padding: 0;
    size: 97mm 61mm;	/* 91x55mm + 3mm margin */
  }
  .page_container {
    margin: 3mm;
    margin-bottom: 0;
    border: none;
  }
}

動作確認した環境

ソース一式:
https://github.com/aikige/html_business_card_template

OS/Chrome:

% sw_vers
ProductName:	macOS
ProductVersion:	12.1
BuildVersion:	21C52
% Google¥ Chrome --version
Google Chrome 96.0.4664.110

Reference

https://developers.google.com/web/updates/2017/04/headless-chrome

Discussion