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

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

新規登録して質問してみよう
ただいま回答率
85.37%
HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

2回答

763閲覧

positionでの理屈がわかりません、なぜこうなるのですか?

yuka11556

総合スコア2

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

1クリップ

投稿2024/08/03 08:12

編集2024/08/03 08:23

とあるサイトでpositonの勉強をしておりましたが以下のコードが解説を読んでもどうしても理解できません。

html

1<h1>sample07</h1> 2<section id="section01"> 3<div class="box box01"> 4 box01 5</div> 6<div class="box box02"> 7 box02 8</div> 9</section>

css

1#section01{ 2 background-color:pink; 3 border:2px solid #00f; 4 position:absolute; 5} 6.box { 7 width: 100px; 8 height: 100px; 9 border:1px solid #f00; 10 font-size:20px; 11} 12.box01{ 13 background-color: #aaa; 14} 15.box02{ 16 background-color: #bbb; 17 position:absolute; 18 top:50px; 19 left:50px; 20}

[解説]
#section01に指定した青線がbox01を囲って、背景ピンクがなくなっています。
これは、#section01がposition:absoluteを指定されたことで通常の位置より浮いて(通常の位置とはh1要素と並列の位置)、box01の下に重なっているため、背景ピンクが見えなくなってしまっているのです。
そして、box02が#section01を基準にtop:50px、left:50pxに位置しています。

[疑問点]
これは、#section01がposition:absoluteを指定されたことで通常の位置より浮いて(通常の位置とはh1要素と並列の位置)、box01の下に重なっているため、背景ピンクが見えなくなってしまっているのです。

box01の下に重なっているとのことなのですが、#section01はブロック要素であるのでwidthはブラウザ幅になるのにbox1はwidthが100pxでなぜ見えなくなるのかわかりません。加えてなんで背景は消えてborderの青線がbox01を囲うのかが全く分かりません

どなたかもう少し詳しく解説して頂けないでしょうか?

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

なんとなくですが、包含ブロックだけでなく整形コンテキストとかも知らないと混乱しそうな気がします。

MDN ブロック整形コンテキスト

このブロック整形コンテキストは概ね、レンダリング要素を並べて表示するためのレイヤーのようなものとイメージすると理解しやすいです。

MDNの解説通りルート要素(html要素)は最初の最も基本的なレイヤー(ブロック整形コンテキスト)で、表示幅はページ幅(≒ブラウザのクライアント領域の幅)になります。
(※これがiframeの内側であれば、子ページの表示幅は親ページで指定されたiframeの幅になったりします)

そのhtml要素(body要素)の直下に記述されているブロック要素は、上記解説の「新しいブロック整形コンテキストの生成」をしない限り、全て同一のレイヤーに配置&レンダリングされます。
この場合、スタイルで特殊な位置指定やwidthプロパティが指定されない(つまりwidth:autoである)ブロック要素は大抵は包含ブロックであるhtml要素に従いページ幅にぴったり収まるようにレンダリングされます
(通常のボックスレイアウトモデルに従い、ページ幅に合わせてmargin/border/paddingを解決するみたいな感じです)。

おそらく、コメントの『#section01=初期包含ブロック=ブラウザ幅という考えになってしまいます』というのはここ辺りの考え方に基づくものではないでしょうか。

さて、ここで新しいブロック整形コンテキストを生成した際の考え方ですが
特にposition:absoluteの場合、「既存の(包含ブロックを含む)レイヤーの1つ上に浮かぶ、全く新しいレイヤー」のようなイメージが近いです。

この新しく浮いたレイヤーは、その内部のレンダリング(サイズ決定と各要素の配置)は独自で解決し、レイヤー自身を包含ブロックである親のレイヤー内に配置するような流れになります。

示されたサンプルで言うと、#section01の直接の親要素はbody要素ですがレンダリング時は新しいレイヤーとなり
サイズ計算ではbody内部=ページ幅ぴったりにおさまるような挙動ではなく Lhankor_Mhy さんが示されているような判定で#section01自身のスタイル値を参照することになります。


ちなみにですが、新しいブロック整形コンテキストの生成が例えば「表のセル」である場合は「新しい浮いたレイヤー」を生成するわけではなく、
「票のセル内ごとの新しいレイヤー」が生成されるようなイメージで、そこでのサイズ計算は親のtable関連要素のスタイル指定であったり自動計算時は表全体のレンダリングに影響されたり……と、position:absoluteとはまた違う考え方になったりします。


これは完全に余談なのですが、position:absoluteでは「重ね合わせコンテキスト」とかいうものも生成され、やっぱりレイヤーのような考え方で説明されたりしています。
(よくz-index指定してるのに思った通りの要素が前面に出ない!とかで問題になりがちなやつです)

