# ResponsiveStyles

# Responsive styles

## Media queries

```tsx
// Demo.module.css
.demo {
  background-color: var(--mantine-color-blue-filled);
  color: var(--mantine-color-white);
  padding: var(--mantine-spacing-md);
  text-align: center;

  @media (min-width: em(750px)) {
    background-color: var(--mantine-color-red-filled);
  }
}

// Demo.tsx
import classes from './Demo.module.css';

function Demo() {
  return <div className={classes.demo}>Demo</div>;
}
```


## Configure breakpoints

`theme.breakpoints` are used in all responsive Mantine components. Breakpoints are expected to be set in `em` units.
You can configure these values with [MantineProvider](https://mantine.dev/llms/theming-mantine-provider.md):

```tsx
import { createTheme, MantineProvider } from '@mantine/core';

const theme = createTheme({
  breakpoints: {
    xs: '30em',
    sm: '48em',
    md: '64em',
    lg: '74em',
    xl: '90em',
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      {/* Your app here */}
    </MantineProvider>
  );
}
```

Default `theme.breakpoints` values:

## Breakpoints variables in CSS modules

It is not possible to use CSS variables inside media queries – these values cannot be dynamically
generated by [MantineProvider](https://mantine.dev/llms/theming-mantine-provider.md). To use Mantine theme breakpoints
in your `.css` files, you will need the `postcss-simple-vars` package:

```bash
yarn add postcss-simple-vars
```

```bash
npm install postcss-simple-vars
```

Add it to your [PostCSS config](https://mantine.dev/llms/styles-postcss-preset.md) in `postcss.config.cjs`:

```js
module.exports = {
  plugins: {
    'postcss-preset-mantine': {},
    'postcss-simple-vars': {
      variables: {
        'mantine-breakpoint-xs': '36em',
        'mantine-breakpoint-sm': '48em',
        'mantine-breakpoint-md': '62em',
        'mantine-breakpoint-lg': '75em',
        'mantine-breakpoint-xl': '88em',
      },
    },
  },
};
```

Then you will be able to access these variables in your `.css` files:

```css
.demo {
  @media (max-width: $mantine-breakpoint-xs) {
    background-color: red;
  }
}
```

Will be transformed to:

```css
@media (max-width: 36em) {
  .demo {
    background-color: red;
  }
}
```

> **Dynamic breakpoints are not supported**
>
> Values that are defined in `postcss-simple-vars` config are static and
> are not connected to the [theme](https://mantine.dev/llms/theming-theme-object.md) – if values change,
> you will need to update them manually in both theme override and postcss config.

## hiddenFrom and visibleFrom props

All Mantine components that have a root element support the `hiddenFrom` and `visibleFrom` props.
These props accept a breakpoint (`xs`, `sm`, `md`, `lg`, `xl`) and hide the component when the
viewport width is less than or greater than the specified breakpoint:

```tsx
import { Button, Group } from '@mantine/core';

function Demo() {
  return (
    <Group justify="center">
      <Button hiddenFrom="sm" color="orange">
        Hidden from sm
      </Button>
      <Button visibleFrom="sm" color="cyan">
        Visible from sm
      </Button>
      <Button visibleFrom="md" color="pink">
        Visible from md
      </Button>
    </Group>
  );
}
```


## Hidden and visible from as classes

If you are building a custom component and want to use the same logic as in the `hiddenFrom` and `visibleFrom` props
but you do not want to use Mantine components, you can use the `mantine-hidden-from-{x}` and `mantine-visible-from-{x}`
classes.

```tsx
function CustomComponent() {
  return (
    <>
      <div className="mantine-hidden-from-md">Hidden from md</div>
      <div className="mantine-visible-from-xl">Visible from xl</div>
    </>
  );
}
```

## Component size based on media query

Some components support the `size` prop, which changes various aspects of component appearance.
The `size` prop is not responsive – it is not possible to define different component sizes for different
screen sizes. Instead, you can render multiple components with different sizes and show/hide them
based on media queries with the `className` or `hiddenFrom`/`visibleFrom` props:

```tsx
// Demo.tsx
import { TextInput } from '@mantine/core';

function Demo() {
  return (
    <>
      <TextInput size="xs" hiddenFrom="sm" label="My input" placeholder="My input" />
      <TextInput size="xl" visibleFrom="sm" label="My input" placeholder="My input" />
    </>
  );
}
```


## use-media-query hook

You can use [use-media-query hook](https://mantine.dev/llms/hooks-use-media-query.md) to change some of component props
based on media query. Note that this approach is not recommended for most of the cases if you have
ssr in your application (you use Next.js, React Router, Gatsby or any other framework that includes ssr)
as it may cause hydration mismatch. If you do not have ssr in your application (for example, if you use Vite),
then you can safely use this hook to change props of components or conditionally render components
based on hook return value.

[use-media-query hook](https://mantine.dev/llms/hooks-use-media-query.md) can be safely used to change props of components that are not rendered
on server side (modals, tooltips, etc.). In the following example, it is safe to use `useMediaQuery` hook to
change [Tooltip](https://mantine.dev/llms/core-tooltip.md) props as it is not rendered on server side:

```tsx
import { Tooltip, Button, em } from '@mantine/core';
import { useMediaQuery } from '@mantine/hooks';

function Demo() {
  const isMobile = useMediaQuery(`(max-width: ${em(750)})`);

  return (
    <Tooltip label={isMobile ? 'Mobile' : 'Desktop'}>
      <Button>Hover me</Button>
    </Tooltip>
  );
}
```


## use-matches hook

`use-matches` hook exported from `@mantine/core` is an alternative to [use-media-query](https://mantine.dev/llms/hooks-use-media-query.md)
if you need to match multiple media queries and values. It accepts an object with media queries as keys and
values at given breakpoint as values.

Note that `use-matches` hook uses the same logic as [use-media-query](https://mantine.dev/llms/hooks-use-media-query.md) under the hood,
it is not recommended to be used as a primary source of responsive styles, especially if you have ssr in your application.

In the following example:

* Starting from `theme.breakpoints.lg`, color will be `red.9`
* Between `theme.breakpoints.sm` and `theme.breakpoints.lg`, color will be `orange.9`
* Below `theme.breakpoints.sm`, color will be `blue.9`

```tsx
import { Box, useMatches } from '@mantine/core';

function Demo() {
  const color = useMatches({
    base: 'blue.9',
    sm: 'orange.9',
    lg: 'red.9',
  });

  return (
    <Box bg={color} c="white" p="xl">
      Box with color that changes based on screen size
    </Box>
  );
}
```


## Container queries

[Container queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_container_queries)
enable you to apply styles to an element based on the size of the element's container.
If, for example, a container has less space available in the surrounding context,
you can hide certain elements or use smaller fonts. Container queries are supported
in [all modern browsers](https://caniuse.com/css-container-queries).

You can use `rem` and `em` functions from [postcss-preset-mantine](https://mantine.dev/llms/styles-postcss-preset.md#remem-functions)
in container queries. Note that CSS variables do not work in container queries and because of that
[rem scaling](https://mantine.dev/llms/styles-rem.md#rem-units-scaling) feature is not available. If you rely on this feature,
it is better to define breakpoints in `px` units.

```tsx
// Demo.module.css
.root {
  min-width: 200px;
  max-width: 100%;
  min-height: 120px;
  container-type: inline-size;
  overflow: auto;
  resize: horizontal;
}

.child {
  background-color: var(--mantine-color-dimmed);
  color: var(--mantine-color-white);
  padding: var(--mantine-spacing-md);

  @container (max-width: 500px) {
    background-color: var(--mantine-color-blue-filled);
  }

  @container (max-width: 300px) {
    background-color: var(--mantine-color-red-filled);
  }
}

// Demo.tsx
import classes from './Demo.module.css';

function Demo() {
  return (
    <div className={classes.root}>
      <div className={classes.child}>Resize parent element to see container query in action</div>
    </div>
  );
}
```


## Responsive style props

You can use object syntax to add responsive styles with [style props](https://mantine.dev/llms/styles-style-props.md).
Note that responsive style props are [less performant](https://mantine.dev/llms/styles-styles-performance.md) than regular style props,
it is not recommended to use them in large lists of elements.

```tsx
import { Box } from '@mantine/core';

function Demo() {
  return (
    <Box
      w={{ base: 200, sm: 400, lg: 500 }}
      py={{ base: 'xs', sm: 'md', lg: 'xl' }}
      bg={{ base: 'blue.7', sm: 'red.7', lg: 'green.7' }}
      c="#fff"
      ta="center"
      mx="auto"
    >
      Box with responsive style props
    </Box>
  );
}
```


Responsive values are calculated the following way:

* `base` value is used when none of breakpoint values are applied
* `xs`, `sm`, `md`, `lg`, `xl` values are used when the viewport width is larger that the value of corresponding breakpoint specified in [theme.breakpoints](https://mantine.dev/llms/styles-responsive.md)

```tsx
import { Box } from '@mantine/core';

function Demo() {
  return <Box w={{ base: 320, sm: 480, lg: 640 }} />;
}
```

In this case the element will have the following styles:

```css
/* Base styles added to element and then get overwritten with responsive values */
.element {
  width: 20rem;
}

/* 48em is theme.breakpoints.sm by default */
@media (min-width: 48em) {
  .element {
    width: 30rem;
  }
}

/* 75em is theme.breakpoints.lg by default */
@media (min-width: 75em) {
  .element {
    width: 40rem;
  }
}
```
