座談会
前編 ブラウザによって異なる印刷対応状況

スマートフォンの登場で、Webサイトそのものを印刷して情報を保存するニーズは低減しましたが、ユーザーや、サイトの性質により印刷が必要とされる場合もあります。これまで制作はどのような対応をしてきたか、また印刷手法にはどのようなものかあるか、それぞれの経験を語ります。

2016年06月23日発行

目次

スマートフォンの登場で、Webサイトそのものを印刷して情報を保存する方法はあまり提供されなくなってきたかもしれません。ですが、ページやサイトの性質によっては、いまだに印刷が必要とされる場合もあります。これまで制作側はどのような対応をしてきたか、また現在、どんな有効な手法があるのか、技術情報を交えた座談会でお届けします。

参加者

座談会の参加者は次のとおりです。

  • 中村 享介(@kyosuke) フロントエンド・エンジニア
  • 高津戸 壮(@Takazudo) フロントエンド・エンジニア
  • 坂巻 翔大郎(@GeckoTang) フロントエンド・エンジニア

なお、この座談会の進行・構成は、編集の外村 奈津子が担当しました。

表示どおりの印刷でなければバグ!?

――印刷機能というと、スマートフォンが普及する以前のほうがユーザー側はよく使っていたと思います。その頃の印刷実装とはどうだったのでしょう?

中村:メディアクエリがブラウザ実装された頃、これを使うとWebページの印刷を良くできるんじゃないかと思いました。その当時、印刷ページはどうあるべきかを考えて、勝手に実装してみたことはあります。クライアントから特に要望があったわけではないのですが。

――そのときの印刷ページはどういうものにしたのですか?

中村:たとえばナビゲーションは印刷時は使うわけじゃないから、表示する必要ないですよね。そうやって、不要なものをなくして印刷時に必要なものだけが表示されるようにしたんです。そうしたら「サイトの表示どおりに印刷されないバグ」が上がってきました(笑)。

高津戸:昔のブラウザは、IEのhasLayout周りのバグが原因でCSSで設定した背景画像が印刷されないとか、700pxくらいまでの幅しか印刷できないことがありました。今ではズームアウトしてページ幅全体が紙に収まるようにうまい具合に調節してくれるブラウザが主流ですが、以前は、大きい画面は縮小されたりせず、印刷したときに右側が切れてしまうブラウザが主流でした。そうすると、やはり同じようなバグ報告がありました。

中村:サイトのチェックを紙に印刷して行うって時代だったから。

坂巻:僕は、印刷には対応してないので、紙に印刷するんじゃなくて、画面をそのままキャプチャーするツールを使ってくださいってお願いしてました。

――なるほど。

中村:まあ、そういう時代があったので、特に要望がなければ、制作側でも印刷時にナビゲーションを消したり、ヘンに気を利かせないほうがいいというのはありましたよね。全部画面どおりに印刷されるのが、クライアントの「印刷する」ってことの基本的な認識だったので。

W3CのサイトはPCで表示すると多くのナビゲーションが表示されている
W3Cのサイトは印刷時に不要なナビゲーションを消すように設計されている

最近の印刷機能の要望

――では、最近の印刷実装事情はどうでしょうか。

中村:最近は漫然とサイト全部を印刷するっていう需要は減りましたね。

高津戸:そうですね。印刷したいページにしっかりと目的があるものが多いです。たとえば、ぐるなびのページなんかも地図とクーポンを印刷する機能がありますね。A4くらいの幅が狭い紙でもきちんと収まって印刷される。

きちんと情報が収まった印刷ページ(ぐるなびの地図印刷機能より)

――現在は紙に出してサイトをチェックするということ自体がなくなりました?

中村:いや、それはどうかわからないですね。ピクセルグリッドのクライアントからはそういうサイト全体に関して、印刷ができないというクレームはないですけど。

――ユーザー側は、サイトページの印刷はほとんど行わなくなったのかな?

中村:印刷はサイトの情報を持ち出したいという要望で使われてきた面があったと思いますが、今はスマホで開けばいいというのはありますよね。ただ予想外の用途で使われることはありますよ。たとえば、問い合わせフォームなんかは印刷されることはないだろうって思っていたんですけど、「問い合わせのために必要な項目」をメモするために印刷されていたケースがありました。

