前回の記事で、CSSのメディアクエリについて書きながら、「前にも同じようなこと書いたような……」と思って探してみると、やっぱり書いてたからとりあえずリンクしたものの、その以前の記事でも今度書くって言ってたCSSによるレイアウトについてまだ書けてなかったというね。

まあ、こういう記事って誰のために書くの? って話だけど、自分で説明できることは他所のサイトを紹介するんじゃなくて、自分で説明したいよねってこと。

もちろん、俺が編み出したノウハウとかオンリーワンな話のほうが世のため人のためになるってもんだけど、構わず今日もお付き合いください。

ブロック要素とインライン要素

そもそも要素(エレメント)とは、HTML要素のことであるが、HTMLタグと、タグに囲まれた部分を合わせてそう呼ぶ。

たとえば <div> はdiv開始タグであり、 </div> はdiv終了タグであるが、これらに囲まれた <div>プリンちゃんは俺の嫁</div> 全体をdiv要素と呼ぶ。

タグと要素は混同されることが多いので注意。

ちなみに終了タグのない <img><br> で表される要素のことを空要素と呼び、XHTMLではスラッシュを付けて <img /><br /> と書くことになっていたが、HTML5ではスラッシュを省略できる。

要素はHTML文書において、構造や意味ごとに区別する(マークアップ)ために存在する。

HTML要素にはブロック要素(ブロックレベル要素)とインライン要素がある。

いや、厳密にいうとHTML5でこれらの概念は廃止されたが、実質的にはそれほど変わっていないので、あると思って差し支えない。

ブロック要素とは、スペースいっぱいの幅を取るボックスのような要素のことで、一つの要素で一つの行を占め、前後の要素は上下に配置される。

ブロック要素は必然的に長方形の領域を占め、幅と高さは自動計算されるが、指定することもできる。

ブロック要素には div, p, h1, h2, header, table, ul, ol, dl, pre, blockquote, form などがある。

ブロック要素をレイアウト目的で使う場合、その四角い領域のことをボックスと呼んだりする。

インライン要素とは、ブロック要素の中にあり、単なる文字や画像など、行の中に含まれる要素のことである。

インライン要素の領域は内容に応じたものとなり、幅と高さは基本的に指定できない。

インライン要素には span, strong, em, b, i, s, sup, sub, q, code, img, iframe, input, textarea, br などがある。

インライン要素はかつて、テキストを装飾する目的で使われていたが、現在はそれら自体には装飾の機能はなく、CSSによって装飾することになっている。

なお、ブロック要素とインライン要素は現在ではあくまで表示上の区別であって、CSSの display プロパティによってdiv要素をインラインにしたり、span要素をブロックにしたりすることもできる。

div { display: inline; }
span { display: block; }

CSSを書く場所

CSSをWebページで使うとき、記述する場所は以下の3通りある。

  1. 外部CSSファイル
  2. HTML内のstyle要素
  3. HTMLタグ内のstyle属性

1.と2.では、スタイル(装飾)を適用する対象となるHTML要素を「セレクター」を使って指定し、CSSを書く。

3.では、スタイルを適用する対象となる要素の(開始)タグに直接、style属性の属性値としてCSSを書く。

管理のしやすさから、1.の方法がよく使われる。

なぜなら、一つのサイト内ではすべてのページでほぼ共通のCSSが用いられるので、独立した外部ファイルだとすべてのページに渡る変更も一括で修正できるためである。

ただ、その場(タグ)限りでスタイルを適用したい場合、3.の書き方もよく使われる。

<span style="font-size: 16px; color: #ff0000;">文字サイズ16px・文字色赤</span>

spanタグにstyle属性を指定して、文字を装飾する例

3.の書き方では、スタイルを適用する対象となるHTML要素に直接CSSを記述するため、セレクターが不要となる。

また、1.や2.の記述とスタイルが競合した場合、3.の記述のほうが優先される。

以後のCSSは1.と2.の記法を用いるが、セレクターの有無以外に違いはない。

CSSセレクター - 装飾対象を指定する

CSSで要素にスタイルを適用するには、「どの要素にスタイルを適用するか」を指定する必要があり、「セレクター」という仕組みを使用する。

セレクターには以下の指定方法がある(一部)。

* (アスタリスク)
任意の要素
div (要素名)
div 要素
div span (空白)
div 要素の子孫である span 要素
div > span (大なり記号)
div 要素の(直近の)子である span 要素。“>”の前後の空白はなくてもいい
div + p (プラス)
div 要素の直後にある p 要素(コメントは含めない)。“+”の前後の空白はなくてもいい
div, span (カンマ)
div 要素、または span 要素。カンマの直後の空白はなくてもいいし、代わりに改行でもいい
.hoge (ドット)
“hoge”というクラス名(class 属性の属性値)をもつ要素。例: <div class="hoge">
#foo (井桁……いわゆるシャープ)
“foo”というID名(id 属性の属性値)をもつ要素。例: <span id="foo">
[title] (角括弧)
値によらず title 属性をもつ要素
[type="text"] (角括弧・イコール・クオーテーション)
type 属性の属性値として“text”をもつ要素。クオーテーションマークはシングルクオーテーションでもいい