投稿2024/08/04 11:00

pecmm

総合スコア636

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuka11556

2024/08/05 07:19

pecmm 様 丁寧なご回答ありがとうぞございます。 Lhankor_Mhy様の方に追記のコメントを書かせていただきました。 もしもお時間があれば、またご教授して頂けますと幸いです。 どうぞよろしくお願いいたします。
guest

0

静的配置されたブロック要素の幅は、包含ブロックの幅になろうとしますが、
絶対配置されたブロック要素の幅は、必ずしも包含ブロックの幅になりません。

詳しくは以下の表がわかりやすいです。
https://drafts.csswg.org/css-position/#abspos-auto

この場合、left width rightがすべてautoなので、表の1行目が該当します。
width → shrink-to-fit とあるとおり、この場合は幅は内部コンテンツにフィットしようとします。

投稿2024/08/03 08:45

編集2024/08/03 08:45
Lhankor_Mhy

総合スコア36865

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuka11556

2024/08/03 13:37 編集

回答ありがとうございます。 包含ブロックという言葉自体知らず、色々調べさせていただきました。包含ブロックとはpositonの移動の基準となるものという認識でいいでしょうか?今まで、positionとは親要素を基準として位置が決まる、という風に認識しておりましたが、そもそもこの考え方自体が根本的に違っていて、条件によって基準となる包含ブロックが変わる。。。ということでしょうか? 今回の場合ですと#section01にabsoluteがついていて親要素が無い状態=#section01が包含ブロックになるというわけではなく、Lhankor_Mhyさんがおっしゃるようにleft width rightがすべてautoなので、表の1行目が該当する=width → shrink-to-fit とあるとおり、この場合は幅は内部コンテンツにフィットするということで合ってますか? ただ私が調べたサイトに「position:absolute 直近の布置ボックス(positionがsitaticでない要素)のパディング辺。該当するボックスがなければ、初期包含ブロック」と書かれており、この場合だと#section01に該当する包含ブロックがないので、やはり#section01=初期包含ブロック=ブラウザ幅という考えになってしまいます。。。。 なんだかこういまいちピンと来なくて。私自身が無知なのでもう少し教えてくださると嬉しいです。申し訳ないですorz
Lhankor_Mhy

2024/08/04 04:49

> 包含ブロックとはpositonの移動の基準となるものという認識でいいでしょうか? 包含ブロックの機能はそれだけではありませんが、position:absolute に関してはそうです。 > 条件によって基準となる包含ブロックが変わる。。。ということでしょうか? ご認識の通りです。 > この場合は幅は内部コンテンツにフィットするということで合ってますか? そうです。 > #section01に該当する包含ブロックがないので、やはり#section01=初期包含ブロック=ブラウザ幅 #section01 は初期包含ブロックではありませんが、#section01 の包含ブロックは初期包含ブロックでブラウザ幅である、というのは正しいです。 --- まず、『ブロック要素であるのでwidthはブラウザ幅になる』とはどういうことでしょうか。 これは、より厳密に表現するならば『width: auto の時にブロック要素であるのでwidthはブラウザ幅になる』ということです。そして、これは大雑把には正しいですが、たとえば margin-left: 100px であれば当然ブラウザ幅から100pxを引いた幅になるはずです。 では、position: staticの場合の計算方法を考えてみましょう。 これは、仕様によるとこうなります。 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = 包含ブロックの幅 https://www.w3.org/TR/CSS22/visudet.html#blockwidth つまり、width: autoであれば、包含ブロックの幅から他のプロパティの値を引いて計算できます。 --- いよいよ本題の絶対配置の場合なのですが、これは仕様によると、 'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含ブロックの幅 となっています。 ですので、上記計算式の left から right まですべてが 0 と指定されているならば、width: auto の時にブラウザ幅になる、という理解は間違っていません。 --- ところで、auto になっているプロパティが width だけなら話が早いのですが、他のプロパティも auto の場合はどうするんでしょうか? 計算だけでは求められないですよね。 その場合、仕様にどの要素を優先するかが決めてあります。 また、逆にプロパティにすべて値が設定してあって、包含ブロックの幅と異なる値にどうしてもなってしまう場合はどうするのでしょうか。これも仕様で定めてあります。 --- ご質問の場合、border が 2px ずつ、margin と padding が 0、left と right が auto と指定されています。 この場合、仕様では、left を静的配置した場合と同じ位置の値、width はコンテンツ幅として、最後に right を上記の計算式に合うように計算することになっています。 具体的には、包含ブロックの幅=初期包含ブロックの幅=ブラウザ幅=1000pxだと仮定すると、 0(left)+0+2+0+100(width)+0+2+0+x(right) = 1000 x=896 ですから、 right: auto は right: 896px と解釈される、ということです。 --- さらにわからない点があれば、コメントでご連絡ください。
Lhankor_Mhy

