Material-ui: v1: tabs that are scrollable do not center

Created on 10 Feb 2018  路  23Comments  路  Source: mui-org/material-ui

  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

Tabs that receive the prop centered should always center.

Current Behavior

They remain left aligned if they are also set scrollable.

Steps to Reproduce

https://codesandbox.io/s/kk371k1w75

Your Environment

| Tech | Version |
|--------------|---------|
| Material-UI | @next |
| React | 16.2.0 |
| browser | chrome |

Tabs good first issue

Most helpful comment

I have an alternate solution for centered + scrollable tabs and is not dependent on media queries, so works with dynamic number of tabs. Seems to work in Chrome, Firefox and Safari. Does anyone see any issues with this approach?

https://codesandbox.io/s/material-ui-centered-scrollable-tabs-ud26w

All 23 comments

@barbalex Good catch! We should add a warning about it. It's not possible.

@oliviertassinari Sad that it is not possible. Because this seems like the feature that would make tabs work well from huge to tiny screen sizes.

@oliviertassinari Would this not work if the tabs were per css centered div's whose bottom border is highlighted when the tab is active?

I'm sure this is very naive and there are good reasons it is not solved that way. But I'm curious.

@barbalex I try to do some changes for this issue and I think we can to do something. I should think

any update on this? or a work around? I would love to use scrollable tabs at smaller viewports while keeping them centered at larger viewports

any update on this? or a work around?

@KyleAsaff The plan going forward is to add a warning to prevent people from reaching this set of properties.

I would love to use scrollable tabs at smaller viewports while keeping them centered at larger viewports

You can dynamically toggle properties based on the screen width with the withWidth() higher order component. I think that we should better document this module.

Thanks @oliviertassinari! For anyone looking for a workaround, I created one using react-measure. I have pasted the relevant portion of the code in the snippet below:

import React from 'react';
import { Link, withRouter } from 'react-router-dom';
import AppBar from 'material-ui/AppBar';
import Tabs, { Tab } from 'material-ui/Tabs';
import Measure from 'react-measure';

class Navigation extends React.Component {

  state = {
    appBarWidth: 1179,
  }

  render() {
    const { navigation } = this.props;
    const { appBarWidth } = this.state;

    return (
      <div>
        <Measure
          bounds
          onResize={(contentRect) => {
            this.setState({ appBarWidth: contentRect.bounds.width });
          }}
        >
          {({ measureRef }) => (
            <div ref={measureRef}>
              <AppBar position="static" color="default">
                <Tabs
                  value={navigation.value}
                  onChange={this.handleChange}
                  indicatorColor="primary"
                  textColor="primary"
                  scrollButtons="auto"
                  centered={appBarWidth > 1179}
                  scrollable={appBarWidth < 1179}
                >
                  <Tab label="Overview" component={Link} to="/overview" />
                  <Tab label="PDP" component={Link} to="/ecomm/pdp" />
                  <Tab label="Shoppable Galleries" component={Link} to="/ecomm/shoppable_galleries" />
                  <Tab label="Shoppable Instagram" component={Link} to="/ecomm/shoppable_instagram" />
                  <Tab label="Brand Emails" component={Link} to="/email/brand_emails" />
                  <Tab label="Shopping Cart Abandonment" component={Link} to="/email/shopping_cart_abandonment" />
                </Tabs>
              </AppBar>
            </div>
            )}
        </Measure>
      </div>
    );
  }
}

@KyleAsaff react-measure is a good solution you can also use material-ui/withWidth or react-virtualized/AutoSizer.

@KyleAsaff thank you for sharing your code, it helped me so much for this kind of problem

What about dynamic tabs?
This won't work when I build the tabs dynamically. centered on scrolleable is a must.
Any suggestions?

I don't understand why centered tabs can't be scrollable (therefore left-aligned) after the container width has been becoming smaller than its content 馃

I'd also like to be able to combine these, if it's feasible.

Found a simple solution if you want the fullWidth style (where the tabs spread to cover the entire area) instead of the centered style (where they're bunched up in the middle).

First, turn off centered, and turn on fullWidth and scrollable. Then just add a flexShrink: 0 style to each of the Tab components. This overrides the shrinking that fullWidth normally allows. Since we're scrolling, we don't want shrinking.

what's good @jacobweber !! that's clutch, great call right there. Seconding that as a solution. It's super slick to use the fullWidth and scrollable, definitely looks the best. And setting each tab to flexShrink: 0 prevents them from overlapping as they would without the additional css. Thanks again!

Oops. @jacobweber 's great workaround seems not to work any more since last update: https://github.com/mui-org/material-ui/pull/13980

:-(

Not being able to center and scroll looks broken on desktop.

@barbalex Try adding flexGrow: 1 instead. Looks like the defaults have changed.

Did something change?

I was able to make it centered with two lines of css.

Setting flex-grow: 0 on MuiTabs-scroller and justify-content: center on first MuiTabs-flexContainer in the tabs tree.

Works perfectly, unless I am missing something. @oliviertassinari do you want me to make a PR?

Add variant="scrollable" prop to Tabs and omit centered prop.

Then add

@media (min-width: 768px) {
  .MuiTabs-flexContainer {
    justify-content: center;
  }
}

to center on larger screens.

I have an alternate solution for centered + scrollable tabs and is not dependent on media queries, so works with dynamic number of tabs. Seems to work in Chrome, Firefox and Safari. Does anyone see any issues with this approach?

https://codesandbox.io/s/material-ui-centered-scrollable-tabs-ud26w

related to @jacobweber answer, the magic margin: auto instead of flexShrink: 0 works for me :)

variant: fullWidth and styling margin: 'auto' works for me.

I would suggest to please address this issue in the API section. centered is still not working..

A workaround that works across all viewports could be this. Not adding the breakpoint breaks the tabs on small viewports.

variant="scrollable"

tabs:{
    [theme.breakpoints.up("md")]: {
      margin:'auto'
    }

  }

Hope this helps!

If anyone is still looking for a solution. Here is my approach

const scrollableTabs = useMediaQuery(theme.breakpoints.down('sm'));
<Tabs variant={scrollableTabs ? "scrollable" : "centered" } scrollButtons="on" centered>
</Tabs>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

zabojad picture zabojad  路  3Comments

reflog picture reflog  路  3Comments

ghost picture ghost  路  3Comments

iamzhouyi picture iamzhouyi  路  3Comments

sys13 picture sys13  路  3Comments