セレクターは以下のようにいくつでも組み合わせることができる。

div span strong
div 要素の子孫である span 要素の子孫である strong 要素
div + p > .hoge
div 要素の直後にある p 要素の子である、“hoge”というクラス名をもつ要素
div#aaa.bbb.ccc[title="akari"]
ID名に“aaa”を、クラス名に“bbb”と“ccc”を、title 属性に“akari”という値をもつ div 要素

一般的に、特定の要素を指定するためにクラス名やID名のセレクターを使い、それを見越してHTMLを書くことになる。

ちなみにクラスとIDの違いだが、IDは一つの文書(ページ)中に重複があってはならない。

クラスは一つの要素にいくつでも付けられるし、一つの文書中でいくら重複があってもいい。

なお、一つのタグにクラス名を複数付けるには、空白で区切って書く。

<div class="akaza yoshikawa toshino funami">

マージン、パディング、ボーダー、幅・高さ

この節の内容は主にボックス要素が対象である。

CSSの初心者だけでなく、上級者も時々つまずくポイントである。

margin(マージン)とは要素の外側の余白のことである。

padding(パディング)とは、要素の内側の余白のことである。

マージンとパディングの違いは下図を見ればわかりやすいが、ボーダー(枠線)の外側に余白を付けるのがマージン、ボーダーの内側に余白を付けるのがパディングである。

ボックスモデル
ボックスモデル

かくして要素はマージン、パディング、ボーダーの分も含めてスペースを取るのだが、ここで要素の幅・高さとはどこのサイズかという問題が出てくる。

実は、CSSで指定する要素の幅・高さはボーダーの外側のサイズではなく、ボーダー、パディングを含まない内容部分のみのサイズを指す。

つまり、要素の実際のサイズは、CSSで指定した幅・高さに加え、パディング、ボーダーの領域を含めたものとなる(その外側にマージンが付く)。

この仕様を「ボックスモデル」と呼ぶが、さすがに直観的じゃないとか、計算がめんどいとか、凝ったレイアウトが実現不可能になるとかいった種々の問題が現れた。

たとえば、幅が50%のボックスを横に二つ並べて100%とし、それぞれ左側に20pxの余白を付けたい場合、普通に width: 50%; margin-left: 20px; とすると、要素の実際の幅は50%+20pxとなり、二つで100%に収まらなくなってしまう。

これを解決するCSS3の新機能が box-sizing プロパティだ。

要素に box-sizing: border-box; と指定すると、幅・高さの指定がボーダーの端を基準としたものになる、すなわちボーダー、パディングを含めたサイズになる。

人によってはCSSを初期化するとき、すべての要素にこれを指定することもあるくらい、便利なプロパティなので覚えて損はない。

この節ではここまで、ブロック要素について説明してきたが、インライン要素の場合ここまでの説明とはいくらか異なる。

まず、インライン要素には幅と高さを指定することができない(一部の要素は指定可能)。

そして、インライン要素にもマージンとボーダーを指定することができるが、パディングを指定することはできない。

要素に display: inline-block; を指定すると、インライン要素でありながら幅・高さやパディングを指定できるようになり、その内側の要素に対してはブロック要素のように振る舞う。

ここで少しマージンに関する興味深い仕様を紹介しよう。

まず、ネガティブマージンという負(マイナス)のマージン。

マージンにのみ負の値を指定することができるが、その場合、

マージンがマイナス→本来マージンが付くことによって領域が移動する方向と逆方向に領域が移動→位置をずらしたり、すでにある余白を減らしたり、隣の要素にかぶせたりできる

……というテクニカルなことが起こる(下図)。

ネガティブマージン
ネガティブマージン

マージンをマイナスに、と聞くと、パディングもマイナスにしたいと思うこともあるが、残念ながらパディングはマイナスにできない。

そして、マージンの相殺。

たとえば、上の要素Aと、その下に隣接する要素Bがあり、Aの下マージンが20px、Bの上マージンが10pxである場合、結果としてAとBの間隔は30px、ではなく20pxとなる(下図)。

マージンの相殺
マージンの相殺

上からのマージンと下からのマージンは重なり合って相殺するのだ。

つまりマージンとは、「最低これだけ空ける」という指定であるといえる。

