City of Ghent Style Guide

Tabs

The tabs component allows users to switch between two or more related sections of content on the same web page, displaying one section at a time.

When to use this component

Use the tabs component when:

  • Two or more related sections of content exist on a web page that can be clearly labelled.
  • Users typically are not interested to see all sections.
  • Users typically will not need to see all sections at once.
  • The first section is more relevant than the other sections for most users.

When not to use this component

Do not use the tabs component when a page reload is triggered. In this case, use the display switcher component instead.

Furthermore, do not use a tabs component:

  • To hide content that is essential to all users.
  • When users will need to see all sections at once, for instance to compare information in the different sections.
  • When the sections are equally relevant for most users or when users typically are interested in a few specific sections. In this case, use an accordion instead.
  • When users have to read through all the related sections of content in order, for example, to understand a process.
  • To show progress or a linear flow when collecting user input in multiple steps or to guide users through a process. In these cases, use a multistep form or a wizard instead.
  • When the amount of content in the tabs will make the page too long or too slow to load.

Alternatives to using a tabs component:

  • Reduce and simplify the content so that it can be placed as is on the page, without hiding it or the need for an tabs component.
  • Split the content accross multiple pages. In this case, the display switcher component can be used to let users switch between the pages.
  • Keep the content as is on the page, separate the content by headings.
  • Use a table of contents component to let users navigate quickly to specific sections of content.

Accessibility

  • The tabbed interface component contains tabs and their associated content panels.
  • The content panel uses the role tabpanel.
  • An element with role tab is used as a grouping label, providing a link for selecting the tabpanel to be rendered to the user.
  • Assign the aria-controls relationship of a tab to the ID of its tabpanel.
  • Authors manage the selected state of each tab by maintaining its aria-selected state.
  • A tablist is the container role for a set of elements with the role attribute set to tab.

Functionality

  • Tab - only the active tab is in the tab order. The user reaches the tabbed panel component by pressing the tab key until the active tab title receives focus.
  • Left Arrow - with focus on a tab, pressing the left arrow will move focus to the previous tab in the tab list and activate that tab. Pressing the left arrow when the focus is on the first tab in the tab list will move focus and activate the last tab in the list.
  • Right Arrow - with focus on a tab, pressing the right arrow will move focus to the next tab in the tab list and activate that tab. Pressing the right arrow when the focus is on the last tab in the tab list will move focus to and activate the first tab in the list.
  • Up arrow - behaves the same as left arrow in order to support vertical tabs
  • Down arrow - behaves the same as right arrow in order to support vertical tabs
  • Home - with focus on a tab, moves the focus to the first tab.
  • End - with focus on a tab, moves the focus to the last tab.

Javascript

For full documentation of the used javaScript library, see allieTabs

<div class="tabs {{ modifier }}" data-tabs>
  <ul role="tablist">
    {% for tab in tabs %}
      <li role="presentation">
        <a role="tab" href="#{{ modifier ~ tab.target }}" aria-controls="{{ modifier ~ tab.target }}">
          {{ tab.label }}
        </a>
      </li>
    {% endfor %}
  </ul>
  {% for tab in tabs %}
    <div role="tabpanel" id="{{ modifier ~ tab.target }}">
      {{ tab.content }}
    </div>
  {% endfor %}
</div>
<div class="tabs light" data-tabs>
    <ul role="tablist">
        <li role="presentation">
            <a role="tab" href="#lighttab1" aria-controls="lighttab1">
                tab 1
            </a>
        </li>
        <li role="presentation">
            <a role="tab" href="#lighttab2" aria-controls="lighttab2">
                tab 2
            </a>
        </li>
        <li role="presentation">
            <a role="tab" href="#lighttab3" aria-controls="lighttab3">
                tab 3
            </a>
        </li>
    </ul>
    <div role="tabpanel" id="lighttab1">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae distinctio dolore in, odio odit sapiente. Accusamus hic illum quaerat repellendus!</p>
    </div>
    <div role="tabpanel" id="lighttab2">
        <ul>
            <li>Lorem ipsum dolor sit amet.</li>
            <li>Expedita illo mollitia tempore temporibus.</li>
            <li>Explicabo harum nam nobis sequi.</li>
            <li>Ab ea earum impedit optio.</li>
            <li>Dolorem ipsa libero nobis repellendus.</li>
        </ul>
    </div>
    <div role="tabpanel" id="lighttab3">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae distinctio dolore in, odio odit sapiente. Accusamus hic illum quaerat repellendus!</p>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae distinctio dolore in, odio odit sapiente. Accusamus hic illum quaerat repellendus!</p>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae distinctio dolore in, odio odit sapiente. Accusamus hic illum quaerat repellendus!</p>
    </div>