2024/08/04 04:57

(ほんとは、この説明は古いものらしいのです。CSS Positioned Layout Module Level 3 では同じ結果になる別の説明をしていますが、新しい仕様はまだドラフトなので古い方で理解しても許されるでしょう、というか許してください。)
yuka11556

2024/08/05 07:27 編集

Lhankor_Mhy 様 pecmm 様 お二人ともお忙しい中、お時間を割いて丁寧に教えて下さり、本当に感謝いたします。 自分なりにお二人のおっしゃってることを参考にして、自分自身でも調べさせていただきました。頭の中を整理するためにも、間違って解釈してないかを確認させていただくためにも、下記に自分なりの解釈をまとめ書かせていただきます。また追記で質問がありますのでまた、教えていただけますと幸いです。 ブロック要素の幅は、包含ブロックを設定する要素があり、それを参考に決められる。ほとんどのケースは包含ブロックというのは、親要素に基づいた幅で決められる。 例えば以下のようなhtmlがあった場合以下のような包含ブロックが採用される。 <HTML> <HEAD> <TITLE>Illustration of containing blocks</TITLE> </HEAD> <BODY id="body"> <DIV id="div1"> <P id="p1">This is text in the first paragraph...</P> <P id="p2">This is text <EM id="em1"> in the <STRONG id="strong1">second</STRONG> paragraph.</EM></P> </DIV> </BODY> </HTML> ■ボックスを生成する要素 ■包含ブロックを設定する要素 body            初期包含ブロック(UA-依存) div1            body p1            div1 p2            div1 em1            p2 strong1          p2 pecmm様がおっしゃられる通り、「#section01=初期包含ブロック=ブラウザ幅という考えになってしまいます」という私の考えは、このbodyが初期包含ブロックを参考にしているという考えからきていると思います(width幅の指定がなく、width:autoであった場合) 私の解釈の話の続きにもどります。 ただし、positionを使用した場合は、新しいブロック整形コンテキストが生成される。これは既存の(包含ブロックを含む)レイヤーの1つ上に浮かぶ、全く新しいレイヤーという考えに近い。(pecmm様の言葉、そのまま引用しちゃってます。)個人的には親要素から独立したレイヤーのようなものを考えてます…。 そして本題であった私の質問を教えてもらったことをもとに解釈していくと [当初の質問の疑問点] これは、#section01がposition:absoluteを指定されたことで通常の位置より浮いて(通常の位置とはh1要素と並列の位置)、box01の下に重なっているため、背景ピンクが見えなくなってしまっているのです。 box01の下に重なっているとのことなのですが、#section01はブロック要素であるのでwidthはブラウザ幅になるのにbox1はwidthが100pxでなぜ見えなくなるのかわかりません。加えてなんで背景は消えてborderの青線がbox01を囲うのかが全く分かりません [現時点での私の解釈] 今回のケースだと#section01にposition:absoluteを使用したことにより、新しいブロック整形コンテキストが生成され、ルート要素から外れた。positioon:absoluteを使用する場合の包含ブロックの幅は「'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含ブロックの幅」で算出される。 ここまではしっくり来ますし、おおよそ合っているのでは、と思うのですが(解釈、違ってたらすみません) ただLhankor_Mhyさんが計算してくださった -- ご質問の場合、border が 2px ずつ、margin と padding が 0、left と right が auto と指定されています。 この場合、仕様では、left を静的配置した場合と同じ位置の値、width はコンテンツ幅として、最後に right を上記の計算式に合うように計算することになっています。 具体的には、包含ブロックの幅=初期包含ブロックの幅=ブラウザ幅=1000pxだと仮定すると、 0(left)+0+2+0+100(width)+0+2+0+x(right) = 1000 x=896ですから、 right: auto は right: 896px と解釈される、ということです -- といったことなのですが、ここで引っかかっています…。 実際にブラウザ幅を1000pxにして検証ツールで#section01のがどうなってるか見たのですが、 コンテンツ領域:101.600 パディング領域:0 境界領域:1.600 マージン領域:0 positionのtopが90.875 rightが887.200 bottomが443.525 leftが8 といった表示になっており。 そもそもなんでposititionのtopには数字を入れていないのにtopが90.875といった数字がでてくるのかがわからず…。(bottomも同様です) また、境界領域:1.600となっていますが実際の線の太さは2pxなのになぜ?となっています。 コンテンツ領域:101.600となっており、100pxで無いのは、これは#section01が.box01を包み込むような形になってるので微妙な誤差が出てるということでしょうか? また追記で質問がありまして、他サイト様に以下のような説明文がありまして。。。 以下他サイト様からの説明文を引用します。↓ --- ■10.1 "包含ブロック"の定義 要素のボックスの位置及びサイズは,一定の長方形に関連して計算されることが 多い。この長方形を要素の包含ブロックと呼ぶ。 要素の包含ブロックの定義を次に示す。 ①内部にルート要素が存在している,初期ブロックと呼ばれる包含ブロックは,利用者エージェントが包含ブロックを選択する。 ②その他の要素については,要素が絶対位置決めされない場合,包含ブロックは,最も近接するブロックレベルの先祖ボックスによって形成される。 ③要素が'position: fixed'という値をもつ場合,包含ブロックは,表示域によって設定される。 ④要素が'position: absolute'という値をもつ場合,包含ブロックは,最も近接する先祖によって,次の方法で設定される。この場合の先祖は,'static'以外の'position'をもつ。 4-1.先祖がブロックレベルである場合は,包含ブロックは,先祖のパディング辺によって形成される。 4-2.先祖が行内レベルである場合,包含ブロックは,先祖の'direction'特性に依存する。 'direction'が'ltr'である場合,包含ブロックの上辺及び左辺は,先祖が生成する最初のボックスの内容上辺及び内容左辺とし,下辺及び右辺は,先祖の最後のボックスの内容下辺及び内容右辺とする。 'direction'が'rtl'である場合,上辺及び右辺は,先祖が生成する最初のボックスの上辺及び右辺とし,下辺及び左辺は,先祖の最後のボックスの内容下辺及び内容左辺とする。 これらの先祖が存在しない場合,ルート要素のボックスの内容辺が包含ブロックを設定する。 --- 今回の#section01のケースは「これらの先祖が存在しない場合,ルート要素のボックスの内容辺が包含ブロックを設定する」に合致してるということでしょうか?そのためwidth → shrink-to-fit とになったのでしょうか?(ルート要素のボックス内容辺という言葉の意味自体いまいちわかっていないです…。ルート要素のボックス内容辺=内部コンテンツである.box01という認識でいいのでしょうか?)
Lhankor_Mhy

