The Ultimate MUI AppBar Position Tutorial: Z-Index and Height

The Material UI AppBar is a useful component for creating top of page toolbars, menus, and logos. However, sometimes it is challenging to keep the AppBar from covering content. It can also be a challenge to position the height and z-index.

In this tutorial we will show how to create an AppBar that does not block content. Here’s what we will create:

MUI AppBar Height and Z-Index Example
MUI AppBar Height and Z-Index Example

Full code for this tutorial is in the Resources section.

How to Customize AppBar Z-Index

The AppBar is one of eight components in MUI v5 that has a default z-index on the theme object. It’s value is set to 1100. This is just a relational value that places it above some components (like the mobile stepper) and below other components (like the drawer).

If we have a component that does not have a theme on the z-index, but we want it to be higher than the AppBar, we have a couple of options. One is to create a custom theme and add a new z-index to it as seen in the code below:

const CustomTheme = createTheme({
  zIndex: {
    button: 1125
  }
});

We have a new field on the theme.zIndex object called button, but it does not auto-apply to buttons. We’d have to add the zIndex, for example through the sx prop:

<Button sx={{ zIndex: customTheme.zIndex.button}} />

If we don’t want to add a value to the theme, we can use a trick like this to make a component’s z-index higher than the AppBar’s:

<Button sx={{ zIndex: theme.zIndex.appBar + 1 }} />

In my tutorial I wanted the AppBar to be above the Drawer. I couldn’t simply do something like the below because it wouldn’t be interpreted as 1100 + 1.

<AppBar sx={{ zIndex: `drawer` + 1}} />

Instead I had to pass in a theme object to a styling value so I could access the theme:

const themedStyles = (theme: Theme) => {
  return {
    appBar: {
      zIndex: theme.zIndex.drawer + 1
    },
  }
}

const theme = useTheme();

return (
  <AppBar position="fixed" sx={themedStyles(theme).appBar}>
)

How to Set AppBar Height

The height of the AppBar is dynamic and based on the height of the content. The default height is 0, so it can be easy to “lose” the AppBar if you haven’t yet given it any child components.

A common child component is the Toolbar. It has a minimum height of 64px:

MUI AppBar height
MUI AppBar height

If you want to set a minimum height for the AppBar that is higher than the Toolbar or without using a Toolbar, simply add the following code to the AppBar:

<AppBar position="fixed" sx={{ minHeight: "5rem" }}>

Of course, choose whatever value you desire. Using minHeight is important because it will let your AppBar expand vertically to contain its children while still giving a desired minimum vertical structure to your component.

What to Do If the AppBar Covers Content

If your AppBar is covering the main content or perhaps covering a drawer, consider the following options:

  • Review the children components in the AppBar and add the same component to the Drawer/main. For example, if the AppBar contains a Toolbar, add an empty Toolbar to the top of the Drawer
  • Use a const for the height of the AppBar and the same const for the marginTop of components inside the main or Drawer components

Here’s a code example of adding the Toolbar above the main component:

<Toolbar />
<main style={{ ...themedStyles(theme).content }}>
  <Typography>App Content Area</Typography>
</main>

The Toolbar has a minimum height even if it has no contents, so it pushes the main component down on the y-axis and makes the main component not hidden behind the AppBar.

Here’s an example of setting the marginTop. In this case, I knew the Toolbar minHeight was 64px, so I set the marginTop to 4rem (64px in this case):

<Drawer>
  <List sx={{ mt: "4rem" }}>
</Drawer>
MUI AppBar Covers Content Example
MUI AppBar Covers Content Example

Resources

Here’s how to control the Drawer styling.

Here is the fill code for this tutorial:

import { AppBar, Drawer, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Toolbar, Typography } from "@mui/material"
import { useTheme, Theme } from "@mui/material/styles";
import AppsIcon from "@mui/icons-material/Apps";

const drawerWidth = 240;

const themedStyles = (theme: Theme) => {
  return {
    menuButton: {
      marginRight: 2
    },
    appBar: {
      zIndex: theme.zIndex.drawer + 1
    },
    drawer: {
      width: drawerWidth,
      "& .MuiBackdrop-root": {
        display: "none"
      }
    },
    drawerPaper: {
      width: drawerWidth,
      backgroundColor: "rgba(120,120,120,0.2)"
    },
    content: {
      padding: 3,
      maxWidth: 720,
      minWidth: 375,
      marginLeft: drawerWidth + 8,
    }
  }
}

export default function CustomZIndexAppBar() {
  const theme = useTheme();

  return (
    <div>
      <AppBar position="fixed" sx={{ ...themedStyles(theme).appBar }}>
        <Toolbar>
          <Typography variant="h6" noWrap>
            MUI AppBar
          </Typography>
        </Toolbar>
      </AppBar>
      <Drawer
        disableEnforceFocus
        variant="temporary"
        open={true}
        sx={themedStyles(theme).drawer}
        PaperProps={{
          sx: themedStyles(theme).drawerPaper,
          elevation: 9
        }}
      >
        {/* <Toolbar /> */}
        <List sx={{ mt: "4rem" }}>
          {["Home", "Page 1", "Page 2", "Page 3"].map((text, index) => (
            <ListItem key={text}>
              <ListItemButton>
                <ListItemIcon>
                  <AppsIcon />
                </ListItemIcon>
                <ListItemText primary={text} />
              </ListItemButton>
            </ListItem>
          ))}
        </List>
      </Drawer>
      <Toolbar />
      <main style={{ ...themedStyles(theme).content }}>
        <Typography>App Content Area</Typography>
      </main>
    </div>
  )
}
Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.