クリックしたliタグをtranslateYする
主な流れ
・クリックしたliタグをtranslateY(-10px)する
・effectクラスで装飾する
・「.offsetLeft」を使ってactiveクラスの左上座標を取得し、CSS変数にsetPropertyする
デメリット
・circle::beforeの影がeffect::before, effect::after に重なるため、要素の半透明にできない
・circleを角丸に変えたとき、circle::before が角丸の影にできない
・FontAwesomeが重くてサイト表示に時間がかかる ⇒ 使うものだけSVG画像をDLしたほうが良さそう
・ナビゲーションとして使う場合、ボタンを押したときに別のページに飛んでしまい、JSの動きを見ることすらできない => ナビゲーションよりタブとして使うべきアニメーションだと思う
HTML
font awesome のCDNは廃止されたため、CDNJSという海外のサイト(https://cdnjs.com/libraries/font-awesome)を使ってLinkタグを貼り付けること
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" integrity="sha512-Evv84Mr4kqVGRNSgIGL/F/aIDqQb7xQ2vcrdIwxfjThSH8CSR7PBEakCr51Ck+w+/U6swU2Im1vVX0SVk9ABhg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<nav>
<ul>
<li class="active"><i class="fa-solid fa-house"></i></li>
<li><i class="fa-solid fa-location-dot"></i></li>
<li><i class="fa-solid fa-building"></i></li>
<li><i class="fa-solid fa-envelope"></i></li>
<li><i class="fa-solid fa-phone"></i></li>
</ul>
<div class="effect">
<div class="circle"></div>
</div>
</nav>
CSS
:root {
--w-h-item: 60px;
--position-active: 170px;
}
body {
background-color: #f2f2f2;
}
nav {
position: fixed;
inset: auto 0 0;
border-bottom: 20px solid #fff;
color: #fff;
width: min(500px, 100%);
--w-h-item: 60px;
--position-active: 170px;
}
nav ul {
padding: 0;
margin: 0;
display: grid;
grid-template-columns: repeat(5, 60px);
grid-template-rows: 60px;
justify-content: space-between;
}
nav ul li {
display: flex;
justify-content: center;
align-items: center;
font-size: 15px;
transition: 0.5s;
}
nav ul li.active {
transform: translateY(-10px);
}
nav ul li.active i {
color: #fff;
}
/***** 装飾部分 *****/
nav .effect {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: calc( var(--w-h-item) + 10px );
overflow: hidden;
z-index: -1;
}
nav .effect::before {
position: absolute;
left: 0;
bottom: 0;
content: "";
width: calc( var(--position-active) - 10px );
height: var(--w-h-item);
background-color: #fff;
border-top-right-radius: 30px;
transition: 0.5s;
}
nav .effect::after {
position: absolute;
right: 0;
bottom: 0;
content: "";
width: calc( 100% - var(--position-active) - var(--w-h-item) - 10px );
height: var(--w-h-item);
background-color: #fff;
border-top-left-radius: 30px;
transition: 0.5s;
}
nav .effect .circle {
position: absolute;
left: var(--position-active);
width: var(--w-h-item);
height: var(--w-h-item);
background-color: #039ffa;
border-radius: 50%;
box-shadow: 0 20px 20px #555;
transition: 0.5s;
}
nav .effect .circle::before {
position: absolute;
left: -10px;
right: -10px;
bottom: -10px;
content: "";
height: 100%;
background-color: transparent;
border-radius: 50%;
box-shadow: 0 50px 0 30px #fff;
transform: 0.5s;
}
※1 … insetを使うことでtop,left,right,bottomを一括で指定できます
Javascript
let nav = document.querySelector("nav");
let items = document.querySelectorAll("li"); ※2
items.forEach( item => {
item.onclick = () => {
let oldActive = nav.querySelector("li.active");
if (oldActive) {
oldActive.classList.remove("active");
}
item.classList.add("active");
nav.style.setProperty("--position-active", item.offsetLeft + "px");
}
});
//
let itemActive = nav.querySelector("li.active");
if (itemActive) {
nav.style.setProperty("--position-active", itemActive.offsetLeft + "px");
}
※1 … item.onclick = () => { … } は item.onclick = function() { … } と同じです。(アロー関数)
また、onClickではなく、onclickです。
※2 … Allの入れ忘れに注意
※3 … .offsetLeftによって左上座標が取得できます
参考サイト
【https://www.youtube.com/watch?v=RIr9CxF28-0&list=WL&index=2】
BACK