マージンが相殺するのは上下方向だけであり、また他にもいくつかの条件があるが、ややこしいので省略。

パディングは相殺しないので、余白にマージンを使うのかパディングを使うのか、場合によって使い分けよう。

最大幅、最大高を指定

max-width, min-width, max-height, min-height の各プロパティを使えば、それぞれ幅・高さの最大値や最小値を指定することができる。

たとえば width: 500px; とした要素で、さらに max-width: 100%; とすれば、画面の幅が500pxを下回るスマホで要素が横にはみ出すのを防ぐことができる。

逆に width: 100%; とした要素で、さらに max-width: 500px; とすれば、どんなに画面の幅を広げても要素の幅が500pxを上回ることはない。

このように%による相対指定と数値による絶対指定を組み合わせて、モバイルに対応する際に便利だが、頭が混乱しないように注意(俺もたまにそうなる)。

画像が親要素をはみ出さないように img { max-width: 100%; } としてしまうのは常套手段だ。

ボーダーの指定のしかた

CSSでボーダーを指定する場合、枠線の幅 border-width 、色 border-color 、線の種類 border-style をそれぞれ指定しなければならない。

/* 枠線の幅:2px */
    border-width: 2px;
/* 枠線の色:#999999 */
    border-color: #999999;
/* 枠線の種類:実線 */
    border-style: solid;
/* まとめて指定(順序は問わない) */
    border: 2px #999999 solid;

枠線の種類には他に破線 dashed や点線 dotted や二重線 double や枠線なし none などがある。

それぞれの指定は省略することができ、幅を省略するとゼロ(つまり枠線なし)に、色を省略するとおそらく黒っぽい色に、種類を省略すると none になる。

上下左右の4値構文

マージン、パディング、ボーダーは上下左右にあり、それらを別々に指定することができる。

このとき margin-toppadding-bottomborder-left のように上下左右別のプロパティを使用することもできるが、4値構文によって上下左右をまとめて指定することもできる。

/* 値が四つだと上・右・下・左の順 */
    margin: 10px 20px 30px 40px;
/* 値が三つだと上・左右・下の順 */
    padding: 10px 20px 30px;
/* 値が二つだと上下・左右の順 */
    border-style: solid double;
/* 値が一つだと上下左右すべて同じ */
    border: 1px #ff9999 solid;
/* ボーダーを上下左右個別に指定するなら
   線幅や色などをまとめて指定できる */
    border-top: 3px #001acc dashed;

上・右・下・左という順序は必ず覚えてほしい。

左右揃え、上下揃え

ブロック要素の中でテキストなどを行の左・右・中央に揃えたい場合があるだろう。

その場合 text-align プロパティを使用する。

/* 左揃え */
    text-align: left;
/* 中央揃え */
    text-align: center;
/* 右揃え */
    text-align: right;

なお、左右均等割り付けには text-align: justify; を……と言いたいところだが、実はこれ、英語などの“単語単位”の均等割り付けであり、文字単位ではなく、残念ながら日本語には一切対応していない。

一方、上下揃えについては一筋縄ではいかない。

上下揃えを指定する vertical-align というプロパティがあるのだが……

/* 上端揃え */
    vertical-align: top;
/* 中央揃え */
    vertical-align: middle;
/* 下端揃え */
    vertical-align: bottom;
/* ベースラインに合わせる:初期値 */
    vertical-align: baseline;
/* テキストの上端揃え */
    vertical-align: text-top;
/* テキストの下端揃え */
    vertical-align: text-bottom;
/* 上付き文字 */
    vertical-align: super;
/* 下付き文字 */
    vertical-align: sub;
/* ベースラインから行の高さに対する割合、正数で上、負数で下 */
    vertical-align: 10%;
/* ベースラインから単位付きの距離、正数で上、負数で下 */
    vertical-align: 5px;

なんだこれ……

そして、このプロパティが使えるのはインライン要素とテーブルのセルだけである。

また、おそらくインライン要素に対してこのプロパティを使っても、期待通りの結果を得られないだろう。

テーブルセルなら別だが、通常のブロック要素に対して上端揃えや下端揃えをしたい場合、 vertical-align プロパティは使わず、上下にマージンかパディングで余白を付けるのが一番簡単だろう。

中央揃えをしたい場合、行の高さ(≠文字の大きさ)を指定する line-height プロパティをブロック要素の高さに揃えると期待通りに近い表示となるだろう。

div {
    height: 100px;
    line-height: 100px;
}

ブロック要素の幅を指定する

ブロック要素の幅は、デフォルトでは auto となっている。

これは先述の通り、(親のブロック要素の)幅いっぱいになるように自動計算される。

autoは「100%」とは異なり、マージンやパディングを指定しても幅がはみ出したりせず、親要素の(ボーダーやパディングを含まない)内側の幅に合わせられる。

