FlexBox枠内のPreタグ領域がFlexBoxの枠をはみ出してしまう現象の回避方法 - CSS

FlexBox枠内のPreタグ領域がFlexBoxの枠をはみ出してしまう現象を回避するためのコードを紹介します。

現象の確認

現象が発生するコードを確認します。
下記のHTMLファイルとCSSファイルを作成します。

コード

flex-pre-overflow.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="flex-pre-overflow.css" />
    <title></title>
</head>
<body>
    <div class="container">
        <div class="LeftFrame">
            左側の枠です。<br />
1つ目のPre枠です。<br />
<pre>
private void button1_Click(object sender, EventArgs e)
{
  int[] a = new int[5];
  a[0] = 24;
  a[1] = 33;
  a[2] = 12;
  a[3] = 8;
  a[4] = 25;

  foreach (int x in a) {
    textBox1.Text += x.ToString() + " / ";
  }
}
</pre>

2つ目のPre枠です。<br />
<pre>
AnalyticsReportingService.Initializer initializer = new AnalyticsReportingService.Initializer();
initializer.HttpClientInitializer = credential;
initializer.ApplicationName = "app";
AnalyticsReportingService service = new AnalyticsReportingService(initializer);
</pre>

        </div>
        <div class="RightFrame">
            右側の枠です。<br />

        </div>
    </div>
</body>
</html>
flex-pre-overflow.css
.container{
    display:flex;
}

.LeftFrame {
    flex:2;
    background-color:#c8e6d7;
}

.RightFrame {
    flex: 1;
    background-color: #c5dae4;
}

pre{
    background:#f0f0f0;
    border:1px#43b9f1 solid ;
    margin-left:1rem;
    margin-right:1rem;
}

解説

FlexBoxを利用して2段組みのページを作成します。LeftFrameのflexプロパティの値が2、RightFrameのflexプロパティの値が1のため、2:1の比率の段組みになります。
さらに、左側の枠の内部にはPreタグを記述して、ページのコンテンツを掲載します。

実行結果

プロジェクトを実行しWebブラウザで、HTMLファイルを表示します。
ウィンドウ幅を広くした状態では下図の画面が表示されます。左と右の段組みの幅の比率が2:1になっていることが確認できます。


ウィンドウ幅を狭めていきます。右と左の段組みの比率が変わらずに段組みのカラムの幅が狭まります。



Preタグのエリアの一番長い行の幅まで縮まりました。


さらにウィンドウ幅を縮めようとすると、Preタグのエリアの幅が縮まらず、左側の枠も縮まらず、右側の枠の幅だけが狭まります。このため、左と右の段組みの幅の比率が2:1でなくなります。


さらにウィンドウ幅を狭めても、左の枠は幅が変わらず、右側の枠の幅だけが狭まります。



さらに縮めると、ウィンドウの横スクロールバーが表示されてしまいます。


原因

左側の枠のスタイルの指定がデフォルトの状態で min-width:auto になっていることが原因です。preタグのエリア全体を左側のカラムに配置するため、preタグのエリアがちょうど含まれる横幅のサイズをmin-widthの自動の値としてしまうことが原因と考えられます。

対処法

幅が変わらないカラムに対して、 min-width:0 を明示的に指定します。

コード

flex-pre-overflow.css のLeftFrameクラスに min-width:0 を記述します。
flex-pre-overflow.css
.container{
    display:flex;
}

.LeftFrame {
    flex:2;
    background-color:#c8e6d7;
    min-width:0;
}

.RightFrame {
    flex: 1;
    background-color: #c5dae4;
}

pre{
    background:#f0f0f0;
    border:1px#43b9f1 solid ;
    margin-left:1rem;
    margin-right:1rem;
}

表示結果

CSSを変更後HTMLファイルをWebブラウザで表示します。ウィンドウ幅が広い状態では下図の表示となります。


ウィンドウ幅を縮めます。Preタグの行の一番長い行の幅より縮めると、CSS修正前は枠の横幅が縮まりませんでしたが、修正後はPreタグの枠の幅も縮まります。ただし、preタグ内のコンテンツの文字列がpreタグの外にはみ出してしまっています。


ウィンドウ幅を縮めると、preタグの枠の幅も縮まります。その結果左と右の枠の横幅も2:1の比率が維持された状態で縮まります。一方でpreタグエリア内のテキストははみ出してしまっています。



さらにウィンドウ幅を縮めると、Preタグのコンテンツがウィンドウ幅より長くなるため、ウィンドウに横スクロールバーが表示されてしまいます。

Preタグのエリアにスクロールバーを表示する

先の修正で枠の幅の動作は意図した通りのものになりましたが、preタグ内のコンテンツがはみ出してしまいます。preタグ内は自動で改行されないほうが良いため、preタグのエリアにスクロールバーを表示して内部をスクロールできる状態にして、はみだしを防ぐ動作にします。

コード

flex-pre-overflow.css のpreタグのスタイルに overflow-x:scroll; を追記します。
.container{
    display:flex;
}

.LeftFrame {
    flex:2;
    background-color:#c8e6d7;
    min-width:0;
}

.RightFrame {
    flex: 1;
    background-color: #c5dae4;
}

pre{
    background:#f0f0f0;
    border:1px#43b9f1 solid ;
    margin-left:1rem;
    margin-right:1rem;
    overflow-x:scroll;
}

表示結果

CSSの修正後、HTMLファイルをWebブラウザで表示します。下図の画面が表示されます。


ウィンドウ幅を狭めます。preタグの一番長い文字列より幅が狭くなると、preタグのエリアに横スクロールバーが表示されます。


