人の失敗に敏感な、ユゲタです。
とある、WEBサイトで使えるツールを開発していた時に、何故だかわからないが、ページ内の上部の方で、なんだかズレが生じていることに気が付きました。
どうやら、とあるエレメントのmargin(margin-top) の値分ズレているという事まで分かったんですが、
これってcssのmarginのバグというか、失敗というか、仕様とは言い切れないmarginの特性のようなものらしく、
上位階層(設定していあるエレメント以外)への影響について調査してみることにしました。
調査事始め
とりあえず、サンプルとして次のようなHTML構成を作ってみました。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="a">
<p>TEST</p>
</div>
</body>
</html>
<style>
body{
background-color:#eee;
}
.a{
background-color:rgb(255,128,128);
}
p{
border : 1px solid black;
margin : 50px;
}
</style>
これをブラウザで表宇すると・・・
こんな風に表示されますが、少し解説すると、div.aの中に表示されているpなんですが、pにmargin:50px;がセットされているので、
本来であれば、このように表示されてほしいんですが、縦軸のmarginが、親要素に吸い取られているように見えます。
marginの妙
これは、marginがついたオブジェクトを縦並びに並べても同じ原因で、想定通りにならないということ同じ現象で、
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>aaa</p>
<p>bbb</p>
<p>ccc</p>
</body>
</html>
<style>
body{
background-color:#eee;
}
p{
border : 1px solid black;
margin : 50px;
}
</style>
このサンプルソースを表示すると、
こーなります。
この事象を知っている人は、回避法なども心得ていると思いますが、初心者はまあまあハマりんぐな、事象であることは間違いないでしょう。
簡単に説明すると、
margin-topとmargin-bottomは、その前後にくるエレメントで相殺する
というcssの不思議な特性が影響しているようです。
でも、本来はこういった動きにはなってはいけないんですが、どのブラウザでも、同じ挙動になります。
もはや、ブラウザの仕様としてあきらめるとして、どうやったら、これを回避できるのかと言うと、それを次にまとめてみました。
回避法
1. 親要素にborderをセットする
親要素にborder(border-width)が0以外の値でセットされていると、きちんと、innerにmarginがセットされます。
.a{
border:1px solid transparent;
background-color:rgb(255,128,128);
}
色をtransparentにすると、透明色でわからないようにセットできます。
2. 親要素にpaddingをセットする
borderでなくて、paddingでもイケるようです。
.a{
padding:0.1px;
background-color:rgb(255,128,128);
}
それも、0.1pxのような、目で見てわからない値にセットすることで、誤差として値を埋め込むことでも、marginが正常に表示されます。
3. position:absolute または、fixedをセットする
position:absolute;内においては、marginは相殺されずに正常に表示されます。
.a{
position:absolute;
background-color:rgb(255,128,128);
}
どちらも、独立エレメントとして、確率されるからでしょうね。
でも、サイズ指定などをしないといけないので、少し不便かも
4. overflow:hiddenをセットする。
多くのサイトで書かれている対応方法がコレで、親要素に、overflow:hidden;をセットするだけなのだそうです。
.a{
overflow:hidden;
background-color:rgb(255,128,128);
}
overflow:visibleでは、相殺モードになってしまうので、hiddenにするのがポイントのようですが、bodyなどにはセットしてしまうと、スクロールができなくなったりもするので、
使用場所によって、上記のどれかを選択して行う必要があるようです。
ベストプラクティス
とりあえず、ボクの行き着いた結論として、こうしたmarginを周辺に影響させないようにするには、marginを受け止めてくれる親要素を1階層増やしておいて、
overflow:hiddenをセットしておくのが、難も考えずに不具合が起きにくいのではないかと考えた。
とにかくHTMLのネストが深くなってしまうのは、いただいかたが無いのかもしれない・・・
0 件のコメント:
コメントを投稿