Programmatically create responsive styled components with react and styled-components
// this file is just here to change the name of the gist
import React from 'react'
import styled from 'styled-components'
const makeResponsiveComponent = (rulesets, tagName = 'div') =>
styled(tagName)`${buildStyles(rulesets)}`
const buildStyles = rulesets =>
rulesets.reduce(
(cssString, { constraint, width, rules }) =>
`${cssString} @media (${constraint}-width: ${width}) { ${rules} }`
, '')
export const hideAt = breakpoints => {
const rulesets = Object.entries(breakpoints).reduce(
(rulesets, [constraint, width]) =>
[...rulesets, {
constraint,
width,
rules: `display: none;`
}]
, []
)
return makeResponsiveComponent(rulesets)
}
export const Breakpoint = ({ min, max, children }) => {
const Component = hideAt({ min, max })
return <Component>{children}</Component>
}
export default makeResponsiveComponent
import React from 'react'
import styled from 'styled-components'
import ResponsiveFonts from './responsive-fonts'
import {
MediumAndUp,
LargeAndUp,
SmallAndDown,
MediumAndDown,
MediumOnly
} from './breakpoints.jsx'
import { Breakpoint } from './make-responsive-component'
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
text-align: center;
`
export default () =>
<Wrapper>
<ResponsiveFonts>
<SmallAndDown>sm and down</SmallAndDown>
<MediumAndUp>med and up</MediumAndUp>
<MediumAndDown>med and down</MediumAndDown>
<MediumOnly>medium only</MediumOnly>
<LargeAndUp>lg and up</LargeAndUp>
<Breakpoint max="1200px">only on huge width</Breakpoint>
</ResponsiveFonts>
</Wrapper>
import { hideAt } from './make-responsive-component'
export const SmallAndDown = hideAt({ min: '320px' })
export const MediumAndDown = hideAt({ min: '960px' })
export const MediumOnly = hideAt({ max: '640px', min: '960px' })
export const MediumAndUp = hideAt({ max: '640px' })
export const LargeAndUp = hideAt({ max: '960px' })
// functions to generate styled components with any arbitrary sets of style rules and corresponding breakpoints
import React from 'react'
import styled from 'styled-components'
const makeResponsiveComponent = (rulesets, tagName = 'div') =>
styled(tagName)`${buildStyles(rulesets)}`
const buildStyles = rulesets =>
rulesets.reduce(
(cssString, { constraint, width, rules }) =>
`${cssString} @media (${constraint}-width: ${width}) { ${rules} }`
, '')
export const hideAt = breakpoints => {
const rulesets = Object.entries(breakpoints).reduce(
(rulesets, [constraint, width]) =>
[...rulesets, {
constraint,
width,
rules: `display: none;`
}]
, []
)
return makeResponsiveComponent(rulesets)
}
export const Breakpoint = ({ min, max, children }) => {
const Component = hideAt({ min, max })
return <Component>{children}</Component>
}
export default makeResponsiveComponent
// example usage
import makeResponsiveComponent from './make-responsive-component'
export default makeResponsiveComponent(
[
{
constraint: 'min',
width: '0px',
rules: `
font-size: 14px;
color: rebeccapurple;
`
}, {
constraint: 'min',
width: '320px',
rules: `
font-size: 28px;
color: cyan;
`
}, {
constraint: 'min',
width: '640px',
rules: `
font-size: 42px;
color: green;
`
}, {
constraint: 'min',
width: '960px',
rules: `
font-size: 56px;
color: red;
`
}
]
)