width プロパティを使って幅を指定すると、ブロック要素の幅を強制的にその幅にすることができる。

Webページにおいて大小のボックスを配置したレイアウトを作るには必須のテクニックだ。

ところが、ブロック要素は幅をいっぱいに取らなくても、1行を占有することには変わりがなく、極端にいえば、幅がたった1pxでも前後の要素とは改行される。

ブロック要素どうしを改行させず、横に並べる方法は次の節で紹介する。

繰り返しになるが、ブロック要素の実際の幅はCSSで指定した幅に加え、ボーダー(枠線)とパディング(枠の内側の余白)が追加されるので、大きさの計算には要注意。

幅を狭くした要素を左右中央に配置するには、右マージンと左マージンの両方を auto に設定すると、左右の余白が等しくなるように自動計算される。

    margin-right: auto;
    margin-left: auto;
/* 以下は4値構文を利用した例。
   上下のマージンも指定していることに注意 */
    margin: 0 auto;

ブロック要素を横に並べる

ブロック要素を横に並べる最も簡単な方法は、 float (フロート)プロパティを使う方法である。

<div>BOX 1</div>
<div>BOX 2</div>
<div>BOX 3</div>

HTMLの記述。シンプルなブロック要素が三つ並んでいる。

div {
    float: left; /* float(左寄せ) */
    width: 100px;
    height: 100px;
    ...
}

CSSの記述。

float プロパティがなければ、三つのdiv要素が縦に並ぶだけだが、CSSにより下図のようになる。

float レイアウト
float レイアウト

float プロパティを使うと、要素の幅が内容に合わせたサイズになる(もちろん指定することも可能)。

float プロパティとはいわゆる“回り込み”であり、指定された要素は左または右に寄せられ、続く要素はその反対側に回り込む。

……と説明するより、実際に見てみたほうがよくわかるだろう(下図)。

float による回り込み
float による回り込み

Wordあたりで文書を作るときによくあるこんな表示を実現するものだが、文字だけでなく他の float されたブロック要素も回り込むのが素敵なところだ。

そのおかげで、ブロック要素を横に並べることができる。

float を指定するといつまでも回り込んだままなので、解除するには解除したい起点となるブロック要素に対し clear プロパティを使う。

/* float: left; を解除 */
    clear: left;
/* float: right; を解除 */
    clear: right;
/* float: left; も float: right; も解除 */
    clear: both;

なお、「この要素の終わりで float を解除したい!」という場合、それを行なえるCSSプロパティはないが、“clearfix”と呼ばれる小技によって可能となる。

CSSにこう書いておき……

.clearfix:after {
    content: '';
    display: block;
    clear: both;
}

HTMLでは float された要素を含むブロック要素のタグに clearfix というクラス名を付けると……

<div class="clearfix">
    <div class="float">float1</div>
    <div class="float">float2</div>
    <div class="float">float3</div>
</div>
<p>
もうfloat解除されてるよ!
</p>

あら不思議。

float なボックスの直後にあるp要素に clear を指定しなくても、 float が解除されている!

どうしてこうなるのか、原理を説明してもややこしいので、“なるものはなる!”と覚えておこう。

ところで、クラス名は何でもいいのだが、このテクニックを考えた昔の偉い人が“clearfix”と名付けたので、俺たちがとやかく言ってもべつにいいけど、まあ何でもいい。

float を使うときに注意してほしいのは、 float な要素は外から見れば高さがゼロとして扱われる点だ。

※もう少し厳密にいうと、浮いてしまって元の居場所がなくなる。

よって、 float な要素しかもたないブロック要素も、中身の高さがゼロなので、あとで clear しなければ全体の高さもゼロになってしまう。

すなわち次の( float でない)ブロック要素は float な要素の高さ(スペース)を無視してかぶさってくる(中身は回り込むが)。

ここで上の clearfix が役に立つんですよ!(某電話帳のCM風)

2カラムのレイアウトを float を使って実現する

このブログのように、メイン領域とサイドバーの2カラム(列)からなるレイアウトを、 float を使って実現してみよう。

目標は下図のように、上部のヘッダー、下部のフッターの間に、左側にメイン領域、右側にサイドバーを配置する。

float による2カラムレイアウト
float による2カラムレイアウト

HTMLは以下の通りで、前回の記事を踏まえたシンプルな構造となっている。

<body>
<div id="wrapper">

<header id="header">【ヘッダー】</header>
<main id="main">【メイン領域】</main>
<aside id="sidebar">【サイドバー】</aside>
<footer id="footer">【フッター】</footer>

</div>
</body>

