Mobile Tab Navigation UI In JavaScript And CSS

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

Preview:

Mobile Tab Navigation UI In JavaScript And CSS

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

You Might Be Interested In:


Leave a Reply