Author: | nat-davydova |
---|---|
Views Total: | 2,631 views |
Official Page: | Go to website |
Last Update: | August 8, 2019 |
License: | MIT |
Preview:

Description:
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); } });