Tabby, a very simple tabbed content UI

Toggle between different content. Very simple but could be expanded upon.

CodePen

JavaScript

// **************************************************
//  Tabby
// **************************************************
const tabby = () => {
    // get the required elements
    const tabby = document.querySelector('.tabby')

    // guard clause to make sure the '.tabby' element exists on the page
    if (tabby == null) {
        return
    }

    // get the required elements
    const tabs = tabby.querySelectorAll('.tabby-tabs button')
    const photos = tabby.querySelectorAll('.tabby-photos .item')
    const text = tabby.querySelectorAll('.tabby-text .item')

    // tabs
    tabs.forEach((tabElement) => {
        tabElement.addEventListener('click', (event) => {
            let selectedTab = tabElement.dataset.tab

            // activate tab
            tabs.forEach((disableTabs) => {
                disableTabs.classList.remove('active')
            })
            tabElement.classList.add('active')

            // activate photos
            photos.forEach((photoElement) => {
                photoElement.classList.remove('active')

                let selectedPhotos = photoElement.dataset.tab
                if (selectedPhotos == selectedTab) {
                    photoElement.classList.add('active')
                }
            })

            // activate text
            text.forEach((textElement) => {
                textElement.classList.remove('active')

                let selectedText = textElement.dataset.tab
                if (selectedText == selectedTab) {
                    textElement.classList.add('active')
                }
            })

            event.preventDefault()
        })
    })
}
tabby()

HTML

<section class="tabby-container">
    <div class="tabby">
        <div class="tabby-heading">
            <div class="content-heading">
                <h2>Portland Japanese Garden</h2>
                <p>Your Summer Sanctuary</p>
            </div>
        </div>

        <div class="tabby-tabs">
            <button data-tab="1" class="item active"><span>Japanese</span> Maple Tree</button>
            <button data-tab="2" class="item"><span>Heavenly Falls</button>
            <button data-tab="3" class="item"><span>King of the River</span> Koi Fish</button>
        </div>

        <div class="tabby-photos">
            <div data-tab="1" class="item active">
                <!-- glide.js slideshow markup usually goes here -->
                <!--
                <div class="slideshow arrows-default transition-fade">
                </div>
                -->
                <img src="https://images.unsplash.com/photo-1542324253097-09d465f007bc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" alt="">
            </div>

            <div data-tab="2" class="item">
                <!-- glide.js slideshow markup usually goes here -->
                <!--
                <div class="slideshow arrows-default transition-fade">
                </div>
                -->
                <img src="https://images.unsplash.com/photo-1638173539707-e40a980868cd?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" alt="">
            </div>

            <div data-tab="3" class="item">
                <!-- glide.js slideshow markup usually goes here -->
                <!--
                <div class="slideshow arrows-default transition-fade">
                </div>
                -->
                <img src="https://images.unsplash.com/photo-1638528504549-1f703fdec80a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" alt="">
            </div>
        </div>

        <div class="tabby-text">
            <div data-tab="1" class="item active">
                <p>Japanese Maple Tree sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.<br><br>Japanese Maple Tree Totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est.</p>
            </div>

            <div data-tab="2" class="item">
                <p>Heavenly Falls sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.<br><br>Heavenly Falls Totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est.</p>
            </div>

            <div data-tab="3" class="item">
                <p>King of the River Koi Fish sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.<br><br>King of the River Koi Fish Totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est.</p>
            </div>
        </div>
    </div>
</section>

CSS

// **************************************************
//  General
// **************************************************

@import url('//fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400&display=swap');

html,
body {
  position: relative;
  color: #000;
  font-family: 'Lato', sans-serif;
  font-size: 16px;
  line-height: 1;
  margin: 0;
}

p {
  margin: 0 0 1em 0;
  font-size: 1.25rem;
  line-height: 2;

  &:last-of-type {
    margin-bottom: 0;
  }
}

// **************************************************
//  Tabby
// **************************************************
.tabby-container {
  padding-block: 6em;
  background-color: #EBEBEB;
  
  @media (max-width: 1360px) {
    padding-block: 4em;
  }
}

.tabby {
    display: grid;
    grid-template-columns: minmax(auto, 830px) minmax(auto, 960px);
    max-width: 1790px;
    margin-left: auto;

    @media (min-width: 2000px) {
      grid-template-columns: minmax(auto, 830px) minmax(auto, 100%);
      margin-inline: auto;
    }

    @media (max-width: 1820px) {
      margin-left: 1em;
    }

    @media (max-width: 1600px) {
      grid-template-columns: minmax(auto, 830px) minmax(auto, 830px);
    }

    @media (max-width: 1360px) {
      grid-template-columns: 1fr;
      margin-left: 0;
    }
}

// heading
.tabby-heading {
  display: flex;
  flex-direction: column;
  justify-content: center;

  @media (max-width: 1360px) {
    margin-bottom: 1em;
    text-align: center;
  }
}

// tabs
.tabby-tabs {
  background-color: #EBEBEB;
  display: flex;
  justify-content: center;
  gap: 0.5em;

  @media (max-width: 500px) {
    flex-direction: column;
    margin-bottom: 0.5em;
  }

  button {
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: 248px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 97px;
    border: none;
    background-color: #DDDDDD;
    font-size: 1.25rem;
    line-height: 1.75rem;
    transition: all 0.5s;
    cursor: pointer;

    @media (max-width: 720px) {
      font-size: 1rem;
    }

    @media (max-width: 500px) {
      flex-basis: auto;
      height: 75px;
      line-height: 1.5rem;
    }

    &.active {
      background-color: #fff;
      color: #497AAB;
    }

    &:hover,
    &:focus {
      color: #497AAB;
    }
  }
}

// glide.js slideshow CSS:

// photos
/*
.tabby-photos {
  background-color: #fff;

  // fixes slideshow width/height in smaller viewports due to Glide.js
  .slideshow,
  .glide,
  .glide__track,
  .glide__slides,
  .glide__slide {
    width: 100% !important;
    height: 100%;
  }

  // fixes left/right margins added by Glide.js
  .glide__slide {
    margin-left: 0 !important;
    margin-right: 0 !important;

    img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }
}
*/

// photos
.tabby-photos {
  background-color: #fff;
  
  img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

// text
.tabby-text {
  background-color: #fff;
  padding-block: 4em;
  padding-inline: 7em;
  
  @media (max-width: 1600px) {
    padding-block: 2em;
    padding-inline: 3em;
  }

  @media (max-width: 1360px) {
    padding-inline: 1em;
  }
}

// hide and show
.tabby-photos {
  display: grid;
  grid-template-columns: 1fr;

  .item {
    grid-column-start: 1;
    grid-column-end: 2;
    grid-row-start: 1;
    grid-row-end: 2;
    z-index: 0;
    opacity: 0;

    &.active {
      z-index: 1;
      opacity: 1;
    }
  }
}

.tabby-text {
  .item {
    display: none;

    &.active {
      display: block;
    }
  }
}




// **************************************************
//  Content Heading
// **************************************************
.content-heading {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;

  > * {
    order: 1;
    margin: 0;
  }

  p:first-of-type {
    order: 0;
    margin-bottom: 0.5em;
    color: #000;
    font-size: 1.1rem;
    line-height: 1;
    text-transform: uppercase;
  }
}

CodePen