CSSの実習(8) - レイアウト関連の指定(2)・ポジショニング。
- お詫び(平成23年11月12日)
- 本コンテンツでサンプルとしている HTML 文書に以下のマークアップ漏れがありました。
平成23年11月10日以降に本コンテンツをご利用の方は、訂正した HTML 文書を御覧ください。
ご迷惑をお掛け致しました事を深くお詫び申し上げます。
前回の実習(7) - レイアウト関連の指定(1)・フローティングでは、フローティングを用いて要素を左右に寄せる事でレイアウトを実現しました。
今回はより高度なレイアウト関連のスタイル指定として、CSSの奥義とも言えるポジショニング(位置指定配置)を利用してみます。
ポジショニング関連のプロパティはポジショニング(位置指定配置)関連の主なプロパティに纏めておきましたので、そちらも適宜参照してください。
ポジショニングの指定で出来る事。
CSSでのポジショニングとは、要素の配置の事です。
通常のウェブブラウザでは、ブロックレヴェル要素を上から下に、一次元的にレイアウトすると言う配置をデフォルトで行いますが、ポジショニングを変更する事で二次元的なレイアウトも可能になります。
或いは、要素の前後関係を入れ替えたように表示させる事も可能になります。
- 但し、ブロックレヴェル要素の前後の入れ替えは、上下のmarginプロパティにマイナスの値を指定する事でも実は可能です。
ポジショニングに関するプロパティについての詳細は、ポジショニング関連の主なプロパティをご覧ください。
今回やりたい事。
今回は、二つある<section>要素のうち、初めの方を左半分に寄せ、後の方を右半分に寄せる事にしましょう。
この際、どちらも同じ幅になるようにします。
今回も、実習としてやりたい事を挙げておりますが、もし読者の方がここで挙げているスタイルではなく、別のスタイルにしてみたいと思うのであれば、それを実際にやってみるのが何よりの実習です。
是非挑戦してみてください。
実際のスタイル定義。
さて、これから実際に前回までのスタイル定義ファイル style.css にスタイルを追記していきましょう。
まず、基本スタイルではポジショニングはデフォルト通りにします。
CSSの仕様ではデフォルトではポジショニングは変更しない事となっておりますが、実際のウェブブラウザではそのようになっているかどうかは分かりません。
確かに、実際にブラウザのデフォルトスタイルで特定の要素の配置をいじるような代物は聞いた事がありませんが、絶対無いとも断言出来ません。
- 何故なら、HTMLの仕様に於いてデフォルトスタイルでポジショニングの設定を禁じていないからです。
そこで、念のため、初めに決めた通りの基本スタイルとしてポジショニングはデフォルトに従うようにしてやります。
スタイル定義ファイル style.css 内の全称セレクタに対するプロパティ定義に、以下のように追記する事で新たなプロパティを指定します。
* {position: static;background-color: transparent;background-image: none;color: #000;margin: 0;padding: 0;border: none 0;background-color: #fff;color: #000;font-family: "MS Pゴシック", sans-serif;font-size: 100%;font-style: normal;text-decoration: none;font-weight: normal;text-align: left;line-height: 1.5em;text-indent: 0;float: none;}
positionプロパティはフローティングの指定
で、今回は static 値、すなわち特にデフォルトから動かさないものとしております。
問題:二つある<section>要素をどう判別しよう?
さて、今回は二つある<section>要素のうち、一つを左側、もう一つを右側に置くものとします。
二つある<section>要素のうち、片方は左、もう片方は右に置こうと言うのですから、当然これらの要素へは異なったスタイルが与えられると言う事になる筈です。
それでは、この二つの<section>要素をどう判別しましょうか。
HTML 文書に予め id 属性で固有名を与えておけば、一意セレクタ(IDセレクタ)を用いる事で簡単に分別が可能になります。
そこで、今回教材として用いている HTML 文書に、以下の加筆を行いましょう。
<!DOCTYPE html><html lang="ja"><head><meta charset="shift_jis" /><title>HTMLとは何か</title></head><body><article><h1>HTMLについて。</h1><section id="WHAT_IS_HTML"><h2>HTMLとは。</h2><p><dfn>HTML</dfn>はウェブで公開する電子文書を作る為の言語です。</p><p>HTMLは<a href="http://www.w3.org">W3C(ワールドワイドウェブコンソーシアム)</a>に依って標準規格化されております。</p></section><section id="CHARACTERISTICS"><h2>HTMLの特徴。</h2><p>HTMLの特徴は</p><ul><li>画像を埋め込める</li><li>文字の色など表示方法を指定出来る</li></ul><p>では<em>ありません</em>。</p><p>確かに画像を埋め込んだりする事も可能です。</p><figure class="sample"><img alt="" src="HorikitaUsagi.GIF" width="218" height="269" /></figure><p>しかし、表示方法は寧ろ指定しない事こそ本来のHTMLの在り方です。</p><p>HTMLの最大の特徴は</p><ul><li>ハイパーリンクが使える</li><li>どんな環境でも読めるようになっている</li></ul><p>この二点に尽きます。</p></section></article><hr /><address>Copyright(C) 2011 しらぎくさいと <a href="mailto:marguerite.site@gmail.com">marguerite.site@gmail.com</a></address></body></html>
- 一番目の<section>要素に
id="WHAT_IS_HTML"属性を与えて、当該要素にWHAT_IS_HTMLと言う固有名を、 - 二番目の<section>要素に
id="CHARACTERISTICS"属性を与えて、当該要素にCHARACTERISTICSと言う固有名を
それぞれ与えております。
今回、何をするのか。
以上で準備が整いました。
今回は初めに述べた通り、二つある<section>要素を左右に並べると言う事をやってみます。
先ず、具体的にどうするのかについて述べます。
二つある<section>要素のうち、先行側を左側に、後続側を右側に配置しますが、その際行える方法は以下のいずれかとなります。
- 先行する側(左側)をポジショニングで位置合せし、後続する側(右側)は左側に合わせて余白を取る事で重ならないようにする。
- 後続する側(右側)をポジショニングで位置合せし、先行する側(左側)は右に余白を与える事で右側に重ならないようにする。
つまり、ポジショニングで位置合せすべきなのは片側のみであり、もう片方はそれに合わせて左か右に余白を取る事で重ならないようにするだけで良いと言う事になるのです。
どちらの<section>要素を位置合せすれば良いか?
それでは、今回はどちらを取れば良いでしょうか。
話がちょっと長くなるので、詳細は別文書で解説いたしますが、結論から言えば、小さい方をポジショニングすると言うのが正しいのです。
今回はサンプル HTML 文書をご覧になれば明らかにお分かりのように、後続の<section>要素の方が大きいので、先行する<section>要素をポジショニングするものとします。
どの位置にポジショニングすれば良いか?
続いて、ポジショニングを行う以上、どの位置にポジショニングすれば良いのかを考えなければなりません。
二つの<section>要素は、<article>要素の直下になっているので、<article>要素を基準にポジショニングすれば良いでしょう。
つまり、<article>要素の表示位置を絶対位置の基準点にする必要があります。
- 絶対表示位置の基準点となるブロックを、コンテナブロックと呼びます。つまり、今回は<article>要素をコンテナブロックにすると言う事になります。
<article>要素をポジショニングの基点にする。
これには、<article>要素に以下のスタイル定義を与える事で実現します。
- <article>要素自身は一切動かさない事に注意してください。
article {display: block;position: relative;top: 0;left: 0;}section {display: block;}
ここで、display block; プロパティが出て来ました。
これは、当該要素をブロックレヴェル要素の形で表示すると言う指定です。
インターネットエクスプローラ 8.0 までなど、HTML 5 を認識しないウェブブラウザでは、HTML 5 になって新たに導入された<article>要素はインライン要素と見なしてしまいます。
このため、このように display プロパティで明確にブロックレヴェル要素の形で表示するよう指定します。
同様の理由から、<section>要素にもこのプロパティを与えております。
- 本当の事を言えば、他のブロックレヴェル要素も当然にこの指定が必要です。
何故なら、デフォルトの
displayプロパティ値はinlineすなわち、インライン要素の形と決められているからです。にも拘らずブロックレヴェル要素で表示すべきとされている要素が今までそのように表示されてきたのは、ウェブブラウザが独自にそのように実装していたからに他なりません。
このため、今回の場合で言えば、
- <html>要素(HTML文書全体)
- <body>要素(HTML文書本体)
- <article>要素(記事セクション)
- <section>要素(セクション)
- <h1>要素及び<h2>要素(見出し)
- <p>要素(段落)
- <ul>要素(順不同リスト)
- <hr>要素(段落間の区切り)
- <figure>要素(画像などのブロック)
- <address>要素(文書作成者への連絡先情報)
には、
display: block;プロパティを与える必要があります。また、<li>要素(リスト項目)についても、
display: list-item;プロパティを与える必要があります。加えて、全称セレクタで指定される基本スタイルでも
display: inline;プロパティを与えておくべきです。更に言えば、<head>要素(文書のメタデータの集まり)の内容テキストは表示されるべきでないので、これは
display: none;プロパティで非表示にします。今回はこれらについても書き足しました。
実際の加筆については、何箇所にも及ぶのでここでは省きます。最終的なスタイル定義をご覧ください。
- この辺りについてはかなりカタイ事を言っているように見えるかも知れませんが、仕様を考えるとこうせざるをえないのです。ただ、最低でも、上記の二要素と<figure>要素は後発の要素ですので、HTML 5 より前の世代のウェブブラウザに対して明確にする必要はあります。
一方、position: relative; プロパティは、本来表示されるべき位置からズラして表示させる指定です。
そのズレは、
- 上下方向なら
topプロパティまたはbottomプロパティ - 左右方向なら
leftプロパティまたはrightプロパティ
を指定します。
ここでは一切ズラさないので、top プロパティ、left プロパティともに 0 を指定しております。
- 実を言うと、これらのプロパティのデフォルト値は 0 と決められているのですが、一切ズラさない事を強調するために敢えて記述しております。
<section>要素の位置を決める。
続いて、実際の<section>要素の縦方向の位置を検討しましょう。
<article>要素の内容として、先ず表題の見出しとなる<h1>要素が入っております。
<section>要素はその直後ですので、この<h1>要素の高さを考慮する必要があります。
<h1>要素のスタイル定義を見ると、
- 上方向のマージンは 0 (全称セレクタに対するプロパティ定義を適用)
- 上方向のパディングは 0 (全称セレクタに対するプロパティ定義を適用)
- 要素本体の高さは、内容テキストの行の高さそのものなので、
line-heightプロパティの値である 1.2文字分。但し、これはデフォルトのフォントサイズの200%(font-sizeプロパティで指定)なので、1.2×200% = 2.4文字分となります。 - 下方向のパディングは 0 (全称セレクタに対するプロパティ定義を適用)
- 下方向のマージン、
margin-bottomプロパティでの指定に依り 1文字分。但し、これはデフォルトのフォントサイズの200%(font-sizeプロパティで指定)なので、1×200% = 2文字分となります。また、下方向のマージンはその下に表示されている<h2>要素の上マージンと相殺されます。
<h2>要素に与えた上マージン(
margin-topプロパティ)は 3文字ですが、デフォルトのフォントサイズの120%となっているので、3×120% = 3.6文字分となります。この結果、<h2>要素に与えた上マージンの方が大きいので、こちらの値が採られ、結局 3.6文字分のマージンとなります。
- 0+0+2.4+0+3.6 = 6
つまり、上端より 6文字分下に位置すべきと言う事になります。
一方、横方向は左端に位置すれば良いので、左端と言う事にします。
先行する<section>要素のスタイル指定。
以上で必要な検討が終わりました。
それでは、先行する<section>要素のポジショニングを実現しましょう。
先行する側は左にポジショニングすれば良いのですが、その位置は<article>要素から見て
- 左端
- 上端から 6文字分下
となります。
また、この<section>要素内にある<h2>要素の上マージンは 0にしておきます。
そこで、そのようなスタイルを実現しましょう。
まだ一意セレクタ(IDセレクタ)を与えたスタイル定義は記述しておりませんので、以下のように追記します。
/* 特別なIDを持った要素へのスタイル定義 */section#WHAT_IS_HTML {position: absolute;top: 6em;left: 0;width: 49%;margin: 0;padding: 0;}section#WHAT_IS_HTML h2 {margin-top: 0;}
ここでは、先ずposition: absolute;で、上位要素である<article>要素から見た絶対位置に表示する指定をします。
position: absolute; プロパティは、上位でデフォルト値でない position プロパティを与えられた要素を基準にした絶対位置に表示すると言う指定です。
<article>要素にデフォルトでない position プロパティを与えているため、親要素である<article>要素基準となるのです。
続いて、その絶対位置を決めますが、これは
- 上下方向なら
topプロパティまたはbottomプロパティ - 左右方向なら
leftプロパティまたはrightプロパティ
を指定します。
- 左端
- 上端から 6文字分下
となりますので、上記のような top プロパティ、left プロパティが与えられます。
続いて、width プロパティで横幅を指定します。
横幅は親要素となる<article>要素の半分、つまり 50%としたいのですが、そうすると右側の要素とぴったりくっついてしまうので、それより若干小さい 49%を与えております。
margin プロパティとpadding プロパティは、これらの横方向の値が横幅に影響を与えるので、零にしております。
- つまり、これらのプロパティ値を調整する事で、幅を適切に取りつつ、隙間を与える事も可能になります。
この後にある section#WHAT_IS_HTML h2 と言うセレクタは、この左にポジショニングされた<section>要素内の<h2>要素を対象とします。
後続の<section>要素のスタイル指定。
続いて、後続の<section>要素ですが、こちらはポジショニングは不要です。
しかし、このままだと先行する要素に重なってしまうので、その分余白を与えます。
具体的には、以下のようにします。
section#CHARACTERISTICS {margin: 0 0 0 51%;padding: 0;}
強いて言うなら、左余白を 50% としないで、51% とした事くらいでしょうか。
これは、左側の要素とぴったりくっ付くと見難くなってしまうため、敢えて余計に余白を与えたものです。
ここまででのスタイル定義ファイルの纏め。
以上のスタイルを纏めると、スタイル定義ファイル style.css は以下のようになっているでしょう。
@charset "shift_jis";* {display: inline;position: static;background-color: transparent;background-image: none;color: #000;margin: 0;padding: 0;border: none 0;background-color: #fff;color: #000;font-family: "MS Pゴシック", sans-serif;font-size: 100%;font-style: normal;text-decoration: none;font-weight: normal;text-align: left;line-height: 1.5em;text-indent: 0;float: none;}html {display: block;background-color: #fff;padding: 2em 1em;}head {display: none;}body {display: block;}article {display: block;position: relative;top: 0;left: 0;}section {display: block;}h1 {display: block;margin-bottom: 1em;background-color: #ff0;color: #090;font-style: italic;font-weight: bold;font-size: 200%;line-height: 1.2em;text-align: center;}h2 {display: block;margin: 3em 0 1em;border-color: #cc0;border-style: solid;border-width: 1px 2px 4px;background-color: #fff;background-image: url("Background-H2.GIF");background-repeat: repeat-y;background-position: right top;color: #090;font-size: 120%;line-height: 1.2em;}p {display: block;margin: 1em 0 0 2em;text-indent: 1em;}ul {display: block;margin: 1em 0 0 4em;list-style-image: url("ListMarker.GIF");list-style-type: disc;list-style-position: outside;}li {display: list-item;}figure {display: block;margin: 1em 0 0 2em;}hr {display: block;margin: 3em 0 1em;border: 1px solid #888;clear: both;}address {display: block;}a:link {color: #090;text-decoration: underline;}a:visited {color: #000;text-decoration: underline;}dfn {border-bottom: 2px solid #cc0;color: #090;}em {padding-top: 4px;background-color: #fee;background-image: url("Background-EM.GIF");background-repeat: repeat-x;background-position: left top;color: #000;}/* 特別なIDを持った要素へのスタイル定義 */section#WHAT_IS_HTML {position: absolute;top: 6em;left: 0;width: 49%;margin: 0;padding: 0;}section#WHAT_IS_HTML h2 {margin-top: 0;}section#CHARACTERISTICS {margin: 0 0 0 51%;padding: 0;}/* 特別なクラス名を持った要素のスタイル定義 */figure.sample img {float: left;}