</div>
{
  "modifier": "light",
  "tabs": [
    {
      "label": "tab 1",
      "target": "tab1",
      "content": "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae distinctio dolore in, odio odit sapiente. Accusamus hic illum quaerat repellendus!</p>"
    },
    {
      "label": "tab 2",
      "target": "tab2",
      "content": "<ul>\n<li>Lorem ipsum dolor sit amet.</li>\n<li>Expedita illo mollitia tempore temporibus.</li>\n<li>Explicabo harum nam nobis sequi.</li>\n<li>Ab ea earum impedit optio.</li>\n<li>Dolorem ipsa libero nobis repellendus.</li>\n</ul>"
    },
    {
      "label": "tab 3",
      "target": "tab3",
      "content": "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae distinctio dolore in, odio odit sapiente. Accusamus hic illum quaerat repellendus!</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae distinctio dolore in, odio odit sapiente. Accusamus hic illum quaerat repellendus!</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae distinctio dolore in, odio odit sapiente. Accusamus hic illum quaerat repellendus!</p>"
    }
  ]
}
  • Content:
    .tabs {
    
      [role='tabpanel'] {
        @include theme('background-color', 'color-primary--lighten-5', 'tab-background-color');
    
        padding: 1rem;
        border-radius: border-radius('radius-1');
    
        &:first-of-type {
          border-top-left-radius: 0;
        }
    
        &:target {
          display: block;
        }
    
        &[aria-hidden] {
    
          &[aria-hidden='true'] {
            display: none;
          }
    
          &[aria-hidden='false'] {
            display: block;
          }
        }
      }
    
      [role='tablist'] {
    
        display: flex;
        flex-direction: column;
        margin: 0;
        list-style: none;
    
        @include desktop {
          flex-direction: row;
        }
    
        > li[role='presentation'] {
          flex: 0 0 auto;
    
          a,
          a[href^="mailto:"],
          a[download],
          a[href^="http://"],
          a[href^="https://"] {
            @include reset-link-background;
            @include theme('color', 'color-tertiary', 'default-text-color');
            display: inline-block;
            width: 100%;
            padding: .3rem .8rem;
            border-top-left-radius: border-radius('radius-1');
            border-top-right-radius: border-radius('radius-1');
            font-weight: 400;
            text-align: center;
            text-decoration: none;
    
    
            @include desktop {
              width: auto;
              text-align: left;
            }
    
            &::after {
              @include theme('color', 'color-primary', 'link-underlined-hover-color');
              display: block;
              width: 0;
              margin: 0 auto;
              transition: width 100ms;
              border-bottom: 2px solid;
              content: '';
              overflow: visible;
            }
    
            &[role='tab'][aria-selected='true'],
            &:hover,
            &:focus {
              background: transparent;
    
              &::after {
                width: 1.5rem;
    
                @include desktop {
                  width: 70%;
                }
              }
            }
    
            &[role='tab'][aria-selected='true']:focus::after {
              width: 1.5rem;
    
              @include desktop {
                width: 100%;
              }
            }
          }
    
          [role='tab'][aria-selected='true'] {
            @include theme('background-color', 'color-primary--lighten-5', 'tab-background-color');
    
            border-bottom: 0;
          }
        }
      }
    
      &.light {
        [role='tabpanel'] {
          background-color: transparent;
        }
    
        [role='tablist'] {
          @include theme('border-color', 'color-primary--lighten-5', 'tab-background-color');
          border-bottom: 2px solid;
        }
      }
    }
    
  • URL: /components/raw/tabs/_tabs.scss
  • Filesystem Path: components/31-molecules/tabs/_tabs.scss
  • Size: 2.4 KB