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

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

css：[DEMO](https://codepen.io/nitta_shiori/pen/NYqOeB)
scss：[DEMO](https://codepen.io/nitta_shiori/pen/aqeGLO)

cssのみで記述されたシンプルなものになります。
scssでも実装してみましたが、今回は初心者の方向けにCSSで記述したもので解説していきます！

#共通HTML・CSS
##HTML

```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](https://meyerweb.com/eric/tools/css/reset/)を設定します。
公式ページからコピペするか、headタグ内に下記（cdn）を追加してください。
https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.css

別のリセット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](https://qiita-image-store.s3.amazonaws.com/0/215853/a5268d7d-cebb-172c-b333-ea1450b9d42b.gif
)
##CSS
```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](https://qiita-image-store.s3.amazonaws.com/0/215853/0d47c727-797e-ab6a-7d71-2a10d006095f.gif)

##CSS

```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](https://qiita-image-store.s3.amazonaws.com/0/215853/93855d93-4f26-be5d-f68e-619f5d405e80.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](https://qiita-image-store.s3.amazonaws.com/0/215853/a4e4f34c-3840-d8ab-7c5c-7130e92ffc47.gif)

##CSS

```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](https://qiita-image-store.s3.amazonaws.com/0/215853/7564223a-b993-1313-20af-96b52227088b.gif)

##HTML

共通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

```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](https://qiita-image-store.s3.amazonaws.com/0/215853/a49fc1c8-b5bd-ce22-04a9-6f9295b490a5.gif)

##CSS

```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](https://qiita-image-store.s3.amazonaws.com/0/215853/04ca18e2-8cca-08a9-4dd0-83c63557b41a.gif)

##CSS

```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](https://qiita-image-store.s3.amazonaws.com/0/215853/8aa4846c-c3cd-852a-0155-38bb3f58a786.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](https://codepen.io/nitta_shiori/pen/NYqOeB)
scss：[DEMO](https://codepen.io/nitta_shiori/pen/aqeGLO)