/ 2013-06-30
marginを説明する上で、まずはボックスモデルを知る必要があります。 CSSでmarginを指定すると、上記のボックスモデルのmarginと書かれた部分に、数値が適用されます。 marginにはプロパティが用意されており、省略も可能です。 個別指定 marginの省略 論理プロパティ margin-topなどは見慣れてるけど、margin-startは初めて見るという方もいると思います。 margin-topは、画面から見た物理的な方向に対し、 横書きにmargin-startが指定されている場合は、margin-leftが適用されます。 このプロパティを使用することにより、同一のCSSで縦書き、横書きの切り替えがスムーズになる可能性を持っています。(ただしIE8などは使用不可。) marginに対して、autoを設定した場合は数値は0になります。 ブラウザの幅が600pxの場合 上記の例なら、ブラウザの幅が600pxなので、margin-leftは自動で500pxになります。 横幅を指定した状態で、margin-left, margin-right にautoを指定した場合。 例えば、以下の図のようなレイアウトにしたい場合 ネガティブマージンを使用すると、レイアウトの幅が広がります。 marginでも、paddingでも、空間をあけることが可能です。 margin, padding共に、空間をあけることができます。 paddingは、背景色や、枠線にも影響して余白をあけることができますが、 paddingにはない機能として、marginの相殺があります。 しかしmarginの相殺を理解することで、marginの単一方向の指定や、paddingを使用するよりも、HTML, CSSをクリーンに書ける場合も多くあります。 paddingであれば、divの間は、10px+10px=20px となります。 相殺を理解するには、要素を人に例えるとわかりやすいかもしれません。 脂肪(padding)だと、物理的な距離となります。 これが心の距離(margin)の場合は、Aさんの心の距離が1。 相殺は、数値の大きい方が適用されます。 上記の例では、div同士の間隔は、20pxと30pxで50pxになるはずですが、相殺によって、少ない方の数値が打ち消されます。 相殺は入れ子の状態でも、marginが重なれば発生します。 両方ともにmarginが設定された場合、相殺が発生します。 入れ子の別の例 上記の例では、margin-topは、.parentの方が大きいので30pxが適用されます。 親の要素に特定のCSSを適用することで、子の相殺が発生しません。 さらに上記以外にも、floatによって相殺が発生しない場合があります。 marginとfloatは、密接な関係にあります。 親、子に関わらずmarginを指定している要素に、floatを適用すると相殺をしなくなります。 また width と margin:auto; の関係で記載したように、widthとmarginを指定した場合のautoは、数値を自動算出します。 margin: auto;とfloatを指定した例 floatを使用すると、その要素のmarginはpaddingのような挙動を行います。 floatが親、子の要素にかかると相殺が発生しません。 上の条件が全てではありません。 以下、marginとfloatの相殺の例です。 1つの要素にmarginとfloatが指定されていると、marginの相殺が起きません。 しかし上の例のdiv.testは、marginとfloatが相殺する条件を満たしているので、図のような動きをします。 「floatを解除する」とよく説明されるclearプロパティですが、floatに隣接してはならないかを指示するプロパティです。 'none'以外の値は、潜在的にクリアランスを導入する。クリアランスはマージンの相殺を抑制し、要素のmargin-topの上へ空白のように振る舞う。浮動体を過ぎて垂直に要素を押すために使用される。 'clear'が設定された要素のクリアランスの計算は最初に要素の上ボーダー辺の仮の決定によってされる。要素の'clear'プロパティが'none'である場合、この位置は実際の上ボーダー辺となる。 9.5.2 浮動体に隣接するフローの制御: 'clear'プロパティ - W3C 視覚整形モデル (邦訳) clearは、marginの相殺を抑制し、floatの底辺に要素がつくように、margin-topの値を自動調整するような振る舞いを行います。 以下、margin, float, clearの例です。 .clearにmargin-topに3000pxも指定しています。
本来なら、3000pxの間隔が空くはずですが、float:leftを指定したimgの底辺にくっついてしまっています。 さらに、float:right;を指定した.rightの底辺(marginを含む)には、.clear-rightの上辺が重なっています。 なぜなら、隣接するfloatを指定した要素とmarginは、相殺関係になりますが、.clearのように隣接する要素とmarginに相殺関係が発生しない場合は、そこからが出発点になります。 clearとmargin-topを同時に適用すると、clearプロパティが優先されるので気をつけて下さい。 うんざりしてくるほど、ややこしいmarginですが、間隔を適切にあけたい場合。 完成するレイアウト margin <dl>
<dt>margin デモ1</dt>
<dd>ddタグの中に直接テキストを入れています。</dd> <dt>margin デモ2</dt>
<dd>
<p>ddタグの中にpタグを入れています。</p>
<p>ddとpのmarginが重なるので、相殺が起きます。</p>
</dd> <dt>margin デモ3</dt>
<dd>
<img src="dummy.jpg" alt="" width="480" height="32">
<p>画像が入っても適度に間隔があきます。</p>
<p>また下に入っても問題ありません。</p>
<img src="dummy.jpg" alt="" width="480" height="32">
<p>さら下に入っても問題ありません。</p>
</dd>
</dl> padding dl {
padding:3em 0;
}
dt {
display:inline;
float:left;
}
dd {
padding:0 0 3em 120px;
}
.pt {
padding-top:1em;
}
.pb {
padding-bottom:1em;
}
.last-child {
padding-bottom:0;
}
</style> <dl>
<dt>margin デモ1</dt>
<dd>ddタグの中に直接テキストを入れています。</dd> <dt>margin デモ2</dt>
<dd>
<p class="pb">ddタグの中にpタグを入れています。</p>
<p>pタグ同士の間隔をあけるので、classを入れなければいけません。</p>
</dd> <dt>margin デモ3</dt>
<dd class="last-child">
<img src="dummy.jpg" alt="" width="480" height="32">
<p class="pt pb">画像が入ると、class祭りになります。</p>
<p class="pb">新しくpタグを入れようと思うと、classを更に入れなければなりません。</p>
<img src="dummy.jpg" alt="" width="480" height="232">
<p class="pt">classがやたら増える。</p>
</dd>
</dl> marginの相殺を利用したものと、paddingを使ってレイアウトを組んだものの比較です。 それに対して、marginの相殺を利用すると、HTML, CSSともに、短く書くことができます。
上記のサンプルは、相殺をうまく利用した例です。 ブラウザのデフォルトスタイルシートは、marginと関連があります。 相殺を計算されたうえで、上下にmarginの指定されています。 デフォルトスタイルシートを生かすように構築する場合は、相殺の考え方が大切になります。ボックスモデル
CSSを適用する場合、以下の図を理解する必要があります。marginの種類
margin-(start|end|before|after) は回転方式のブロックに対して、提案されたものです。
margin-startは、論理的な方向になります。
縦書きになった場合は、margin-startは、margin-topが適用されることになります。margin と auto と width の関係
しかし、横幅(width)を指定した状態で、marginの左右のどちらかにautoを指定すると、指定した方に数値を算出します。div {
with:100px;
margin-left:auto;
}
marginの中央配置
左右等分のmarginが算出され、ボックスは中央に配置されます。Negative Margin(ネガティブ・マージン)
marginの数値をマイナス指定することによって、要素を移動や、要素を配置します。
パターンから外れたレイアウトを組む際に、お世話になることが多いです。<style>
/* css reset */
ul {
margin:0;
padding:0;
list-style:none;
}
/* demo */
#list {
margin:0 auto;
border:1px solid #000;
padding:8px 8px 0;
width:488px;
}
ul {
margin-right:-8px; /* ここでネガティブマージンを指定 */
/* width:496px; 追記:IE6,7を無視するならいらない */
overflow:hidden;
}
li {
float:left;
margin:0 8px 8px 0;
width:116px;
height:116px;
background-color:#bbb;
}
</style>
<div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
ただし上記ソースの1つ1つの意味が、理解できていないうちは、多用すべきではありません。margin と padding
<style type="text/css">
.margin {
margin-bottom:10px;
}
.padding {
padding-bottom:10px;
}
</style>
<div class="margin">aa</div>
<div class="margin">bb</div>
<div class="padding">aa</div>
<div class="padding">bb</div>
見た目は同じに見えますが、挙動は全く違います。
marginは要素ごとで間隔をあけることができます。marginの相殺
相殺はmargin同士が重なった場合に起こり、「marginが使いづらい」という印象を与える最大の理由かもしれません。
特定のケースだと、相殺が起きないなどトリッキーな動きをします。
トリッキーすぎて、初学者に「バグじゃないの?」と思われることも、しばしばです。<style type="text/css">
.margin {
margin:10px 0; /* 上下に1emを指定 */
}
.padding {
padding:10px 0; /* 上下に1emを指定 */
}
</style>
<div class="margin">aa</div>
<div class="margin">bb</div>
<div class="padding">aa</div>
<div class="padding">bb</div>
marginは相殺によってdivの間が、10pxしかあきません。
ただしBさんのAさんのことを、それほど想っておらず、心の距離は3だとします。
Aさんは心が縮まっていると思っていても、AさんとBさんの心の距離を客観的に見ると、実際の心の距離は3となります。marginの相殺の数値
<style type="text/css">
.a {
margin:20px 0;
}
.b {
margin:30px 0;
}
</style>
<div class="a">a</div>
<div class="b">b</div>
入れ子での相殺
<style type="text/css">
.parent{
margin:10px 0;
}
.child {
margin:30px 0;
}
</style>
<div class="parent">
<div class="child">child</div>
</div>
<style type="text/css">
.parent {
margin:30px 0;
}
.child {
margin:10px 0 40px;
}
</style>
<div class="parent">
<div class="child">demo</div>
</div>
しかしmargin-bottomは、.childの方が値が大きいので40pxが適用されることになります。
相殺が起こった場合は、大きい方の値が優先されることを覚えておいて下さい。相殺が起こらないケース
margin と float の関係
floatを使いこなすためにも、marginの理解は必須です。marginのかかっている要素に、floatを指定した場合
ただしfloatが指定されると、marginのautoは、必ず数値が0になります。<style>
div {
margin:10px auto;
width:300px;
float:left;
}
.child {
margin:10px;
width:100px;
height:100px;
float:left;
}
</style>
<div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
marginのかかっている要素に、floatが隣接している場合
ただfloatが隣接しているだけなら、marginとfloatで相殺が発生します。
以下はその基本的な条件です。
様々な影響により、相殺が発生する場合としない場合があるので割愛します。<style>
img {
float:left;
margin:0 10px;
}
.test {
margin-top:96px;
}
</style>
<img src="dummy.jpg" alt="" width="80" height="80" />
<img src="dummy.jpg" alt="" width="80" height="80" />
<img src="dummy.jpg" alt="" width="80" height="80" />
<div class="test">floatとmarginの相殺</div>
そしてこの相殺は、floatを解除するclearプロパティにも関係してきます。clearは、floatを解除するものではない
その挙動は、先ほどのサンプルによく似ています。
'clear'プロパティの仕様
clear:none;の場合は、通常通りに振舞います。<style>
img {
float:left;
}
.right {
float:right;
width:80px;
height:240px;
margin-bottom:10px;
}
.clear {
margin-top:3000px;
clear:left;
}
.clear-right {
margin-top:-1000px;
clear:right;
}
</style>
<img src="dummy.jpg" alt="" width="80" height="80" />
<img src="dummy.jpg" alt="" width="80" height="80" />
<img src="dummy.jpg" alt="" width="80" height="80" />
<div class="right"></div>
<div class="clear">clear:left;</div>
<div class="clear-right">clear:right;</div>
これはclearによる仕様です。
clear:left;を指定したことによって、margin-topが自動調整されて、float:left;の指定された要素の後ろにつきます。
この場合、.rightの上辺から底辺までのmargin-topを調整している訳ではありません。
.clearから.rightの底辺までの距離で、margin-topを調整しています。相殺の利点
相殺など利用することにより、クリーンなソースコードが書ける場合も多くあります。
レイアウトをmarginで書いたものと、paddingで書いたものを比較します。<style type="text/css">
dl {
margin:3em 0;
}
dt {
display:inline;
float:left;
}
dd {
margin:1em 0 3em 120px;
}
p {
margin:1em 0;
}
</style>
<style type="text/css">
/* CSSリセット */
dl, dd, p {
margin:0;
}
paddingを使用すると、最後の要素は、padding-bottom:0; を指定したり、classを細かく割り振ったりします。
.mt10, .mt20などのクラスを用意している人は、paddingのような指定を行っていることが多いです。
さらに適切に間隔を保つことができるので、特にCSSを指定していないimg要素がイレギュラーに入ったとしても、ある程度は容易に対処することができます。
デザインによっては、親にborderやpaddingなどを入ることにより、相殺が使えない場合もあります。
しかし、相殺を理解していることで、HTMLやCSSの書く効率が変わってきます。ブラウザのデフォルトスタイルシート
h1やpなどの要素には、ブラウザで、あらかじめCSSがついています。h1 {
margin:0.67em 0;
font-size:2em
}
p {
margin:1em 0;
}
このスタイルシートによって、"文章"を適切にマークアップすれば、適度な間隔を保つようになっています。
marginの仕様とバグは、度々一緒にされることがあります。
marginは、奥深く、経験もある程度必要になります。
marginのバグも回避策は多くあるので、マスターすればCSSの構築に役立ってくれるプロパティになるはずです。