1.6 section類による画面分割
さてさて、HTML5の推奨はsection類を使った文書の構成を行うことにあるようだ。
上図はあるサイトから拝借した絵であるが、なかなかわかり易い。 これでうまくいくのかどうかはともかくとして、少しやってみようと思う。
まずは<header>からやってみよう。
<header style="background-color:#99ccff;">
<h2>header</h2>
menu1 menu2 menu3
</header>
header
menu1 menu2 menu3と表示される。
ウーン、途中に書くとそこでの表示か・・・
今度は<nav>タグと<section>タグを同様に使ってみよう。
<nav style="background-color:rgba(128,0,0,0.3); width:30%;"><h2>navである</h2>
menu1<br>
menu2<br>
</nav>
<section style="background-color:rgba(0,128,0,0.3); width:70%; ">
<h2>section である</h2>
<p> test </p>
<p> test </p>
</section>
section である
test
test
なるほど~。これらのタグ名は分類しやすいようにつけられた名前で、
表示上の違いは無いということか~。
後はhtml作成者に任せるということだね。
section である
test
test
上図は、「position:relative; left:50px;」をnavに、 「position:relative; right:50px;」をsectionに、それぞれCSSを追加した。
最初の目論見とは異なり、基準位置からそれぞれ右に50px、左に50pxずれて表示された。
sectionは画面右端から50pxのつもりであったが、これではダメなようだ。
このhtmlをさらに<div>タグで囲って、以下のように、
<nav style="background-color:rgba(128,0,0,0.3); position:absolute;left:0; width:30%;">
<h2>navである</h2>
menu1<br>
menu2<br>
</nav>
<section style="background-color:rgba(0,128,0,0.3); position:absolute; right:0; width:70%; ">
<h2>section である</h2>
<p> test </p>
<p> test </p>
</section>
</div>
とすると、下図のようになった。
section である
test
test
次のように、
<h2>section</h2>
</section>
と書くと、
section
position:absolute;とすると、親要素のpositionが初期値の場合、画面全体での位置指定(left:0)となる。 また、それ以降の追加コードは下に潜り込んでしまい、見えなくなったので、強制改行<br>で見えるようにした。
だいぶわかってきたような気がする。CSSでタグに属性を与えることで、画面分割が容易になる。
さて、positionの設定なしで画面分割がどこまでできるのか試してみようと思う。 ただし、display:inline-blockを利用し、以下のdiv要素内に3つのsection要素を横に並べて表示してみることにする。
section 2
section 2
section 3
上図は、インラインブロック(display:inline-block)で横に並べて表示したものである。section1,2はwidth:33.3%、section 3はwidth:33.4%とした。 ブラウザ横サイズを変化させると、それに合わせてそれぞれの横幅が変動することは容易に確認できる。
htmlコードを見やすいように記述すると、ブロックの間に隙間ができる現象が起きた。 これは、改行コードが半角1文字のスペースと見做され、section要素間に空白が入ってしまったためである。 これを防ぐために.....</section><section .....と記述したため、いくらかhtml文書が醜くなったが、大した問題ではないだろう。
ところで、CSSの項目で box-sizing:border-box; としておくと、位置合わせをピッタリと行なうことができるようになる。
上図は、図1.6.1のように画面分割が設定できることを示したものである。 上図のsection 1の横サイズを100pxと固定にし、articleの横サイズは残り全体とした。 ブラウザの横サイズを変更すると、section 1は不変でarticleの横サイズだけが変化することを、確認することができる。
結論として、display:inline-blockとして、インラインブロックモードでブロック要素を縦・横に積み上げる方法で、画面分割を容易に行なうことができる。 このとき、box-sizing:border-boxに設定し、vertical-align:topで位置合わせを行い、width: calc(100% - 100px)のようにcalc()を活用する必要があることを明記しておく。
今回、画面分割したWebページ上でさらに画面分割したので、読者の中にはこれが画面分割なのかと疑問に思うかもしれないが、
<body>
<header style=.....>
head section
</header>
<section style=.....>
section 1
</section><section style=.....>
<article style=.....>
article 1
</article>
<article style=.....>
.............
.............
.............
</body>
</html>
のように記述したテストページで確認すれば良いだろう。
上述のように、規則正しくブロックを積み上げる形のWebレイアウトの場合にはこのinline-blockを使う方法はとても有用であるが、自由気ままに様々な要素を配置したい場合もあるだろう。 その場合、非常に難度が跳ね上がり、上述の方法ではほとんど不可能になってしまうこともありそうである。 自由気ままにWebレイアウトを考えたい場合は、position:absoluteやrelativeが有用になるだろう。
次節では、positionプロパティの基礎的な知識を身に着けることにしよう
1.7 positionプロパティ
画面分割においてpositionプロパティが大きな役割を果たしていることが見えてきた。positionプロパティとはどういうものか見てみよう。
| プロパティ値 | 説明 |
|---|---|
| static | 省略値。要素は文書の通常のフローに従って配置され、top, right, bottom, left, z-index プロパティは無視される。 |
| relative | 要素は文書の通常のフローに従って配置され、top, right, bottom, left, z-index プロパティは有効化される。 z-index の値が auto でない場合、新しい重ね合わせコンテキストを生成、 table-*-group, table-row, table-column, table-cell, table-caption の要素における効果は未定義。 |
| absolute | 要素は文書の通常のフローから除外され、ページレイアウト内に要素のための空間が作成されない。 つまり、後続の要素からは無いものと見做され、重ねて表示される。 親がstatic以外ならば、それに対して相対配置される。 そうでなければ、つまり親がstaticならば、初期の包含ブロック(ブラウザ表示の画面全体)に対して相対配置される。 最終的な位置は top, right, bottom, left の値によって決定される。 z-index の値が auto ではない場合、新しい重ね合わせコンテキストを生成。 絶対位置指定ボックスのマージンは、他の要素のマージンと相殺されない。 |
| fixed | 要素は文書の通常のフローから除外され、ページレイアウト内に要素のための空間が作成されない。
つまり、後続の要素からは無いものと見做され、重ねて表示される。 ビューポートによって定められた初期の包含ブロックに対して相対配置されるが、 祖先の一つに transform, perspective, filter の何れかのプロパティが none 以外 (CSS Transforms Spec を参照) に設定されている場合は例外で、 その場合は祖先が包含ブロックとしてふるまう。 (なお、包含ブロック形成に寄与している perspective と filter に矛盾のあるブラウザーがある。) 最終的な位置は top, right, bottom, left の値によって決定される。 この値は、常に新しい重ね合わせコンテキストを作成し、印刷文書の場合、要素は各ページの同じ位置に配置される。 |
| sticky | 要素は文書の通常のフローに従って配置され、直近のスクロールする祖先および包含ブロック (直近のブロックレベル祖先、表関連要素を含む) に対して top, right, bottom, left の値に基づいて相対配置される。 オフセットは他の要素の配置には影響を与えない。 この値は、常に新しい重ね合わせコンテキストを生成する。 なお粘着要素は、直近の祖先がスクロールしない場合でも、「スクロールの仕組み」を持つ直近の祖先 (overflow が hidden, scroll, auto, overlay として作成されたもの) に「粘着」する。 これによって「粘着」のふるまいを効果的に抑止する。 |
上の表は、MDN Web DocsのCSS: カスケーディングスタイルシート>position を参考にまとめてみたものだが、かなり難しい解説になってしまった。正直、自分でもよくわかってない。
ところで、多くの英文サイトで「sticky」の解説があるが、日本語サイトでは「sticky」が載っていないものが多い。 逆に日本語サイトではcenterやpageがCSS3で新規追加されたそうだが、海外サイトでそれらを見つけるのが困難、いやいまだに見つけられない。どういうことだろう?
ということで、centerおよびpageについては現時点では無視することにし、後で暇があれば検証しようと思う。
なお、z-indexは各要素をWeb表示するときの優先度を示すもので、値が大きいほど優先度が高く、描画するとき最後のほうで上から重ね合わせて描画される。 そのため、最初の方で描画したものは後から重ね書きされたもので消されることになる。z-index省略時、z-index:autoとなり、親要素と同じ重ね合わせレベルとなる。
1.7.1 position: static
positionプロパティがstaticの場合、省略時の設定であり、
のように、前の要素の後にそのまま表示され、要素の前後関係は維持される。
width:300px; height:50px;とサイズ指定すると、sectionタグはブロックレベル要素なので、初期設定では後続の文章が回り込むことはないが、Wordでおなじみの回り込み設定も可能である。 また、要素はインライン要素とブロックレベル要素に大別されるが、そのことについても後で詳しく解説する。
今は、とにかく、ブロックレベル要素の挙動はこんな感じと思うことにしよう。
1.7.2 position: relative
positionプロパティがrelativeの場合、top, right, bottom, left, z-index プロパティが使えるようになる。
これはDIV要素
これはDIV要素
上の黄色表示のDIV要素は、上記緑色表示のsection要素のすぐ後に記述したものである。 2番目のsection要素(緑色表示)は右下にずれて表示されていることがわかる。 しかも、top:0 left:0 とした場合のsection要素があっただろうと思われる場所に実体があるかのように、後続のDIV要素は下にずれて表示されている。
また、2番目のsection要素(緑色表示)は、後続のDIV要素に重なって表示されているが、後続の要素よりも優先度が高くなっていることもわかる。
表1.7.1のrelativeの項目にある「要素は文書の通常のフローに従って配置され、・・・・」と書いてあることは、 「要素は文書の通常のフローに従って配置され、その後、top,right,bottom,leftなどの位置設定が適用されて表示される。」と解釈できる。
ここで、width:300px; height:50px;とサイズ指定し、bottom: 20px; right: 40px;とすると、
基準位置は通常のフローに従って配置された、top,right,bottom,leftなどの位置設定を行なう前の位置になる。 それゆえ、bottom:20pxはtop:-20pxと同じ、right:40pxはleft:-40pxと同じになる。
relative指定は、static指定のものに表示位置を変更する機能を付加しただけのものであることがわかった。
上記のsection要素においてid=sec1の要素のz-indexは省略したが、後続の要素よりも高い優先順位で描画表示されていた。 下記のボタンをクリックすると、id=sec1で表示されているsection要素のz-indexが未設定になっていることがわかる。 比較のため、id=sec2のsection要素は1に設定されていることもわかる。実行されているjsプログラムは同じものなので、 信頼できる結果である。
上記の結果から言えることは、z-index:autoの場合(省略時)、z-indexは未設定となっている。 しかし、position:relative設定の場合、後続の要素を描画後に上から重ねて描画されていることは明らかであろう。(Google Chrome, Edge, Firefoxで確認)
z-index値が大きいほど優先順位が高く、優先順位の低いものから描画を開始し、優先順位の高いものは後から重ね書きされるようになっているが、 z-indexが未設定の場合でも、優先順位のようなものがあることが確認できた。
1.7.3 position: absolute
1.6でabsoluteの場合の例をいくつか見てきた。 Webページの画面分割によるレイアウトを考える場合、恐らく活用するべきだろうと思っていたが、 relativeやabsoluteを使わなくても十分に画面分割が可能であることを見た。 しかし、好きな位置に自由に配置したい場合、inline-blockで積み上げる方式では無理が生じることは明らかである。
しかしながら、自由に配置できると言っても、あまりにも自由度が高すぎると逆にどうしたらよいかわからないという問題もありそうである。
それでは、以下のdiv領域に矩形のsection領域をバラまいてみることにする。
section 1
section 2
section 3
section 4
section 5
section 5
section 5
section 5
section 5
section 5
section 5
div要素は、position:relativeとして、div領域内のみにsection要素を配置した。
section要素はすべてposition:absoluteとし、section 1、2はleftパラメータで左からの距離、 section 3~5はrightパラメータで右からの距離を指定した。 ブラウザの横サイズを変えると、section 3~5のみ追随して動くことが確認できる。
ブラウザサイズが変わると全体のデザインが変わるということになり、使い方次第であるが、長所にもなれば欠点にもなる。 様々なところで使えそうだが、活用方法は意外と難しそうである。
ところで、position:absolute設定を使った方法がネットで検索すると沢山見つかる。 画面分割だけではなく、ドロップダウンメニュー表示などの様々なところで活用されているようだ。
1.7.4 position: fixed
ブラウザ画面全体に対して位置を指定するが、スクロールしても動かないように固定される。 この指定の場合、親要素は関係なく、指定した位置に常に表示されるようになる。
以下にposition:relative設定のdiv領域内に矩形sectionを右端と左端に表示することにする。
下記のボタン「→fixed」をクリックすると、position:absolute→fixedに変更し、表示画面最下部の左右に表示されるようになる。 スクロールしても位置は変わらない。
「→absolute」をクリックすると、元に戻る。
1.7.5 position: sticky
下のボックスはw3schools.comのHow TO - Sticky Elementの一部を参考にしたものだが、
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
スクロールしてみるとわかるが、sticky属性を持つsection要素のtop,right,bottom,leftパラメータにより上下左右に設定した値は最小値を示し、その値より小さくならないようになっている。 本来あるべきところは、htmlコードで記述したとおりの前後の要素の間に挟まれた要素の位置であり、スクロールすると中間あたりでそのことが確認できる。
具体的には、top:20px,bottom:20pxと設定した場合、top≧20px、bottom≧20pxを意味し、設定値より小さく表示されないようになっている。 上下にスクロールすると、上の限界と下の限界の間で緑色表示のsection要素が行ったり来たりすることが確認できる。
2番目の横スクロールの例において、ブルー表示のsticky属性を持つsection要素にはdisplay:inline-blockが設定されている。 rightとleftで設定された範囲を行ったり来たりする様子が確認できる。
さて、下図は、上図のスクロール表示を消した場合であるが、かなり様相が変わっている。
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
画面全体をゆっくりと上下にスクロールするとわかるが、 赤色表示のsticky属性を持つsection要素におけるtopとbottomの値はブラウザ表示画面の上端と下端からの位置に切り替わっている。 しかし、親要素divの領域を越えて表示されることはなく、親要素と一緒にスクロールアウトする。 left値も同様に、ブラウザ画面の左端からの位置に切り替わっていることがわかる。
まとめると、
- sticky属性を持つ要素は、親要素の範囲から出ることができない
- 親要素にスクロール機能があれば、top,right,bottom,leftは親要素の範囲からの最小値の距離で位置を決定する。 スクロールの過程で最小値に達すれば、そこで固定表示となる。
- 親要素にスクロール機能がない場合、top,right,bottom,leftはさらにそのスクロールする先祖(最終的にブラウザ表示画面に行きつく) の範囲からの最小値の距離で位置を決定する。 スクロールの過程で最小値に達すれば、そこで一時的に固定表示となるが、さらにスクロールしようとすると、 親要素の範囲から出られないので、親要素の枠にくっついて(sticky)、一緒にスクロールされるようになる。
- スクロール機能を持つ先祖の要素にpaddingが設定されていれば、paddingとの合計値で表示位置が決定される。
- sticky属性を持つ要素のtop値が設定されていれば、スクロールを持つ先祖の領域上端との間にある要素すべてを考慮して位置決めを行なう。
- sticky属性を持つ要素のleft値が設定されていれば、スクロールを持つ先祖の領域左端との間にある要素すべてを考慮して位置決めを行なう。
- sticky属性を持つ要素のbottom値が設定されていれば、スクロールを持つ先祖の領域下端との間にある要素すべてを考慮して位置決めを行なう。
- sticky属性を持つ要素のright値が設定されていれば、スクロールを持つ先祖の領域右端との間にある要素すべてを考慮して位置決めを行なう。
- sticky属性を持つ要素のright値が設定されかつ左側に要素がない場合、right値は下限を示しているだけなので、 left値がなければ左詰め、leftが設定されていればその位置に表示され、right値はほとんど意味をなさない。
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbb
cccccccccccccccc
ddddddddddddddddd
eeeeeeeeeeeeeeeee
上記は3重構造のdiv領域の中にsticky属性を持つsection要素を配置したものである。 最外殻のdiv要素だけスクロールを設定すると、section要素は最外殻の枠の位置とpadding値を基準にして位置を算出していることがわかる。
このことから、まとめに記述したことは、概ね正しいことが理解できる。