Media Queries in Material-UI Using Styled-Components
Asked Answered
S

6

12

Material UI has a nice set of built-in media queries: https://material-ui.com/customization/breakpoints/#css-media-queries

Material UI also allows us to use Styled-Components with Material UI: https://material-ui.com/guides/interoperability/#styled-components

I want to know how to combine the two together. That is, how can I make media queries using Styled Components and Material-UI's built-in breakpoints?

Thanks.

UPDATE:

Here is an example of what I am trying to do:

import React, { useState } from 'react'
import styled from 'styled-components'


import {
  AppBar as MuiAppBar,
  Drawer as MuiDrawer,
  Toolbar,
} from '@material-ui/core'


const drawerWidth = 240

const AdminLayout = ({ children }) => {

  return (
    <BaseLayout>
      <AppBar position="static">
        <Toolbar>
          TOOLBAR
        </Toolbar>
      </AppBar>
      <Drawer>
        DRAWER
      </Drawer>
      {children}
    </BaseLayout>
  )
}

AdminLayout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default AdminLayout

// ------- STYLES -------
const AppBar = styled(MuiAppBar)`
  /* Implement appBar styles from useStyles */
`

const Drawer = styled(MuiDrawer)`
  /* Implement drawer styles from useStyles */
`

// STYLES THAT I WANT TO CONVERT TO STYLED-COMPONENTS
const useStyles = makeStyles(theme => ({
  root: {
    display: 'flex',
  },
  drawer: {
    [theme.breakpoints.up('sm')]: {
      width: drawerWidth,
      flexShrink: 0,
    },
  },
  appBar: {
    [theme.breakpoints.up('sm')]: {
      width: `calc(100% - ${drawerWidth}px)`,
      marginLeft: drawerWidth,
    },
  },
  toolbar: theme.mixins.toolbar,
}))
Stratiform answered 26/1, 2020 at 19:21 Comment(7)
theme.breakpoints.down('sm') is just a string '(min-width:600px)', use it in the styled-componentSomething
That requires me hard-coding the pixel value -- what if I want to use the sm variable?Stratiform
what? you don't hardcoding when you using theme.breakpoints.down('sm')Something
perhaps I'm not following. Would you mind showing me an example of how to use theme.breakpoints.down('sm') in a styled-component?Stratiform
Make a minimal example of what you trying to style with MU without styled-components and I'll show you an example on itSomething
Also, why you need this overhead when you have the default values listed material-ui.com/customization/breakpoints/… (there are only few of them)Something
I have updated the question to show what I am trying to accomplish.Stratiform
F
22

Below is an example showing one way of leveraging the Material-UI theme breakpoints with styled-components. This is passing the Material-UI theme to the styled-components ThemeProvider in order to make it available as a prop within the styles. The example also uses StylesProvider with the injectFirst prop so that the Material-UI styles will occur at the beginning of the <head> rather than the end, so that the styled-components styles occur after the Material-UI styles and therefore win when specificity is otherwise equal.

import React from "react";
import styled, { ThemeProvider as SCThemeProvider } from "styled-components";
import { useTheme, StylesProvider } from "@material-ui/core/styles";
import MuiAppBar from "@material-ui/core/AppBar";

const AppBar = styled(MuiAppBar)`
  background-color: red;
  ${props => props.theme.breakpoints.up("sm")} {
    background-color: orange;
  }
  ${props => props.theme.breakpoints.up("md")} {
    background-color: yellow;
    color: black;
  }
  ${props => props.theme.breakpoints.up("lg")} {
    background-color: green;
    color: white;
  }
`;
export default function App() {
  const muiTheme = useTheme();
  return (
    <StylesProvider injectFirst>
      <SCThemeProvider theme={muiTheme}>
        <AppBar>Sample AppBar</AppBar>
      </SCThemeProvider>
    </StylesProvider>
  );
}

Edit MUI theme breakpoints with styled-components

Related documentation:

Forthwith answered 26/1, 2020 at 20:28 Comment(2)
Something like this worked for me: const GridBox = styled(Box)` ${({theme}) => ` display: grid; grid-template-rows: auto; ${theme.breakpoints.up("sm")} { grid-template-columns: 5fr 3fr; }; } ;Lucero
In my opinion this has too much emotion flavor. I prefer the solution by Mike Mathew that does not use emotion syntax.Disentwine
A
20

If you are using the "Style Objects" approach (i.e., "JavaScript") to styled-components, then this is the way to achieve that same outcome. This builds on top of what Ryan Cogswell mentioned earlier.

