Tab Menu / 30 リキッドモーフィング|Liquid Morphing
デザイン見本
- Tab 1
- Tab 2
- Tab 3
Good morning. This is the content of Tab 1.
Hello. This is the content of Tab 2.
Good evening. This is the content of Tab 3.
流れるような滑らかなアニメーションが特徴のデザインです。選択状態を示す白い背景がスライドアニメーションによって移動し、柔らかな `cubic-bezier` によってゼリーのように伸縮して見える効果を作っています。グラスモーフィズムとの組み合わせでモダンな印象を与えます。
実装コード
HTML
<div class="tab-container">
<ul>
<div class="liquid-bg"></div>
<li class="selected" data-id="tab-1">Tab 1</li>
<li data-id="tab-2">Tab 2</li>
<li data-id="tab-3">Tab 3</li>
</ul>
<div class="tab-content selected" id="tab-1">
Good morning. This is the content of Tab 1.
</div>
<div class="tab-content" id="tab-2">
Hello. This is the content of Tab 2.
</div>
<div class="tab-content" id="tab-3">
Good evening. This is the content of Tab 3.
</div>
</div>
CSS
.tab-container {
position: relative;
padding: 20px;
background: linear-gradient(135deg, #e0c3fc 0%, #8ec5fc 100%);
border-radius: 16px;
}
.tab-container ul {
margin: 0 0 24px 0;
padding: 8px;
list-style: none;
display: flex;
position: relative;
background: rgba(255, 255, 255, 0.4);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 50px;
box-shadow: inset 0 2px 5px rgba(0,0,0,0.05);
}
.tab-container .liquid-bg {
position: absolute;
top: 8px;
left: 8px;
height: calc(100% - 16px);
width: calc((100% - 16px) / 3);
background: #fff;
border-radius: 40px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
z-index: 1;
}
.tab-container ul li {
flex: 1;
text-align: center;
padding: 12px 20px;
cursor: pointer;
position: relative;
z-index: 2;
color: #555;
font-weight: 600;
transition: color 0.3s ease;
}
.tab-container ul li.selected {
color: #6a11cb;
}
.tab-container .tab-content {
display: none;
padding: 30px;
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.5);
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.1);
min-height: 150px;
color: #333;
}
.tab-container .tab-content.selected {
display: block;
animation: liquidFadeIn 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
@keyframes liquidFadeIn {
0% { opacity: 0; transform: translateY(10px) scale(0.98); border-radius: 30px; }
100% { opacity: 1; transform: translateY(0) scale(1); border-radius: 16px; }
}
JS
(function () {
'use strict';
document.addEventListener('DOMContentLoaded', () => {
const tabBoxes = document.querySelectorAll('.tab-container');
for (const box of tabBoxes) {
const liquidBg = box.querySelector('.liquid-bg');
const menuItems = box.querySelectorAll('ul li');
const contents = box.querySelectorAll('.tab-content');
for (let idx = 0; idx < menuItems.length; idx++) {
const item = menuItems[idx];
item.addEventListener('click', () => {
for (const mItem of menuItems) {
mItem.classList.remove('selected');
}
item.classList.add('selected');
for (const content of contents) {
content.classList.remove('selected');
}
const targetKey = item.dataset.id;
const targetContent = document.getElementById(targetKey) || box.querySelector('#' + targetKey);
if (targetContent) {
targetContent.classList.add('selected');
}
if (liquidBg) {
const tX = 'translateX';
liquidBg.style.transform = tX + '(' + (idx * 100) + '%)';
}
});
}
}
});
})();