position/z-index参考ページ

相対配置 position:relativeについて

フロートの次は、position プロパティーによる配置を見てみましょう。position プロパティーを使えば、通常フローでの配置からずらしたり(相対配置)、
任意の場所を指定して配置したり(絶対配置)、スクロールしても常に固定されて表示される(固定配置)ようにすることができます。まずは相対配置から見ていきます。

position: relative を使えば、通常フローによって配置された位置から、ボックスを相対的にずらすことができます。相対的にずらす … これはどういう意味でしょう?
いつものように図を見てみましょう!下の図は、写真とその写真のタイトルを交互に配置しています。

写真と段落を交互に表示

●html /p/
/img src=”image1.jpg” alt=”” //
//p/
/p class=”title”/
画像のタイトル
//p//
/p/
/img src=”image2.jpg” alt=”” //
//p/
/p class=”title”/
画像のタイトル
//body/p/

●css img{
width:300px;
vertical-align: bottom;
padding :5px;
background:#fff;
/* 以下、丸角とドロップシャドウは省略 */
}

.title{
width:260px;
background:rgba(0, 0, 0, 0.4);
color:#fff;
height: 40px;

line-height:40px;
padding: 0 20px;
}

画像には縁取り(padding と背景色)、タイトルとなる p 要素(.title)には width と背景色を指定していますが、通常フローによって、
上から順番にレイアウトされていきますよね!この状態から、タイトルとなる p 要素を相対配置してずらしてみましょう。

●css .title{
… 省略 …
position:relative;
top: -45px;
left: 5px;
}

相対配置したい p 要素(.title)に position: relative を指定します。そして本来通常フローで配置された位置から、
どれだけずらすのか(オフセットと言います)を top, bottom, left, right の各プロパティーで指定します。

上記のコードでは、top :-45px; left: 5px;としました。すると本来ある位置から、下記のようにオフセットされます!

相対配置でオフセットされたタイトル

タイトル部分が top から、-45px の位置に移動されました(上にずれました)。また、top: -45px ではなく、bottom: 45px と書いても同じように配置されます。
また、左から 5px ずれて画像の枠内にピッタリ収まりました!

相対配置(position:relative)では、top、bottom、left、right プロパティーを使って、本来あるべき位置から相対的な距離を指定します。

注意したいのは、top と bottom を同時に指定することはできないし、left と right を同時に指定することはできないということ。
仮に同時に指定しても、bottom よりも top が、right よりも left が優先されます。

(direction プロパティ(文字の表記方向)で値を rtl(right to left) にしてある場合は逆になります。)

相対配置したときの、後続要素への影響

position: relative で配置をオフセットした場合、後続の要素へはどんな影響があるのででょう?position: reletive によってオフセットされた要素の後続の要素は、
オフセットされていない状態 … つまり通常フローでの配置を維持します。逆を言えば、オフセットされたからといって、本来あった場所に空いた余白を、詰めたりしないということ。

後続の要素は、オフセットされた要素が移動前の位置にあるかのように振る舞います。

相対配置では、後続の要素の配置はそのままです

また、position: relative を指定された要素は、通常フローの子供要素と、絶対配置される子孫要素用に、新しく包含ブロックを生成します。
ちょっと難しい言い回しですね …。このことは、次の絶対配置のところで説明しますね!

「CHECK POINT」
相対配置は後続の要素の配置に影響を与えません。
position: relative を指定した要素は、通常フローの子供要素と、絶対配置される子孫要素用に、新しく包含ブロックを生成します。

絶対配置 position: absolute

今度は絶対配置(position: absolute)を見ていきましょう。相対配置は、通常フローでの本来あるべき場所からのオフセットでした。
それに対して絶対配置は、とある場所からのオフセットで位置を決めて配置します。では、とある位置とはどこでしょう?
それは、position が static 以外の直近の祖先要素の包含ブロック(包含ブロック … 覚えてますか?)になります。

