【HTMLとCSSのみ】実務でよく使いそうなボタンホバーアニメーションについてまとめてみる(備忘録)
今回は、ボタンリンクのホバーアニメーションについて、いろんなWebデザインギャラリーを見て、使われているもの中心に紹介していければと思います。
独断と偏見で選んでいること、実装方法も正攻法とは限りませんので、予めご了承ください。
なお、Webデザインギャラリーについては、定期的に見ていますので、そこで新しいボタンリンクのホバーアニメーションを発見しましたら、本記事に追加していければと考えています。
それでは実装に入っていきます。
HTMLの記述について
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="index, follow" />
<title>CSSのみでよく使いそうなボタンホバーアニメーション(備忘録)</title>
<link rel="stylesheet" href="../reset.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<section>
<div class="ly_inner">
<h2>枠線から塗りつぶしに</h2>
<div class="md_textblock">
<p><a href="" class="el_btn01">ボタンテキスト</a></p>
</div>
</div>
<div class="ly_inner">
<h2>影がつく</h2>
<div class="md_textblock">
<p><a href="" class="el_btn02">ボタンテキスト</a></p>
</div>
</div>
<div class="ly_inner">
<h2>丸い装飾が横線に</h2>
<div class="md_textblock">
<p><a href="" class="el_btn03">ボタンテキスト</a></p>
</div>
</div>
<div class="ly_inner">
<h2>点線の円が回転している</h2>
<div class="md_textblock">
<p><a href="" class="el_btn04">ボタンテキスト</a></p>
</div>
</div>
<div class="ly_inner">
<h2>矢印の装飾がスライド</h2>
<div class="md_textblock">
<p><a href="" class="el_btn05">ボタンテキスト<span class="arrow01"></span></a></p>
</div>
</div>
<div class="ly_inner">
<h2>円の周りに薄い円がひろがる</h2>
<div class="md_textblock">
<p><a href="" class="el_btn06">ボタン</a></p>
</div>
</div>
<div class="ly_inner">
<h2>アイコンとテキストが同時に色変更</h2>
<div class="md_textblock">
<p><a href="" class="el_btn07">ボタンテキスト</a></p>
</div>
</div>
<div class="ly_inner">
<h2>テキストが上部にスライドしつつ色変更</h2>
<div class="md_textblock">
<p><a href="" class="el_btn08">
<span>
<span>ボタンテキスト</span>
<span>ボタンテキスト</span>
</span></a></p>
</div>
</div>
<div class="ly_inner">
<h2>横線が右へスライドして新たな横線が現れる</h2>
<div class="md_textblock">
<p><a href="" class="el_btn09">ボタンテキスト</a></p>
</div>
</div>
<div class="ly_inner">
<h2>下から丸い背景が覆われる</h2>
<div class="md_textblock">
<p><a href="" class="el_btn10"><span>ボタンテキスト</span></a></p>
</div>
</div>
<div class="ly_inner">
<h2>下から上へ背景と文字がスライドして現れる</h2>
<div class="md_textblock">
<p>
<a href="" class="el_btn11">
<span class="btn_textWrap">
<span class="btn_content">
<span class="btn_text">ボタンテキスト</span>
</span>
<span class="btn_content" aria-hidden="true" data-nosnippet="">
<span class="btn_text">ボタンテキスト</span>
</span>
</span>
</a>
</p>
</div>
</div>
<div class="ly_inner">
<h2>上下の線がくっつく</h2>
<div class="md_textblock">
<p><a href="" class="el_btn12">ボタンテキスト</a></p>
</div>
</div>
</section>
</main>
</body>
</html>
構造はシンプルですので、特に解説は省略させていただきます。
CSSの記述について
@charset "utf-8";
/* ==========================
初期設定
========================== */
*,
*::before,
*::after {
box-sizing: border-box;
}
img {
width: 100%;
}
/* ==========================
コンテンツの中身
========================== */
.ly_inner {
width: 100%;
max-width: 1080px;
margin: 40px auto;
padding: 20px;
background-color: #fff;
}
.ly_inner h2 {
font-size: 130%;
font-weight: bold;
margin-bottom: 30px;
}
.md_textblock > * + * {
margin-top: 10px;
}
/* ==========================
枠線から塗りつぶしに
========================== */
.el_btn01 {
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
border: 1px solid #222;
color: #222;
transition: background-color 0.4s cubic-bezier(0.19, 1, 0.22, 1),
border 0.4s cubic-bezier(0.19, 1, 0.22, 1),
color 0.4s cubic-bezier(0.19, 1, 0.22, 1);
}
.el_btn01:hover {
color: #fff;
background-color: #5e2525;
border: 1px solid #5e2525;
}
/* ==========================
影がつく
========================== */
.el_btn02 {
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
color: #fff;
background-color: #c78181;
transition: filter 0.4s cubic-bezier(0.19, 1, 0.22, 1),
-webkit-filter 0.4s cubic-bezier(0.19, 1, 0.22, 1);
}
.el_btn02:hover {
-webkit-filter: drop-shadow(0px 6px 13px rgba(0, 0, 0, 0.15));
filter: drop-shadow(0px 6px 13px rgba(0, 0, 0, 0.15));
}
/* ==========================
丸い装飾が横線に
========================== */
.el_btn03 {
position: relative;
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
color: #fff;
background-color: #5e2525;
transition: 0.4s ease-out;
}
.el_btn03::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
right: 32px;
margin: auto;
display: block;
width: 5px;
height: 5px;
background-color: #fff;
border-radius: 5px;
transition: 0.4s ease-out;
}
.el_btn03:hover {
background-color: #c78181;
}
.el_btn03:hover::after {
width: 16px;
height: 1px;
right: 24px;
}
/* ==========================
点線の円が回転している
========================== */
.el_btn04 {
position: relative;
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
color: #fff;
background-color: #c78181;
transition-duration: 0.5s;
transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
border: 2px solid #c78181;
}
.el_btn04::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
margin: auto;
right: 16px;
width: 30px;
height: 30px;
border-radius: 50%;
border-width: 1px;
border-style: dashed;
border-color: #fff;
-webkit-animation: rotateAnime 8s linear infinite;
animation: rotateAnime 8s linear infinite;
transition-duration: 0.5s;
transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
}
.el_btn04::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
margin: auto;
right: 25px;
width: 0;
height: 0;
border-style: solid;
border-width: 5px 0 5px 10px;
border-color: transparent transparent transparent #fff;
transition-duration: 0.5s;
transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
}
.el_btn04:hover {
border: 2px solid #222;
}
.el_btn04:hover::before {
width: 32px;
height: 32px;
}
@keyframes rotateAnime {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
/* ==========================
矢印の装飾がスライド
========================== */
.el_btn05 {
position: relative;
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
background-color: #5e2525;
color: #fff;
transition: 0.4s cubic-bezier(0.19, 1, 0.22, 1);
}
.el_btn05 .arrow01 {
overflow: hidden;
display: block;
position: absolute;
width: 10px;
height: 10px;
right: 24px;
top: 50%;
transform: translateY(-50%);
}
.el_btn05 .arrow01::before,
.el_btn05 .arrow01::after {
content: " ";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url(arrow01.svg) no-repeat;
}
.arrow01::after {
transform: translate(-100%, 100%);
transition-delay: 0s;
}
.el_btn05:hover .arrow01::after {
opacity: 1;
transform: translate(0, 0);
transition-duration: 0.7s;
transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
transition-delay: 0.2s;
}
.el_btn05:hover .arrow01::before {
transition-duration: 0.4s;
transition-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
transform: translate(100%, -100%);
}
/* ==========================
円の周りに薄い円がひろがる
========================== */
.el_btn06 {
margin-left: 40px;
position: relative;
display: grid;
place-content: center;
width: 120px;
height: 120px;
border-radius: 50%;
background-color: #5e2525;
color: #fff;
transition: 0.4s cubic-bezier(0.19, 1, 0.22, 1);
z-index: 1;
}
.el_btn06::after {
content: "";
display: block;
position: absolute;
background: #5e2525;
opacity: 0.07;
width: 120px;
height: 120px;
z-index: -1;
border-radius: 50%;
top: 50%;
right: 50%;
transform: translateX(50%) translateY(-50%);
transition-duration: 0.3s;
}
.el_btn06:hover::after {
transform: translateX(50%) translateY(-50%) scale(1.5);
}
/* ==========================
アイコンとテキストが同時に色変更
========================== */
.el_btn07 {
position: relative;
display: grid;
place-content: center;
padding-left: 32px;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
color: #fff;
background-color: #5e2525;
transition: 0.4s cubic-bezier(0.19, 1, 0.22, 1);
border: 1px solid #fff;
}
.el_btn07::before {
content: "";
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 56px;
width: 16px;
height: 14px;
background: url(mail01.svg) no-repeat;
transition: 0.4s cubic-bezier(0.19, 1, 0.22, 1);
}
.el_btn07:hover {
background-color: #fff;
color: #5e2525;
border: 1px solid #5e2525;
}
.el_btn07:hover::before {
background: url(mail01_hover.svg) no-repeat;
}
/* ==========================
テキストが上部にスライドしつつ色変更
========================== */
.el_btn08 {
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
background-color: #5e2525;
border: 1px solid #5e2525;
color: #fff;
transition: background-color 0.4s cubic-bezier(0.19, 1, 0.22, 1),
border 0.4s cubic-bezier(0.19, 1, 0.22, 1),
color 0.4s cubic-bezier(0.19, 1, 0.22, 1);
}
.el_btn08 > span {
display: flex;
flex-direction: column;
height: 1em;
line-height: 1;
position: relative;
overflow: hidden;
}
.el_btn08 > span > span {
transition: transform 0.5s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
}
.el_btn08:hover {
background-color: #fff;
border: 1px solid #5e2525;
color: #5e2525;
}
.el_btn08:hover > span > span {
transform: translateY(-1em);
}
/* ==========================
横線が右へスライドして新たな横線が現れる
========================== */
.el_btn09 {
position: relative;
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
color: #fff;
background-color: #c78181;
transition: 0.4s cubic-bezier(0.19, 1, 0.22, 1);
}
.el_btn09::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
right: 2rem;
margin: auto;
width: 1rem;
height: 2px;
background-color: #fff;
background-color: var(--btn-clr-main, #fff);
transition: all 0.4s ease-out;
transition: var(--transit-default, all 0.4s ease-out);
}
.el_btn09:hover {
color: #fff;
background-color: #5e2525;
}
.el_btn09:hover::after {
animation: arrowLine 0.8s cubic-bezier(0.5, -0.1, 0.5, 1) forwards;
}
@keyframes arrowLine {
0% {
transform: scale(1, 1);
transform-origin: 100% 0;
}
50% {
transform: scale(0, 1);
transform-origin: 100% 0;
}
50.1% {
transform: scale(0, 1);
transform-origin: 0 0;
}
100% {
transform: scale(1, 1);
transform-origin: 0 0;
}
}
/* ==========================
下から丸い背景が覆われる
========================== */
.el_btn10 {
position: relative;
overflow: hidden;
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
color: #fff;
background-color: #c78181;
}
.el_btn10::after {
content: "";
width: 240px;
height: 140px;
position: absolute;
left: 50%;
transform: translate(-50%);
bottom: -173px;
background-color: #5e2525;
border-radius: 50% 50% 0 0;
transition: 1s;
}
.el_btn10 span {
position: relative;
z-index: 1;
}
.el_btn10:hover::after {
width: 300px;
height: 300px;
}
/* ==========================
下から上へ背景と文字がスライドして現れる
========================== */
.el_btn11 {
position: relative;
overflow: hidden;
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 44px;
border-radius: 40px;
color: #fff;
transition: background-color 0.4s cubic-bezier(0.19, 1, 0.22, 1),
border 0.4s cubic-bezier(0.19, 1, 0.22, 1),
color 0.4s cubic-bezier(0.19, 1, 0.22, 1);
}
.el_btn11::before {
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transition-property: transform;
background-color: #c78181;
transition-duration: 0.6s;
border-radius: 40px;
}
.el_btn11::after {
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 2;
transition-property: transform;
transition-duration: 0.6s;
background-color: #5e2525;
border-radius: 40px;
transform: translateY(101%);
}
.el_btn11:hover::after {
transform: translateY(0);
}
.el_btn11 .btn_textWrap {
position: relative;
z-index: 3;
display: flex;
overflow: hidden;
}
.el_btn11 .btn_content {
transition-property: transform;
transition-duration: 0.6s;
transform: translateY(0);
visibility: visible;
}
.el_btn11:hover .btn_content {
transform: translateY(-100%);
}
.el_btn11 .btn_content:nth-of-type(2) {
position: absolute;
left: 0;
top: 100%;
}
.el_btn11 .btn_text {
transition-property: transform;
transition-duration: 0.6s;
}
/* ==========================
上下の線がくっつく
========================== */
.el_btn12 {
position: relative;
display: grid;
place-content: center;
width: 240px;
max-width: 100%;
min-height: 120px;
border-radius: 40px;
color: #222;
transition: background-color 0.4s cubic-bezier(0.19, 1, 0.22, 1),
border 0.4s cubic-bezier(0.19, 1, 0.22, 1),
color 0.4s cubic-bezier(0.19, 1, 0.22, 1);
}
.el_btn12::before {
position: absolute;
content: "";
left: 0;
display: block;
width: 100%;
border: 0 solid #222;
transition: height 0.6s cubic-bezier(0.19, 1, 0.22, 1);
border-width: 1px;
top: 0;
border-bottom-width: 0;
border-radius: 1rem 1rem 0 0;
height: 1.5rem;
}
.el_btn12::after {
position: absolute;
content: "";
left: 0;
display: block;
width: 100%;
border: 0 solid #222;
transition: height 0.6s cubic-bezier(0.19, 1, 0.22, 1);
border-width: 1px;
bottom: 0;
border-top-width: 0;
border-radius: 0 0 1rem 1rem;
height: 1.5rem;
}
.el_btn12:hover::before {
height: 50%;
}
.el_btn12:hover::after {
height: 50%;
}
枠線から塗りつぶしに
ポイントは、hover前と後で、borderを設定しておくことです。これを設定していないと枠線のずれが生まれてしまいます。
影がつく
こちらはdrop-shadowの使い方が分かれば対応できると思いますので、解説は省略します。
丸い装飾が横線に
疑似要素で丸をつくって、hover時に横線に変化させています。
点線の円が回転している
keyframesを使って回転アニメーションをつけています。
矢印の装飾がスライド
空タグを作って、overflowをhiddenにしてはみ出さないよう設定した上で、疑似要素のbeforeとafterに画像を設定して、hover前後で動きの設定をしています。
円の周りに薄い円がひろがる
疑似要素に薄い円を作って、hover時に広がるように設定しています。z-indexの値の設定にも注意すれば比較的かんたんに実装できます。
アイコンとテキストが同時に色変更
疑似要素にsvg画像を設定しています。hover時に色変更する場合は、別途別の色のsvg画像を用意する必要があります。
ただ、こちらについては、変更に強いコードとは言えませんので、疑似要素よりは、html上にsvgコードを記載して、fillなどのCSSプロパティを使って実装するほうが望ましいかも知れません。
テキストが上部にスライドしつつ色変更
原理はさきほど紹介した「矢印の装飾がスライド」と同様ですので、解説は省略します。
横線が右へスライドして新たな横線が現れる
これは見た目は新しい横線が現れているように見えますが、実際は伸び縮みしているだけです。
animationのkeyframesを使って、transformのscaleの数値でコントロールしています。
下から丸い背景が覆われる
疑似要素で上が丸い形のシェイプを作り、hover時に拡大させるとかんたんに実装できます。
下から上へ背景と文字がスライドして現れる
hover時に現れる背景については、hover前はtransformのtranslateY(101%)を指定して隠しています。あとはhover時に0%にすれば実装できます。
テキストについては、「矢印の装飾がスライド」と原理は同様ですので解説は省略します。
上下の線がくっつく
ボタンといっていいのか迷いましたが、紹介します。疑似要素にborderと高さを指定することで、見切れた見た目にすることができます。
あとはhover時にbeforeとafterを使って、高さを変えてあげることで、線がをくっつかせるアニメーションが実現できます。
以上ですが、今後も実務で使えそうなボタンのホバーアニメーションを見つけましたら随時更新していきたいと思います。