2024/08/05 08:47 編集

> そもそもなんでposititionのtopには数字を入れていないのにtopが90.875といった数字がでてくるのかがわからず…。(bottomも同様です) 幅と同じように、高さも包含ブロックを基準に計算するんです。 https://www.w3.org/TR/CSS22/visudet.html#abs-non-replaced-height なので、top が auto の時には、しばしば静的配置の位置に合います。 > コンテンツ領域:101.600となっており、100pxで無いのは、これは#section01が.box01を包み込むような形になってるので微妙な誤差が出てるということでしょうか? 当方で試してみましたところ、101.600になるのは、125%ズームをしている時かと思います。ブラウザのズーム倍率かOSの画面の拡大率が設定されているかもしれないです。 できれば、webデザインをするときは、100%に設定した方がいいように思います。思わぬずれが起きる時があります。 前述の計算はあくまで例なので、わかりやすさを重視しています。body のデフォルトCSSの影響での8pxとかその辺りまで説明するとわかりにくいかと思い省略しました。 省略しないのであれば、 8(left)+0+2+0+102(width)+0+2+0+x(right)=1000 x=886 です。(まだズームレベルの誤差分が残りますが) > 今回の#section01のケースは「これらの先祖が存在しない場合,ルート要素のボックスの内容辺が包含ブロックを設定する」に合致してるということでしょうか? はい。 > そのためwidth → shrink-to-fit とになったのでしょうか? いいえ。width → shrink-to-fit となるのは、left: auto; right: auto; に設定されているからです。包含ブロックがなにか、というのは関係していません。 > ルート要素のボックス内容辺=内部コンテンツである.box01という認識でいいのでしょうか? いいえ。ルート要素のボックス内容辺は、前述の初期包含ブロックのことです。おおむね、スクロールをしない状態でのビューポートのことと考えていいです。 --- さらにわからないところがあれば、コメントにてお知らせください。
yuka11556

2024/08/06 02:05 編集

Lhankor_Mhy様 何度もありがとうございます。125%ズームにしていて修正したら数値もあっていました。ありがとうございます。 すみません、また質問なのですが…。 #section01の包含ブロックを設定する要素は今回で言うと、ルート要素のボックス内容辺の初期包含ブロック(ビューポート)である。が、今回のケースleft: auto; right: auto; なので、width → shrink-to-fit となり、内部コンテンツである.box01にwidth幅を合わせる…。ということでしょうか?そもそもshrink-to-fit とが内部コンテンツの要素幅に合わせるという意味でしょうか? なぜ、今回の包含ブロックを設定する要素がビューポートであるのに、left: auto; right: auto;だとshrink-to-fit になるのでしょうか?(どうしてもこのあたりがしっくりこないです(ーー;)何度も教えていただいて本当にすみません…)
Lhankor_Mhy