印刷するべきページの印刷

坂巻:制作側からこのページは印刷して使ってほしいと思うことはあります。たとえば、会社のサイトのアクセス(場所や交通手段が掲載されている)のページは、印刷される可能性が高いですよね。それから不動産サイトでは紹介物件の間取り図とか、そういうところは対応してもいいかなと思います。

そういった場合は、印刷専用のページを用意します。印刷ボタンを押すと、その専用のページに遷移して、そのページをブラウザの印刷機能を使って印刷してもらうという方法ですね。そのページではナビゲーションなど印刷ページに不要なものは消して、必要な要素だけにしてあります。

――専用ページなんですね。

坂巻:サイトページに対して、ダイレクトにCSSでメニューを消したりなんだりの処理をするといろいろつらいので。専用ページを用意してしまうのがいいですね。

中村:そう、その専用ページに遷移したときに、最低限のCSSがかかっている状態にします。そしてそのページを印刷してもらうと。

高津戸:CMSで管理していると、その手法はやりやすいですね。

中村:そうですね。ユーザーは印刷専用ページを印刷プレビューという位置付けで見ているので、見たページと違うものが印刷されてしまったということにもならないし。

【ワンポイント】印刷専用のCSSを読み込む

ここで出てきた「印刷専用のページを用意する」というのは、別途印刷用のHTMLを生成せずに、そのURLを再度開いてURLの最後に?printというクエリを付けておくという方法です。JSがそのページを読んだときに?printというクエリが付いていれば、印刷用のCSSを読み込むわけです。

URLに特定のクエリが付いている場合、要素を非表示にする
デモ中の「URLに?printをつけて開く」をクリックすると、デモのURLの最後に?printを付けて別タブで表示される。表示されたページを見ると、印刷用CSSが読み込まれてヘッダとフッタが非表示になっている印刷専用のページになっているのがわかる。

クエリの有無を判別して、印刷用のCSSを読み込むコードは次のようになります。

window.addEventListener('load', function(){
  // URLの末尾に?printが含まれているかどうか
  var isPrintMode = /\?print$/.test(location.href)
  var head = document.getElementsByTagName('head')[0];
  var link;
  // ?printがあれば
  // link要素を作成して、印刷用のCSSを読み込ませる
  if (isPrintMode) {
    link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = './print.css';
    link.type = 'text/css';
    head.appendChild(link);
  }
}, false);

URLにある文字が含まれるかは、/\?print$/.test(location.href)を使うと調べることができます。あとは、?printが含まれていれば、指定したCSSファイルが読み込まれるようにします。

印刷時の表の改ページ

――現在、案件として印刷機能の実装はありますか?

坂巻:今、手がけている実装は、印刷ボタンがあってそれを押すと専用のページに遷移して、そのページを印刷するというものですね。裏では、基本のCSSに加えて、印刷用のCSSを読み込んでいます。……その印刷の改ページが面倒くさい(笑)。

高津戸:ああ、なるほどね。

坂巻:たとえばテーブル(表)を印刷するとします。そのとき、tr要素の中に入っているコンテンツが多いと、ページの途中で切れてしまうんですよ。そうすると、ページをまたいで切れているじゃないかと、言われるわけです。

そうなると、では改ページしますか?ってなるわけですよ。改ページする仕様 13.3.1 改ページプロパティ:'page-break-before'、'page-break-after'、'page-break-inside'はあるんですけど、必ずしも望んだとおりになるとは限らないです。

プロパティ概要
page-break-insideauto, avoid印刷時の要素内での改ページを避ける
page-break-beforeauto, always, left, right, avoid印刷時の要素の前での改ページの指定
page-break-afterauto, always, left, right, avoid印刷時の要素の後での改ページの指定

中村:ブラウザによっても違うんだよね。改ページって。trに指定したら改ページされるんだっけ?

坂巻:いや、僕が対応していたときは、tdの中の要素でやらないとだめでした。中の要素にdivを付けて、それに対して指定します。