CSSを適用しやすくするためにID名を付けたり、前回の記事にはなかったがbody要素の内容すべてを囲むdiv要素(ID名が“wrapper”)を使っているのがコツだが、赤字の部分にこれからCSSを適用していく。

#main {
    float: left;
    width: 600px;
}
#sidebar {
    float: right;
    width: 300px;
}

ちなみにこのレイアウトの幅、このブログのものと全く同じだよ。知ってた?

このCSSにより、メイン領域が左に float され、サイドバーが右に float されて、上の図の通りのレイアウトになった。

あとは、“wrapper”のdiv要素に幅を指定してページ全体の幅とし、ほぼ完成なのだが……

思い出してほしい。 float は忘れずに clear しなければならないことを。

これを忘れてしまうと、ヘッダーのすぐ下に、メイン領域とサイドバーの存在を無視してフッターが表示されてしまう!

というわけで、footer要素に clear しておこう。

#wrapper {
    margin: 0 auto;
    width: 980px;
}
#footer {
    clear: both;
}

clearfix を使う場合は、メイン領域(main要素)とサイドバー(aside要素)をdivタグで囲み、そのdivタグに“clearfix”というクラス名を付ける。

あとは、内容を追加したり、スタイルを弄ったりすればもう完成。

ね、簡単でしょ?(前回の記事に続き2回目)

要素を絶対位置に配置

要素の位置を上下左右から指定できるようにするには position プロパティを使う。

ちょっと使い方が特殊だが、覚えてほしい。

/* position 系のプロパティをすべて無効にし、本来の位置に配置する、初期値 */
    position: static;
/* 本来の位置を起点とした相対配置にする */
    position: relative;
/* ページの四隅を起点とした絶対配置にする */
    position: absolute;
/* 画面の四隅を起点とした絶対配置にする */
    position: fixed;

そして、 position プロパティとともに使い、要素を配置するのが以下のプロパティ群だ(俺は勝手に position 系プロパティと呼んでいる)。

top
要素の上端(マージンまでを含む、以下同じ)の位置を下方向に移動させる量(負の値だと逆の上方向、以下同様)
right
要素の右端の位置を左方向に移動させる量
bottom
要素の下端の位置を上方向に移動させる量
left
要素の左端の位置を右方向に移動させる量
z-index
重なりの優先度。0が基準で大きいほど上(手前)に表示。負の値は不可。親要素より下も不可。初期値は auto =親要素と同じ

※あえて top, right, bottom, left という順番で書いている理由は上の「4値構文」で説明した通り。CSSにおいては重要なので、覚えてね。

これらを組み合わせて要素を自由に配置できるが、まずは position: absolute;position: fixed; の違いについて。

absolute はページの端が起点であるため、HTMLにおける要素の位置に関わらず配置される(初期状態では左上に)が、ページをスクロールすると要素も一緒にスクロールする。

fixed はページではなく画面(ブラウザの表示領域)の端が起点であるため、HTMLにおける要素の位置に関わらず配置される(初期状態では左上に)のは absolute と同様であるが、ページをスクロールしても画面に追従し、要素はスクロールしない。

このブログにおいて、画面の右下に見えている上向きの矢印(ページトップに戻るボタン。スマホで見てる人は広告に隠れて見えないかも)が、 position: fixed; で配置された要素である。

下図は、 position プロパティを使用した配置変更の例である。

position レイアウト
position レイアウト

次に absolute の重要な特徴について。

absolute はページの端が起点と説明したが、親要素の position プロパティに static 以外の値が設定されている場合、その親要素の端を起点とした絶対配置となる。

あるブロック要素に position: relative; を指定しておき、その子要素に position: absolute; を指定することで、子要素を親要素内に(外でもいい)自由に配置できるようになるというわけだ。

自由すぎて迷子になってしまわないように注意だが、もう一つ注意点。

float での現象に近いが、絶対配置(absolute/fixed)にすると親要素の元を離れ、元の居場所がなくなってしまうので、本来確保されるべき領域が確保されなくなる。

絶対配置の子要素しかもたない親要素は、幅と高さを指定しないと大きさがゼロになってしまう。

つまり親要素の領域は、幅や高さを必要に応じて指定することで確保しなければならない。

次に rightbottom による指定について。

普通、HTML要素は上・左を基準に配置されるが、絶対配置において right を指定すると要素の右が基準となり、 bottom を指定すると要素の下が基準となる。

模式図は下図を参照。

right と bottom
right と bottom

次に絶対位置の%による指定について。

位置を%で指定すると、親要素の幅・高さを100%とする位置に配置される。

すなわち、いずれの方向も100%を指定すると親要素の範囲外に配置される。

100%+○○px、というふうに配置したい場合は、マージンと組み合わせるとうまくいく。

パーセントの position
パーセントの position

