ボーダーラインアニメーションをいくつか実装してみたいなと思い、色々調べて実装してみたので、今回は備忘録として実装したボーダラインアニメーションのやり方について紹介しようと思います。
開発環境
Next.jsでReactを使用して、今回のアニメーションはSCSSを使って実装しました
- Next.js
- SCSS(SCSS modules)
CSS modulesとは
CSSのクラス名をグローバルスコープではなく、ローカルスコープで定義できるようにする技術です。
CSSでは別ファイルで同じで同じクラス名を使うことができません。
しかしCSS modulesを使うと自動的に名前がユニークになり、それを使って下のようにスタイルを適用できるようになります。
.title{
color: #000000
}
import style from "./style.module.scss":
const Components = () =>{
return(
<div className={style.title}>Hello</div>
)
}
メニューバー(ヘッダ-)がhoverされたら線が出るように
メニューバーで要素をhoverしたら、紫の線が伸びるアニメーションを実装しました。
- tsxファイル
import style from "@/features/header/styles/style.module.scss"
export const Header = () =>{
return (
<div className={style.headerContainer}>
<div className={style.menuContainer}>
<div className={style.headerContent}>Home</div>
<div className={style.headerContent}>About</div>
<div className={style.headerContent}>Works</div>
</div>
</div>
)
}
- scssファイル
.headerContainer {
display: flex;
position: relative;
}
.menuContainer{
display: flex;
position: absolute;
right: 0;
}
.headerContent{
font-size: 2rem;
margin: 1rem 1rem 1rem 4rem;
position: relative;
&::after {
content: '';
position: absolute;
bottom: 0;
right: 0;
width: 0;
height: 3px;
background-color: theme.$purple;
transition: width 0.3s ease;
}
&:hover::after {
width: 100%;
left: 0;
}
}
やり方
ここでは擬似要素afterを使って下の紫の線を作っています。
beforeとafterとは
タグで囲んでいる要素の前方に追加要素を加えることができる擬似要素のことです。
beforeは要素の前方に、afterは要素の後方に追加します。
例えば、下のようなhtmlがあったとします。
<h1>こんにちわ</h1>
下のようなcssを追加したとします。
h1::before {
content: "☀️";
}
このような場合には、webサイト上では下のように表示されます。
See the Pen Untitled by mao ozaki (@maooz4426) on CodePen.
&::after {
content: '';
position: absolute;
bottom: 0;
right: 0;
width: 0;
height: 3px;
background-color: theme.$purple;
transition: width 0.3s ease;
}
position:absolute
を指定して、親要素から右下の位置のに高さ3pxだけある紫色の物体を配置しています。
そこからtransitionで横に広がるアニメーションが0.3sで適度な速度で加減速するようにしています
そこからafter要素がhoverされたら左からwidthを100%になるようにしています。これによって紫の線が、scssに当てている要素の下に右から左に流れるようにアニメーションすることができます。
&:hover::after {
width: 100%;
left: 0;
}
Imageコンポーネントの周りを小さな光が回るように
このXでのツイートのようにアイコンの周りをうっすら光るものが動くアニメーションを追加しました。
<div className={style.icon}>
<Image
src={`/icon.png`}
alt="icon"
width={500}
height={500}
/>
</div>
.icon{
border-radius: 50%;
box-shadow: 0 0 10px 5px theme.$darkpurple;
position: relative;
display: inline-block;
width: 500px;
height: 500px;
}
@property --angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.icon::after ,.icon::before{
content: '';
position: absolute;
border-radius: 50%;
background-image:
conic-gradient(from var(--angle), transparent 0%,
transparent 65%,
theme.$darkpurple 71%,
theme.$purple 72%,
theme.$darkpurple 73%,
transparent 79%,
transparent 100%);
top: 50%;
left: 50%;
width: 103%;
height: 103%;
translate: -50% -50%;
display: block;
z-index: -1;
animation: border-animation 1.5s linear infinite;
}
.icon::before{
filter: blur(1.5rem);
}
@keyframes border-animation {
from{
--angle: 0deg;
}
to{
--angle: 360deg;
}
}
どうやっているのか
点の表現はまず下の部分で主に行っています。
↓この部分
.icon::after ,.icon::before{
content: '';
position: absolute;
border-radius: 50%;
background-image:
conic-gradient(from var(--angle), transparent 0%,
transparent 65%,
theme.$darkpurple 71%,
theme.$purple 72%,
theme.$darkpurple 73%,
transparent 79%,
transparent 100%);
top: 50%;
left: 50%;
width: 103%;
height: 103%;
translate: -50% -50%;
display: block;
z-index: -1;
animation: border-animation 1.5s linear infinite;
}
擬似要素であるbefore、afterを使って、htmlに記述せず要素を追加します。
これらの要素はアイコンの周りに見える必要があります。
Imageタグが中央にあるのでpositionやtop、leftプロパティを使って中央に持ってきています。
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
border-radiusで完全に円形にします。
border-radius: 50%;
widthとheightで大きさを調節します。
100%だと完全に重なって見えないので少しだけ大きさを調節します。
width: 103%;
height: 103%;
background-imageで背景イメージを設定しています。
background-image:
そのイメージとしてconic-gradientで作成したイメージを使っています。
conic-gradientは放射状に色を変えていく関数です
conic-gradient(開始角度、どの位置でどの色か)
今回の場合で言うと、まずアニメーション用にカスタムプロパティを設定しています。
@property --angle {
syntax: "<angle>"; //角度を扱う
initial-value: 0deg; //0度から
inherits: false; //継承しないので指定した要素のみで扱う
}
conic-gradient上で先ほどのカスタムプロパティを開始位置として使用します。
そこからどの角度でどのような色をしているかを記述しています。
今回は360度の内71%の位置は濃いめの紫、72%は普通の紫、73%は濃いめの紫とコントラストをつけて光ってる感じをだすようにしています。
conic-gradient(from var(--angle), transparent 0%,
transparent 65%,
theme.$darkpurple 71%,
theme.$purple 72%,
theme.$darkpurple 73%,
transparent 79%,
transparent 100%);
ここにアニメーションをつけて回転するようにします。
@keyframes
でcssのアニメーション制御を行うことができます。これを使ってカスタムプロパティを0度から360度変動するようにしています。
@keyframes border-animation {
from{
--angle: 0deg;
}
to{
--angle: 360deg;
}
}
そこからanimationで何秒でそのアニメーションを行うか指定します。
animation: border-animation 1.5s linear infinite;
また、blurをつけて少しネオンが光ってる感じも出しています。
.icon::before{
filter: blur(1.5rem);
}
参考にした動画