Responsive styles

@mantine/core package exports several components that can help you organize responsive styles without writing CSS. Note that in most cases that are not covered in this guide, the best approach to make your app responsive is to add styles with createStyles function.

Configure breakpoints

theme.breakpoints are used in all responsive Mantine components. Breakpoints are set in px (rem, em and other values are not supported). You can configure these values with MantineProvider:

import { MantineProvider } from '@mantine/core';
function YourApp() {
return (
<MantineProvider
theme={{
breakpoints: {
xs: 500,
sm: 800,
md: 1000,
lg: 1200,
xl: 1400,
},
}}
>
<App />
</MantineProvider>
);
}

Default theme.breakpoints values are the same as in Bootstrap:

BreakpointViewport width
xs576px
sm768px
md992px
lg1200px
xl1400px

Layout components

Most of layout components support responsive features. This section includes basic responsive features, visit components documentation to learn more.

Grid component allows you to set columns span based on theme.breakpoints. Grid is based on flexbox and can be used in older browsers (IE11+):

1
2
3
4
<Grid>
<Grid.Col md={6} lg={3}>1</Grid.Col>
<Grid.Col md={6} lg={3}>2</Grid.Col>
<Grid.Col md={6} lg={3}>3</Grid.Col>
<Grid.Col md={6} lg={3}>4</Grid.Col>
</Grid>

SimpleGrid component allows you to create a layout with given amount of columns with equal width. SimpleGrid is based on CSS grid and can have issue in older browsers (IE11+):

1
2
3
4
5
<SimpleGrid
cols={4}
spacing="lg"
breakpoints={[
{ maxWidth: 980, cols: 3, spacing: 'md' },
{ maxWidth: 755, cols: 2, spacing: 'sm' },
{ maxWidth: 600, cols: 1, spacing: 'sm' },
]}
>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</SimpleGrid>

AppShell component can be used to create a common layout pattern: Header – Navbar – Content:

Your application goes here
import { AppShell, Navbar, Header } from '@mantine/core';
function Demo() {
return (
<AppShell
padding="md"
navbar={<Navbar width={{ base: 300 }} height={500} padding="xs">{/* Navbar content */}</Navbar>}
header={<Header height={60} padding="xs">{/* Header content */}</Header>}
styles={(theme) => ({
main: { backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.gray[0] },
})}
>
{/* Your application here */}
</AppShell>
);
}

AppShell includes several responsive features with which you can build collapsible Navbar without any additional styles (demo):

import { useState } from 'react';
import { AppShell, Burger, Header, MediaQuery, Navbar, Text, useMantineTheme } from '@mantine/core';
function Demo() {
const [opened, setOpened] = useState(false);
const theme = useMantineTheme();
return (
<AppShell
// navbarOffsetBreakpoint controls when navbar should no longer be offset with padding-left
navbarOffsetBreakpoint="sm"
// fixed prop on AppShell will be automatically added to Header and Navbar
fixed
navbar={
<Navbar
padding="md"
// Breakpoint at which navbar will be hidden if hidden prop is true
hiddenBreakpoint="sm"
// Hides navbar when viewport size is less than value specified in hiddenBreakpoint
hidden={!opened}
width={{ base: 400, breakpoints: { sm: '100%', lg: 300 } }}
>
<Text>Application navbar</Text>
</Navbar>
}
header={
<Header height={70} padding="md">
{/* You can handle other responsive styles with MediaQuery component or createStyles function */}
<div style={{ display: 'flex', alignItems: 'center', height: '100%' }}>
<MediaQuery largerThan="sm" styles={{ display: 'none' }}>
<Burger
opened={opened}
onClick={() => setOpened((o) => !o)}
size="sm"
color={theme.colors.gray[6]}
mr="xl"
/>
</MediaQuery>
<Text>Application header</Text>
</div>
</Header>
}
>
<Text>Resize app to see responsive navbar in action</Text>
</AppShell>
);
}

Media queries in createStyles

In most cases using createStyles function is cleanest way to add responsive styles to any element. Consider using it first before hacking your way out of writing CSS with other approaches:

import { createStyles } from '@mantine/core';
const useStyles = createStyles((theme) => ({
container: {
height: 100,
backgroundColor: theme.colors.blue[6],
// Media query with value from theme
[`@media (max-width: ${theme.breakpoints.xl}px)`]: {
backgroundColor: theme.colors.pink[6],
},
// Static media query
'@media (max-width: 800px)': {
backgroundColor: theme.colors.orange[6],
},
},
}));
function Demo() {
const { classes } = useStyles();
return <div className={classes.container} />;
}

MediaQuery component

MediaQuery component lets you apply styles to given component or element if given media query matches:

(max-width: 1200px) and (min-width: 800px) breakpoints
<MediaQuery
query="(max-width: 1200px) and (min-width: 800px)"
styles={{ fontSize: 20, '&:hover': { backgroundColor: 'silver' } }}
>
<Text>(max-width: 1200px) and (min-width: 800px) breakpoints</Text>
</MediaQuery>

Changing component size based on media query

Most of Mantine components support size prop with xs, sm, md, lg and xl values. You cannot change these values within component props. Instead you can use MediaQuery component to render different components based on media query:

<>
<MediaQuery smallerThan="sm" styles={{ display: 'none' }}>
<TextInput size="xl" />
</MediaQuery>
<MediaQuery largerThan="sm" styles={{ display: 'none' }}>
<TextInput size="md" />
</MediaQuery>
</>

The approach with MediaQuery component will work with SSR. If you do not need SSR support the more cleaner way to change size is to use use-media-query hook:

import { TextInput } from '@mantine/core';
import { useMediaQuery } from '@mantine/hooks';
function Demo() {
// Will always return false during ssr, use only when you do not have ssr
const largeScreen = useMediaQuery('(min-width: 900px)');
return <TextInput size={largeScreen ? 'xl' : 'md'} />;
}

Inline media queries with sx

All Mantine components support sx prop with which you can add styles (including responsive styles) to root component element:

<TextInput
sx={(theme) => ({
background: theme.colors.gray[0],
padding: theme.spacing.md,
'@media (max-width: 755px)': {
padding: theme.spacing.sm,
},
})}
/>

If you want to add styles with sx prop to non-Mantine component, you can wrap it in Box:

// Example with react-router-dom Link
import { Link } from 'react-router-dom';
import { Box } from '@mantine/core';
function Demo() {
return (
<Box
component={Link}
to="/some-path/"
sx={(theme) => ({
fontSize: theme.fontSizes.md,
'@media (max-width: 755px)': {
fontSize: theme.fontSizes.sm,
},
})}
>
Styled react-router link
</Box>
);
}
Build fully functional accessible web applications faster than ever
Feedback
Your feedback is most valuable contribution to the project, please share how you use Mantine, what features are missing and what is done good
Leave feedback