top なら margin-topleft なら margin-left と方向を合わせるのがコツだ。

ところで topbottom 、または leftright を同時に指定するとどうなるか。

height/width の値が auto である場合は、それぞれ要素の上下/左右の端が指定された位置になるように要素の高さ/幅が自動的に設定される。

height/width の値が auto でない場合は、要素の幅/高さについてはそれぞれ height/width の指定が優先され、位置は top/left の指定が優先される。

なお、インライン要素も絶対配置にすることができる。

要素からはみ出した部分を隠す

ブロック要素に幅や高さを指定したり、親要素を超える大きさをもつ内容を含めたりすると、子要素が親要素の領域をはみ出してしまうことがある。

はみ出した部分はどのように表示されるのかというと、普通に表示される。

とはいっても、要素外の領域を間借りしているだけなので、他の要素があった場合、重なって表示されてしまう。

要素からはみ出した部分の表示方法は、 overflow プロパティで指定できる。

/* はみ出した部分を表示:初期値 */
    overflow: visible;
/* はみ出した部分を見えなくする */
    overflow: hidden;
/* スクロールバーを表示 */
    overflow: scroll;
/* はみ出していればスクロールバーを表示 */
    overflow: auto;

※スクロールバーを表示 = スクロール可能になる
※モバイルブラウザではスクロールバーは表示されないかも

scroll だと要素内に収まる場合でもスクロールバーを表示してしまうので、普通は auto を指定する。

そしてこのプロパティでは、値を空白で区切って二つ書くことにより、X軸方向(横)とY軸方向(縦)の順で個別に指定することもできる。

また、X軸方向とY軸方向を個別に指定するプロパティ overflow-xoverflow-y もある。

/* X軸方向・Y軸方向 の順 */
    overflow: visible scroll;
/* 上の1行と下の2行は同じ指定 */
    overflow-x: visible;
    overflow-y: scroll;

overflow-xoverflow-y の一方だけを visible 以外に指定すると、もう一方は勝手に auto に設定されるようだ。

もっとも、親のブロック要素の縦幅は子要素の量に応じて伸縮するし、テキスト要素は親のブロック要素の右端で自動的に改行されるので、子要素が巨大な画像だったり、縦幅を小さく指定したりしない限り、子要素が親のブロック要素をはみ出すことは基本的にない。

さっそく例外だが、テキスト要素が親のブロック要素の右端で自動的に改行されないようにするには、 white-space プロパティを使う。

/* 標準の状態:初期値 */
    white-space: normal;
/* テキストが親のブロック要素の右端で自動的に改行されない */
    white-space: nowrap;
/* HTMLソース中の「連続する半角スペース」「タブ文字」「改行文字」をそのまま表示 */
    white-space: pre;

pre 以外では、HTMLソース中の「連続する半角スペース」「タブ文字」「改行文字」およびそれらの連続は、一つの半角スペースとして表示される。

nowrap を使用することでテキストが親のブロック要素をはみ出してしまうことがあるので、 overflow プロパティで見た目を整えよう。

親のブロック要素を右(左も)にはみ出したテキストを「…」のように三点リーダで表示したい場合、ちょっと手間がかかる。

以下のように三つのプロパティをセットで指定しなければならない。

.santen {
    white-space: nowrap; /* 自動改行しない */
    overflow: hidden; /* はみ出した部分を隠す */
    text-overflow: ellipsis; /* はみ出しそうなときに三点リーダを表示 */
}

text-overflow プロパティはまだ勧告されていない仕様であるため、他の値も仕様として提案されているが、多くのブラウザで対応しているのは ellipsis だけである。

この場合、三点リーダが表示されるのは親要素の(パディングを含めない)コンテンツ領域内となり、三点リーダの分だけ表示領域をさらに狭めることになる。

だってあかりは、だってあかりは、だってあかりは、主役だよー!!!

要素を非表示に

HTMLソース中に存在する要素を表示したくない場合がある(コメントアウトするのではなく)。

CSSによって要素を非表示にする方法は実にいろいろある。

  • display: none; でなかったことにする。領域やマージンもなかったことになる。
  • visibility: hidden; で不可視にする。領域やマージンは確保される。
  • opacity: 0; で要素全体を透明化する。領域やマージンは確保される。
  • color: transparent;font-size: 0px; などで中身の文字を見えなくする。
  • 領域の幅や高さをなくし、 overflow: hidden; などではみ出した部分を隠す。
  • text-indent: -9999px; などで内容を要素外に飛ばし、 overflow: hidden; などで(以下略)

これらの方法は、たとえばモバイル向けなどで一部の要素を非表示にしたりするのに利用されるが……

