How to Add MUI Badges to Tabs, Buttons, and Components in Containers

A difficult challenge when using Material-UI Badges is making sure they don’t get cut off or hidden when they overflow a component. Badges on the Tab component have this problem.

Another challenge is making sure Badges don’t expand with a container and position far away from their anchor component. Badges on Buttons inside of Stacks are an example of this problem.

Here’s the Tab and Button Badges without proper styling. No, I didn’t accidentally cut off the Tab badge when I took the screenshot.

MUI Tab and Button Badge Problem
MUI Tab and Button Badge Problem

We’ll resolve these issues with purely CSS solutions using the MUI v5 sx prop. Along the way we will gain a better knowledge of default MUI classes on Badges, Tabs, and Buttons and use these classes to create valuable nested selectors.

Here’s what the proper Badge rendering looks like:

MUI Tab and Button Badge Solution

Full Code examples are in the sections below.

How to Add a Material-UI Badge on the Tab Component

By default, a Badge on a Tab is rendered with its top half invisible. This is due to the Tabs component wrapper around a Tab.

MUI Tab with Badge
MUI Tab with Badge

The Tabs wrapper is a series of three divs, each with default styling of overflow: hidden. Even worse, two of these have overflow styling inline, making it harder to override.

I have identified two methods for fixing this. One of them is cleaner from a code perspective, but it adds extra height to the layout. The other uses !important, which feels bad but is necessary when MUI applies inline styling by default.

Here’s how to style the tab indicator.

Tab Badge with Padding-Top

We can simply add paddingTop: 12px to the Tabs sx prop and target the MuiTabs-flexContainer class. However, you may not want to add 12px of height to your layout.

<Tabs
  value={value}
  onChange={handleChange}
  aria-label="tabs with badge"
  sx={{ "& .MuiTabs-flexContainer": {paddingTop: "12px"} }}
>
  <Badge badgeContent="t1" color="error">
<Tab label="Tab One" />
  </Badge>
  <Tab label="Tab Two" />
  <Tab label="Tab Three" />
</Tabs>

This added 12 pixels of top padding to the lowest nested containing Tabs div. Overflow is still hidden, but now there is room for the badge.

Tab Badge with Overflow: Visible

The other option is to add overflow: visible using the sx prop.

sx={{overflow: "visible", "& .MuiTabs-scroller": {overflow: "visible !important"}}}

The first styling adjusts the overflow on the top div.

The second, which targets MuiTabs-scroller class, requires !important due to the inline styling applied to this div by default. Since we only have the option of targeting using the sx prop, which generates a class, we can only override inline styling with !important.

How to Add a Material-UI Badge on a Button Component Inside a Stack

It is simple to add a Badge to an MUI Button and get the desired result when the Button is alone. It is challenging to get the Badge to position properly when the Button is wrapped in a containing component:

MUI Button Badge Position
MUI Button Badge Position

In this example I have a Stack component wrapping Tabs and a Button. The Button has a Badge. Unfortunately, the Badge is positioning to the far right of the available space.

MUI Badge in Container
MUI Badge in Container

The reason this happens is because the Badge renders a wrapping span around the Button. The Button is an appropriate width based on it’s contents, but the span is the length of the parent Stack wrapper.

We can fix this by adding maxWidth: max-content to the Badge. See the example code:

<Stack>
  <Tabs/>
  <Badge badgeContent="BB" color="error" sx={{maxWidth: "max-content"}}>
    <Button variant="contained">Badge Me!</Button>
  </Badge>
</Stack>

Resources and Related Links

Check out these additional useful MUI posts:

MUI Badge Docs

Share this post:

Leave a Comment

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