もし、position が static 以外の要素がなければ、body の包含ブロックになります。簡単に言えば、position に absolute か relative が指定されている、
直近の祖先要素の包含ボックスって事ですね!

でも、この包含ボックスは、従来の包含ボックスとはちょっと違います。というのも、position: relative のところで前述したとおり、
「position:relative を指定された要素は、通常フローの子供要素と、絶対配置される子孫要素用に、新しく包含ブロックを生成します。」ということでした。
つまり、絶対配置用に新しく作られた包含ボックスとう事になります。ちょっと難しいですね …。言葉だと難しいので、図を使って見ていきましょう。

目指すレイアウトは以下の形。画像部分に、position: absolute を使ってみましょう!

目標のレイアウト

●html
/div class=”post”/
/h4//a href=”#”/絶対配置でレイアウトしよう!//a///h4/
/img class=”eyecatch” src=”image.jpg” alt=”” //
/p/絶対配置を使って …//p/
/p//a class=”more” href=”#”/続きを読む »//a///p/
//div/

上から見出し、画像、段落という順番でマークアップしています。まずは通常フローでの配置を見てみましょう

通常フローでのレイアウト

HTML で記述されている順番とおり、上から見出し、画像、段落 … という順番で並んでいます。この場合、親要素である div.post
が生成している包含ボックスは、padding の内側になりますよね!

それでは、div 要素に position: relative を指定して、画像に position: absolute を指定してみましょう。
(この時の position: relative は、相対配置するのが目的ではなく、新しい包含ボックスを作るために指定します。)
絶対配置のオフセットの位置は、とりあえず top: 0、left: 0 とします。

●css
div.post{
width:190px;
padding:10px;
background:#fff;
position:relative;
}

img.eyecatch{

position:absolute;
top:0px;
left:0px;
}

するとブラウザでの表示は以下のようになります。