検索エンジンに過剰な情報を提供するために利用された過去があるため、Googleなどはこれらの不適切な利用をSEO(検索エンジン最適化)スパムとみなすので注意。

なお、通常のユーザーからは隠し、スクリーンリーダーを利用する視覚障害者などには表示させる方法として使う場合、以下の方法が使える。

.screen-reader-text {
    display: block;
    width: 1px; /*  */
    height: 1px; /*  */
    overflow: hidden; /*  */
    opacity: 0; /*  */
    position: absolute; /*  */
    top: 0px; /*  */
    left: 0px; /*  */
}

これはかなり念入りな指定となるが、まず幅と高さをゼロにはしないで、1pxにしておく(①)。

はみ出した部分を隠し(②)、さらに1pxの領域から中身が見えないように透明化する(③)。

さらに、絶対配置にして(④)、左上に張り付かせる(⑤)。

そして、スクリーンリーダーだけに表示(というか音読)させたい要素に“screen-reader-text”というクラス名を付ければOK(クラス名は何でもいい)。

<label class="screen-reader-text" for="erase">\アッカリ〜ン/</label>
<input type="button" id="erase" value="押すと消えます">

擬似クラスと擬似要素

●注:似ではなく、似である。

クラスとはCSSを適用するためにHTMLタグに付ける名前の一種であるが、CSSには擬似クラスというものがある。

これは、HTMLに記述するクラスではないが、HTML要素の(ページ上の)現在の状態を表し、これをセレクターとしてCSSを記述することができる。

たとえば :hover という擬似クラスは、その要素にマウスオーバー(マウスポインターを合わせること)している状態を表す。

これにCSSを適用することにより、要素にマウスオーバーしているときだけ別のスタイルを適用することが可能になる。

ハイパーリンクの文字列にマウスオーバーすると文字の色が変わったりするのはWeb界の常識であるが、このような擬似クラスが使われているのだ。

a {
    color: #333333;
}
a:link { /* リンクテキスト */
    text-decoration: underline;
}
a:link:hover, /* マウスオーバー時 */
a:link:active { /* マウスクリック中 */
    color: #999999;
    text-decoration: none;
}
a:visited { /* リンクが訪問済みのとき */
    color: #999999;
}

このブログで実際に使っている指定の一部。わざわざ a:link と書いている理由は、リンクでないa要素が存在するため。

他にも :focus (マウスなどで選択されフォーカスがある時)や :disabled (フォーム内の要素が無効化されているとき)などの擬似クラスが存在する。

擬似クラスセレクターには、必ず頭に「コロン」を付ける。

擬似クラスを使いこなすことにより、よりユーザー・フレンドリーなサイトを作ることができる。

次に擬似要素だが、これを使うとHTMLタグすらない場所に、CSSを使って要素を挿入することができる。

擬似要素は主に :before:after の2種類であり、それぞれセレクターで指定した要素の前と後に擬似的な要素を追加し、それにスタイルを適用できる。

span:before {
    content: '前に付けるテキスト';
    font-color: #00ff00;
}
span:after {
    content: '後に付けるテキスト';
    display: block;
    width: 100px;
    background-color: #9999ff;
}

※クオーテーションマークはダブルクオーテーションでもいい。

擬似要素によって追加されたテキストは、一般的なブラウザではマウスドラッグで選択できないが、スクリーンリーダーでは問題なく読み上げるらしい。

擬似要素を追加するには content プロパティに値が必要であり、テキストなしの擬似要素が必要なら content: ''; と空文字列を指定する。

逆に、擬似要素を解除したい場合は content: none; と指定する。

擬似要素セレクターにも頭に「コロン」を付けるが、実はCSS3においては擬似クラスとの区別のため、本来は「コロン」二つ :: を付けることになっている(ダブルコロンと呼ばれる)。

しかし、かつて両者の区別がなかった頃の古いブラウザーとの互換性のため、「コロン」一つで記述するのが一般的となっている。

スタイルの継承と重ね合わせ

CSSの C とは Cascading の略であり、階層とか段階とかいう意味である。

SSとはスタイルシートの略である。

CSSの一部のプロパティ値は、親要素から子要素へと継承されていく。

font-size, color, line-height は継承されるプロパティの例である。

よって、たとえば body { font-size: 14px; } とすれば、あらゆる要素に文字サイズを指定しなくても、ページ中のすべての要素の文字サイズが14pxとなってくれる。

プロパティ値は最も近い親のものが継承されるので、たとえbody要素に14pxという文字サイズを指定したとしても、 div.aaa { font-size: 12px; } と指定すれば、“aaa”というクラス名をもつdiv要素の中ではすべての要素の文字サイズが12pxとなってくれる。

また、スタイルの継承はプロパティごとに行われるので、親要素のすべてのスタイルを継承しながら、一部のスタイルのみを指定によって書き換える、ということも可能である。