table要素が印刷時にページをまたいでいる
table要素を使ったサンプル。Chromeのプリントプレビューでの表示は、要素がページをまたいでいる。デモはこちら
table要素が印刷時にページをまたがないようにする
table要素を使ったサンプル。page-break-inside: avoid;を指定すると、要素がページをまたがなくなる。デモはこちら

坂巻:僕が長いことやっている案件があるんですけど、表組みの印刷対応が多くて苦しんでます。たとえば横にすごく長い表組みがあったとしますよね。この座談会時に確認した僕のChromeでは、印刷するときに、どんなに横に長くても縮小して収めてくれています。でもFirefoxはそれができていませんでした。表が見切れてしまう。ただ、ブラウザやOS、その設定によってもこの現象が変わるようで......*。

Chrome v51での印刷プレビュー
最初のセルと最後のセルにはわかりやすいように色を付けてある。最初と最後のセルが表示されているので、表がページの幅に収まっていることがわかる。(印刷プレビューに利用しているデモ
Firefox v47での印刷プレビュー(プレビューでPDFを開く)
右側の色の付いたセルが表示されず、表が収まらず途中で見切れているのがわかる。(印刷プレビューに利用しているデモ
*注:横に長い表組みの印刷

この記事公開時の坂巻のMac版のChrome バージョン51.0.2704.103で、横に長い表組みを印刷した際に、OS Xのシステム環境設定の「一般」の「スクロールバーの表示」の設定で表示結果が異なっていました。「マウスまたはトラックパッドに基づいて表示」あるいは「スクロール時に表示」に設定すると、横に長い表組みは収まりきりませんでしたが、「常に表示」の設定にすると表はすべて収まりました。このようにOSやブラウザのバージョンによっても、印刷の状況が異なるのが現状のようです。坂巻が検証した結果は以下のとおりでした。

ブラウザ印刷のされ方
OS X Chrome v51スクロールバーの表示設定を「常に表示」にしていれば、表が縮小され収まる
OS X Firefox v47表が見切れる
Windows 8.1, 10 Chrome表が縮小され収まる
Windows 8.1, 10 Firefox表が縮小され収まる
Windows10 IE11表が見切れる
Windows10 Edge表が見切れる

坂巻:表組みは印刷と相性悪いですね。

中村:でもわりと印刷したいのって、表だったりするよね(笑)。

ヘッダの印刷

坂巻:ナビゲーションなどに使われるposition: fixed;があるんですけど、あれはページメディア単位で指定の場所に固定されるんですね。印刷の場合、紙1枚、1枚がメディアにあたります。なので、position: fixed;でナビゲーションを固定すれば、ページが分かれても1枚1枚にナビゲーションが印刷されるはずなんです。仕様*では。

*注:position: fixedの仕様

printメディアタイプの場合、ボックスは各ページごとにレンダリングされ、たとえページがビューポートを通して見られる場合でもページボックスに対して固定される(たとえば、印刷プレビューの場合)。

原文:Choosing a positioning scheme: position property

日本語訳:位置決めスキームの選択:'position'プロパティ

中村:仕様としてはそうなんですよね。

坂巻:ほかにもtheadtfootもページごとの先頭や末尾に入る仕様*なんです。それができないと表組みがページに分かれた場合、「これ切ってセロテープで貼って見るの?」ってことになりますよね。

*注:theadtfootの仕様

table-row-groupと同様だが、視覚整形に対して、行グループは常にすべての行と行のグループの前に、かつ任意の上部のキャプションの後に表示される。印刷ユーザーエージェントは、テーブルによって広げられる各ページのヘッダー行を繰り返してもよい。テーブルがdisplay: table-header-groupをもつ複数の要素を含む場合、最初のもののみがヘッダーとしてレンダリングされる。他のものはあたかもdisplay: table-row-groupを持つかのように扱われる。

原文:17.2 The CSS table model

日本語訳:table-header-group(HTMLでTHEAD)

――(笑)

坂巻:でもこれがChromeではずっとできない。Chromeの開発では、2013年に「できないね」っていうissue(Fixed position boxes should repeat on each page for media=print)が上がってたんです。それがどうやら最近修正されて、ページごとに繰り返すことができるようになるらしい。

――2013年ですか。

中村:そうですね。issueを見るたびに「放置されてるな」って思ってました(笑)。2016年の4月末に、どうやらこのバグが解消されることになったらしい。

坂巻:まあ、Chromiumで直っただけなので、それがCanaryを経て、Stable(安定版)に反映されるのがいつになるのか、わからないですけど。

中村:Firefoxならできるんだけどね。SafariとChromeは印刷系の実装は遅れていますね。

坂巻:その統一感のなさが困るんです。全部のブラウザが「できる」ってことがほとんどないと思う。

――そうなんですね。

坂巻:ほかにもたとえば、@page規則の中でmarginプロパティを利用すると、印刷余白を指定することができるんですよ。

@page {
  margin: 0;
}

でもそれをChromeでやると、ヘッダが消えてしまうんです。これはどういうことだと(笑)。

Chrome v51での印刷プレビュー
@page { margin: 0; }を指定すると、Chromeではヘッダやフッタが消える。(デモはこちら
Firefox v47での印刷プレビュー
同じページをFirefoxで印刷しようとすると、ページの余白は消えているが、ヘッダ・フッタは消えていない。

余白が0のときにヘッダ・フッタを消すというのがChromeの挙動、でもFirefoxは消えません。こんなように、ブラウザ間で統一感がないんですよね。

(後編に続く)

中村 享介
中村 享介
フロントエンド・エンジニア

デザイン事務所のWebデザイナー、Web制作会社のWebディレクターを経て、フリーランスのFlash・JavaScriptエンジニアとして独立後、株式会社ピクセルグリッドを設立。 多数のリニューアル、新規立ち上げを取り仕切った経験をもち、情報設計、デザイン、フロントエンド、サーバーサイド、ネットワークといったひと通りのWebサイト制作技術に精通する。Web制作の他にも経営、講演、執筆など幅広く活動している。

著書に『WebクリエイティブのためのDOM Scripting』(単著:毎日コミュニケーションズ、2007年4月20日)、『jQuery逆引きマニュアル』(共著:インプレス、2010年12月17日)などがある。

高津戸 壮
高津戸 壮
フロントエンド・エンジニア

Web制作会社、フリーランスを経て、株式会社ピクセルグリッドに入社。数多くのWebサイト、WebアプリケーションのHTML、CSS、JavaScript実装に携わってきた。受託案件を中心にフロント周りの実装、設計、テクニカルディレクションを行う。スケーラビリティを考慮したHTMLテンプレート設計・実装、JavaScriptを使った込み入ったUIの設計・実装を得意分野とする。 著書に『改訂版 Webデザイナーのための jQuery入門』(技術評論社、2014年11月14日)がある。 CSS Nite 2011ベストセッションにおいて、全170セッションの中から、ベスト10セッションに、CSS Nite 2013ベストセッションでは、全278セッション中、ベスト20セッションに選出。

外村 奈津子
外村 奈津子
エディター

情報出版社に在籍中、Mac雑誌、中高年向けフリーペーパー、コラムサイト運営、健康食雑誌、グラフィック・Web技術書籍編集、IT系ニュースサイトの編集記者を経験。その後フリーランスのエディター/ライターとして独立。2011年4月より株式会社ピクセルグリッドへ入社。ピクセルグリッドが提供するフロントエンド技術情報を提供するサービス「CodeGrid」の編集を担当している。行政書士試験合格(未登録)。

坂巻 翔大郎
坂巻 翔大郎
フロントエンド・エンジニア

大手ソフトウェアダウンロード販売会社、Web制作会社などで、マークアップエンジニア、プログラマ、サービス企画、ディレクターを経験。2013年、株式会社ピクセルグリッドに入社。HTML、CSS、JavaScriptなどをオールラウンドに担当。とりわけ、プログラマブルなCSSの設計、実装を得意とする。 趣味で作成したゲーム「CSS PANIC」は、JavaScriptを一切使わず、HTMLとCSSのみで実装。海外サイトで紹介されるなど話題となった。