• Organism
  • CORE COMPONENT
  • Taxonomic name: O-TABS-PRIMARY
  • Added on: v3.1.0 (08/12/17)
  • Updated on: v5.9.0 (13/07/21)

Primary tabs

Tabs allow users to quickly switch between large linked areas of content. This primary variant sits at the top of a page when the entire content of a page needs to change when switching between tabs, ie, when a different tab is selected, it changes the content of the whole page.


Design and usage

Placement

  • All primary tabs are only placed at the top of a page.

Structure

  • Primary tabs can be used with both light and dark accent colour backgrounds.
  • Primary tabs can optionally have the breadcrumb or wayfinder preceeding the H1.
  • Heading groups:

    • Heading groups can be used with the standard, icon and sub-label variants:

      • H1;
      • H1 with H2;
      • H1 with H3.
    • Heading groups be placed above the tabs.
  • Primary, Secondary and Tertiary CTAs:

    • Primary Tabs can display Primary, Secondary and Tertiary CTAs.
    • CTAs must be placed between the heading group and the tabs.
    • Do not show more than two CTAs at a time.
  • Notification cards:

    • Primary Tabs can display notification cards.
    • Notification cards must be placed between the heading group and the tabs.
    • Do not display more than one notification card at a time.
  • Body copy:

    • Primary Tabs can display body copy.
    • Any body copy must be placed between the heading group and the tabs.
    • Do not show more than 144 characters at any breakpoint.
  • Based on the device width, as many tabs as will fit will be displayed. Once tab labels are too wide, they will be displayed as part of a scrollable carousel; this carousel is swipeable as well as having forward / backward buttons which also help with informing users that extra items are available to view.
  • Do not attempt to mix and match tabs styles with a group (for example, one tab with a sub-heading and one with an icon). You can, however, have one set of tabs using sub-headings and another elsewhere on the page using icons.

Labels

  • Keep labels simple and short - no more than two or three words long and clearly describe the destination content.

Use case and exception scenarios

  • Use within sections of a page with multiple sections of content.
  • Do not use tabs when there would be more than six tabs in a group.
  • Do not use tabs when a user needs to see all the information contained within them in the same view (eg. when making comparisons).

Examples

Standard primary tabs

  • Standard tabs should be used by default.
  • All the content is loaded during page load and hidden using JavaScript behind tabs.
  • For non-JavaScript, all tab content is loaded running down the page with the tab headings reverting to a H2 heading with a full width keyline followed by the relevant content block.
  • Only apply accent colour classes to the block containing the .o-tabs-primary__heading class

Interactive example

Code example

<div class="l-section o-tabs-primary">
	<div class="o-tabs-primary__heading [accent colour modifiers]">
		<div class="l-content-container">
			<!-- Insert optional breadcrumb or wayfinder here -->			<!-- Single heading -->
			<h1 class="a-heading a-heading--1 [ Heading weight modifier ]">...</h1>
			<!-- or heading group ( H1 with H2 or H3 )-->
			<div class="m-heading-group">
				<h1 class="m-heading-group__item a-heading a-heading--1 [ Heading modifiers ]">...</h1>
				<p class="m-heading-group__item a-heading [ Heading modifiers ]">...</p>
			</div>
			<!-- End of heading -->			<!-- Insert optional button group, paragraph, notification card here -->
		</div>
	</div>
	<div class="o-tabs-primary__tabs m-tabs" data-module="m-tabs" data-module-load="true">
		<h2 class="a-heading a-heading--2 a-heading--light m-tabs__heading">...</h2>
		<div class="m-tabs__content">
			<div class="l-content-container">
				...
			</div>
		</div>
		...
	</div>
</div>

Primary tabs with sub-headings

  • Optional sub-headings can be applied to tabs, but must not be used in conjunction with icons within the tab heading.

Interactive example

Code example

<div class="l-section o-tabs-primary">
	<div class="o-tabs-primary__heading [accent colour modifiers]">
		<div class="l-content-container">
			<!-- Insert optional breadcrumb or wayfinder here -->			<!-- Single heading -->
			<h1 class="a-heading a-heading--1 [ Heading weight modifier ]">...</h1>
			<!-- or heading group ( H1 with H2 or H3 )-->
			<div class="m-heading-group">
				<h1 class="m-heading-group__item a-heading a-heading--1 [ Heading modifiers ]">...</h1>
				<p class="m-heading-group__item a-heading [ Heading modifiers ]">...</p>
			</div>
			<!-- End of heading -->			<!-- Insert optional button group, paragraph, notification card here -->
		</div>
	</div>
	<div class="o-tabs-primary__tabs m-tabs" data-module="m-tabs" data-module-load="true">
		<h2 class="a-heading a-heading--2 a-heading--light m-tabs__heading">...<span class="m-tabs__subheading">[ optional subheading ]</span></h2>
		<div class="m-tabs__content">
			<div class="l-content-container">
				...
			</div>
		</div>
		...
	</div>
</div>

Primary tabs with icons

  • Each icon should be made up as a single sprite with a fixed size of 156px x 50px, with the three versions of the individual icons (grey, blue and white) within it being no more than 50px square and centred horizontally at 26px, 78px and 130px (for sprites made up with icons with a 1:1 ratio icon, this will leave 1px blank space on either side of each icon within the sprite).

    Tab icon sprite example - car insurance
    Tab icon sprite example - car insurance
    Tab icon sprite example - spacing
    Tab icon sprite example - with visible indicators to show blank space either side of icons
  • Icons must not be used in conjunction with sub-headers within the tab heading.

Interactive example

Code example

<div class="l-section o-tabs-primary">
	<div class="o-tabs-primary__heading [accent colour modifiers]">
		<div class="l-content-container">
			<!-- Insert optional breadcrumb or wayfinder here -->			<!-- Single heading -->
			<h1 class="a-heading a-heading--1 [ Heading weight modifier ]">...</h1>
			<!-- or heading group ( H1 with H2 or H3 )-->
			<div class="m-heading-group">
				<h1 class="m-heading-group__item a-heading a-heading--1 [ Heading modifiers ]">...</h1>
				<p class="m-heading-group__item a-heading [ Heading modifiers ]">...</p>
			</div>
			<!-- End of heading -->			<!-- Insert optional button group, paragraph, notification card here -->
		</div>
	</div>
	<div class="o-tabs-primary__tabs m-tabs" data-module="m-tabs" data-module-load="true">
		<h2 class="a-heading a-heading--2 a-heading--light m-tabs__heading">
			<span class="m-tabs-icon">
				<img src="..." decoding="async" width="156" height="150" alt="" />
			</span>
		...</h2>
		<div class="m-tabs__content">
			<div class="l-content-container">
				...
			</div>
		</div>
		...
	</div>
</div>

Primary tabs with static links to external pages

  • Should only be used when you need to load new URLs for each tab's content, for example, when the page load times would be too heavy but you want better SEO.
  • The page it loads must have the same primary tabs header with the appropriate tab selected.
  • Do not load a new page without the same header and tabs.
  • For non-JavaScript, tab headings revert to a list of styled links which send users to static pages containing the content for that link, plus the content for the currently selected tab.
  • The example below is for visual representation only and has blanked links; there is a working example on a dedicated page.

Interactive example

Code example

<div class="l-section o-tabs-primary">
	<div class="o-tabs-primary__heading [accent colour modifiers]">
		<div class="l-content-container">
			<!-- Insert optional breadcrumb or wayfinder here -->			<!-- Single heading -->
			<h1 class="a-heading a-heading--1 [ Heading weight modifier ]">...</h1>
			<!-- or heading group ( H1 with H2 or H3 )-->
			<div class="m-heading-group">
				<h1 class="m-heading-group__item a-heading a-heading--1 [ Heading modifiers ]">...</h1>
				<p class="m-heading-group__item a-heading [ Heading modifiers ]">...</p>
			</div>
			<!-- End of heading -->			<!-- Insert optional button group, paragraph, notification card here -->
		</div>
	</div>
	<div class="o-tabs-primary__tabs m-tabs m-tabs--links" data-module="m-tabs" data-module-load="true">
		<div class="m-tabs__list">
			<div class="l-content-container">
				<ul class="a-list-plain">
					<li><a href="..." class="a-heading a-heading--3 a-heading--light m-tabs__heading">...</a></li>
					...
				</ul>
			</div>
		</div>
		<h2 class="a-heading a-heading--2 a-heading--light m-tabs__heading">...</h2>
		<div class="m-tabs__content" id="...">
			<div class="l-content-container">
				...
			</div>
		</div>
	</div>
</div>

Primary tabs with lazy-loading content

  • These tabs should be used when you need to load each tab separately because of heavy page load times or backend constraints.
  • They are poor for search engine optimisation (SEO) needs and shouldn't be used if SEO is important to your customer experience (eg. product pages).
  • For non-JavaScript, tab headings revert to a list of styled links which send users to static pages containing the content for that link, plus the content for the currently selected tab.

Interactive example

Code example

<div class="l-section o-tabs-primary">
	<div class="o-tabs-primary__heading [accent colour modifiers]">
		<div class="l-content-container">
			<!-- Insert optional breadcrumb or wayfinder here -->			<!-- Single heading -->
			<h1 class="a-heading a-heading--1 [ Heading weight modifier ]">...</h1>
			<!-- or heading group ( H1 with H2 or H3 )-->
			<div class="m-heading-group">
				<h1 class="m-heading-group__item a-heading a-heading--1 [ Heading modifiers ]">...</h1>
				<p class="m-heading-group__item a-heading [ Heading modifiers ]">...</p>
			</div>
			<!-- End of heading -->			<!-- Insert optional button group, paragraph, notification card here -->
		</div>
	</div>
	<div class="o-tabs-primary__tabs m-tabs m-tabs--links m-tabs--links-lazy" data-module="m-tabs" data-module-load="true">
		<div class="m-tabs__list">
			<div class="l-content-container">
				<ul class="a-list-plain">
				<li><a href="..." class="a-heading a-heading--3 a-heading--light m-tabs__heading">...</a></li>
					<li><a href="..." class="a-heading a-heading--3 a-heading--light m-tabs__heading">...</a></li>
					...
				</ul>
			</div>
		</div>
		<h2 class="a-heading a-heading--2 a-heading--light m-tabs__heading">...</h2>
		<div class="m-tabs__content" id="...">
			<div class="l-content-container">
				...
			</div>
		</div>
	</div>
</div>

Development and test

Notes for developers

Primary tabs are built to be used in conjunction with Section tabs, with the primary tab code acting as a wrapper at whole page level and restyling the elements contained within it. Please refer to the Section tabs documentation for notes regarding variants with subheadings or icons.

Primary tabbed content will require container classes such as <div class="l-content-container"> to align the content to the required grid layout.

By default the first tab will be opened on page load. This can be changed if required by applying js-m-tab-open to any m-tabs__heading.

A tab can be linked to and automatically opened by adding an ID to any .m-tabs__heading

Sub-headings

Optional sub headers can be applied to primary tabs when wrapped in a span using the .m-tabs__sub-heading class.

Icon tabs

Optional icons can be applied to both primary or section tabs when wrapped in a span using the .m-tabs-icon class.

Using accent colours

Only apply accent colour classes to the block containing the .o-tabs-primary__heading class

<div class="l-section o-tabs-primary">
	<div class="o-tabs-primary__heading [accent colour modifier classes]">
		<div class="l-content-container">
			<h1 class="a-heading a-heading--1">Primary tab heading</h1>
		</div>
	</div>
	...
</div>

Tabs with static links to external pages / tabs with lazy-loading content

The content for the initially loaded tab should be included in the page markup to ensure a suitable non-JavaScript fallback. Ensure that the id of this content div matches the link on the appropriate tab in the list.

Printing

It is possible to force the printing of all tab sections through the use of the modifier class o-tabs-primary--print. This should only ever be used to satisfy legal requirements for all information to be available when printed. The use of this feature should always be challenged, as if the content if legally important, it should probably not be hidden within tabs in the first place.

Controling tabs programatically

Primary tabs can be controlled programatically to open a specified tab and optionally scroll to it.

Method Description
open( '#headingId' ) Open the tab associated with the content ID provided. This will not open any parent tabs and will not scroll the content into view.
open( '#headingId', true ) Open the tab associated with the content ID provided. Any parent tab sections will be opened and the content will be scrolled into view.

For example:

document.addEventListener( 'frameworkready', function () {
	FRAMEWORK.require([ 'blocks/m-tabs' ], function ( mTabsModule ) {
		var mTabsEl = document.querySelector( '#tabsId' ),
			mTabsInstance = mTabsModule.initInstance( mTabsEl );		mTabsInstance.open( '#tabHeadingId', true );
	});
});

Changing locale settings

Locale settings should be updated to include appropriate translations for the 'Previous' and 'Next' messages to accompany the carousel arrows, and also for the message on the loading indicator for the tabs with lazy-loading content.

en: {
	mTabs : {
		previousText : 'Previous',
		nextText : 'Next',
		loadingText : 'Please wait',
	},
},

For more information on this, see our page on how to change locale settings within JavaScript.


Notes for testers

  • Ensure that links can be accessed via the mouse as well as via tabbing using the keyboard.
  • Use a screen reader to confirm that the links are understandable as to where they will be going when listed out of context of the page.
  • Ensure that when hovering over a link the style changes noticeably.
  • Ensure that when a link has focus the style changes noticeably.
  • There should be a clear visual distinction between the currently selected tab and the others.
  • The whole of the tab must look and be clickable.
  • When JavaScript is not available, the tabs should fall back to being headings followed by content. Tabs with static links and tabs with lazy-loading content should display a list of links followed by a single heading and content block relevant to the currently selected tab.

Classes overview

The following table gives you a quick overview of the CSS classes that can be applied.

Class Outcome Required Applied to Comments
.o-tabs-primary Base style for primary tab area Yes div Acts as a wrapper at whole page level and restyles the elements contained within
.o-tabs-primary--print Modifier to force the print of all tab sections   .o-tabs-primary  
.o-tabs-primary__heading Base style for main heading Yes .o-tabs-primary > div  
.o-tabs-primary__tabs Base style for tab headings Yes .o-tabs-primary__heading + div Used in conjunction with section tabs

Keyboard operations

TAB

Tabbing to an anchor should make the anchor clearly visually different so that the focus point on the page is obvious to the user.

SPACE or ENTER

With focus on an anchor, pressing SPACE or ENTER will open the link. If the link is internal to the page it will scroll the page otherwise it will load the new page.

Component releases

  • Added on: v3.1.0 (08/12/17)
  • Updated on: v5.9.0 (13/07/21)

Latest update:

  • updated: Primary tabs can be controlled programatically to open a specified tab and optionally scroll to it.

Full version history

A full history of changes and enhancements detailing all minor and major updates to the component.

View full version history

Want something new in Framework, or to chat about an issue you're having with it?

Contact the team