あれ … ちっちゃい X(

画像は div 要素の左上に配置されてしまいました。さらに、div 要素のボックスの高さが低くなっています …。これはどういう事でしょう?

絶対配置されると、通常フローからは切り離される

まず、position: relative を指定した div 要素は、position: abosolute 用に新しい包含ボックスを生成しますよね!つまり通常フロー用の包含ボックスとは別に、
もうひとつの包含ボックスを作るんですねー。その時の包含ボックスは、padding の内側ではなく、border の内側になります!

絶対配置用の包含ボックス

それでは、どうして div 要素の高さが低くなったんでしょう?それは画像を透かして見ると、よく分かります!

画像を透過してみた

見出しや段落など、通常フローの流れに乗っている要素は、通常フローの包含ボックスの中に収まっています。
そして、画像自体は通常フローから完全に切り離されて、再配置されているんです。

絶対配置された要素(画像)は、通常フローから完全に取り払われるので、後続の要素ははじめからその要素が無かったかのように振る舞います。
よく、透明人間のよう … と例えられていますね!でも、実際には上記のようなレイアウトでは困ります …。そこで h4 タグに margin-top を指定して、
見出しが見えるようにしましょう。

h4{
margin-top:130px;
}

マージンなどを調整

これで見出しが見れるようになりました!最後に画像の位置をちょっと調整する為に、top と left の値を指定し直しました。
もしくは top: 0、left: 0 のまま、margin-top: 10px、margin-left: 10px としても OK です。

absolute で絶対配置された要素のマージンは、他のどの要素のマージンとも相殺しません。

●css
img.eyecatch{
position:absolute;
top:10px;
left:10px;
}

「続きを読む」のリンクの部分は、普通に a要素を display: block でブロックボックス化して、text-align を right にしただけです。これで完成です!

「CHECK POINT」
絶対配置された要素は、通常フローから完全に切り離されて再配置されます。
後続の要素は、はじめから絶対配置された要素が無かったかのように振る舞います(透明人間みたい)。
絶対配置された要素のマージンは、他のどの要素のマージンとも相殺しません。

重なり順は z-index で指定しよう!

いきなりですけど、z-index は、要素の重なりを指定するプロパティーです。重なり … 何ていうか、そのまんまです …。

要素の重なり

普段はあまり要素同士の重なりを意識することは少ないかもしれませんが、position プロパティーで要素を本来の位置からずらした場合は、
上記の図のように重なる事がありますよね!要素の重なり … 基本的には HTML で後から書いたものが上層に、先に書いたものが下層に配置されます。
その重なり順を変更するのが z-index プロパティーです。

まず、この z-index は、position: static 以外を指定した要素にしか指定できません。つまり z-index を使用する要素には、
position プロパティーで、relative、absolute、fixed のいずれかを指定する必要があります!

それでは詳しく z-index を見ていきましょう。ちなみに、z というアルファベットは、z 軸という意味。横方向が x 軸、縦方向が y 軸、重なりが z 軸ですね!

z-index

まず、z-index の値には整数(マイナスも指定可)か、auto を指定します。z-index を記述しなくても、
position プロパティーで relative か absolute、fixed を指定した要素には、z-index: auto が自動的に指定されます。

ここでは、auto の事は一度忘れて、整数を指定してみましょう。

①スタック文脈とスタックレベル

z-index で指定する整数 …。整数は大きい方が上層へ、小さい方が下層に配置されます。基本的に各要素は、スタック文脈というものに属しています。
スタック文脈 … 難しそうな言葉ですねー … 以前ブロック整形文脈とか、インライン文脈とか出てきましたね!

スタック文脈は、z 軸の重なりの流れ … とイメージしてもらえればいいと思います。

このスタック文脈の流れの中で、スタックレベルという数値で重なり順を決めているんですねー。z-index で指定する整数 … これがスタックレベルなんです。

記述例

z-index: 10;
さて、それでは上記の図1のスタックレベル … つまり重なり順を z-index で操作してみましょう。

●html
/div id=”group1″/
/div id=”blue1″/青1//div/
/div id=”blue2″/青3//div/
/div id=”blue3″/青2//div/
//div/

●css
#group1 { /* グループ */
position: relative;

z-index: 0; }
#blue1{ /* 青1 */
position: absolute;
top: 40px;
left: 40px;
z-index: 30;
}
#blue2{ /* 青2 */
position: absolute;

top: 65px;
left: 120px;
z-index: 20;
}
#blue3{ /* 青3 */
position: absolute;
top: 90px;
left: 200px;
z-index: 10;
}

それぞれの z-index の値、スタックレベルに注目してくださいね!

ボックスの重なり順が、z-index の値(スタックレベル)が大きい順に変更されました!スタック文脈の中で、順番が入れ替わったんですね!

重なり順が変わった!

②ちょっと寄り道クリッカブルエリアと z-index

ここで少し寄り道です。上記の図の中、2番目のボックスがリンクだった場合を考えてみましょう。本来なら、ボックス全体がクリックできるはずですが、上に要素が重なっていれば、当然その部分はクリックできなくなります。

クリックできるエリア

上記の図のように、斜線の部分だけしかクリックできません …。当然といえば、当然ですよね!ユーザーが操作する部分では、z-index の重なり順にも注意が必要ですね!

スタック文脈はひとつとは限らない

さて、それでは元に戻りましょう!もうちょっと詳しく z-index について見ていきす。今度は、同じようなグループのボックスを作って重ねてみる事にします。

違うグループを重ねる

CSS は以下のようになっています。青いグループは一切変更してません。(top、left などは省略して記述います。)

●css
#group1 { /* 青いグループ */
position: relative;
z-index:0;
}
#blue1{ /* 青1 */
position: absolute;
z-index: 30;
}
#blue2{ /* 青2 */
position: absolute;
z-index: 20;
}
#blue3{ /* 青3 */
position: absolute;
z-index: 10;
}

