How to Style the Material-UI Tooltip

The Material-UI Tooltip is an exceptionally well designed component. It has a number of props delivering great versatility for numerous use cases. However, styling the MUI Tooltip is still a manual process that requires a strong grasp of CSS.

In this Tutorial I will demonstrate how to style the Tooltip in many ways, including width, height, padding, margin, text font and color, background color, and more. Below is a screenshot of the component we will create. The text is long to demonstrate a line break at the end of the first sentence.

Styled MUI Tooltip
Styled MUI Tooltip

IMPORTANT!!! An important styling feature of the Tooltip is that you can style it either using the styled API and apply the popper class from the props like below:

const StyledTooltip = styled(({ className, ...props }) => (
  <Tooltip {...props} classes={{ popper: className }} />
))(({ theme }) => ({
  //...styling values
  }
}));

OR you can style it by passing the sx prop to the PopperProps prop:

PopperProps={{
  sx: {
    "& .MuiTooltip-tooltip": {
      border: "solid skyblue 1px",
      color: "deepskyblue"
    }
  }
}}

Full code is in the Resources section, as well as a Code Sandbox live example link. Here’s a tutorial on how to customize Tooltip position and internal components, plus styling the anchor arrow.

Material-UI Tooltip Imports

Here are the MUI v5 imports for Tooltip, as well as other imports used in my tutorial:

import Tooltip, { tooltipClasses } from "@mui/material/Tooltip";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import { styled } from "@mui/material/styles";

The tooltipClasses import is a useful way to get access to all the names of CSS classes applied by default to the tooltip. Tooltips use a popover component, and it can be hard to examine those in the DOM and see classes needed for styling (a hack for this is to set the leaveDelay prop to a high value. Then it will stay open after hovering so you can click the tooltip popover and examine it’s DOM contents).

Here are the v4 imports for tooltip if you have not yet upgraded:

import Tooltip from '@material-ui/core/Tooltip';

MUI Tooltip DOM and All Classes

I set leaveDelay={2000000} and was able to examine the DOM. Below is a screenshot before I added custom styling.

MUI Tooltip DOM
MUI Tooltip DOM

Notice the tooltip is composed of two divs. The first is generated as a “Popover”, and you can see evidence of that in the class names. The second is the actual Tooltip contents. Most styling will be applied to the tooltip contents, which means we need to use the MuiTooltip-tooltip class seen below.

MUI Tooltip Classes
MUI Tooltip Classes

This list above is all the default classes applied to the Tooltip component. I console logged the tooltipClasses import to get this list.

MUI Tooltip Width and Height

The first styling I applied was width and height. For this styling and all the others below, I had to use the styling API as mentioned in the intro.

[`& .MuiTooltip-tooltip`]: {
  maxWidth: 250,
  height: 50,
}

Notice that I had to target the child div with nested selector .MuiTooltip-tooltip.

An alternative way I could have accessed the selector is below. This makes use of the tooltipClasses import.

[`& .${tooltipClasses.tooltip}`]: {
  maxWidth: 250,
  height: 50,
}

MUI Tooltip Font, Text Color, Background Color, and Border

Next up was styling the text and color:

[`& .MuiTooltip-tooltip`]: {    
  fontFamily: "'Grape Nuts', Helvetica",
  color: "deepskyblue",
  backgroundColor: "rgba(255,255,0,0.4)",
}

The color and background color are applied to the child div. These could have been applied to the parent div (the one with popover class), but it takes up more space than the visible popup, so you have a strangely large background color to your tooltip.

Furthermore, applying background color at this level overrides the background color applied by default.

If you don’t have Google Fonts imported, you won’t have access to the Grape Nut font.

Just to test things, I applied the border using sx instead of the styled API. Since the styled API is setting the popper class, it works.

sx={{
  "& .MuiTooltip-tooltip": {
    border: "solid skyblue 1px"
  }
}};

As mentioned in the intro, if you want to directly style with sx instead of styled API, pass the sx prop value to the PopperProps. The MUI DatePicker also is styled using PopperProps.

MUI Tooltip zIndex

The syntax for applying the zIndex was a bit tricky.