次に、スタイルの重ね合わせについて。

p {
    font-size: 16px;
}
.bbb {
    color: #0000ff;
}

上のように p という要素セレクターと .bbb というクラスセレクターにそれぞれスタイルが設定されているとき、“bbb”というクラス名をもつp要素には両方のセレクターが当てはまるので、両方のスタイルが適用される、つまり文字はサイズが16pxかつ、色が青になる。

これを応用すれば、様々なセレクターの指定のしかたを使い分けることによって、CSSの記述量を削減したり、まとめて指定したりできるようになる。

たとえば上の例でいうと、“bbb”というクラス名をp要素以外に用いないことにすれば、 p.bbb というセレクターを書かなくても .bbb でいいし、 .bbb というセレクターに font-size: 16px; と書かなくてもいいことになる。

スタイルの重ね合わせもプロパティごとに行われる。

以上のように、プロパティ値は継承や重ね合わせによって「階層的に」適用されていくのがわかる。

ここで、じゃあ複数のセレクターで同じプロパティを指定し、プロパティ値が競合したらどうなるのかという疑問が出てくるが、それについては次の節で説明する。

セレクターの優先度

ある要素に当てはまる複数のセレクターにおいて、同一プロパティに異なる値が指定されている状態、つまり競合が起こった場合、一定の優先度によって適用されるスタイルが決まる。

優先順位の低いセレクターのプロパティは優先順位の高いセレクターのプロパティに上書きされる。

その優先順位は以下のリストの通りである。

  1. (HTMLタグの style 属性に書かれたスタイル)
  2. IDセレクターを含む場合、その合計数が多いセレクター
  3. クラスセレクターや擬似クラスセレクターを含む場合、その合計数が多いセレクター
  4. 要素名セレクターや擬似要素セレクターを含む場合、その合計数が多いセレクター
  5. ここまでで同順となる場合、ソース上で後(下)にあるセレクター
  6. 同一のセレクター内にある場合、ソース上で後にあるプロパティ
  7. ブラウザが持つ内蔵CSSの記述

この優先順位を利用して、クラス名やID名をHTMLタグに付けたり、セレクターを詳細に指定したりすることで、本来適用されるスタイルを上書きすることができる。

また、Web開発者はこの優先順位に留意して、思わぬ競合が起こらないようにしなければならないが、この優先順位を覆し、指定したプロパティを最優先で適用することができる禁呪が存在する。

ほんとは教えたくないけど……

.aaa {
    font-size: 20px !important;
}
.aaa.bbb {
    font-size: 14px;
}

CSSの記述。

<p class="aaa bbb">わあい 20px あかり 20px 大好き</p>

HTMLの記述。

上の記述の場合、p要素の文字サイズは本来、クラス名二つが当てはまるセレクターの14pxが適用されるはずが、クラス名一つしか当てはまらないセレクターの20pxが適用されることになる。

これが、上に赤字で示した禁呪 !important の力である。

プロパティ値に続いて !important を指定したプロパティは、他のセレクターよりもHTMLタグの style 属性よりも優先して適用されるようになる。

この禁呪は正しく使えば便利なのだが、とかく駆け出しの魔法使いWeb開発者は多用してしまいがちで、注意を要する。

というのも、 !important を使いすぎると、CSSが思い通りにならないときに、どこかでこれを使ったのが原因であることに気付きにくく、またどこで使ったのか見つけにくいからである。

また、 !important どうしで競合してしまった場合、どのスタイルが適用されてしまうのかが定義されていないらしい。

つまり、思わぬ不具合の温床となるので、駆け出しの魔法使いWeb開発者にはこの禁呪を使ってほしくないのである。

よって、できればこの禁呪には頼らず、セレクターの詳細度や記述順を工夫してCSSを書いてほしい。

まとめ

今回はCSSの初歩からよく使うレイアウトまで、長々と紹介した。

今までの記事で「いつかCSSによるレイアウトを紹介する」と二度も言っていたようだが、まだ書いてなかったので。

CSSはHTMLと違って、いきなり覚えることが多くて大変だと思うので、一つずつ身に付けてWebページをデザインしながら習得していってもらえれば。

今回の記事では俺が初心者にとって重要だと思う事項を優先的に紹介したつもりだが、初心者には難しすぎるところがあったり、逆に大事なところが抜けているかもしれない。

そういうところに気付いたら、この記事の内容を修正していく予定だ。

また、質問があったら遠慮なくコメントとかTwitterへの返信などしてもらえれば。

プロじゃないので相談料は無料である。
そのかわり、解決を約束することもない。

なんか例文がおかしかったような気もするが、あくまで例なので気にしないでほしい。