Some might prefer this if switching over from another CSS-in-JS system (like Material-UI's built-in JSS). Also, the "Style Objects" approach only requires you to bring in props one time as opposed to using the props variable on any line. It's good to have choices. 😇

Style Object

const AppBar = styled(MuiAppBar)((props) => ({
  backgroundColor: red;

  [props.theme.breakpoints.up("sm")]: {
    backgroundColor: orange,
  },
  [props.theme.breakpoints.up("md")]: {
    backgroundColor: yellow,
    color: black,
  },
  [props.theme.breakpoints.up("lg")]: {
    backgroundColor: green,
    color: white,
  },
}));

Style Object, but more concise

Since we only need to access the props one time using the JavaScript approach and we only use theme in this style area, we can destructure theme from the incoming props for a bit less code.

const AppBar = styled(MuiAppBar)(({ theme }) => ({
  backgroundColor: red;

  [theme.breakpoints.up("sm")]: {
    backgroundColor: orange,
  },
  [theme.breakpoints.up("md")]: {
    backgroundColor: yellow,
    color: black,
  },
  [theme.breakpoints.up("lg")]: {
    backgroundColor: green,
    color: white,
  },
}));

Note: If you are using TypeScript and have set up your styled-components theme to match the Material-UI theme, then type safety still works as expected in either the CSS or JavaScript approach.

Architect answered 24/9, 2020 at 13:47 Comment(0)
S
0

The breakpoints are provided as part of the default theme.

They are constants and won't change, therefore you can use them across the components or styled themes:

import React from 'react';
import styled from 'styled-components';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles(theme => {
  console.log('md', theme.breakpoints.up('md'));
  return {};
});

const BP = {
  MD: `@media (min-width:960px) `,
};

const Container = styled.div`
  background-color: green;

  ${({ bp }) => bp} {
    background-color: red;
  }
`;

export default function StyledComponentsButton() {
  useStyles();
  return <Container bp={BP.MD}>Example</Container>;
}

Edit Styled Components

Something answered 26/1, 2020 at 19:56 Comment(3)
Thanks for your answer and all the time you have put into this. I'm sorry to say, though, but this is not what I am trying to do. For starters, const BP hard-codes the pixel value for the md breakpoint. But I want to use the md breakpoint that is found in theme.breakpoints. Secondly, I don't want to have rely on a prop -- I just want to insert the media query into the Styled Component.Stratiform
My question is how do I access theme.breakpoint inside a styled-component.Stratiform
Pass it with styled-themes as I mentioned couple of timesSomething
H
0

The syntax may look weird, but trying this code will explain everything

const StyledDiv = styled.div`
  ${({theme}) => {
  console.log(theme.breakpoints.up('lg'));
  return "";
}}
`;
// you will see in your console
// @media (min-width:1280px)

Once you understand that theme.breakpoints.up('lg') is same as @media (min-width:1280px) everything become obvious. everytime you put theme.breakpoints.up(key) it get replaced with @media... string.

Hifi answered 25/9, 2022 at 20:54 Comment(0)
T
0

I totally agree with the answer https://mcmap.net/q/891317/-media-queries-in-material-ui-using-styled-components

I get the official document Here from Mui-system which is imported by material-ui inside.

I'll paste some example here

const StatWrapper = styled('div')(
  ({ theme }) => `
  background-color: ${theme.palette.background.paper};
  box-shadow: ${theme.shadows[1]};
  border-radius: ${theme.shape.borderRadius}px;
  padding: ${theme.spacing(2)};
  min-width: 300px;
`,
);

const StatHeader = styled('div')(
  ({ theme }) => `
  color: ${theme.palette.text.secondary};
`,
);

const StyledTrend = styled(TrendingUpIcon)(
  ({ theme }) => `
  color: ${theme.palette.success.dark};
  font-size: 16px;
  vertical-alignment: sub;
`,
);

const StatValue = styled('div')(
  ({ theme }) => `
  color: ${theme.palette.text.primary};
  font-size: 34px;
  font-weight: ${theme.typography.fontWeightMedium};
`,
);

const StatDiff = styled('div')(
  ({ theme }) => `
  color: ${theme.palette.success.dark};
  display: inline;
  font-weight: ${theme.typography.fontWeightMedium};
  margin-left: ${theme.spacing(0.5)};
  margin-right: ${theme.spacing(0.5)};
`,
);

const StatPrevious = styled('div')(
  ({ theme }) => `
  color: ${theme.palette.text.secondary};
  display: inline;
  font-size: 12px;
`,
);

return (
  <StatWrapper>
    <StatHeader>Sessions</StatHeader>
    <StatValue>98.3 K</StatValue>
    <StyledTrend />
    <StatDiff>18.77%</StatDiff>
    <StatPrevious>vs last week</StatPrevious>
  </StatWrapper>
);
Tureen answered 24/4, 2024 at 15:41 Comment(0)
R
-3

const StyledDrawer = styled(Drawer)(
  ({ theme }) => `
  .MuiDrawer-paper {
    ${theme.breakpoints.up('sm')} {
      width: 370px;
    }

    ${theme.breakpoints.down('sm')} {
      width: 100vw;
    }
  }   
`)

Riggall answered 21/4, 2022 at 2:1 Comment(1)
Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.Defeatism

© 2022 - 2025 — McMap. All rights reserved.