I have almost 30 tabs inside Material UI Tabs, the user has to scroll two times to see all the tabs, I would like to show the tabs in two rows with scroll instead of one row with scroll, this will help the user to see most of the tabs in one glance.
How can I do something like this ?, I looked over Material UI document but i couldn't find anything useful, I tried manually giving it CSS style but I wasn't able to achieve my goal (my CSS skills are mediocre).
To show what I mean by multiple row tabs
, here is a sample image :
Any help is much appreciated.

- 701
- 6
- 27
-
1https://codesandbox.io/s/o7pmooy636?file=/gotabs.js:1167-1179 – DevLoverUmar Dec 12 '20 at 11:36
-
this may be helpful – DevLoverUmar Dec 12 '20 at 11:36
-
@DevLoverUmar Instead of having subTabs, i want the tabs to be in two rows, i don't want to create category, i just want to make the current tabs easier to access and see – Ali Ahmadi Dec 13 '20 at 07:55
5 Answers
You can set flexWrap: 'wrap' in the tab container component which is a flexbox:
<Tabs
// disable the tab indicator because it doesn't work well with wrapped container
TabIndicatorProps={{ sx: { display: 'none' } }}
sx={{
'& .MuiTabs-flexContainer': {
flexWrap: 'wrap',
},
}}
{...}
>
https://codesandbox.io/s/69733826-material-ui-responsive-tabs-5q57p?file=/demo.js

- 116
- 2
- 11
I did a little hack:
Use 2 different Tabs components and adjust indexes:
<Box sx={{ display: 'flex',justifyContent: 'center', flexWrap: 'wrap'}}>
<Tabs value={value} onChange={handleChange}>
<Tab label='Precios'/>
<Tab label='Usuarios'/>
<Tab label='Plan'/>
</Tabs>
<Tabs value={value - 3 } onChange={handleChange2}>
<Tab label='Empleados'/>
</Tabs>
</Box>
And manage change for this adjustment:
const handleChange = (event, newValue) => {
setValue(newValue);
};
const handleChange2 = (event, newValue) => {
setValue(newValue + 3);
};
You just change the number 3 for the number of tabs in your first component.
Saludos

- 21
- 1
-
This could actually work, but it needs quite a bit of coding to refine it into a usable component, for one thing I think we can make the number of `tabs` dynamic so u can define the number of rows, another thing to consider is the scroll, using scroll variant tabs will be difficult to handle and will result in a bad UX, I think its best if we make our own scroll so each `tabs` doesn't have an scroll – Ali Ahmadi Feb 19 '22 at 18:40
I am struggling with similar problem. I have gone throw the documentation and looks like this is not possible using Tabs/Tab features. For now I can see two options:
- Use properties variant="scrollable" and scrollButtons="auto" like mentioned above. This will not give you what you expected but at least it is working.
- Implement your own tabs. You can use Grid for it. Below example is just to show an approach. It is not redy solution, but it can be easily adjusted.
const useStyles = makeStyles((theme) => ({
navigationLinkContainer: {
// up to you
},
navigationLinkButtonActive: {
color: '#ffffff',
// up to you
},
}));
const NavigationLink = (props) => {
const classes = useStyles();
return (
<Grid item className={classes.navigationLinkContainer}>
<Button
component={Link}
onClick={props.onClick}
>
{props.children}
</Button>
</Grid>
);
};
const NavigationHeaders = (props) => {
const classes = useStyles();
const { headers, className } = props;
const [activeTab, setActiveTab] = React.useState('');
const isActive = (headerId) => headerId === activeTab;
return (
<>
<Grid container >
{headers.map((header) => (
<NavigationLink
className={classnames(isActive(header.id) && classes.navigationLinkButtonActive)}
key={header.id}
onClick={() => setActiveTab(header.id)}
>
{header.title}
</NavigationLink>
))}
</Grid>
{/* some content here shown base on activeTab */}
</>
);
};
I also came to the conclusion that this is not currently possible with Tabs/Tab. I tried using <br />
, <hr />
, <Divider />
, functions to insert breaks, making multiple rows of tabs (which messed up selection), wrapping Tabs in span
with max-width
(also messed up selection), you name it. I ultimately decided to use scroll on small screens.
I figured out the smallest screen size that would show my tabs properly, then used scroll for any smaller.
const mql = window.matchMedia('(max-width: 2000px)');
const smallScreen = mql.matches;
<Tabs
value={tabValue}
onChange={handleTabChange}
orientation="horizontal"
variant={smallScreen ? 'scrollable' : 'standard'}
centered={!smallScreen}
>
<Tab label="1" />
<Tab label="1" />
<Tab label="3" />
<Tab label="4" />
<Tab label="5" />
</Tabs>
You could add an event handler to change on resize, but was not necessary for my use case

- 31
- 7
Try going through the doc of any stuff you use to safe unnecessary problems in future
visit this for more details and full code https://material-ui.com/components/tabs/
<div className={classes.root}>
<AppBar position="static">
<Tabs value={value}
onChange={handleChange}
aria-label="simple tabs example"
indicatorColor="primary"
textColor="primary"
variant="scrollable"
scrollButtons="auto"
aria-label="scrollable auto tabs example"
>
<Tab label="Item One" {...a11yProps(0)} />
<Tab label="Item Two" {...a11yProps(1)} />
<Tab label="Item Three" {...a11yProps(2)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
Item One
</TabPanel>
<TabPanel value={value} index={1}>
Item Two
</TabPanel>
<TabPanel value={value} index={2}>
Item Three
</TabPanel>
</div>
Edit: please notice the variant in Tabs

- 6,687
- 5
- 44
- 67
-
1I think you misunderstood my question, i know how to use tabs, what i want to do is show all the `
`s in two rows and if there is no space for them, then an scroll is enabled, right now the ` `s are shown in a single row. – Ali Ahmadi Dec 14 '20 at 17:05 -
1Your example doesn't achieve what I described, please take a look a this demo which shows what i mean by two rows, the third example titled "TabStrip in two rows" : https://demos.telerik.com/aspnet-ajax/tabstrip/examples/functionality/scrolling-and-multi-row-tabs/defaultcs.aspx – Ali Ahmadi Dec 14 '20 at 20:44