2024/08/06 03:04

では、計算の部分をもう少し丁寧に書きますね。 width: auto; left: auto; right: auto; なので未定の値が3つあります。それぞれ、w,l,r と置きます。 そうすると、 'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含ブロックの幅 は、 l + 0 + 2 + 0 + w + 0 + 2 + 0 + r = 包含ブロックの幅 となります。これは、解けないです。 たとえば、l,r を 0 にすれば、w = 包含ブロックの幅 - 4 と静的配置のような幅になりますし、w をコンテンツ幅にして、l と r が等しくなるように分ける、とすればセンタリングのような配置になります。 いろいろな解釈ができるのですが、いろいろな解釈をされてしまうとどのような表示になるかわからないので、デザインするときに困ります。 なので、ルールが必要です。 この場合、left: auto は「静的配置(position: static)の位置にせよ」というルールがあります。これについては「なんで?」と聞かないでください。そういうルールだからそういうルールなのです。 ご提示のコードでは、position: static のときに#section01は左から8pxの位置にあるので、left: 8px と解釈されます。 つまり、 8 + 0 + 2 + 0 + w + 0 + 2 + 0 + r = 包含ブロックの幅 となります。変数が二つ残っていますので、まだ解決しないですね。 この場合、width: auto は「内部コンテンツ幅にせよ」というルールがあります。これについては「なんで?」と聞かないでください。そういうルールだからそういうルールなのです。 ご提示のコードでは、内部コンテンツ幅は 102px なので 8 + 0 + 2 + 0 + 102 + 0 + 2 + 0 + r = 包含ブロックの幅 となります。 これを解くと、 r = 包含ブロックの幅 - 8 - 2 - 102 - 2 となり、全てのauto幅が解決されました。 --- つまり、width: auto の幅は、絶対配置の際には包含ブロックの幅を基準に計算しようとしますが、他にも未定のプロパティがあり計算できない場合は内部コンテンツ幅になる、ということです。 ここが、静的配置の場合と違うところです。 静的配置の場合は、「margin-left, width, margin-right が全て auto の時は、margin を 0 と扱え」というルールがあり、width はなるべく大きく取られるようになっています。
yuka11556

2024/08/06 05:53

Lhankor_Mhy様 何度も本当にありがとうございます…。やっとわかってきた気がします・・・! #section01の包含ブロックを設定する要素=ビューポートである。 例えばビューポートの幅が1000pxであったとする。しかし、これが#section01のwidth幅となるわけではない。なぜなら、今回のケースはleft: auto; right: autoであるので、「'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含ブロックの幅」という公式に当てはめたときに、w,l,r の値が分からないからである。 よって以下のルールにのっとり、数値を決める。 left: auto は「静的配置(position: static)の位置にせよ」 よって今回のケースはleft:8px width: auto は「内部コンテンツ幅にせよ」 よって今回のケースはwidth:102px r = 包含ブロックの幅 - 8 - 2 - 102 - 2 包含ブロック幅はビューポート1000pxであるので 1000-8-2-102-2=886pxになる 私のいまいちピンとこなかった原因は、親要素がないposition:absoliuteは確かに初期包含ブロックが包含ブロックになる。そして私は、包含ブロックの幅がそのままwidthになると勘違いしてました。そうではなくて、今回のケースのposition:absoluteを用いた場合の包含ブロックとは、'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含ブロックの幅(包含ブロックの幅が1000pxになるようにする)という公式を用いて、widthが決められる。さらに今回に関してはleft:auto right:autoのため、数値を定めるためのルールを用いて数値を算出する。そのため、widthは内部コンテンツと同じ幅になる…ということでしょうか!?この理解でよければシックリきます! そしてもう1点、追加で質問がありまして…。 #section01が.box01の下に入り込んでしまうのは、そもそものhtmlの特性に下に書かれた要素が上に来るからという特性があるからでしょうか?
Lhankor_Mhy

2024/08/06 06:30

ご理解の通りです! --- > そもそものhtmlの特性に下に書かれた要素が上に来るからという特性があるからでしょうか? 以下のような順番が決められているため、背景(ピンクの背景色)は一番下に来るからです。 https://developer.mozilla.org/ja/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_without_z-index ここでいう「ルート」とは、pecmmさんのご回答に合った「重ね合わせコンテキスト」のルート要素のことで、ここでは#section01のことです。
yuka11556

2024/08/07 05:42 編集

