CSS animation day17 となりました。
本日は、Gooey Effect を使って、別のボタンを作ります。
1. 完成版
2. 参考文献
3. 分解してみる
❶.
まずは、前回 のコードを使って、ボタンを5つに増やしましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="css/styles.css" />
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.7.1/css/all.css"
integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr"
crossorigin="anonymous"
/>
</head>
<body>
<div class="container">
<div class="gooey">
<input type="checkbox" id="start" />
<label for="start">
<div class="menu-open-button">
<i class="fas fa-plus plus"></i>
</div>
</label>
<div class="circle1">
<i class="far fa-envelope mail"></i>
</div>
<div class="circle2">
<i class="far fa-question-circle question"></i>
</div>
<div class="circle3">
<i class="far fa-envelope mail"></i>
</div>
<div class="circle4">
<i class="far fa-question-circle question"></i>
</div>
<div class="circle5">
<i class="far fa-question-circle question"></i>
</div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="filter">
<feGaussianBlur
in="SourceGraphic"
stdDeviation="20"
result="blur"
/>
<feColorMatrix
in="blur"
mode="matrix"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 17 -7"
result="filter"
/>
<feBlend in="SourceGraphic" in2="filter" />
</filter>
</defs>
</svg>
</div>
</body>
</html>
body {
margin: 0;
padding: 0;
}
.container {
position: relative;
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.gooey {
width: 100%;
height: 100vh;
margin: 0 auto;
filter: url("#filter");
}
.plus {
font-size: 3em;
color: #fff;
padding: 27px 29px;
}
.mail {
font-size: 3em;
color: #fff;
padding: 26px;
}
.question {
font-size: 3em;
color: #fff;
padding: 26px;
}
#start {
display: none;
}
.menu-open-button {
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
background: green;
cursor: pointer;
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition-duration: 400ms;
transform: scale(1, 1);
z-index: 2;
}
.menu-open-button:hover {
transform: scale(1.1, 1.1);
}
.circle1,
.circle2,
.circle3,
.circle4,
.circle5 {
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
background: green;
transition: transform ease-out 200ms;
transform: translate3d(0, 0, 0);
}
次に、これらにアニメーションを設定します。
イメージは、ボタンを押したら、下側に半円を描くようにボタンが動くようにします。
#start:checked ~ .circle2 {
transform: translate3d(120px, 130px, 0);
transition-timing-function: ease;
transition-duration: 600ms;
}
#start:checked ~ .circle3 {
transform: translate3d(0, 200px, 0);
transition-timing-function: ease;
transition-duration: 600ms;
}
#start:checked ~ .circle4 {
transform: translate3d(-120px, 130px, 0);
transition-timing-function: ease;
transition-duration: 600ms;
}
#start:checked ~ .circle5 {
transform: translate3d(-200px, 20px, 0);
transition-timing-function: ease;
transition-duration: 600ms;
}
#start:checked ~ div i {
animation: blight 600ms ease-in forwards;
}
#start:checked + label div i {
transform: rotateZ(-45deg);
transition-timing-function: ease;
transition-duration: 300ms;
}
@keyframes blight {
0% {
opacity: 0.6;
}
100% {
opacity: 1;
}
}
できました!
・・・
ただ、なんというか・・・
コードが長いです。読む気になりません。
どうにかリファクタリングできないでしょうか?
CSS でループ文使えれば・・・
ということで、Sass を使ってみたいと思います。
Sass とは?という方は、こちら がわかりやすいです。
エディターは、VSCode を使用しているため、Sass の導入は、こちら を参考に、簡単に始められます。
Live Sass Compiler を追加して、ファイルの名前をscss に変更し、
先ほどのcss を変更していきます。
① 継承
.circle {
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
background: green;
}
.menu-open-button {
@extend .circle;
...
}
.circle1,
.circle2,
.circle3,
.circle4,
.circle5 {
@extend .circle;
...
}
緑丸ボタンの設定を、.circle{} として、作り
@extend で、circle 1~5 と, menu-open-button へ継承してます。
別の書き方として、@mixin と @include を使った書き方もできます。
@mixin circle {
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
background: green;
}
.menu-open-button {
@include circle;
...
}
.circle1,
.circle2,
.circle3,
.circle4,
.circle5 {
@include circle;
...
}
こちらも同じ結果となります。
extend とかなり似てますが、何が違うのでしょうか?
@mixin, @include の場合、引数を使うことができ、
@mixin icon($padding) {
font-size: 3em;
color: #fff;
padding: $padding;
}
というように、設定でき
//before
.plus {
font-size: 3em;
color: #fff;
padding: 27px 29px;
}
.mail {
font-size: 3em;
color: #fff;
padding: 26px;
}
.question {
font-size: 3em;
color: #fff;
padding: 26px;
}
このコードが、
//after
.plus {
@include icon(27px 29px);
}
.mail,
.question {
@include icon(26px);
}
こう書けます!!
このように、@mixin, @includeを使えば、引数を与えて使いまわすことができます!
もっと詳しく知りたい方は、
Web制作者のためのSassの教科書 改訂2版 Webデザインの現場で必須のCSSプリプロセッサ Web制作者のための教科書シリーズ
hajipon.com に大変わかりやすく書いてありましたので、ぜひご一読ください。
② ネスト
Sass では、CSSを入れ子で書いていくことができます。
この機能で、コードの記述量が大幅に減り、メンテナンス性が向上するでしょう。ただし、使いすぎるとネストが深くなり、可読性が落ちるので、気をつけましょう!
//before
body {
margin: 0;
padding: 0;
}
.container {
position: relative;
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.gooey {
width: 100%;
height: 100vh;
margin: 0 auto;
filter: url("#filter");
}
.plus {
font-size: 3em;
color: #fff;
padding: 27px 29px;
}
.mail {
font-size: 3em;
color: #fff;
padding: 26px;
}
.question {
font-size: 3em;
color: #fff;
padding: 26px;
}
#start {
display: none;
}
.menu-open-button {
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
background: green;
cursor: pointer;
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition-duration: 400ms;
transform: scale(1, 1);
z-index: 2;
}
.menu-open-button:hover {
transform: scale(1.1, 1.1);
}
.circle1,
.circle2 {
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
background: green;
transition: transform ease-out 200ms;
transform: translate3d(0, 0, 0);
}
#start:checked ~ .circle1 {
transform: translate3d(0, -150px, 0);
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition-duration: 800ms;
}
#start:checked ~ .circle2 {
transform: translate3d(0, -300px, 0);
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition-duration: 800ms;
}
#start:checked ~ div i {
animation: blight 600ms ease-in forwards;
}
#start:checked + label div i {
transform: rotateZ(-45deg);
transition-timing-function: ease;
transition-duration: 300ms;
}
@keyframes blight {
0% {
opacity: 0.6;
}
100% {
opacity: 1;
}
}
//after
body {
margin: 0;
padding: 0;
}
.container {
position: relative;
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.gooey {
width: 100%;
height: 100vh;
margin: 0 auto;
filter: url("#filter");
}
@mixin icon($padding) {
font-size: 3em;
color: #fff;
padding: $padding;
}
.plus {
@include icon(27px 29px);
}
.mail,
.question {
@include icon(26px);
}
@mixin circle {
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
background: green;
}
.menu-open-button {
@include circle;
cursor: pointer;
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition-duration: 400ms;
transform: scale(1, 1);
z-index: 2;
&:hover {
transform: scale(1.1, 1.1);
}
}
.circle1,
.circle2,
.circle3,
.circle4,
.circle5 {
@include circle;
transition: transform ease-out 200ms;
transform: translate3d(0, 0, 0);
}
#start {
display: none;
&:checked {
transition-timing-function: ease;
transition-duration: 600ms;
~ div i {
animation: blight 600ms ease-in forwards;
}
+ label {
div i {
transform: rotateZ(-45deg);
transition-timing-function: ease;
transition-duration: 300ms;
}
}
~ .circle1 {
transform: translate3d(200px, 20px, 0);
}
~ .circle2 {
transform: translate3d(120px, 130px, 0);
}
~ .circle3 {
transform: translate3d(0px, 200px, 0);
}
~ .circle4 {
transform: translate3d(-120px, 130px, 0);
}
~ .circle5 {
transform: translate3d(-200px, 20px, 0);
}
}
}
@keyframes blight {
0% {
opacity: 0.6;
}
100% {
opacity: 1;
}
}
&: を使うことで、入れ子の書き方ができ、記述量が少なくなりました。ただし、やはり使いすぎると読みにくくなるので、注意が必要ですね。
本日はここまでです。
明日から、Sass をいっぱい使っていこうと思います。
それではまた明日〜