Responsive Typography in Material UI?
Asked Answered
S

9

58

Designs commonly have smaller headline fonts for mobile designs.

Does Material UI have a mechanism for making the typography responsive?

I see that the default theme has the font sizes defined in rems - does that mean it's a matter of just reducing the base font-size? (That doesn't seem to work, what if you want to reduce the headline fonts at different rates).

Shippee answered 24/9, 2018 at 3:35 Comment(0)
C
51

Update

MUI v4 has responsive typography built in! Check here for details.

Old response

@Luke's answer is great. I wanted to add some detail to make this work in practice, because both breakpoints and pxToRem are accessible on the theme object... making this becomes a chicken and egg problem! My approach:

import { createMuiTheme } from "@material-ui/core"

const defaultTheme = createMuiTheme({ ... customisations that don’t rely on theme properties... })
const { breakpoints, typography: { pxToRem } } = defaultTheme

const theme = {
  ...defaultTheme,
  overrides: {
    MuiTypography: {
      h1: {
        fontSize: "5rem",
        [breakpoints.down("xs")]: {
          fontSize: "3rem"
        }
      }
    }
  }
}

export default theme
Cardew answered 23/11, 2018 at 13:18 Comment(0)
N
52

None of the other answers uses the variant preset.

The best way to MUI v5, and use variant:

<Typography sx={{ typography: { sm: 'body1', xs: 'body2' } }} >
    Hello world!
</Typography>
Nary answered 27/12, 2021 at 10:31 Comment(4)
This is the best way 😍 Thanks – Hannan
This works, thanks... Before this I was applying the breakpoints directly to variant parameter, it was changing the sizes but weirdly it also changed their font family back to the default roboto for some reason – Candlestick
Note: as it just applies the style, it doesn't actually change the variant prop, and therefore doesn't change the classname – Alsace
If you were to go from h1 to h3, does it have any impact on accessibility? Does it only affect the styling vs changing the Typography component? – Theravada
C
51

Update

MUI v4 has responsive typography built in! Check here for details.

Old response

@Luke's answer is great. I wanted to add some detail to make this work in practice, because both breakpoints and pxToRem are accessible on the theme object... making this becomes a chicken and egg problem! My approach:

import { createMuiTheme } from "@material-ui/core"

const defaultTheme = createMuiTheme({ ... customisations that don’t rely on theme properties... })
const { breakpoints, typography: { pxToRem } } = defaultTheme

const theme = {
  ...defaultTheme,
  overrides: {
    MuiTypography: {
      h1: {
        fontSize: "5rem",
        [breakpoints.down("xs")]: {
          fontSize: "3rem"
        }
      }
    }
  }
}

export default theme
Cardew answered 23/11, 2018 at 13:18 Comment(0)
C
24

As described in the docs you can use the responsiveFontSizes() helper to make Typography font sizes in the theme responsive.

import { createMuiTheme, responsiveFontSizes } from '@material-ui/core/styles';

let theme = createMuiTheme();
theme = responsiveFontSizes(theme);
Coligny answered 31/8, 2020 at 8:6 Comment(3)
mui.com/customization/typography/#responsive-font-sizes – Pyrogenic
This is the easiest out of the box. +1 for recommending this method – Penny
This needs to be the top answer. – Posada
E
18

Update

The latest version of Material UI (v4) fully supports response typography. See the official documentation for details.

Original Answer

As of version 1.x, Material UI does not have a specific mechanism for handling responsive typography.

You can scale the size of all MUI Typography by changing the font-size of the <html> element, as you mentioned. (docs)

