# Source: https://mui.com/material-ui/customization/typography.md

# Typography

The theme provides a set of type sizes that work well together, and also with the layout grid.

## Font family

You can change the font family with the `theme.typography.fontFamily` property.

For instance, this example uses the system font instead of the default Roboto font:

```js
const theme = createTheme({
  typography: {
    fontFamily: [
      '-apple-system',
      'BlinkMacSystemFont',
      '"Segoe UI"',
      'Roboto',
      '"Helvetica Neue"',
      'Arial',
      'sans-serif',
      '"Apple Color Emoji"',
      '"Segoe UI Emoji"',
      '"Segoe UI Symbol"',
    ].join(','),
  },
});
```

### Self-hosted fonts

To self-host fonts, download the font files in `ttf`, `woff`, and/or `woff2` formats and import them into your code.

:::warning
This requires that you have a plugin or loader in your build process that can handle loading `ttf`, `woff`, and
`woff2` files. Fonts will _not_ be embedded within your bundle. They will be loaded from your webserver instead of a CDN.
:::

```js
import RalewayWoff2 from './fonts/Raleway-Regular.woff2';
```

Next, you need to change the theme to use this new font.
In order to globally define Raleway as a font face, the [`CssBaseline`](/material-ui/react-css-baseline/) component can be used (or any other CSS solution of your choice).

```jsx
import RalewayWoff2 from './fonts/Raleway-Regular.woff2';

const theme = createTheme({
  typography: {
    fontFamily: 'Raleway, Arial',
  },
  components: {
    MuiCssBaseline: {
      styleOverrides: `
        @font-face {
          font-family: 'Raleway';
          font-style: normal;
          font-display: swap;
          font-weight: 400;
          src: local('Raleway'), local('Raleway-Regular'), url(${RalewayWoff2}) format('woff2');
          unicodeRange: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF;
        }
      `,
    },
  },
});

// ...
return (
  <ThemeProvider theme={theme}>
    <CssBaseline />
    <Box sx={{ fontFamily: 'Raleway' }}>Raleway</Box>
  </ThemeProvider>
);
```

Note that if you want to add additional `@font-face` declarations, you need to use the string CSS template syntax for adding style overrides, so that the previously defined `@font-face` declarations won't be replaced.

## Font size

Material UI uses `rem` units for the font size.
The browser `<html>` element default font size is `16px`, but browsers have an option to change this value,
so `rem` units allow us to accommodate the user's settings, resulting in a better accessibility support.
Users change font size settings for all kinds of reasons, from poor eyesight to choosing optimum settings
for devices that can be vastly different in size and viewing distance.

To change the font-size of Material UI you can provide a `fontSize` property.
The default value is `14px`.

```js
const theme = createTheme({
  typography: {
    // In Chinese and Japanese the characters are usually larger,
    // so a smaller fontsize may be appropriate.
    fontSize: 12,
  },
});
```

The computed font size by the browser follows this mathematical equation:

<div class="only-light-mode">
  <img alt="font size calculation" style="width: 550px; display: block;" src="/static/images/font-size.svg" width="436" height="48" />
</div>
<div class="only-dark-mode">
  <img alt="font size calculation" style="width: 550px; display: block;" src="/static/images/font-size-dark.svg" width="436" height="48" />
</div>

<!-- https://latex.codecogs.com/svg.latex?\dpi{200}&space;\text{computed}&space;=&space;\text{specification}\cdot\frac{\text{typography.fontSize}}{14}\cdot\frac{\text{html&space;fontsize}}{\text{typography.htmlFontSize}} -->

### Responsive font sizes

