はじめに
iframeを使ったページを印刷するときに、複数ページに分かれて困ったことはありませんか?これをCSSのフレックスボックスで解決できたので共有します。
※この記事はCSSやiframeの知識が初心者を想定して書いてあります。
ブラウザ環境
Chrome バージョン: 131.0.6778.140(Official Build) (64 ビット)を使って検討しました。Edgeではうまく動作しませんでした。
実行結果
次に示すコードを使うと、4つのiframeを縦に2つ、横に2つならべて表示します。印刷したときも同様のレイアウトで1ページに印刷します。
できあがったコード
まずは全体でどのようなコードになったのか示します。
<!DOCTYPE html>
<html>
<head>
<title>Embed map</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { margin: 0; padding: 0; }
.container {
display: flex;
flex-direction: column; /* 縦方向に配置 */
height: 100vh;
}
.row {
display: flex;
flex-direction: row; /* 横方向に配置 */
width: 100%;
height: 50%; /* 高さを50%に設定 */
}
iframe {
width: 100%;
height: 50vh; /* 縦並びのiframeの高さを設定 */
border: none;
}
.half-width-iframe {
width: 50%; /* 横並びにするための幅 */
height: 100%; /* 高さを100%に設定 */
page-break-inside: avoid; /* ページ内での分割を避ける */
}
@media print {
.container {
height: auto;
display: block; /* 印刷時にブロック要素として扱う */
}
.row {
display: flex;
flex-direction: row; /* 印刷時にも横方向に配置 */
height: auto; /* 高さを自動調整 */
page-break-inside: avoid;
page-break-after: auto;
}
iframe {
width: 100%; /* 縦並びのiframeの幅を100%に設定 */
height: auto; /* 印刷時に高さを自動調整 */
page-break-inside: avoid; /* ページ内での分割を避ける */
}
.half-width-iframe {
width: 50%; /* 横並びのiframeの幅を設定 */
height: auto; /* 高さを自動調整 */
}
}
</style>
</head>
<body>
<h3>名前:〇〇〇〇 xxxx年xx月レポート</h3>
<div class="container">
<iframe src="./map_tate.html"></iframe>
<iframe src="./graph_tate.html"></iframe>
<div class="row">
<iframe src="./map_yoko.html" class="half-width-iframe"></iframe>
<iframe src="./graph_yoko.html" class="half-width-iframe"></iframe>
</div>
</div>
</body>
</html>
コードの説明
ポイントを説明します。
<!DOCTYPE html>
- HTML5以降を使用していることを宣言
<head>セクション
<meta charset="utf-8">
- 文字エンコーディングをUTF-8に設定
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- レスポンシブデザインのためにビューポート設定
-
content=width=device-width
:ページがデバイスの画面幅に合わせて表示 -
initial-scale=1.0
:初期表示は100%表示
<style> セクション
body { margin: 0; padding: 0; }
-
body
:デフォルトのマージンを削除、ページ全体の余白とパディングを0に設定
.container {
display: flex;
flex-direction: column; /* 縦方向に配置 */
height: 100vh;
}
-
.container
:縦方向のフレックスボックスレイアウトを設定し、コンテンツ全体の高さをビューポートの高さに設定
.row {
display: flex;
flex-direction: row; /* 横方向に配置 */
width: 100%;
height: 50%; /* 高さを50%に設定 */
}
-
.row
:横方向のフレックスボックスレイアウトを設定し、行の高さをビューポートの50%に設定
iframe {
width: 100%;
height: 50vh; /* 縦並びのiframeの高さを設定 */
border: none;
}
-
ifram
:各iframeの幅を100%に設定、高さを50vh(ビューポート高さの50%)に設定
.half-width-iframe {
width: 50%; /* 横並びにするための幅 */
height: 100%; /* 高さを100%に設定 */
page-break-inside: avoid; /* ページ内での分割を避ける */
}
-
.half-width-iframe
:横並び用のiframeの幅を50%に設定、高さを100%に設定、ページ内での分割を避ける
@ media print セクション
印刷時のスタイルを指定します。
.container {
height: auto;
display: block; /* 印刷時にブロック要素として扱う */
}
-
.container
:高さを自動調整、ブロック要素として表示
.row {
display: flex;
flex-direction: row; /* 印刷時にも横方向に配置 */
height: auto; /* 高さを自動調整 */
page-break-inside: avoid;
page-break-after: auto;
}
-
.row
:横方向のフレックスボックスを維持、高さを自動調整、ページ内での分割を避ける設定
iframe {
width: 100%; /* 縦並びのiframeの幅を100%に設定 */
height: auto; /* 印刷時に高さを自動調整 */
page-break-inside: avoid; /* ページ内での分割を避ける */
}
-
iframe
:幅を100%に設定、高さを自動調整、ページ内での分割を避ける設定
.half-width-iframe {
width: 50%; /* 横並びのiframeの幅を設定 */
height: auto; /* 高さを自動調整 */
}
-
.half-width-iframe
:幅を50%に設定、高さを自動調整
ページのメインコンテンツ
<div class="container">
<iframe src="./map_tate.html"></iframe>
<iframe src="./graph_tate.html"></iframe>
- 縦方向のレイアウトコンテナ、縦並びのiframeを表示
<div class="row">
<iframe src="./map_yoko.html" class="half-width-iframe"></iframe>
<iframe src="./graph_yoko.html" class="half-width-iframe">/iframe>
- 横方向のレイアウトコンテナ、横並びのiframeを表示
まとめ
この構造により、画面上では縦並びと横並びのiframeを実現し、印刷時はすべてが1ページに収まりました。
※Edgeだとうまくいかないので、どなたか教えてください。