Lhankor_Mhy様 自分一人ではここまで辿りつけませんでした。ありがとうございました(__)! 重ね合わせコンテキストについても知らず…。またこちらも調べさせていただきました。 が、こちらもまたしっくり来なくて。またご教授いただければ幸いです。 -- <html>要素は ルートスタックコンテキストをもともと生成している。その他の要素が条件を満たした時に 新しく作られるのは ローカルスタックコンテキストと言う。ルートスタックコンテキストのスタックレベルは 通常は0である。 ルートスタックコンテキストは <body>要素があり、親子関係の要素なら子孫の要素ほど重なりは上のほうになり、兄弟要素ならHTML上に後に書いた要素ほど上のほうに表示される(ツリー順という)。 新しくローカルスタックコンテキストができる条件に他サイト様にて ・position値が「absolute」か「relative」で、z-index値が「auto」以外の要素 と書かれておりました 今回の#section01に関してはz-indexで値が指定されてないのでローカルスタックコンテキストは生成されていない。ローカルスタックコンテキストが生成されていないということは、#section01はルートスタックコンテキストに属している状態であるという風に解釈しています。 他サイト様にて以下のような重なり順のルールの画像がありました。 https://gyazo.com/8f1f8149ce7a540238d93284d16e156f この画像をもとに考えると、#section01はローカルスタックコンテキストは生成はしてないが、重なり順のルールによって、画像の「8-1.z-indexがautoか0の位置指定された要素」に該当するので、ルート要素より上の位置にいる。 -- ここまでは考えたのですが…。(合っているか自信はないです…。)本題であるなぜ#section01がbox01の下に入り込んでしまうのか、というところで引っかかっております。 画像を見ると、.box01は「4.位置指定されていないブロックレベルの要素の子孫」に値するのでは?となってしまい、#section01が.box01より上に来る…と考えてしまいます。#section01と.box01は親子関係なので、セットになっていて、そこではツリー順が有効になって、#section01が.box01の下に入り込むのでしょうか…? またご教授いただければ幸いです。
Lhankor_Mhy

2024/08/07 06:22

これは yuka11556 さんが正しくて、私の説明が間違っていました。 おっしゃるとおり、#section01 は重ね合わせコンテキストを生成していませんでした。うっかりしていました。 前述したMDNの重ね合わせ順は、CSS2.2の仕様書に書かれています。 https://drafts.csswg.org/css2/#z-index その重ね合わせ順リストの後にこう書いてあります。 Within each stacking context, positioned elements with stack level 0 (in layer 6), non-positioned floats (layer 4), inline blocks (layer 5), and inline tables (layer 5), are painted as if those elements themselves generated new stacking contexts, except that their positioned descendants and any would-be child stacking contexts take part in the current stacking context. ざっくり訳すと、 配置された要素、フロートされた要素、インラインブロックとインラインテーブルは、重ね合わせコンテキストを生成したかのように表示される(ただし、子孫の配置された要素は親の重ね合わせコンテキストに参加する) ということです。 つまり、#section01 は重ね合わせコンテキストを生成しないですが、この重ね合わせ順では重ね合わせコンテキストを生成してるかのようにルートの位置に収まる、ということです。 ややこしいですよね。 CSSは後方互換のため、古いプロパティほど過去の負の遺産を背負ってしまいややこしくなっていることが多いのですが、CSSの中でも配置(position)は特にややこしいプロパティだと思います。 --- それにしても、たいていの人はここまで突っ込んだことは考えずに雰囲気でCSSを書いてるもんなんですが……初見できちんと疑問に持てるのはすごいですね。
yuka11556

2024/08/07 07:03 編集

Lhankor_Mhy様 お返事いただきありがとうございます! 誉めて頂き恐縮です…。実はLhankor_Mhy様のブログをこっそりのぞきましたが、本業がweb関係ではないと書かれており、びっくり仰天してます。これだけの知識があって…。 -- #section01 は重ね合わせコンテキストを生成しないですが、この重ね合わせ順では重ね合わせコンテキストを生成してるかのようにルートの位置に収まる -- ルートの位置に収まるというのは、ツリー順ということでしょうか? また重ね合わせコンテキストについて調べていたら新たな疑問が出てきました。 追記で質問させてください。 -- https://developer.mozilla.org/ja/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context_example_2 こちらのサイトに載っている <div id="div1"> <br /> <span class="bold">DIV #1</span><br /> position: relative; <div id="div2"> <br /> <span class="bold">DIV #2</span><br /> position: absolute;<br /> z-index: 2; </div> </div> <br /> <div id="div3"> <br /> <span class="bold">DIV #3</span><br /> position: relative;<br /> z-index: 1; <div id="div4"> <br /> <span class="bold">DIV #4</span><br /> position: absolute;<br /> z-index: 10; </div> </div> div { font: 12px Arial; } span.bold { font-weight: bold; } #div2 { z-index: 2; } #div3 { z-index: 1; } #div4 { z-index: 10; } #div1, #div3 { height: 80px; position: relative; border: 1px dashed #669966; background-color: #ccffcc; padding-left: 5px; } #div2 { opacity: 0.8; position: absolute; width: 150px; height: 200px; top: 20px; left: 170px; border: 1px dashed #990000; background-color: #ffdddd; text-align: center; } #div4 { opacity: 0.8; position: absolute; width: 200px; height: 70px; top: 65px; left: 50px; border: 1px dashed #000099; background-color: #ddddff; text-align: left; padding-left: 10px; } -- なぜdiv2が一番上に来るのでしょうか? 私の考えでは、DIV #3がz-index:1を持っているので、DIV #1はzindexを持っていないので、DIV #3の高さが上で、DIV #1が下になる。なので、DIV #1の子要素であるDIV #2はDIV #3より下に来るのでは…と思ってしまいます またご教授頂ければ幸いです。
Lhankor_Mhy

