いままでの印刷、これからの印刷 前編 ブラウザによって異なる印刷対応状況
スマートフォンの登場で、Webサイトそのものを印刷して情報を保存するニーズは低減しましたが、ユーザーや、サイトの性質により印刷が必要とされる場合もあります。これまで制作はどのような対応をしてきたか、また印刷手法にはどのようなものかあるか、それぞれの経験を語ります。
はじめに
スマートフォンの登場で、Webサイトそのものを印刷して情報を保存する方法はあまり提供されなくなってきたかもしれません。ですが、ページやサイトの性質によっては、いまだに印刷が必要とされる場合もあります。これまで制作側はどのような対応をしてきたか、また現在、どんな有効な手法があるのか、技術情報を交えた座談会でお届けします。
参加者
座談会の参加者は次のとおりです。
- 中村 享介(@kyosuke) フロントエンド・エンジニア
- 高津戸 壮(@Takazudo) フロントエンド・エンジニア
- 坂巻 翔大郎(@GeckoTang) フロントエンド・エンジニア
なお、この座談会の進行・構成は、編集の外村 奈津子が担当しました。
表示どおりの印刷でなければバグ!?
——印刷機能というと、スマートフォンが普及する以前のほうがユーザー側はよく使っていたと思います。その頃の印刷実装とはどうだったのでしょう?
中村:メディアクエリがブラウザ実装された頃、これを使うとWebページの印刷を良くできるんじゃないかと思いました。その当時、印刷ページはどうあるべきかを考えて、勝手に実装してみたことはあります。クライアントから特に要望があったわけではないのですが。
——そのときの印刷ページはどういうものにしたのですか?
中村:たとえばナビゲーションは印刷時は使うわけじゃないから、表示する必要ないですよね。そうやって、不要なものをなくして印刷時に必要なものだけが表示されるようにしたんです。そうしたら「サイトの表示どおりに印刷されないバグ」が上がってきました(笑)。
高津戸:昔のブラウザは、IEのhasLayout周りのバグが原因でCSSで設定した背景画像が印刷されないとか、700pxくらいまでの幅しか印刷できないことがありました。今ではズームアウトしてページ幅全体が紙に収まるようにうまい具合に調節してくれるブラウザが主流ですが、以前は、大きい画面は縮小されたりせず、印刷したときに右側が切れてしまうブラウザが主流でした。そうすると、やはり同じようなバグ報告がありました。
中村:サイトのチェックを紙に印刷して行うって時代だったから。
坂巻:僕は、印刷には対応してないので、紙に印刷するんじゃなくて、画面をそのままキャプチャーするツールを使ってくださいってお願いしてました。
——なるほど。
中村:まあ、そういう時代があったので、特に要望がなければ、制作側でも印刷時にナビゲーションを消したり、ヘンに気を利かせないほうがいいというのはありましたよね。全部画面どおりに印刷されるのが、クライアントの「印刷する」ってことの基本的な認識だったので。
最近の印刷機能の要望
——では、最近の印刷実装事情はどうでしょうか。
中村:最近は漫然とサイト全部を印刷するっていう需要は減りましたね。
高津戸:そうですね。印刷したいページにしっかりと目的があるものが多いです。たとえば、ぐるなびのページなんかも地図とクーポンを印刷する機能がありますね。A4くらいの幅が狭い紙でもきちんと収まって印刷される。
——現在は紙に出してサイトをチェックするということ自体がなくなりました?
中村:いや、それはどうかわからないですね。ピクセルグリッドのクライアントからはそういうサイト全体に関して、印刷ができないというクレームはないですけど。
——ユーザー側は、サイトページの印刷はほとんど行わなくなったのかな?
中村:印刷はサイトの情報を持ち出したいという要望で使われてきた面があったと思いますが、今はスマホで開けばいいというのはありますよね。ただ予想外の用途で使われることはありますよ。たとえば、問い合わせフォームなんかは印刷されることはないだろうって思っていたんですけど、「問い合わせのために必要な項目」をメモするために印刷されていたケースがありました。
印刷するべきページの印刷
坂巻:制作側からこのページは印刷して使ってほしいと思うことはあります。たとえば、会社のサイトのアクセス(場所や交通手段が掲載されている)のページは、印刷される可能性が高いですよね。それから不動産サイトでは紹介物件の間取り図とか、そういうところは対応してもいいかなと思います。
そういった場合は、印刷専用のページを用意します。印刷ボタンを押すと、その専用のページに遷移して、そのページをブラウザの印刷機能を使って印刷してもらうという方法ですね。そのページではナビゲーションなど印刷ページに不要なものは消して、必要な要素だけにしてあります。
——専用ページなんですね。
坂巻:サイトページに対して、ダイレクトにCSSでメニューを消したりなんだりの処理をするといろいろつらいので。専用ページを用意してしまうのがいいですね。
中村:そう、その専用ページに遷移したときに、最低限のCSSがかかっている状態にします。そしてそのページを印刷してもらうと。
高津戸:CMSで管理していると、その手法はやりやすいですね。
中村:そうですね。ユーザーは印刷専用ページを印刷プレビューという位置付けで見ているので、見たページと違うものが印刷されてしまったということにもならないし。
【ワンポイント】印刷専用のCSSを読み込む
ここで出てきた「印刷専用のページを用意する」というのは、別途印刷用のHTMLを生成せずに、そのURLを再度開いてURLの最後に?print
というクエリを付けておくという方法です。JSがそのページを読んだときに?print
というクエリが付いていれば、印刷用のCSSを読み込むわけです。
このデモ中の「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-inside | auto, avoid | 印刷時の要素内での改ページを避ける |
page-break-before | auto, always, left, right, avoid | 印刷時の要素の前での改ページの指定 |
page-break-after | auto, always, left, right, avoid | 印刷時の要素の後での改ページの指定 |
中村:ブラウザによっても違うんだよね。改ページって。tr
に指定したら改ページされるんだっけ?
坂巻:いや、僕が対応していたときは、td
の中の要素でやらないとだめでした。中の要素にdiv
を付けて、それに対して指定します。
table要素を使ったサンプル。Chromeのプリントプレビューでの表示は、要素がページをまたいでいる。デモはこちら
table要素を使ったサンプル。page-break-inside: avoid;
を指定すると、要素がページをまたがなくなる。デモはこちら
坂巻:僕が長いことやっている案件があるんですけど、表組みの印刷対応が多くて苦しんでます。たとえば横にすごく長い表組みがあったとしますよね。この座談会時に確認した僕のChromeでは、印刷するときに、どんなに横に長くても縮小して収めてくれています。でもFirefoxはそれができていませんでした。表が見切れてしまう。ただ、ブラウザやOS、その設定によってもこの現象が変わるようで......*。
最初のセルと最後のセルにはわかりやすいように色を付けてある。最初と最後のセルが表示されているので、表がページの幅に収まっていることがわかる。(印刷プレビューに利用しているデモ)
右側の色の付いたセルが表示されず、表が収まらず途中で見切れているのがわかる。(印刷プレビューに利用しているデモ)
*注:横に長い表組みの印刷
この記事公開時の坂巻の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メディアタイプの場合、ボックスは各ページごとにレンダリングされ、たとえページがビューポートを通して見られる場合でもページボックスに対して固定される(たとえば、印刷プレビューの場合)。
中村:仕様としてはそうなんですよね。
坂巻:ほかにもthead
やtfoot
もページごとの先頭や末尾に入る仕様*なんです。それができないと表組みがページに分かれた場合、「これ切ってセロテープで貼って見るの?」ってことになりますよね。
*注:thead
やtfoot
の仕様
table-row-group
と同様だが、視覚整形に対して、行グループは常にすべての行と行のグループの前に、かつ任意の上部のキャプションの後に表示される。印刷ユーザーエージェントは、テーブルによって広げられる各ページのヘッダー行を繰り返してもよい。テーブルがdisplay: table-header-group
をもつ複数の要素を含む場合、最初のもののみがヘッダーとしてレンダリングされる。他のものはあたかもdisplay: table-row-group
を持つかのように扱われる。
——(笑)
坂巻:でもこれが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でやると、ヘッダが消えてしまうんです。これはどういうことだと(笑)。
@page { margin: 0; }
を指定すると、Chromeではヘッダやフッタが消える。(デモはこちら)
同じページをFirefoxで印刷しようとすると、ページの余白は消えているが、ヘッダ・フッタは消えていない。
余白が0
のときにヘッダ・フッタを消すというのがChromeの挙動、でもFirefoxは消えません。こんなように、ブラウザ間で統一感がないんですよね。
(後編に続く)