ウィンドウ幅を狭くしても、左と右のカラムの幅の比率は2:1のままです。


スクロールバーを操作するとpreタグ内のコンテンツをスクロールして表示できます。

Flex枠が入れ子になる場合

Flex枠が入れ子(ネスト構造)になる場合の動作を確認します。

コード

以下のコードを記述します。
flex-pre-overflow-nest.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="flex-pre-overflow-nest.css" />
    <title></title>
</head>
<body>
  <div class="container">
    <div class="LeftFrame">

    </div>
    <div class="RightFrame">

      <div class="container-inside">
        <div class="LeftInsideFrame">

          左側の枠です。<br />
          1つ目のPre枠です。<br />
<pre>
private void button1_Click(object sender, EventArgs e)
{
  int[] a = new int[5];
  a[0] = 24;
  a[1] = 33;
  a[2] = 12;
  a[3] = 8;
  a[4] = 25;

  foreach (int x in a) {
    textBox1.Text += x.ToString() + " / ";
  }
}
</pre>

          2つ目のPre枠です。<br />
<pre>
AnalyticsReportingService.Initializer initializer = new AnalyticsReportingService.Initializer();
initializer.HttpClientInitializer = credential;
initializer.ApplicationName = "app";
AnalyticsReportingService service = new AnalyticsReportingService(initializer);
</pre>

        </div>
        <div class="RightInsideFrame">
          右側の枠です。<br />
        </div>
      </div>

    </div>
  </div>
</body>
</html>
flex-pre-overflow-nest.css
.container{
    display:flex;
}

.container-inside {
  display: flex;
}


.LeftFrame {
    padding: 1rem 1rem 1rem 1rem;
    flex:1;
    background-color:#bae2ce;
}

.RightFrame {
  padding: 1rem 1rem 1rem 1rem;
  flex: 5;
  background-color: #add4e6;
}

.LeftInsideFrame {
  padding: 1rem 1rem 1rem 1rem;
  min-width:0;
  flex: 4;
  background-color: #f5edc2;
}

.RightInsideFrame {
  padding: 1rem 1rem 1rem 1rem;
  flex: 1;
  background-color: #e8baa8;
}

pre {
  background: #f0f0f0;
  border: 1px#43b9f1 solid;
  margin-left: 1rem;
  margin-right: 1rem;
}

LeftInsideFrameのみmin-width:0;を設定しています。この状態の動作を確認します。
ページを表示し幅が広い場合の表示ま問題ありません。

ウィンドウ幅を狭めます。Preタグ内のコンテンツがPre枠より狭い場合は問題は起きません。


Preタグ内のコンテンツがPre枠の幅より広い状況になるとコンテンツがPre枠からはみ出します。


さらにウィンドウ幅を狭めると、右側の枠の大きさが変化せず、左側の緑色の枠の幅のみが狭まります。


さらにウィンドウ幅が狭くなると、横スクロールバーが表示されてしまいます。


原因

Flexの枠が入れ子になる場合は、上位の枠もmin-width:0; を指定しないと、preタグの大きさに合わせて枠が広がってしまいます。

対処法

外側の右側の枠のクラスRightFrame にもmin-width:0;を指定します。
.RightFrame {
  padding: 1rem 1rem 1rem 1rem;
  min-width: 0;
  flex: 5;
  background-color: #add4e6;
}

.LeftInsideFrame {
  padding: 1rem 1rem 1rem 1rem;
  min-width:0;
  flex: 4;
  background-color: #f5edc2;
}

動作確認

ウィンドウ幅を狭めても、左側の緑色の枠のみが狭くなる動作にならなくなりました。



ただし、はみ出したPre枠内のコンテンツがページ幅を超えてしまう場合に、横スクロールバーが表示されます。 この現象の対処法は、Pre枠にスクロールバーを表示します。

対応後のコード

CSSファイルを以下のコードに修正します。
flex-pre-overflow-nest.css
.container{
    display:flex;
}

.container-inside {
  display: flex;
}

.LeftFrame {
    padding: 1rem 1rem 1rem 1rem;
    flex:1;
    background-color:#bae2ce;
}

.RightFrame {
  padding: 1rem 1rem 1rem 1rem;
  min-width: 0;
  flex: 5;
  background-color: #add4e6;
}

.LeftInsideFrame {
  padding: 1rem 1rem 1rem 1rem;
  min-width:0;
  flex: 4;
  background-color: #f5edc2;
}

.RightInsideFrame {
  padding: 1rem 1rem 1rem 1rem;
  flex: 1;
  background-color: #e8baa8;
}


pre {
  background: #f0f0f0;
  border: 1px#43b9f1 solid;
  margin-left: 1rem;
  margin-right: 1rem;
  overflow-x:auto;
}

preタグのスタイルにoverflow-x:auto;を追加しています。

動作確認

上記の修正したCSSに更新し、HTMLをWebブラウザで表示します。下図のページが表示されます。
ウィンドウ幅が広い場合の表示は問題ないです。


ウィンドウ幅を狭め、Pre枠よりPre枠内部のコンテンツの幅が大きくなると、Preタグ内に横スクロールバーが表示されます。


さらにウィンドウの幅を狭めます。左側の枠の幅も保たれた状態です。


さらにウィンドウ幅を狭めても横スクロールバーは表示されません。


Flexの枠が入れ子の場合も、枠の大きさを維持しつつ、Preタグのあふれが無い状態にできました。
#Afterword{[ Preタグは利用頻度が少ないため、この現象に出会う機会は少ないですが、起きてしまった場合に原因がPreタグと 枠のmin-widthの設定にあることを特定するのはなかなか難しいです。

]}
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2019-12-01
iPentec all rights reserverd.