const styles = theme => ({
  "@global": {
    html: {
      [theme.breakpoints.up("sm")]: {
        fontSize: 18
      }
    }
  }
}

Edit Material UI - scale font size

Theme overrides

As far as i know, the only other option is to use theme overrides to define custom styles for each of the Typography variants.

This requires replicating some of the logic in createTypography.js (ie setting line heights to maintain vertical rhythm)

const theme = createMuiTheme({
  overrides: {
    MuiTypography: {
      headline: {
        fontSize: pxToRem(24),
        [breakpoints.up("md")]: {
          fontSize: pxToRem(32)
        }
      }
    }
  }

Edit Material UI - Responsive font size

Enterprising answered 25/9, 2018 at 9:12 Comment(3)
Good answer, thanks. Any idea why responsive typography isn't a thing in Material-UI? It seems like a no brainer. – Shippee
Where's the breakpoints variable coming from in your 2nd snippet? I know it should come from a theme, but that's exactly the thing your creating and is not created yet at the time you're using breakpoints. – Gebhardt
This is the legit answer. Thanks for sharing Luke! – Flinty
V
14

MUI v5 adds sx prop to all MUI components which supports responsive values where you can pass an object to define the values at different breakpoints:

<Typography
  sx={{
    fontSize: {
      lg: 30,
      md: 20,
      sm: 15,
      xs: 10
    }
  }}
>
  This text is resized on different screen breakpoints
</Typography>

Similar to Box, Typography also supports system properties so you can skip the sx prop and pass the fontSize property directly. The code below is the same as above, just a bit shorter to write:

<Typography
  fontSize={{
    lg: 30,
    md: 20,
    sm: 15,
    xs: 10
  }}
>
  This text is resized on different screen breakpoints
</Typography>

Codesandbox Demo

Vacate answered 25/10, 2021 at 18:23 Comment(1)
This answer is great for those small tweaks you always need to do with responsive design. Perhaps an image should not be displayed for example in the mobile view. Thanks for sharing. – Disinfectant
D
7

My approach with v5

import { createTheme } from "@mui/material";

let theme = createTheme({
  // ...
});

theme = createTheme(theme, {
  typography: {
    h1: {
      fontSize: 53,
      [theme.breakpoints.only("sm")]: {
        fontSize: 71,
      },
    },
  },
});
export default theme;

Distillate answered 11/2, 2022 at 13:1 Comment(0)
C
5

This seem to be working for me v5

in App.js

...

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

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

...

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Router>
       .....
      </Router>
    </ThemeProvider>
  );
}

"To automate this setup, you can use the responsiveFontSizes() helper to make Typography font sizes in the theme responsive." https://mui.com/customization/typography/#responsive-font-sizes

Chorography answered 26/1, 2022 at 23:20 Comment(0)
S
1

MUI 5

Next.js 14

/typography.ts

I've successfully resolved the responsive breakpoints issue by implementing Mui v5 with Typescript.

import { DM_Sans } from "next/font/google";
import {
  TypographyVariants as TypographyVariantsOption,
  createTheme,
} from "@mui/material/styles";

export const dm_sans = DM_Sans({
  weight: ["100", "300", "400", "500", "600", "700"],
  style: ["normal", "italic"],
  subsets: ["latin"],
  display: "swap",
});

export interface TypographyVariants extends TypographyVariantsOption {}

const theme = createTheme({
  breakpoints: {
    values: {
      xs: 0,
      sm: 600,
      md: 900,
      lg: 1170,
      xl: 1530,
    },
  },
});

export default {
  fontFamily: `${dm_sans.style.fontFamily}`,
  htmlFontSize: 16,
  fontSize: 14,
  fontWeightLight: 300,
  fontWeightRegular: 400,
  fontWeightMedium: 500,
  fontWeightBold: 700,
  h1: {
    ...dm_sans.style,
    fontWeight: 500,
    fontSize: "3.5rem",
    lineHeight: 1.167,
    letterSpacing: "-0.02em",
    [theme.breakpoints.down("md")]: {
      fontSize: "2rem",
    },
  },
  h2: {
    ...dm_sans.style,
    fontWeight: 500,
    fontSize: "2.5rem",
    lineHeight: 1.263157895,
    letterSpacing: "-0.013",
  },
  h3: {
    ...dm_sans.style,
    fontWeight: 400,
    fontSize: "1.62rem",
    lineHeight: 1.384615385,
    letterSpacing: "0em",
  },
  h4: {
    ...dm_sans.style,
    fontWeight: 500,
    fontSize: "1.5rem",
    lineHeight: 1.33333,
    letterSpacing: "0.006",
  },
  h5: {
    ...dm_sans.style,
    fontWeight: 500,
    fontSize: "1.25rem",
    lineHeight: 1.334,
    letterSpacing: "0em",
  },
  h6: {
    ...dm_sans.style,
    fontWeight: 500,
    fontSize: "1.125rem",
    lineHeight: 1.6,
    letterSpacing: "0.0075em",
  },
  subtitle1: {
    ...dm_sans.style,
    fontWeight: 400,
    fontSize: "1.125rem",
    lineHeight: 1.75,
    letterSpacing: "0.013em",
  },
  subtitle2: {
    ...dm_sans.style,
    fontWeight: 500,
    fontSize: "1rem",
    lineHeight: 1.57,
    letterSpacing: "0.013em",
  },
  body1: {
    ...dm_sans.style,
    fontWeight: 300,
    fontSize: "1.125rem",
    lineHeight: 1.555555556,
    letterSpacing: "0.013em",
  },
  body2: {
    ...dm_sans.style,
    fontWeight: 400,
    fontSize: "0.938rem",
    lineHeight: 1.4,
    letterSpacing: "0.01071em",
  },
  button: {
    ...dm_sans.style,
    fontWeight: 500,
    fontSize: "0.938rem",
    lineHeight: 1.6,
    letterSpacing: "0.013em",
    textTransform: "uppercase",
  },
  caption: {
    ...dm_sans.style,
    fontWeight: 400,
    fontSize: "0.938rem",
    lineHeight: 1.6,
    letterSpacing: "0.01875em",
  },
  overline: {
    ...dm_sans.style,
    fontWeight: 400,
    fontSize: "0.688rem",
    lineHeight: 2.66,
    letterSpacing: "0.013em",
    textTransform: "uppercase",
  },
} as TypographyVariants;
Stinkhorn answered 24/9, 2018 at 3:35 Comment(0)
A
0

In your css file add something like this:

.MuiTypography-h1 {
   font-size: 4rem !important;
   font-weight: 400 !important;
}

.MuiTypography-h2 {
   font-size: 3.2rem !important;
   font-weight: 400 !important;
}

.MuiTypography-h3 {
   font-size: 2.5rem !important;
   font-weight: 400 !important;
}

.MuiTypography-h4 {
   font-size: 2rem !important;
   font-weight: 400 !important;
}

.MuiTypography-h5 {
   font-size: 1.65rem !important;
   font-weight: 400 !important;
}

.MuiTypography-h6 {
   font-size: 1.23rem !important;
   font-weight: 700 !important;
}

.MuiTypography-h1.responsive {
   font-size: clamp(1.8rem, 4.7vw, 4rem) !important;
}

.MuiTypography-h2.responsive {
   font-size: clamp(1.6rem, 4.1vw, 3.2rem) !important;
}

.MuiTypography-h3.responsive {
   font-size: clamp(1.4rem, 3.5vw, 2.5rem) !important;
}

.MuiTypography-h4.responsive {
   font-size: clamp(1.2rem, 3vw, 2rem) !important;
}

.MuiTypography-h5.responsive {
   font-size: clamp(1.12rem, 2.6vw, 1.65rem) !important;
}

.MuiTypography-h6.responsive {
   font-size: clamp(.95rem, 2.05vw, 1.23rem) !important;
}

This will not only make typography headers with the class name of responsive become responsive, it will also fix the problem of MUI headers being to big. You can play around with the values to change the size of the typography.

Adowa answered 13/5 at 17:38 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.