First, I had to properly make the theme available to the styled component. Then I had to access the proper fields on the object, and the MUI v5 syntax is a bit different than v4.

const StyledTooltip = styled(({ className, ...props }) => (
  <Tooltip {...props} classes={{ popper: className }} />
))(({ theme }) => ({
  zIndex: theme.zIndex.tooltip + 1  
}));

Notice that I have the zIndex at the top level of the popover. Unlike the rest of the styling, we want to make sure the entire popover benefits from the zIndex.

To test this, I created a second Button with Tooltip. I was sure to hover over the higher zIndex Tooltip first so that it would naturally render ‘below’ the lower zIndex Tooltip. Then the power of the zIndex kicked in, and the higher value zIndex Tooltip was placed on top of the lower value Tooltip:

MUI Tooltip zIndex Example
MUI Tooltip zIndex Example

MUI Tooltip Spacing (Padding and Margin)

Padding was simple to set and to understand. Padding needs to be added to the child div and creates space between the content and the border.

Margin was simple to set, but it’s effects are trickier. If I set it on the parent div, it was overridden. If I set it on the child div, it’s effects are taken into account after adjusting for any margin and transformation on the parent. I recommend not adjusting the margin because it may produce unexpected effects.

[`& .MuiTooltip-tooltip`]: {
  margin: 4,
  padding: 8

}

MUI Tooltip with Line Break and Wrap

Adding a line break in your text requires a CSS value and an escape character.

First, set this value:

[`& .MuiTooltip-tooltip`]: {
  whiteSpace: "pre-line"
}

This enables proper processing of the line break escape character: “\n”.

Wherever you want to force a line break, add the escape character. I did it in the following place: “I have a lot of good things to say about MUI!\n It’s the greatest….”.

The forced line break is like a controlled wrap. You can also set other wrap values like whiteSpace: “nowrap” to eliminate wrapping and whiteSpace: “wrap” (the default) to have natural wrapping.

Resources and Related Posts

Here’s a demo that shows how to add a ToolTip to a disabled component.

Here is the full code for this tutorial:

import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import { styled } from "@mui/material/styles";
import Tooltip, { tooltipClasses } from "@mui/material/Tooltip";

const StyledTooltip = styled(({ className, ...props }) => (
  <Tooltip {...props} classes={{ popper: className }} />
))(({ theme }) => ({
  zIndex: theme.zIndex.tooltip + 1,
  //margin: 4,
  [`& .MuiTooltip-tooltip`]: {
    maxWidth: 200,
    height: 100,
    fontFamily: "'Grape Nuts', Helvetica",
    backgroundColor: "rgba(255,255,0,0.4)",
    //color: "deepskyblue", see sx value
    margin: 4,
    padding: 8,
    whiteSpace: "pre-line"
    //border: "solid yellow 1px"
  }
}));

const soManyWords =
  "I have a lot of good things to say about MUI!\n  It's the greatest thing since sliced bread!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Super!";

//included just to show sx works if popper class gets props
const tooltipTop = {
  "& .MuiTooltip-tooltip": {
    border: "solid skyblue 1px",
    color: "deepskyblue"
  }
};

export default function BasicTooltip() {
  return (
    <Stack sx={{ alignItems: "flex-start" }} spacing={6}>
      <StyledTooltip
        title={soManyWords}
        //leaveDelay={2000000} //set to 100000000  to be able to examine the DOM
        placement="bottom"
        sx={tooltipTop} //works with styled component because it passes popper class
      >
        <Button sx={{ fontSize: 24 }}>Tooltip Below</Button>
      </StyledTooltip>
      {/* <Tooltip
          leaveDelay={2000000}
          PopperProps={{ sx: tooltipTop }} //here's how you 'directly' use sx
          title={soManyWords}
          placement="top"
        >
          <Button sx={{ fontSize: 24 }}>Tooltip Above</Button>
        </Tooltip> */}
    </Stack>
  );
}

Here’s a guide to the MUI Snackbar.

Here’s an article on styling the Popover component.

Code Sandbox Link

Tooltip API Docs

Share this post:

Leave a Comment

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