CSSのフレックスボックスを使って複数iframeを1枚に印刷する

## はじめに
iframeを使ったページを印刷するときに、複数ページに分かれて困ったことはありませんか？これをCSSのフレックスボックスで解決できたので共有します。

※この記事はCSSやiframeの知識が初心者を想定して書いてあります。

## ブラウザ環境
Chrome バージョン: 131.0.6778.140（Official Build） （64 ビット）を使って検討しました。Edgeではうまく動作しませんでした。

## 実行結果
次に示すコードを使うと、4つのiframeを縦に2つ、横に2つならべて表示します。印刷したときも同様のレイアウトで1ページに印刷します。

## できあがったコード
まずは全体でどのようなコードになったのか示します。
``` html
<!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>
```

## コードの説明
ポイントを説明します。
``` html
<!DOCTYPE html>
```
+ HTML5以降を使用していることを宣言

### \<head\>セクション
``` html
<meta charset="utf-8">
```
+ 文字エンコーディングをUTF-8に設定

``` html
<meta name="viewport" content="width=device-width, initial-scale=1.0">
```
+ レスポンシブデザインのためにビューポート設定
+ `content=width=device-width`：ページがデバイスの画面幅に合わせて表示
+ `initial-scale=1.0`：初期表示は100％表示

### \<style\> セクション
``` css
        body { margin: 0; padding: 0; }
```
+ `body`：デフォルトのマージンを削除、ページ全体の余白とパディングを0に設定

``` css
        .container {
            display: flex;
            flex-direction: column; /* 縦方向に配置 */
            height: 100vh;
        }
```
+ `.container`：縦方向のフレックスボックスレイアウトを設定し、コンテンツ全体の高さをビューポートの高さに設定

``` css
        .row {
            display: flex;
            flex-direction: row; /* 横方向に配置 */
            width: 100%;
            height: 50%; /* 高さを50%に設定 */
        }
```
+ `.row`：横方向のフレックスボックスレイアウトを設定し、行の高さをビューポートの50%に設定

``` css
        iframe {
            width: 100%;
            height: 50vh; /* 縦並びのiframeの高さを設定 */
            border: none;
        }
```
+ `ifram`：各iframeの幅を100%に設定、高さを50vh（ビューポート高さの50%）に設定

``` css
        .half-width-iframe {
            width: 50%; /* 横並びにするための幅 */
            height: 100%; /* 高さを100%に設定 */
            page-break-inside: avoid; /* ページ内での分割を避ける */
        }
```
+ `.half-width-iframe`：横並び用のiframeの幅を50%に設定、高さを100%に設定、ページ内での分割を避ける

### @ media print セクション
印刷時のスタイルを指定します。
``` css
            .container {
                height: auto;
                display: block; /* 印刷時にブロック要素として扱う */
            }
```
+ `.container`：高さを自動調整、ブロック要素として表示

``` css
            .row {
                display: flex;
                flex-direction: row; /* 印刷時にも横方向に配置 */
                height: auto; /* 高さを自動調整 */
                page-break-inside: avoid;
                page-break-after: auto;
            }
```
+ `.row`：横方向のフレックスボックスを維持、高さを自動調整、ページ内での分割を避ける設定

``` css
            iframe {
                width: 100%; /* 縦並びのiframeの幅を100%に設定 */
                height: auto; /* 印刷時に高さを自動調整 */
                page-break-inside: avoid; /* ページ内での分割を避ける */
            }
```
+ `iframe`：幅を100%に設定、高さを自動調整、ページ内での分割を避ける設定

``` css
            .half-width-iframe {
                width: 50%; /* 横並びのiframeの幅を設定 */
                height: auto; /* 高さを自動調整 */
            }
```
+ `.half-width-iframe`：幅を50%に設定、高さを自動調整

### ページのメインコンテンツ
``` css
    <div class="container">
        <iframe src="./map_tate.html"></iframe>
        <iframe src="./graph_tate.html"></iframe>
```
+ 縦方向のレイアウトコンテナ、縦並びのiframeを表示

``` css
        <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だとうまくいかないので、どなたか教えてください。