CSS
scss
初心者

[簡単]コピペするだけ!ナビゲーションホバーエフェクト

自分のメモも含めて、最近よく見かけるナビゲーションのホバーエフェクトをまとめてみました。

css:DEMO
scss:DEMO

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 - 下からにゅっと出てくるエフェクト

type1.gif

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%に変更するだけですね!

type2 - ラインが左から右に駆け抜けるエフェクト

type2.gif

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(数値);でラインを拡大縮小で表示させるのですが、これだけだとラインのセンターからの拡大縮小になります。↓↓
sample.gif

そこで、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;と記述すると動きがおかしくなります。(実際に私ははしょらせておかしくなりました...泣)

type3 - 取り消し線エフェクト

type3.gif

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%);

type4 - ホバー時に日本語表記になるエフェクト

type4.gif

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の値を変更します。

type5 - ラインで四方を囲うエフェクト

type5.gif

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の数値をいじって戻す感じですね!

type6 - ラインでなぞるようなエフェクト

type6.gif

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したときの記述です。

562572cba4ded3567703bac920e2f564.png

ポイントは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したときの挙動をどうしよう。。となったときに参考にしてみてください。
ものによってはボタンにも適応できます👌
最後まで読んでいただきありがとうございました!

css:DEMO
scss:DEMO