#group2 { /* 赤いグループ */
position: relative;
z-index: 0;
}
#red1{ /* 赤1 */
position: absolute;
z-index: 35;
}
#red2{ /* 赤2 */
position: absolute;
z-index: 25;
}
#red3{ /* 赤3 */
position: absolute;
z-index: 15;
}

ここで試しに z-index の数字(スタックレベル)の大きい順に並べてみましょう。

値の大きい順

赤1 – 値 35
青1 – 値 30
赤2 – 値 25
青2 – 値 20
赤3 – 値 15
青3 – 値 10
グループ1 – 値 0
グループ2 – 値 0
ここでおや?っと思う人もいるかもしれません。z-index は、数字の大きいものほど上層にきて、小さいもの程下層にくると説明しました …。でも実際の順番は以下のようになっています。
実際に表示されている順番

赤1 – 値 35
赤2 – 値 25
赤3 – 値 15
グループ2 … 値 0
青1 – 値 30
青2 – 値 20
青3 – 値 10
グループ1 – 値 0
決して数字の大きい順に並んでいません ..。これはどういう事なんでしょう?実はここには 3つのスタック文脈が混在しているんです。… ちょっと整理してみましょう。

まず、body をルートにしたスタック文脈があり、その流れには、グループ1 1とグループ2 2が属しています。

グループ1 – 値 0
グループ2 – 値 0
z-index の数値、スタックレベルは同じ 0 ですね。同じスタックレベルの場合は、後から登場する要素の方が上に重ねられますから、グループ1 1の上にグループ2 2が重なっている … という訳なんです。

それから … 実は z-index の値に整数を入れると、それ自身のスタックレベルを 0 とした局所的(ローカル)なスタック文脈が自動的に作られるんです。これを局所スタック文脈と言います。そして、グループ1、グループ2の中に、それぞれ別の局所スタック文脈がある … という訳なんです。グループ1、グループ2ともに、z-index に整数「0」を指定していましたね!

グループ 1 1内の局所スタック文脈

青1 – 値 30
青2 – 値 20
青3 – 値 10
グループ 2 2内の局所スタック文脈

赤1 – 値 35
赤2 – 値 25
赤3 – 値 15
こんな風に、それぞれ別の文脈に属していたんですね!なので、それぞれの文脈の中で、きちんとスタックレベル通りに重なっていました。

もう少し見てきましょう。今度はグループ1 1 とグループ2 2の重なり順を入れ替えてみましょう。上記のサンプルでは、両方とも z-index: 0 でしたけど、今度はグループ1 1を「5」に、グループ2 2を「1」にしてみましょう。

グループの重なり順を変更

重なり順とスタックレベル

青1 – 値 35
赤1 – 値 30
青2 – 値 25
赤2 – 値 20
青3 – 値 15
赤3 – 値 10
でも、ここには大きな落とし穴があります …。実は IE7 には、z-index: auto にバグがあるんです。z-index: auto を指定しても、IE7 ではそれ自身を「0」とした局所スタック文脈を生成してしまいます。なので上記のように、青と赤を交互に重ねる … ということは出来ないんです。これは有名なバグですが、IE7 をターゲットにしている場合は、z-index に auto を指定しても、局所スタック文脈が生成されてしまう … 結果、違う親要素間の z-index のコントロールは思うようにできない … ということだけ覚えておきましょう。

z-index の重なりは、スタック文脈という流れの中での指定です。単純にスタックレベルの高い方が上層にくる … という訳ではなく、スタック文脈がどこに存在しているか?を見極めないと混乱するばかり…。z-index をマスターするには、要素が属しているスタック文脈を把握することがポイントですね!

「CHECK POINT」
z-index の重なりは、スタック文脈という流れの中で重なっています。
要素が属しているスタック文脈を把握しよう!
クリックしたり、ユーザーが操作する部分は最上層に配置しよう!