要素の上の方をホバーするとコンテンツAが表示、右の方をホバーするとコンテンツBが表示といったように、特定の要素をホバーした際にその位置によって異なるコンテンツを表示させる動きをCSSで実装したものです。
実際の動きを見た方が早いと思うのでいきなりデモを紹介すると、要素がひとつ配置されていてホバーしたら何か変化をつけたい場合、よくあるのは異なる1パターン分の見栄えを用意して表示させるというものですが、以下デモの場合はこの要素に上下左右それぞれ異なる位置でホバーすると、その位置によって異なるコンテンツが表示されるようになっています。
こういった動きを実装する際はJavaScriptを利用するということが多いですが、今回はこれをCSSのみで実装してみたものになります。
まずHTMLは下記のようなものを使用し、.box-default
内はホバー前のデフォルト表示用のコンテンツを記述しておきます。
.box-top-contents
や.box-right-contents
などclass名の末尾に「contents」が付いているものについては、例えば要素の上の方でホバーした場合に出したいコンテンツは.box-top-contents
内に記述するといったように、それぞれ特定の位置でホバーした際に表示させたいコンテンツを記述します。
.box-top-position
や.box-right-position
などclass名の末尾に「position」が付いているものについては、ホバー位置を判断するために使用する要素になるので中身は空にしておきます。
<div class="box">
<div class="box-default">default</div>
<div class="box-top-position"></div>
<div class="box-top-contents">top</div>
<div class="box-right-position"></div>
<div class="box-right-contents">right</div>
<div class="box-bottom-position"></div>
<div class="box-bottom-contents">bottom</div>
<div class="box-left-position"></div>
<div class="box-left-contents">left</div>
</div>
CSSはデモ用の装飾に関する部分を省いた最低限必要なコードのみ紹介すると下記のように記述します。
デモと全く同じ見栄えにしたい場合は、上にあるCodePenで使用しているコードを利用してください。
.box {
position: relative;
overflow: hidden;
}
.box-default {
width: 300px;
height: 300px;
}
[class$="-contents"] {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
opacity: 0;
visibility: hidden;
}
[class$="-position"] {
position: absolute;
z-index: 3;
width: 70.7%;
height: 70.7%;
transform: rotate(45deg);
}
.box-top-position {
top: 0;
right: 0;
transform-origin: 100% 0;
}
.box-right-position {
right: 0;
bottom: 0;
transform-origin: 100% 100%;
}
.box-bottom-position {
bottom: 0;
left: 0;
transform-origin: 0 100%;
}
.box-left-position {
top: 0;
left: 0;
transform-origin: 0 0;
}
[class$="-contents"]:hover,
[class$="-position"]:hover + [class$="-contents"] {
z-index: 4;
opacity: 1;
visibility: visible;
}
ざっくりとどのような形で実装しているかを説明すると、まず特定の位置でホバーした際に表示させるコンテンツ(.box-top-contents
や.box-right-contents
など)をそれぞれposition: absolute;
で配置しつつ、初期表示では非表示のコンテンツとしたいのでopacity: 0;
とvisibility: hidden;
も併せて指定しておきます。
各コンテンツの装飾などに関するスタイルについては、デフォルト時のものを含め下記のような形でそれぞれ設定し、その際に上のサンプルコードにもあったように.box-default
に対して任意の幅と高さを設定(サンプルコードはいずれも300px
に設定)します。
幅と高さを設定は他の指定方法でももちろん可能なので、使用箇所に応じて変更してください。
.box-default {
/* default contents style */
}
.box-top-contents {
/* top contents style */
}
.box-right-contents {
/* right contents style */
}
.box-bottom-contents {
/* bottom contents style */
}
.box-left-contents {
/* left contents style */
}
次にホバー位置を判断するために使用する要素である.box-top-position
や.box-right-position
などを共通スタイルとして同じくposition: absolute;
を使用して配置しますが、その際にz-index
の値を先ほどのコンテンツよりも高い状態にしつつ、transform: rotate(45deg);
で回転させた状態にしておきます。
また、幅と高さを設定(サンプルコードはいずれも70.7%
に設定)しますが、この値は.box-default
で指定した要素のサイズによって適切なものに変更してください。
上記共通スタイルを指定したら、次に下記のような形でそれぞれ異なる位置指定とtransform-origin
を設定していき、ここまで記述した時点で.box-default
上の上下左右にそれぞれ三角形の要素が表示されているような状態になると思います。
ちゃんと配置されているかどうかはデベロッパーツールなどで確認するか、各要素に一時的に背景色などを付けてあげると確認しやすいです。
.box-top-position {
top: 0;
right: 0;
transform-origin: 100% 0;
}
.box-right-position {
right: 0;
bottom: 0;
transform-origin: 100% 100%;
}
.box-bottom-position {
bottom: 0;
left: 0;
transform-origin: 0 100%;
}
.box-left-position {
top: 0;
left: 0;
transform-origin: 0 0;
}
あとは、それぞれホバー位置を判断するための要素(class名の末尾に「position」が付いているもの)にホバーしたら特定の要素が表示されるように設定すれば完成になります。
今回のサンプルの場合は表示・非表示についてはopacity
とvisibility
を切り替える形にしており、さらにホバー時に表示させる要素の選択については隣接セレクタを利用しています。
また、非表示になっていたコンテンツ(class名の末尾に「contents」が付いているもの)はホバー後に表示されたままにしたいのでこの要素にもホバー設定をし、その際にz-index
が一番上になるようにも併せて指定をします。
[class$="-contents"]:hover,
[class$="-position"]:hover + [class$="-contents"] {
z-index: 4;
opacity: 1;
visibility: visible;
}
今回はサンプルなので動きも簡易的なものですしHTMLがごちゃつく感じもありはしますが、このような動きをCSSのみで実装することができ、使い方次第で面白い見せ方も実装することができそうです。
今回は表示・非表示を単純に切り替えるだけでしたが、例えばtransform
を利用して横からスライドさせるとか拡大しながら表示させるなどの見せ方もCSSを少し記述を追加するだけで実装できると思います。