2024/08/07 11:39

不動産のお仕事ください! --- > ルートの位置に収まるというのは、ツリー順ということでしょうか? いえ、仕様書の重ね合わせ順で言うと、1番になる、ということです。 --- > DIV #3がz-index:1を持っているので、DIV #1はzindexを持っていないので、DIV #3の高さが上で、DIV #1が下になる。なので、DIV #1の子要素であるDIV #2はDIV #3より下に来るのでは… DIV#1 は重ね合わせコンテキストを生成しないので、DIV#1 と DIV#2 と DIV#3 は同じコンテキストにいます。なので、DIV#3 とそのコンテキスト下にいる DIV#4 は DIV#2 より下になります。 開発者ツールなどで、DIV#1 に z-index: 0 を追加してみると、DIV#2 が DIV#3 の下にもぐるはずです。確認してみてください。
yuka11556

2024/08/08 08:15 編集

Lhankor_Mhy様 不動産のお仕事ください! →私に頼らずともLhankor_Mhy様なら素晴らしい成績を残されていると思います…。お役に立てず申し訳ないです(ーー;) --- > DIV #3がz-index:1を持っているので、DIV #1はzindexを持っていないので、DIV #3の高さが上で、DIV #1が下になる。なので、DIV #1の子要素であるDIV #2はDIV #3より下に来るのでは… DIV#1 は重ね合わせコンテキストを生成しないので、DIV#1 と DIV#2 と DIV#3 は同じコンテキストにいます。なので、DIV#3 とそのコンテキスト下にいる DIV#4 は DIV#2 より下になります。 開発者ツールなどで、DIV#1 に z-index: 0 を追加してみると、DIV#2 が DIV#3 の下にもぐるはずです。確認してみてください。 --- DIV#1 は重ね合わせコンテキストを生成しない…これはわかります。z-indexを指定してないからですよね。DIV#1 と DIV#2 と DIV#3 は同じコンテキストにいます…ここがいまいちわからないです…。DIV#1はz-indexを指定していないのでDIV#1のz-indexはautoで、DIV#2 と DIV#3はz-indexが指定されているので、 DIV#1より高い位置にいるのではと思ってしまいます。 教えていただいたサイトのスタッキングコンテキストのz-indexへの影響を読ませていただきました。 -- z-index: autoの要素の中にz-index: 1の要素があった場合、要素の出現順によっては、 z-index: auto < スタッキングコンテキスト < z-index: 1 という関係性が成り立ちます。 この時、親要素より上にある、スタッキングコンテキストを子要素が上回るという、現象が発生します。 -- 今回のケースはこれに該当するのでしょうか? z-index: auto(DIV#1) < スタッキングコンテキスト(DIV#2 と DIV#3 )< z-index: 1(DIV#4) ただやはり、DIV#1 と DIV#2 と DIV#3 は同じコンテキストにいますがしっくりこないです…(-_-;)
Lhankor_Mhy

2024/08/08 10:32

DOMツリーとスタッキングコンテキストツリーを分けて考えるといいかと思います。 DOMツリーとしては、 body  ├DIV#1─DIV#2  └DIV#3─DIV#4 ですが、 スタッキングコンテキストツリーとしては、DIV#1 はコンテキストを持たないので子がおらず、 body  ├DIV#1  ├DIV#2  └DIV#3─DIV#4 です。 z-index は同じスタッキングコンテキストの兄弟同士で比較されます。 なので、DIV#1 と DIV#2 と DIV#3 が比較されることになります。 DIV#1 z-index: auto = 0 DIV#2 z-index: 2 DIV#3 z-index: 1 なので、手前から、DIV#2、DIV#3、DIV#1 の順に重なる、ということです。
yuka11556

