jared-shepherd of Kaiden Web Managment
12/12/2018 - 8:20 AM

Layout - Tabbed Interface

Simple tabbed, responsive interface as the basis for adding tabs wherever you'd like. Live demo can be found here: https://codepen.io/sh3p/live/QzbxBG.

<div class="tab-layout-container">
  <ul class="tab-list">
    <li class="tab-item active-tab" data-tab="1">Tab Title 1</li>
    <li class="tab-item" data-tab="2">Tab Title 2</li>
    <li class="tab-item" data-tab="3">Tab Title 3</li>
    <li class="tab-item" data-tab="4">Tab Title 4</li>
    <li class="tab-item" data-tab="5">Tab Title 5</li>
  </ul>
  <ul class="tab-content-list">
    <li class="tab-content active-tab" data-tab="1">A simple, responsive tabbed interface that has minimal styling.</li>
    <li class="tab-content" data-tab="2">Tab 2 Content</li>
    <li class="tab-content" data-tab="3">Tab 3 Content</li>
    <li class="tab-content" data-tab="4">Tab 4 Content</li>
    <li class="tab-content" data-tab="5">Tab 5 Content</li>
  </ul>
</div>
$containerHeight: 500px;
$containerPadding: 15px;
$tabItemHeight: 40px;
$activeTabBackground: hsl(0, 0%, 98%);
$activeTabBorder: 1px solid hsl(0, 0%, 90%);
$numberOfTabs: 5;
$contentPadding: 20px;
$maxWidthForMobile: 850px;

ul {
  padding: 0;
  margin: 0;
}

.tab-layout-container {
  min-height: $containerHeight;
  padding: $containerPadding;
  position: relative;
}

.tab-list {
  list-style: none;
  margin: 0;
  border: $activeTabBorder;
}

.tab-item {
  display: inline-block;
  width: 100% / $numberOfTabs;
  text-align: center;
  padding: 0;
  margin: 0 -2px;
  height: $tabItemHeight;
  line-height: $tabItemHeight;
  cursor: pointer;
  
  &.active-tab {
    font-weight: bold;
    background-color: $activeTabBackground;
    border: $activeTabBorder;
    border-top-width: 0;
    border-bottom-width: 0;
  }
  
  &:last-child {
    @media (max-width: $maxWidthForMobile) {
        border-bottom: 0;
    }
  }
  
  @media (max-width: $maxWidthForMobile) {
    display: block;
    width: 100%;
    border-bottom: $activeTabBorder;
    
    &.active-tab {
      border-bottom: $activeTabBorder;
    }
  }
}

.tab-content-list {
  position: absolute;
  list-style: none;
  top: $tabItemHeight + $containerPadding;
  left: $containerPadding;
  right: $containerPadding;
  bottom: $containerPadding;
  border: $activeTabBorder;
  border-top: none;
  
  
  @media (max-width: 850px) {
    top: $tabItemHeight * $numberOfTabs + $containerPadding;
  }
}

.tab-content {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 0;
  padding: 0;
  overflow: hidden;
  
  &.active-tab {
    padding: $contentPadding;
    max-height: $containerHeight;
  }
}
(function() {
  //Tabs
  let tabs = document.getElementsByClassName('tab-item');
  //Content
  let tabContents = document.getElementsByClassName('tab-content');

  //Loop through tabs and add click listener
  for (let i = 0; i < tabs.length; i++) {
    let tab = tabs[i];
    tab.addEventListener('click', function() {
      updateTabs(tab);
    });
  }

  function updateTabs(tab) {
    //If this tab isn't active
    if (!tab.classList.contains('active-tab')) {
      deactivateTabs();
      activateNewTabs(tab);
    }
  }

  function deactivateTabs() {
    let activeElements = document.querySelectorAll('.active-tab');
      
    for (let j = 0; j < activeElements.length; j++) {
      const element = activeElements[j];
      element.classList.remove('active-tab');
    }
  }

  function activateNewTabs(tab) {
    if (tab) {
      tab.classList.add('active-tab'); //activate tab
      activateTabContent(tab); //active tab content
    }
  }

  function activateTabContent(tab) {
    let tabContents = document.querySelectorAll('.tab-content');

    for (let i = 0; i < tabContents.length; i++) {
      const content = tabContents[i];
      
      if (content.dataset.tab == tab.dataset.tab) {
        content.classList.add('active-tab');
      }
    }
  }
})()