8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

モダンブラウザとElectronでの印刷時に余白をピッタリ調整する

Last updated at Posted at 2020-02-18

モチベーション

ElectronではwebContents.print()関数やwebContents.printToPDT()関数を使って簡単に印刷やPDF作成ができます。この時、CSSで印刷サイズをmm等の実物長さで指定することで、実際の印刷時の各種要素の大きさを指定できるので便利です。が、注意しないと余分な余白が入ってしまいます。経験則からくる注意点を情報共有します。

※2020/2/19:色々試行錯誤して、@pageとの関連、print()printToPDF()の違いなど大幅に改定しました。

最重要注意点

  • ChromeおよびChromium系ブラウザ、Electron(7.1.9~8.0.1で確認)において、@page内に記述したmargin, margin-left, margin-right,margin-top,margin-bottomについては、単位の変換におそらくbugがあり、設定値よりも1.5~1.8倍程度大きく設定されてしまう。
    • 確認したversion(これ以外も確認していないだけでおそらくbugがある)
      • Chrome: 80.0.3987.106
      • Electron: 7.1.9~8.0.1
      • Edge (Chromium): 80.0.361.54
  • 回避策として、@page内ではmargin系の設定値の 単位として%を使う。
  • Firefox、Edge(Legacy)では%以外の単位も問題なく動く。
  • margin-topmargin-bottom%を使う際は、ブラウザによって解釈が異なる
    • Chrome, Firefox, Edge(Chromium):ページ横幅に対する割合を設定する
    • Edge(Legacy):ページ縦幅に対する割合を設定する

注意点(試行錯誤の結果)

  • CSSでpaddingmarginを正しく設定する。特に設定しない時は、明示的に0mmを設定すること。デフォルトでは0mmでないことがある。
  • body要素にもpaddingmarginを明示的に設定する事。実際に余分な余白が消えずに悩んだが、body要素のmarginがデフォルトで0mmではなかったことが原因だった。
  • 印刷時だけ設定したいCSSは@media print項目で設する。
  • ブラウザ上の表示はどれだけ長くても縦に長い1枚ページであるのに対し、印刷時は縦幅も固定で複数ページに分割される。
  • 印刷時のページ毎のマージンは、HTML要素のプロパティーではなく、@pageのプロパティーとして設定するべき。さもなくば、 改ページ部分での上下マージンが反映されない。
  • webContents.print()はElectron 7.xではmarginType:"custom"を設定するとクラッシュする。
  • webContents.print()marginTypeに"default"以外の値を設定しても、"default"と表示が変わらない。(バグとも思える。Electron version 8.0.1)。
  • webContents.printToPDF()marginsType:0(デフォルトマージン)にすると CSSの@pageに設定したmargin, margin-left, margin-right,margin-top,margin-bottomが適用される。 marginsType:1(マージンなし)にすると、これらのCSS設定も無視される。
  • webContents.printToPDF()marginsType:0と、webContents.print()marginType: "default"はCSSの適用と表示に関して(おそらく)同じ挙動。

body要素の中にdiv要素があり、その中に文章が書かれている場合のCSS記述は次のようになります。

@page{
  size: A4;
/*  本来は以下の記述で良いはずが、Chromium系バグで設定値より大きくなってしまう
  margin-left:   15mm;
  margin-right:  15mm;
  margin-top:    20mm;
  margin-bottom: 20mm;
回避策として以下のように%で指定する
*/
  margin-left:   7.143%;   /* = 15mm / 210mm */
  margin-right:  7.143%;
  margin-top:    9.524%;      /* = 20mm / 210mm "横幅"に対する割合*/
  margin-bottom: 9.524%;
}
@media print{
  body{
    padding: 0mm;  
    margin: 0mm;   /* これが無いと余分な余白が入る */
  }
  div{
    padding: 0mm;
    margin: 0mm;
    width:100%;
  }
}

上記の様なCSSに対して、印刷のJavascriptコードはprint()関数のoptionとして次のようにmarginType:"default"を指定する。

  const wc = browserWindow.webContents;
  wc.print({margins:{marginType:"default"}},
    (success, error) => {
        if(success){
            console.log('Print successfully.');
        }else{
            console.log(error);
        }
    });

また、PDF出力時のJavascriptコードはprintToPDF()関数のoptionとして次のようにmarginsType:0を指定する。

  const wc = browserWindow.webContents;
  wc.printToPDF({pageSize:"A4", marginsType:0}).then(data => {
     fs.writeFile(result.filePath, data, (error) => {
       if (error) throw error;
         console.log('Write PDF successfully.');
       })
     }).catch(error => {
       console.log(error);
     });

雑感

Electronの印刷はとても楽でいいですね。CSSで微調整できるところも素敵です。すごい時代になってますね。

子供の頃、親父にPCを買ってもらった際、弟と協力して年賀状印刷ソフトを作ったのを思い出しました。当時はVisual Basic6で印刷物の位置合わせをするのに苦労しました。

雑感(改定時)

Chrome,Chromiumのバグと気づくまで今回は時間が掛かりました。Firefoxがあってよかった。Edge(Legacy)が無くなってしまった弊害として、今回の様なブラウザエンジンのバグに気づきにくくなりますね。そういう意味で復活して欲しいなぁ、EHTMLエンジン。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?