2024/08/09 01:20 編集

Lhankor_Mhy様 ご回答ありがとうございます。 わざわざコンテキストツリーを図にしてくださってありがとうございます。 すみません、まだしっくりこなくて教えてほしいです(ーー;)本当にすみません… -- DIV#1 はコンテキストを持たないので子がいない →DOMツリーが変化し以下のスタッキングコンテキストツリーになる。 body  ├DIV#1  ├DIV#2  └DIV#3─DIV#4 -- DIV#1の下になぜDIV#2が来るのでしょうか?おっしゃる通り、「DIV#1 はコンテキストを持たないので子がいないから。」ということだとは思うのですが…。コンテキストを持たない親要素とコンテキストを持っている子要素があった場合、親要素から子要素が外れるということなのでしょうか?
Lhankor_Mhy

2024/08/09 02:59

ツリーはわかりにくかったですか。 では、別の方法で説明しましょう。 MDNにこのように書かれています。 > Z 軸方向に重なった要素の描画順序の簡単な計算方法は、それがバージョン番号のようなものを持っていると考えることです。親要素のメジャーバージョン番号の下に、子要素のマイナーバージョン番号があるものとします。 この方法で考えると、 DIV#1 はauto=0、そのDOM親要素bodyはスタッキングコンテキストを持っていない、そのDOM親要素htmlはスタッキングコンテキストを持っていてauto=0、なので、0.0 DIV#2 は2、そのDOM親要素DIV#1はスタッキングコンテキストを持っていない、そのDOM親要素bodyはスタッキングコンテキストを持っていない、そのDOM親要素htmlはスタッキングコンテキストを持っていてauto=0、なので、0.2 DIV#3 は1、そのDOM親要素bodyはスタッキングコンテキストを持っていない、そのDOM親要素htmlはスタッキングコンテキストを持っていてauto=0、なので、0.1 DIV#4 は10、そのDOM親要素DIV#3は1、そのDOM親要素bodyはスタッキングコンテキストを持っていない、そのDOM親要素htmlはスタッキングコンテキストを持っていてauto=0、なので、0.1.10 となります。バージョン番号順に並べると、 DIV#2 0.2 DIV#4 0.1.10 DIV#3 0.1 DIV#1 0.0 となりますから、DIV#2 が一番上に行きます。 --- たとえば、ここで、DIV#1 に z-index: 0 を追加するとスタッキングコンテキストを形成するので、 DIV#4 0.1.10 DIV#3 0.1 DIV#2 0.0.2 DIV#1 0.0 と順番が変わります。
yuka11556

2024/08/09 09:20

Lhankor_Mhy 様 何度もありがとうございます。ようやくわかったような気がします。 教えていただいたURLに「親要素が高さをもっていると子要素の高さを内包する(親要素にスタッキングコンテキストが生成される)」と書かれていたのですが、親要素のindex.(メジャーバージョン番号)の下に、子要素のマイナーバージョン番号として、子要素のindexが追加されるからですね。バージョンに直すとわかりやすいです! 「DIV#1 と DIV#2 と DIV#3 は同じコンテキストにいます。」 これがよくわからなかったのですが、「htmlはスタッキングコンテキストを持っていてauto=0。」この説明でシックリきました。htmlはスタッキングコンテキストを持っているから、DIV#1 と DIV#2 と DIV#3 は同じコンテキストにいるのですね! 丁寧に説明して頂いてありがとうございます(__)!!! -- まだ質問がありまして…(-_-;) positionのrelativeとabsoluteなのですが… よくサイトの解説を読んでいると、relativeは相対配置・absoluteは絶対配置といった説明を見ます。 -- とあるサイト様の解説 ・relative staticで配置される位置から相対的な指定 ・absolute:親要素(relative)を基準とした絶対的な指定。親要素の指定がない場合、ウィンドウが全体の基準 -- relativeとは相対的な位置で決められる。相対的位置とは何かの位置を基準にその位置から決められるといったようなイメージをもっています。ただabsoluteも絶対配置とはわかるのですが、親要素(relative)を基準とした絶対的な指定ならば、基準が決められているのだから相対的位置とも解釈できないのか、と…。 相対的位置・絶対的位置の意味の違いが明確に分からないです…。
Lhankor_Mhy

2024/08/10 00:48 編集

ご自身で書かれている通りです。 relative は、自身を基準に配置されます。なので、top: 0 としても位置が変わりません。 absolute は、包含ブロックを基準に配置されます。なので、top: 0 とすると、包含ブロックの上辺に配置されます。 実際に手を動かしてみれば違いはすぐ理解できると思うのですが、どういったところがわからないですか? もしかして、「相対」「絶対」の名づけが適切ではないのでは、というご質問でしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問