positionプロパティから逃げない(Tipsあり)
一昔前までのマークアップは、「float」が使いこなせるかどうかが一つの大きな壁だった印象ですが、現在では「position」を使いこなせるかどうかでコーダーの技量を測れるように思います。
長くマークアップをしているコーダーさんでも、以外と「なあなあ」で使っている方もいらっしゃいますので、改めて「覚えておくと今後楽になるかもしれない」点を幾つか挙げさせていただきます。
positionプロパティとは
positionプロパティをざっくり言うと「要素をどのように配置するか」を表すプロパティで、下記5つの値が設定可能です。
potision: static
positionを指定しない「通常の状態」
position: absolute
親要素を無視して絶対座標で配置
position: relative
元々ある位置から相対的に配置
positoin: fixed
常にブラウザ上の同じ位置に配置
position: sticky
画面上の一定の位置にスクロールされるとfixed的にふるまう
詳しく解説しようとするとスタッキングコンテキストなどのややこしい問題に触れることになってしまいますので、ここではTips的に「よくある勘違い」や「こう使うと使いやすい」といったポイントを挙げていきます。
position: staticにはz-indexが効かない
slickやbxslider等のカルーセルライブラリを使用していると、スライダーの部分には「z-index: 1000」などと「絶対に一番上に表示したい」という固い意志を感じる値が設定されています。
position: staticの要素(positionを設定していない要素)を「z-index: 1000」よりも上に表示しようと「z-index: 10000」を設定したとしても、position: staticの要素はz-indexが効かない2次元に生きている要素ですので、3次元の世界を認識させるためにはstatic以外の値を設定する必要があります。
absoluteやfixedでは意図しない場所に移動してしまいますので、position: relativeを設定すると解決します。
positon: staticな要素にz-indexを指定したくなったら、「position: relative」を設定する。
relativeであればtop、right、left、bottomを指定しなければ見た目上の位置は変わらない。
position: absoluteで”親要素”を基準の位置として使用する
クイックリファレンス等ではあまり触れられないことですが、下記のように「ブラウザの左上に表示させる」ことを意図した場合でも、
.myclass {
position: absolute;
top: 0;
left: 0;
}
<div style="position: relative">
<div class="myclass">text</div>
</div>
のように親クラスに「static」以外のpositionプロパティが設定されていた場合は、「親要素の上から0px、左から0px」に配置されます。
意外と知らない方が稀にいらっしゃいますので、この後上げるTipsの基礎知識として。
position: absoluteをイメージマップの代わりに使用する
「イラスト上の任意の場所をクリックしたら別ページに遷移したい」というケースは、少し凝ったデザインの案件であればそれほど珍しくありません。
昔ながらのHTMLであれば、イメージマップを使用していましたが、ピクセル指定しかできない上にメディアクエリを使うことということもできませんので、モバイルが当たり前の時代にはそぐわない仕様になっています。
そんな時、position: absoluteを使用してイメージマップ代わりに使用します。
下記のような画像があったとして、「青色のところをクリックできるように」したいと思った場合は、
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.inner {
margin: 0 auto;
width: 1100px;
padding: 60px 0;
}
.content {
margin: 0 auto;
width: 800px;
height: 419px;
position: relative;
background-image: url(./map-bg.png);
background-repeat: no-repeat;
}
.content a {
width: 150px;
height: 150px;
display: block;
position: absolute;
}
.content a:hover {
background-color: rgba(255, 255, 255, 0.2);
}
.content a:nth-child(1){ top: 30px; left: 30px; }
.content a:nth-child(2){ top: 135px; left: 325px; }
.content a:nth-child(3){ bottom: 30px; right: 30px; }
</style>
</head>
<body>
<div class="wrap">
<div class="inner">
<div class="content">
<a href="#1"></a>
<a href="#2"></a>
<a href="#3"></a>
</div>
</div>
</div>
</body>
</html>
のように、position: relativeを設定した親要素の子要素として、position: absoluteを設定したaタグを配置してあげれま実現できます。
この方法のメリットとしては、
・%指定もできるので、レスポンシブ対応可能
・CSSで一を指定するので、メディアクエリを使用可能
と、イメージマップよりも圧倒的に使い勝手が良いのでお勧めです。
position: absoluteで親要素の中央に配置する
position: absoluteを指定した場合のtop、right、left、bottomはパーセント指定することが可能です。このパーセント指定を利用して
のような配置をしようと下記のように記述しても、
.content {
background-color: chartreuse;
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
}
「top, leftは要素の左上の座標」と認識されるので「親要素の中心」と「子要素の中心」は一致せず、下記のようにズレが発生します。
そんなときは、下記のように「transformプロパティ」で中央に移動することが可能です。
.content {
background-color: chartreuse;
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
補足すると、transform: translate()をパーセント指定する場合、「100% = 要素の幅(高さ)」になるので、要素のサイズ半分だけマイナス方向にずらしてあげればOKということです。
ふわっとフェードインするアニメーションをtransformを利用して実装しているなどのケースで「transformを別のことに使用しているので使いにくい」という場合は、
.content {
background-color: chartreuse;
width: 100px;
height: 100px;
position: absolute;
top: calc(50% - 50px);
left: calc(50% - 50px);
transform: translate(-50%, -50%);
}
のように子要素のサイズの半分だけcalc()を使ってずらしてあげることでも実現可能ですが、「子要素のサイズが分かる」ことが前提になりますので、特に理由がなければtransformを使用したパターンをお勧めします。
終わりに
知っている人からすると当たり前のことしか書いてないかもしれませんが、クイックリファレンス的なものでCSSを覚えた方などは「絶対配置とか何に使うの…?」という感じでしょうし、今さらなのか触れられている情報が多くない印象でしたのでまとめてみました。
何か思いつけば追記するかもしれません。