質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.55%

インラインフレーム(iframe)の理解できない現象…

解決済

回答 2

投稿

  • 評価
  • クリップ 2
  • VIEW 7,286

imamura

score 132

理解不足によるものと承知でタイトルにしましたが、本当に理解に苦しんでいます。

  1. iframeのサイズをsytleで指定してもサイズが小さく表示される
  2. iframeに被せるようにdivを配置してもiframeの方が上に表示される
  3. iframeに被せたdivにopacityを1未満で指定すると上に表示される

Mac safari,chrome,opera にて動作を確認しました
firefoxは「1.サイズが小さく表示される」は発生しませんでした

イメージ説明

index.html

<!DOCTYPE html>
<html>
<head>
  <style>
  body {padding:0;margin:0}
  .overpanel {
    background-color: pink;
    border: 1px solid red;
    box-sizing: border-box;
    width: 600px;
    height: 200px;
    margin: auto;
    margin-top : -200px;
  }
  .frame {
    width: 600px;
    height: 200px;
    display: block;
    margin: auto;
    float: none;
  }
  .contents  {
    border: 20px solid skyblue;
    box-sizing: border-box;
    background-color: lightgreen;
    width: 600px;
    height: 200px;
    margin: auto;
  }
  </style>
</head>
<body>
<div style="height:50px;"></div>
<!-- -->
<iframe class="frame" src="iframe-content.html" marginheight="0" frameborder="0" scrolling="yes"></iframe>
<div class="overpanel"></div>
<!-- -->
<div class="contents"></div>
<div class="overpanel"></div>

</body>
</html>

iframe-content.html

<html>
<head>
  <style>
  .contents  {
    border: 20px solid skyblue;
    box-sizing: border-box;
    background-color: lightgreen;
    width: 100%;
    height:500px;
  }
  </style>
</head>
<body>
  <div class="contents"></div>
</body>
</html>

iframeのサイズをsytleで指定してもサイズが小さく表示される
iframeのサイズを幅600pxにしていますが、実際には584pxで表示されています。
styleではなくiframe要素widthでwidth="600"にしても結果は同じでした。

iframeに被せるようにdivを配置してもiframeの方が上に表示される
iframeの次に配置したdivをマイナスマージンすることで上に重ねていいます。
通常、後から指定されたものが上に重なると理解しているのですが、そうなりません。

iframeに被せたdivにopacityを1未満で指定すると上に表示される
なんらかの理由でiframeの優先度が強いのかと思ったのですが…
opacity:0.99を指定すると上に表示されます。opacity:1だと下になります。
とても不可解な挙動に思えます。

1番の目的は「iframeの上にdivを重ねる」ということなのですが、サイズが小さくなることもデザイン上困っています。
原因と対策をご存知でしたら教えていただけるとうれしいです。

よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+4

 iframeのサイズをsytleで指定してもサイズが小さく表示される

iframe-content.html で body { margin: 0; } にしてください。

 iframeに被せるようにdivを配置してもiframeの方が上に表示される

iframeに限らずimgやただのテキストでも、divが後ろに表示されます。試してみてください。
また、<div class="overpanel">ほげほげ</div> のように文字を書くと、それはiframeの前に表示されます。試してみてください。
つまり、

  • 奥から順に .overpanelの背景 → iframe/img → .overpanelのテキスト

ということになります。

なぜこのようになるか、仕様書で事細かに決まっています。
次のリストが、ページの描画順番です。数字が大きいほど後に描画されます(つまり、最前面に来ます)。
9 Visual formatting model

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

英語でわかりにくいかと思いますが、ざっくりいうと、

  1. スタックコンテキスト(今回は<html>のみ)の背景とボーダー
  2. スタックレベルが負である子スタックコンテキストとその子孫
  3. インラインレベル以外の要素(ただし2, 6, 7は除外)
  4. フロートしている要素(ただし2, 6, 7は除外)
  5. インラインレベルの要素(ただし2, 6, 7は除外)
  6. スタックレベルが0である子スタックコンテキストとその子孫、あるいはポジショニングされている要素
  7. スタックレベルが正である子スタックコンテキストとその子孫

です。これに今回のHTMLを当てはめると、

  1. (該当なし)
  2. (該当なし)
  3. .overpanelの背景(ただし、.overpanelの中身のインラインレベルのものは描画されない)
  4. (該当なし)
  5. iframe、img、テキストなど(.overpanelの中身のものも含む)
  6. (該当なし)
  7. (該当なし)

同じ数字に分類されているものは、HTMLの順番に描画されます。
(iframe がインラインレベルの要素に分類されています。たしかに display: block; が指定されていますが、iframeは置換インライン要素なので本体部分はインライン要素と見なされるためです。)

ここから分かる通り、

  • 奥から順に .overpanelの背景 → iframe/img → .overpanelのテキスト

のように描画される訳です。
「iframeの優先度が強い」というよりかは、「.overpanelの背景色の優先度が低い」のです。


上の解説は細かなことまで書いており分かりにくくなりましたが、要するに一般的なHTMLでは、下の順で描画されます。

  1. ブロックレベル要素の背景色(ソース順)
  2. 他のすべてのインラインレベル要素とテキスト(ソース順)

 iframeに被せたdivにopacityを1未満で指定すると上に表示される 

先程のリストで 「スタックコンテキスト」 という聞きなれない単語が出てきたかと思います。
実は、opacityを1未満で指定すると、その要素がスタックコンテキストになる のです。
MDN スタック文脈

1 未満の opacity 値を持つ要素

この場合、先程の描画順のリストはこうなります。

  1. (該当なし)
  2. (該当なし)
  3. (該当なし)
  4. (該当なし)
  5. iframe、img、テキストなど
  6. .overpanel
  7. (該当なし)

ゆえに、opacity:0.99 を指定するとiframeの上に表示されるのです。

なぜこういう挙動になっているかというと、透過処理の複雑化を避けるためです。
ある要素が スタックコンテキスト になると、背景色とインライン要素の描画順が分離することがなくなります。
つまり、その要素の子孫要素すべてを描画してから、全体の透過を一気にできるのです。

 対策

.overpanel が描画順の5, 6, 7に来てくれれば、iframeの上に描画されることがわかりました。
ですので、一番簡素な方法は、

.overpanel {
    position: relative;
}

として、.overpanelの描画順を6にすることです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/15 01:47

    回答ありがとうございます。
    なるほど!とても良くわかりました。
    iframeがfloatがデフォルトで指定されいたりとdivとは違うなと感じてはいましたが、表示順位も違っていたわけですね。
    問題の解決だけではなくhtmlの理解に大変勉強になりました。
    ありがとうございます。

    キャンセル

0

iframe-content.html のほうに

body { margin: 0px; padding: 0px; }

を追加してみて。

重ね表示の順番はz-indexっていうCSSがありますよ。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/15 01:45

    回答ありがとうございます。
    iframeで呼び出される側のmarginが影響するとは思いもよりませんでした。
    勉強になりました。
    z-indexだとうまくいきました。htmlが少々複雑になりますがこれもありですね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.55%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる