Site icon Ampersand Tutorials

Materialize CSS Tabs: Complete Guide with Examples

Quick answer: A Materialize tab set is a ul.tabs whose each li.tab contains an anchor pointing at a div#id pane. Materialize 1.0.0 does not initialise tabs for you — you must call M.Tabs.init(document.querySelectorAll('.tabs')), or run M.AutoInit() to cover every component on the page. Add the tabs-fixed-width class to spread the tabs evenly across the width. The usual mistake is forgetting the init call, which leaves the tabs styled but dead.

Part of our Materialize series. If the framework is not on your page yet, run the Materialize CSS tutorial first for the CDN setup.

Working tabs in one block

The structure is a list of triggers followed by the content panes. Each anchor’s href matches a pane id, which is how Materialize knows what to show.

<ul class="tabs">
  <li class="tab col s6"><a class="active" href="#overview">Overview</a></li>
  <li class="tab col s6"><a href="#pricing">Pricing</a></li>
</ul>

<div id="overview" class="col s12">Overview content.</div>
<div id="pricing" class="col s12">Pricing content.</div>
document.addEventListener('DOMContentLoaded', function () {
  M.Tabs.init(document.querySelectorAll('.tabs'), {
    swipeable: true,
    duration: 300,
  });
});

The active class on the first anchor is the initial state. Because each tab is a real anchor, Materialize also updates the URL hash, which means a reload lands on the same tab — useful for shareable links. The panes themselves do not need any special class; the col s12 classes only apply if you are placing them inside a row of the grid.

Classes and options

Class or optionWhereEffect
tabs-fixed-widthon the ulEvery tab shares an equal width
col s6 / s4on each liSets the width of a tab on the 12-column grid
activeon one anchorMarks the tab open on load
swipeableJS optionAllows swiping between panes on touch devices
durationJS optionTransition length in milliseconds
responsiveThresholdJS optionSwitches to the mobile layout below this width
ComponentHow options are shownChoose it when
TabsAll headings visible at onceTwo to six short panels the user compares
DropdownOne label, options on clickMany options, or a single action menu
CarouselOne panel, advanced by controlOrdered, story-like content
CollapsibleStacked headers, open in placeLong content on small screens

Fixed-width versus responsive

By default Materialize tabs size themselves to their content, so two short tabs sit at the left while four long ones nearly fill the bar. Add tabs-fixed-width when you want a predictable, evenly divided strip. On narrow screens the plugin can switch to a scrollable “swipe” layout; set responsiveThreshold to the breakpoint where that should happen.

<ul class="tabs tabs-fixed-width">
  <li class="tab"><a href="#a">One</a></li>
  <li class="tab"><a href="#b">Two</a></li>
  <li class="tab"><a href="#c">Three</a></li>
</ul>

Switching tabs from code

You can select a tab programmatically, which is handy after a form save or when a deep link needs to open a specific pane. The instance exposes a select method that takes the pane id.

const instance = M.Tabs.getInstance(document.querySelector('.tabs'));
instance.select('pricing');

// Recalculate indicator positions after the tab bar's size changes
instance.updateTabWidth();

Call updateTabWidth() whenever the tab bar is revealed after being hidden — for example inside a modal or a sidenav. Materialize measures tab widths at init time, so a bar that started with a width of zero draws its underline in the wrong place until you ask it to recalculate.

Common mistakes

Tabs behave much like a dropdown menu or an carousel in that they all switch between named panels — the difference is that tabs keep every option visible at once. For the button styling used inside panes, see the Materialize buttons guide.

Building a settings screen with several tabbed sections? Ampersand Academy teaches front-end development one-to-one, using your own project as the curriculum.

Frequently asked questions

Why are my Materialize tabs not switching?

The tabs were probably never initialised. Call M.Tabs.init on the tab elements, or run M.AutoInit, and confirm each anchor href matches the id of its content pane.

How do I make Materialize tabs equal width?

Add the tabs-fixed-width class to the ul. Every tab then takes an equal share of the bar instead of sizing to its own label length.

How do I open a specific Materialize tab on page load?

Put the active class on the anchor for that tab, or link to the page with the matching hash. On initialization you can also call the instance select method with the pane id.

Why is the Materialize tab indicator in the wrong position?

The bar was likely measured while hidden or before the layout settled. Call updateTabWidth on the tab instance after it becomes visible to recalculate the indicator.

Can Materialize tabs be swiped on mobile?

Yes. Set the swipeable option to true when initialising. Materialize then allows dragging horizontally between panes on touch devices.

Exit mobile version