媒体查询没有正确触发值?

时间:2019-11-12 02:13:47

标签: css reactjs media-queries styled-components

我开始用styled-components编写自己的设计系统。但是我一直在努力使组件具有响应能力。

// Container.tsx
import React from 'react'
import styled from 'styled-components'

import { media } from '../utils/mediaQuery'

export const StyledContainer = (isFluid: boolean) => {
  return styled(
    ({ element: Component, containerRef, ...props }) => {
      console.log(isFluid)
      return (
        <Component ref={containerRef} {...props}>
          {props.children}
        </Component>
      )
    }
  )`
    width: 100%; /* Fix component tight to center*/
    margin-right: auto;
    margin-left: auto;
    padding-right: ${({ theme }) => theme.container.paddingX}rem;
    padding-left: ${({ theme }) => theme.container.paddingX}rem;

    ${isFluid ? '' : media.xl`max-width: 1040px;`}
    ${isFluid ? '' : media.lg`max-width: 960px;`}
    ${isFluid ? '' : media.md`max-width: 720px;`}
    ${isFluid ? '' : media.sm`max-width: 576px;`}
  `
}

type CProps = {
  fluid?: boolean
  element?: React.Component | string
  children: React.ReactNode | React.ReactNode[]
}

const Container = React.forwardRef(
  (props: CProps, ref: React.Ref<HTMLElement>) => {
    const { fluid = false, children, element = 'div' } = props

    const BaseContainer = StyledContainer(fluid)

    return (
      <BaseContainer element={element} containerRef={ref}>
        {children}
      </BaseContainer>
    )
  }
)

export default Container
// ../../utils/mediaQuery
import {
  css,
  SimpleInterpolation,
  CSSObject,
  FlattenSimpleInterpolation,
} from 'styled-components'


export const breakpoints: { [key: string]: number } = {
  xl: 1200,
  lg: 992,
  md: 768,
  sm: 576,
  xs: 376
}

export const media = Object.keys(breakpoints).reduce(
  (
    accumulator: {
      [key: string]: (
        styles: CSSObject | TemplateStringsArray,
        ...interpolations: SimpleInterpolation[]
      ) => FlattenSimpleInterpolation
    },
    label: string
  ) => {
    const size = breakpoints[label]

    Object.assign(accumulator, {
      [label]: (
        styles: CSSObject | TemplateStringsArray,
        ...interpolations: SimpleInterpolation[]
      ) => css`
        @media screen and (min-width: ${size}px) {
          ${css(styles, ...interpolations)}
        }
      `
    })

    return accumulator
  },
  {}
)

一切正常。所有CSS都捆绑成块文件,控制台上没有错误或错误出现。我的预期结果是媒体查询值的顺序,该组件的屏幕尺寸后面紧跟max-width。但是我的实际结果是@media screen and (min-width: 576px) {...},它与${isFluid ? '' : media.sm`max-width: 576px;`}捆绑在一起,覆盖了其他查询。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

尝试颠倒媒体查询定义的顺序:

${isFluid ? '' : media.sm`max-width: 576px;`}
${isFluid ? '' : media.md`max-width: 720px;`}
${isFluid ? '' : media.lg`max-width: 960px;`}
${isFluid ? '' : media.xl`max-width: 1040px;`}

因此,最终的CSS将是:

media screen and (min-width: 576px) {...}

media screen and (min-width: 720px) {...}

media screen and (min-width: 960px) {...}

media screen and (min-width: 1040px) {...}

对于CSS媒体查询,您首先需要最小的min-width定义。

最后一个min-width: 576px之前,这意味着576px上方的任何屏幕都将采用该样式。

Stackoverflow answer解释了原因。