The `theme.typography.*` [variant](#variants) properties map directly to the generated CSS.
You can use [media queries](/material-ui/customization/breakpoints/#api) inside them:

```js
const baseTheme = createTheme();

const theme = createTheme({
  typography: {
    h3: {
      fontSize: '1.2rem',
      '@media (min-width:600px)': {
        fontSize: '1.5rem',
      },
      [baseTheme.breakpoints.up('md')]: {
        fontSize: '2.4rem',
      },
    },
  },
});
```

```tsx
import { createTheme, ThemeProvider } from '@mui/material/styles';
import Typography from '@mui/material/Typography';

const theme = createTheme();

theme.typography.h3 = {
  fontSize: '1.2rem',
  '@media (min-width:600px)': {
    fontSize: '1.5rem',
  },
  [theme.breakpoints.up('md')]: {
    fontSize: '2rem',
  },
};

export default function CustomResponsiveFontSizes() {
  return (
    <ThemeProvider theme={theme}>
      <Typography variant="h3">Responsive h3</Typography>
    </ThemeProvider>
  );
}

```

To automate this setup, you can use the [`responsiveFontSizes()`](/material-ui/customization/theming/#responsivefontsizes-theme-options-theme) helper to make Typography font sizes in the theme responsive.

```jsx
// import of a small, pure module in a private demo
// bundle size and module duplication is negligible

// eslint-disable-next-line no-restricted-imports
import { convertLength } from '@mui/material/styles/cssUtils';
import { createTheme, responsiveFontSizes } from '@mui/material/styles';
import Box from '@mui/material/Box';
import { LineChart } from '@mui/x-charts';

let theme = createTheme();
theme = responsiveFontSizes(theme);

const colors = [
  '#443dc2',
  '#2060df',
  '#277e91',
  '#378153',
  '#4d811d',
  '#63780d',
  '#996600',
];
const variants = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'subtitle1'];

export default function ResponsiveFontSizesChart() {
  const convert = convertLength(theme.typography.htmlFontSize);
  const toPx = (rem) => parseFloat(convert(rem, 'px'));

  let dataset = theme.breakpoints.keys.map((key) => {
    const viewport = theme.breakpoints.values[key];
    const value = theme.breakpoints.up(key);

    const rep = { viewport };
    variants.forEach((variantName) => {
      const variant = theme.typography[variantName];
      if (variant[value]) {
        const fontSize = toPx(variant[value].fontSize);
        rep[variantName] = fontSize;
      } else if (viewport === 0) {
        const fontSize = toPx(variant.fontSize);
        rep[variantName] = fontSize;
      }
    });
    return rep;
  });

  dataset = [
    ...dataset.slice(0, dataset.length - 1),
    {
      ...dataset[dataset.length - 2],
      viewport: dataset[dataset.length - 1].viewport,

      subtitle1: dataset[0].subtitle1,
    },
  ];

  return (
    <Box sx={{ height: 380, width: '100%', color: 'black' }}>
      <LineChart
        dataset={dataset}
        series={variants.map((variantName) => ({
          curve: 'stepAfter',
          dataKey: variantName,
          label: variantName,
          connectNulls: true,
        }))}
        xAxis={[
          {
            scaleType: 'linear',
            dataKey: 'viewport',
            valueFormatter: (value) => value.toString(),
            tickNumber: 10,
            max: 1600,
            tickLabelStyle: { fontSize: 15 },
            label: 'viewport (px)',
          },
        ]}
        yAxis={[
          {
            valueFormatter: (value) => value.toString(),
            tickNumber: 5,
            min: 0,
            max: 100,
            tickLabelStyle: { fontSize: 15 },
            labelStyle: {
              fontSize: 15,
            },
            label: 'font-size (px)',
          },
        ]}
        colors={colors}
        margin={{ left: 70 }}
        sx={{
          [`.MuiChartsAxis-left .MuiChartsAxis-label`]: {
            transform: 'translateX(-5px)',
          },
          [`.MuiChartsAxis-bottom .MuiChartsAxis-label`]: {
            transform: 'translateY(5px)',
          },
          [`.MuiChartsAxis-root text`]: {
            fill: '#808080',
          },
          [`.MuiChartsAxis-root line`]: {
            stroke: '#808080',
          },
        }}
      />
    </Box>
  );
}

```

You can see this in action in the example below. Adjust your browser's window size, and notice how the font size changes as the width crosses the different [breakpoints](/material-ui/customization/breakpoints/):

```js
import { createTheme, responsiveFontSizes } from '@mui/material/styles';

let theme = createTheme();
theme = responsiveFontSizes(theme);
```

```tsx
import {
  createTheme,
  responsiveFontSizes,
  ThemeProvider,
} from '@mui/material/styles';
import Typography from '@mui/material/Typography';

let theme = createTheme();
theme = responsiveFontSizes(theme);

export default function ResponsiveFontSizes() {
  return (
    <div>
      <ThemeProvider theme={theme}>
        <Typography variant="h3">Responsive h3</Typography>
        <Typography variant="h4">Responsive h4</Typography>
        <Typography variant="h5">Responsive h5</Typography>
      </ThemeProvider>
    </div>
  );
}

```

### Fluid font sizes

To be done: [#15251](https://github.com/mui/material-ui/issues/15251).

### HTML font size

You might want to change the `<html>` element default font size. For instance, when using the [10px simplification](https://www.sitepoint.com/understanding-and-using-rem-units-in-css/).

:::warning
Changing the font size can harm accessibility ♿️. Most browsers agree on the default size of 16px, but the user can change it. For instance, someone with an impaired vision could set their browser's default font size to something larger.
:::

The `theme.typography.htmlFontSize` property is provided for this use case,
which tells Material UI what the font-size on the `<html>` element is.
This is used to adjust the `rem` value so the calculated font-size always match the specification.

```js
const theme = createTheme({
  typography: {
    // Tell Material UI what the font-size on the html element is.
    htmlFontSize: 10,
  },
});
```

```css
html {
  font-size: 62.5%; /* 62.5% of 16px = 10px */
}
```

You need to apply the above CSS on the HTML element of this page to see the below demo rendered correctly.

```tsx
import { createTheme, ThemeProvider } from '@mui/material/styles';
import Typography from '@mui/material/Typography';

const theme = createTheme({
  typography: {
    // Tell MUI what the font-size on the html element is.
    htmlFontSize: 10,
  },
});

export default function FontSizeTheme() {
  return (
    <ThemeProvider theme={theme}>
      <Typography>body1</Typography>
    </ThemeProvider>
  );
}

```

## Variants

The typography object comes with [13 variants](/material-ui/react-typography/#component) by default:

- h1
- h2
- h3
- h4
- h5
- h6
- subtitle1
- subtitle2
- body1
- body2
- button
- caption
- overline

Each of these variants can be customized individually:

```js
const theme = createTheme({
  typography: {
    subtitle1: {
      fontSize: 12,
    },
    body1: {
      fontWeight: 500,
    },
    button: {
      fontStyle: 'italic',
    },
  },
});
```

```tsx
import { createTheme, ThemeProvider } from '@mui/material/styles';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';

const theme = createTheme({
  typography: {
    subtitle1: {
      fontSize: 12,
    },
    body1: {
      fontWeight: 500,
    },
    button: {
      fontStyle: 'italic',
    },
  },
});

export default function TypographyVariants() {
  return (
    <div>
      <ThemeProvider theme={theme}>
        <Typography variant="subtitle1">subtitle</Typography>
        <Typography>body1</Typography>
        <Button>Button</Button>
      </ThemeProvider>
    </div>
  );
}

```

## Adding & disabling variants

In addition to using the default typography variants, you can add custom ones, or disable any you don't need. Here is what you need to do:

**Step 1. Update the theme's typography object**

The code snippet below adds a custom variant to the theme called `poster`, and removes the default `h3` variant:

```js
const theme = createTheme({
  typography: {
    poster: {
      fontSize: '4rem',
      color: 'red',
    },
    // Disable h3 variant
    h3: undefined,
  },
});
```

**Step 2. (Optional) Set the default semantic element for your new variant**

At this point, you can already use the new `poster` variant, which will render a `<span>` by default with your custom styles.
Sometimes you may want to default to a different HTML element for semantic purposes, or to replace the inline `<span>` with a block-level element for styling purposes.

To do this, update the `variantMapping` prop of the `Typography` component globally, at the theme level:

```js
const theme = createTheme({
  typography: {
    poster: {
      fontSize: 64,
      color: 'red',
    },
    // Disable h3 variant
    h3: undefined,
  },
  components: {
    MuiTypography: {
      defaultProps: {
        variantMapping: {
          // Map the new variant to render a <h1> by default
          poster: 'h1',
        },
      },
    },
  },
});
```

**Step 3. Update the necessary typings (if you are using TypeScript)**

:::info
If you aren't using TypeScript you should skip this step.
:::

You need to make sure that the typings for the theme's `typography` variants and the `Typography`'s `variant` prop reflects the new set of variants.

<!-- Tested with packages/mui-material/test/typescript/augmentation/typographyVariants.spec.ts -->

```ts
declare module '@mui/material/styles' {
  interface TypographyVariants {
    poster: React.CSSProperties;
  }

  // allow configuration using `createTheme()`
  interface TypographyVariantsOptions {
    poster?: React.CSSProperties;
  }
}

// Update the Typography's variant prop options
declare module '@mui/material/Typography' {
  interface TypographyPropsVariantOverrides {
    poster: true;
    h3: false;
  }
}
```

**Step 4. You can now use the new variant**

```tsx
import { createTheme, ThemeProvider } from '@mui/material/styles';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';

const theme = createTheme({
  typography: {
    // @ts-ignore
    poster: {
      fontSize: '4rem',
      color: 'indianred',
    },
    // Disable v3 variant
    h3: undefined,
  },
  components: {
    MuiTypography: {
      defaultProps: {
        variantMapping: {
          // @ts-ignore
          poster: 'h1', // map our new variant to render an <h1> by default
        },
      },
    },
  },
});

export default function TypographyCustomVariant() {
  return (
    <ThemeProvider theme={theme}>
      <Box sx={{ '& > *': { display: 'block' } }}>
        {/* @ts-ignore */}
        <Typography variant="poster">poster</Typography>
        <Typography variant="h3">h3</Typography>
      </Box>
    </ThemeProvider>
  );
}

```

```jsx
<Typography variant="poster">poster</Typography>;

/* This variant is no longer supported. If you are using TypeScript it will give an error */
<Typography variant="h3">h3</Typography>;
```

## Default values

You can explore the default values of the typography using [the theme explorer](/material-ui/customization/default-theme/?expand-path=$.typography) or by opening the dev tools console on this page (`window.theme.typography`).