最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Media Queries in Emotion Styled Components - Stack Overflow

programmeradmin1浏览0评论

The Emotion docs tell us how to make reusable media queries that works in the css prop. This allows us to make the following queries in a css prop:

<div
  css={{
    color: 'green',
    [mq[0]]: {
      color: 'gray'
    },
    [mq[1]]: {
      color: 'hotpink'
    }
  }}
>

With mq[0] and mq[1] referring to the first two items in a breakpoints array. For example: const breakpoints = [576, 768, 992, 1200].

What's more, this article takes it one step further, by showing up how to get named reusable media queries by using a breakpoint object. It starts by making a similar function as per the emotion docs, but for objects:

const mq = n => {
  const bpArray = Object.keys(bp).map(key => [key, bp[key]]);

  const [result] = bpArray.reduce((acc, [name, size]) => {
    if (n === name) return [...acc, `@media (min-width: ${size}px)`];
    return acc;
  }, []);

  return result;
};

This then allows us to create a breakpoints object with named media queries:

// object
const breakpoints = {
  sm: 500,
  md: 768,
  lg: 992,
  xl: 1200
};


// query
${mq('sm')} { 
  color: gray;
}

So far, so good.

I would now like to do something similar in an emotion styled ponent. As such, I created an breakpoints object and the same function as mentioned in the above article.

I then tried to use the short hand media query in my emotion styled ponent -- like this:

import styled from '@emotion/styled'

const Container = styled.div`
  ${mq('sm')`max-width: 750px;`}
  ${mq('md')`max-width: 970px;`}
  ${mq('lg')`max-width: 1170px`}
`

But when I try this, it does not work. I get the following error message:

TypeError: Object(...) is not a function

Any idea why this is happening and what I can do to get it to work?

Thanks.

The Emotion docs tell us how to make reusable media queries that works in the css prop. This allows us to make the following queries in a css prop:

<div
  css={{
    color: 'green',
    [mq[0]]: {
      color: 'gray'
    },
    [mq[1]]: {
      color: 'hotpink'
    }
  }}
>

With mq[0] and mq[1] referring to the first two items in a breakpoints array. For example: const breakpoints = [576, 768, 992, 1200].

What's more, this article takes it one step further, by showing up how to get named reusable media queries by using a breakpoint object. It starts by making a similar function as per the emotion docs, but for objects:

const mq = n => {
  const bpArray = Object.keys(bp).map(key => [key, bp[key]]);

  const [result] = bpArray.reduce((acc, [name, size]) => {
    if (n === name) return [...acc, `@media (min-width: ${size}px)`];
    return acc;
  }, []);

  return result;
};

This then allows us to create a breakpoints object with named media queries:

// object
const breakpoints = {
  sm: 500,
  md: 768,
  lg: 992,
  xl: 1200
};


// query
${mq('sm')} { 
  color: gray;
}

So far, so good.

I would now like to do something similar in an emotion styled ponent. As such, I created an breakpoints object and the same function as mentioned in the above article.

I then tried to use the short hand media query in my emotion styled ponent -- like this:

import styled from '@emotion/styled'

const Container = styled.div`
  ${mq('sm')`max-width: 750px;`}
  ${mq('md')`max-width: 970px;`}
  ${mq('lg')`max-width: 1170px`}
`

But when I try this, it does not work. I get the following error message:

TypeError: Object(...) is not a function

Any idea why this is happening and what I can do to get it to work?

Thanks.

Share Improve this question asked Jan 1, 2020 at 12:00 MosheMoshe 7,00721 gold badges76 silver badges137 bronze badges 2
  • 2 ${mq('sm')} {max-width: 750px;}? – Agney Commented Jan 1, 2020 at 12:16
  • Thanks -- that did it. – Moshe Commented Jan 1, 2020 at 17:56
Add a ment  | 

2 Answers 2

Reset to default 6

To clarify, there was mainly a minor syntax error in what the OP had posted (there should be no additional backticks in the interpolated string).

A full example of his code including type annotations would look like:

const breakpoints: { [index: string]: number } = {
  sm: 500,
  md: 768,
  lg: 992,
  xl: 1200,
};

const mq = Object.keys(breakpoints)
  .map((key) => [key, breakpoints[key]] as [string, number])
  .reduce((prev, [key, breakpoint]) => {
    prev[key] = `@media (min-width: ${breakpoint}px)`;
    return prev;
  }, {} as { [index: string]: string });

const Container = styled.div`
  ${mq["sm"]} {
    max-width: 750px;
  }
  ${mq["md"]} {
    max-width: 970px;
  }
  ${mq["lg"]} {
    max-width: 1170px;
  }
`;

The @bluenote10 answer is correct. Here's a boosted method if you want to add auto-pletion with your IDE in your css definition.

export const BREAKPOINTS = {
  xs: 420,
  sm: 576,
  md: 768,
  lg: 900,
  xl: 1200,
  xxl: 1536
};

type Mq = keyof typeof BREAKPOINTS;
export const mql = Object.keys(BREAKPOINTS)
  .map((key) => [key, BREAKPOINTS[key as Mq]] as [Mq, number])
  .reduce((prev, [key, breakpoint]) => {
    prev[key] = `@media (min-width: ${breakpoint}px)`;
    return prev;
  }, {} as Record<Mq, string>);
发布评论

评论列表(0)

  1. 暂无评论