
A mobile-inspired tab navigation UI that allows the visitor to switch between screens by clicking/tapping the tabs.
How to use it:
Create the tab navigation & panels.
<div class="tabs">
<!--tabs navigation-->
<div class="tabs__nav">
<ul class="tabs__nav-list">
<li class="tabs__nav-item js-active">Profile</li>
<li class="tabs__nav-item">Settings</li>
<li class="tabs__nav-item">About Us</li>
<li class="tabs__nav-item">FAQ</li>
</ul>
</div>
<!--tabs panels-->
<div class="tabs__panels">
<!--single panel-->
<div class="tabs__panel">
<div class="tabs__panel-card">
<div class="tabs__panel-avatar"></div>
<div class="tabs__panel-content"></div>
</div>
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
</div>
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
</div>
</div>
<!--single panel-->
<div class="tabs__panel">
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
<div class="tabs__panel-content"></div>
</div>
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
</div>
<div class="tabs__panel-card tabs__panel-card--spaced-between">
<div class="tabs__panel-img"></div>
<div class="tabs__panel-img"></div>
<div class="tabs__panel-img"></div>
</div>
</div>
<!--single panel-->
<div class="tabs__panel">
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
</div>
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
<div class="tabs__panel-img"></div>
</div>
<div class="tabs__panel-card">
<div class="tabs__panel-img"></div>
<div class="tabs__panel-content"></div>
</div>
</div>
<!--single panel-->
<div class="tabs__panel">
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
<div class="tabs__panel-content"></div>
</div>
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
</div>
<div class="tabs__panel-card">
<div class="tabs__panel-content"></div>
<div class="tabs__panel-content"></div>
</div>
</div>
</div>
</div>The necessary CSS styles for the tab navigation.
.tabs {
position: relative;
padding: 15px;
height: 100%;
overflow: hidden;
}
.tabs__nav {
position: relative;
}
.tabs__nav-decoration {
position: absolute;
top: 0;
left: 0;
height: 100%;
transition: width .2s linear 0s, -webkit-transform .2s ease-out 0s;
transition: width .2s linear 0s, transform .2s ease-out 0s;
transition: width .2s linear 0s, transform .2s ease-out 0s, -webkit-transform .2s ease-out 0s;
background-color: #119DA4;
border-radius: 3px;
z-index: 1;
}
.tabs__nav-list {
position: relative;
display: flex;
justify-content: space-between;
list-style-type: none;
z-index: 5;
}
.tabs__nav-item {
transition-property: all;
transition-duration: 0.2s;
transition-timing-function: linear;
transition-delay: 0s;
padding: 15px;
cursor: pointer;
}
.tabs__nav-item.js-active {
transition-property: all;
transition-duration: 0.2s;
transition-timing-function: linear;
transition-delay: 0.05s;
color: #fff;
}
.tabs__panels {
position: relative;
margin-top: 30px;
}
.tabs__panel {
position: absolute;
top: 0;
left: 0;
transition: none;
-webkit-transform: scale(0.8);
transform: scale(0.8);
width: 100%;
opacity: 0;
}
.tabs__panel.js-active {
transition: all .25s linear 0s;
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1;
}
.tabs__panel-card {
display: flex;
margin-bottom: 30px;
padding: 15px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2);
}
.tabs__panel-card:last-child {
margin-bottom: 0;
}
.tabs__panel-card--spaced-between {
justify-content: space-between;
}
.tabs__panel-avatar {
flex-shrink: 0;
width: 100px;
height: 100px;
border-radius: 50%;
background-color: rgba(0, 0, 0, 0.15);
}
.tabs__panel-img {
flex-shrink: 0;
width: 80px;
height: 80px;
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.15);
}
.tabs__panel-content {
width: 100%;
margin-left: 30px;
}
.tabs__panel-content:first-child {
margin-left: 0;
}
.tabs__panel-content:not(:last-child) {
margin-right: 30px;
}
.tabs__panel-content:before, .tabs__panel-content:after {
display: block;
width: 100%;
height: 20px;
content: '';
background-color: rgba(0, 0, 0, 0.15);
}
.tabs__panel-content:before {
margin-bottom: 15px;
}The main JavaScript to activate the tab navigation.
const DOM = {
tabsNav: document.querySelector('.tabs__nav'),
tabsNavItems: document.querySelectorAll('.tabs__nav-item'),
panels: document.querySelectorAll('.tabs__panel') };
//set active nav element
const setActiveItem = elem => {
DOM.tabsNavItems.forEach(el => {
el.classList.remove('js-active');
});
elem.classList.add('js-active');
};
//find active nav element
const findActiveItem = () => {
let activeIndex = 0;
for (let i = 0; i < DOM.tabsNavItems.length; i++) {
if (DOM.tabsNavItems[i].classList.contains('js-active')) {
activeIndex = i;
break;
};
};
return activeIndex;
};
//find active nav elements parameters: left coord, width
const findActiveItemParams = activeItemIndex => {
const activeTab = DOM.tabsNavItems[activeItemIndex];
//width of elem
const activeItemWidth = activeTab.offsetWidth - 1;
//left coord in the tab navigation
const activeItemOffset_left = activeTab.offsetLeft;
return [activeItemWidth, activeItemOffset_left];
};
//appending decoration block to an active nav element
const appendDecorationNav = () => {
//creating decoration element
let decorationElem = document.createElement('div');
decorationElem.classList.add('tabs__nav-decoration');
decorationElem.classList.add('js-decoration');
//appending decoration element to navigation
DOM.tabsNav.append(decorationElem);
//appending styles to decoration element
return decorationElem;
};
//appending styles to decoration nav element
const styleDecorElem = (elem, decorWidth, decorOffset) => {
elem.style.width = `${decorWidth}px`;
elem.style.transform = `translateX(${decorOffset}px)`;
};
//find active panel
const findActivePanel = index => {
return DOM.panels[index];
};
//set active panel class
const setActivePanel = index => {
DOM.panels.forEach(el => {
el.classList.remove('js-active');
});
DOM.panels[index].classList.add('js-active');
};
//onload function
window.addEventListener('load', () => {
//find active nav item
const activeItemIndex = findActiveItem();
//find active nav item params
const [decorWidth, decorOffset] = findActiveItemParams(activeItemIndex);
//appending decoration element to an active elem
const decorElem = appendDecorationNav();
//setting styles to the decoration elem
styleDecorElem(decorElem, decorWidth, decorOffset);
//find active panel
findActivePanel(activeItemIndex);
//set active panel
setActivePanel(activeItemIndex);
});
//click nav item function
DOM.tabsNav.addEventListener('click', e => {
const navElemClass = 'tabs__nav-item';
//check if we click on a nav item
if (e.target.classList.contains(navElemClass)) {
const clickedTab = e.target;
const activeItemIndex = Array.from(DOM.tabsNavItems).indexOf(clickedTab);
//set active nav item
setActiveItem(clickedTab);
//find active nav item
const activeItem = findActiveItem();
//find active nav item params
const [decorWidth, decorOffset] = findActiveItemParams(activeItem);
//setting styles to the decoration elem
const decorElem = document.querySelector('.js-decoration');
styleDecorElem(decorElem, decorWidth, decorOffset);
//find active panel
findActivePanel(activeItemIndex);
//set active panel
setActivePanel(activeItemIndex);
}
});






