自分のメモも含めて、最近よく見かけるナビゲーションのホバーエフェクトをまとめてみました。
cssのみで記述されたシンプルなものになります。
scssでも実装してみましたが、今回は初心者の方向けにCSSで記述したもので解説していきます!
#共通HTML・CSS
##HTML
<nav class="type1">
<ul class="type1-menu">
<li><a href="#">HOME</a></li>
<li><a href="#">ABOUT</a></li>
<li><a href="#">WORKS</a></li>
<li><a href="#">CONTACT</a></li>
</ul>
</nav>
通常のナビゲーションをマークアップします。
##CSSをいじる前に…
リセットCSSを設置!
Chrome・IEなどのブラウザによってデフォルトでCSSを持っているので、全てフラットになるようReset CSSを設定します。
公式ページからコピペするか、headタグ内に下記(cdn)を追加してください。
https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.css
別のリセットcssを使用してる場合はお手数ですが、調整をお願いします。
##CSS
nav ul {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
}
nav ul li {
margin-right: 1rem;
}
nav ul li a {
display: block;
padding: 10px;
color: #000000;
text-decoration: none;
}
横並びしたいリストの親要素にdisplay: flex;を付与します。
#type1 - 下からにゅっと出てくるエフェクト
##CSS
.type1 .type1-menu a {
position: relative;
}
.type1 .type1-menu a::after {
position: absolute;
left: 0;
bottom: 0;
display: block;
content: "";
width: 0%;
height: 2px;
background: #000;
transition: all 0.2s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.type1 .type1-menu a:hover::after {
width: 100%;
}
hoverしたときに現れるラインは疑似要素のafterでスタイリングします。:hoverとごちゃごちゃにならないようコロンは2つで記述してます。(コロン1つでもOKです!)
hover前はラインのwidthを0%、hover後はwidthを100%に変更するだけですね!
##CSS
.type2 .type2-menu a {
position: relative;
border-bottom: 2px solid #b2b2b2;
}
.type2 .type2-menu a::after {
position: absolute;
bottom: -2px;
left: 0;
display: block;
content: "";
width: 100%;
height: 2px;
background: #000000;
transform: scaleX(0);
transform-origin: right top;
transition: transform 0.3s;
}
.type2 .type2-menu a:hover::after {
transform: scaleX(1);
transform-origin: left top;
}
通常時の下のラインはaタグにborder-bottomを付与します。
こちらもtype1と同じよう、hoverしたとき疑似要素::afterにスタイリングします。
ポイントとなるのは**transform: scaleX(数値);とtransform-origin;**です。
**transform: scaleX(数値);**でラインを拡大縮小で表示させるのですが、これだけだとラインのセンターからの拡大縮小になります。↓↓
そこで、transform-originで要素の原点を決めてあげます!
hoverしたとき左からラインが流れてほしいので「.type2 .type2-menu a:hover::after」にtransform-origin: left top;、
hoverを外した時にラインが右に流れてほしいので「.type2 .type2-menu a::after」にtransform-origin: right top;を指定します。
また、CSSアニメーションのtransitionにはtransformだけ指定します。
transition: all 0.3s;と記述すると動きがおかしくなります。(実際に私ははしょらせておかしくなりました...泣)
##CSS
.type3 .type3-menu a {
position: relative;
}
.type3 .type3-menu a::after {
position: absolute;
left: 0;
top: 50%;
bottom: 50%;
transform: translate(0, -50%);
display: block;
content: "";
width: 0%;
height: 2px;
background: #000000;
transition: all 0.2s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.type3 .type3-menu a:hover::after {
width: 100%;
}
type1のラインの位置を変えただけです!
上下中央になるよう疑似要素::afterに下記のプロパティを追加しました。
top: 50%;
bottom: 50%;
transform: translate(0, -50%);
##HTML
共通HTMLに少々変更が入ります。
<nav class="type4">
<h2>type4</h2>
<ul class="type4-menu">
<li>
<a href="#">
<span class="en">HOME</span>
<span class="ja">ホーム</span>
</a>
</li>
<li>
<a href="#">
<span class="en">ABOUT</span>
<span class="ja">ページについて</span>
</a>
</li>
<li>
<a href="#">
<span class="en">WORKS</span>
<span class="ja">作品</span>
</a>
</li>
<li>
<a href="#">
<span class="en">CONTACT</span>
<span class="ja">お問合わせ</span>
</a>
</li>
</ul>
</nav>
英語と日本語を表示させたいので、aタグの中にそれぞれspanタグを設置します。
##CSS
.type4 .type4-menu a {
position: relative;
text-align: center;
overflow: hidden;
padding: 10px 22px; //メニューに入るテキスト量によってpaddingは変更してください
}
.type4 .type4-menu a::after {
position: absolute;
bottom: 0;
left: 0;
display: block;
content: "";
width: 0%;
height: 2px;
background: #F05152;
transition: all 0.2s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.type4 .type4-menu a span {
display: block;
width: 100%;
margin: 0 auto;
transition: all 0.2s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.type4 .type4-menu a span.ja {
position: absolute;
top: 100%;
left: 0%;
font-size: 14px;
font-weight: bold;
white-space: nowrap;
color: #F05152;
}
.type4 .type4-menu a:hover::after {
width: 100%;
}
.type4 .type4-menu a:hover span.en {
transform: translate(0%, -150%);
}
.type4 .type4-menu a:hover span.ja {
top: 25%;
}
下からラインが現れるのはtype1の流用ですね!色だけ変更してます。
「span.ja」は通常時見えないようtop: 100%;で下にずらします。
親要素である「.type4 .type4-menu a」にoverflow: hidden;を付与してるのでその領域外からはみ出た「span.ja」は見えなくなってると思います。
hoverさせたとき、英語表記の「span.en」はtransform: translate(0% -150%);で上にずらし、日本語表記の「span.ja」はtopの値を変更します。
##CSS
.type5 .type5-menu li {
position: relative;
overflow: hidden;
}
.type5 .type5-menu li::before,
.type5 .type5-menu li::after {
position: absolute;
display: block;
content: "";
width: 100%;
height: 1px;
background: #000000;
transition: all 0.2s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.type5 .type5-menu li::before {
top: 0;
left: -100%;
}
.type5 .type5-menu li::after {
bottom: 0;
right: -100%;
}
.type5 .type5-menu li a::before,
.type5 .type5-menu li a::after {
position: absolute;
display: block;
content: "";
width: 1px;
height: 100%;
background: #000000;
transition: all 0.2s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.type5 .type5-menu li a::before {
top: 100%;
left: 0;
}
.type5 .type5-menu li a::after {
top: -100%;
right: 0;
}
.type5 .type5-menu li:hover::before {
left: 0;
}
.type5 .type5-menu li:hover::after {
right: 0;
}
.type5 .type5-menu li a:hover::before {
top: 0;
}
.type5 .type5-menu li a:hover::after {
top: 0;
}
ラインそれぞれにスタイルをつけるので記述がやや長くなります。
liとaに疑似要素::beforeと::afterをつけてます。
.type5 .type5-menu li::before → 上線
.type5 .type5-menu li::after → 下線
.type5 .type5-menu li a::before → 左線
.type5 .type5-menu li a::after → 右線
こちらもpositionでそれぞれのラインの位置をずらしておきます。
type4と同じよう親要素の「.type5 .type5-menu li」にoverflow: hidden;を付与して、はみ出た部分は見えないようにします。
hoverしたときはラインが見える位置にtopやrightの数値をいじって戻す感じですね!
##CSS
.type6 .type6-menu li {
position: relative;
overflow: hidden;
}
.type6 .type6-menu li::before,
.type6 .type6-menu li::after {
position: absolute;
display: block;
content: "";
width: 100%;
height: 1px;
background: #000000;
transition: all 0.2s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.type6 .type6-menu li::before {
top: 0;
left: -100%;
}
.type6 .type6-menu li::after {
bottom: 0;
right: -100%
}
.type6 .type6-menu li a::before,
.type6 .type6-menu li a::after {
position: absolute;
display: block;
content: "";
width: 1px;
height: 100%;
background: #000000;
transition: all 0.2s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.type6 .type6-menu li a::before {
top: 100%;
left: 0;
}
.type6 .type6-menu li a::after {
top: -100%;
right: 0;
}
.type6 .type6-menu li:hover::before {
animation: topline 0.1s linear forwards;
}
@keyframes topline {
0% {
left: -100%;
}
100% {
left: 0;
}
}
.type6 .type6-menu li:hover::after {
animation: btmline 0.1s linear forwards 0.2s;
}
@keyframes btmline {
0% {
right: -100%
}
100% {
right: 0;
}
}
.type6 .type6-menu li:hover a::before {
animation: leftline 0.1s linear forwards 0.3s;
}
@keyframes leftline {
0% {
top: 100%;
}
100% {
top: 0;
}
}
.type6 .type6-menu li:hover a::after {
animation: rightline 0.1s linear forwards 0.1s;
}
@keyframes rightline {
0% {
top: -100%;
}
100% {
top: 0;
}
}
ほぼtype5と同じです。アニメーションの手法が違うだけです。
リンクをなぞるようにラインを動かすのですがkeyframesを使い、順番に表示させます。
下記は右線の「.type6 .type6-menu li:hover a::after」をhoverしたときの記述です。
ポイントはdelayになります。
それぞれのラインを0.1sごとに表示させたいのでdelay値は以下になります。
.type6 .type6-menu li::before(上線) → delayさせる必要がないので指定なし
.type6 .type6-menu li::after(下線) → 0.2s
.type6 .type6-menu li a::before(左線) → 0.3s
.type6 .type6-menu li a::after(右線) → 0.1s
#まとめ
デザインの制作はできたけど、hoverしたときの挙動をどうしよう。。となったときに参考にしてみてください。
ものによってはボタンにも適応できます👌
最後まで読んでいただきありがとうございました!