By Paul Scanlon

Understanding Theme UI: 5 - Media Queries

  • JavaScript
  • React
  • Theme UI

In this post i’m going to explain how Theme UI’s Responsive Values work and to get us started…

You don’t need to write any @media rules because Theme UI handles this for you.

If you’re new to Theme UI i’d suggest having a read of the first four posts in this series to bring you up to speed

In post 4 I discussed scales and as a bit of a recap Theme UI has pre-mapped certain CSS properties to keys within the theme object. breakpoints can be considered the same way but instead of being mapped to CSS properties they are used as a min-width value to form the CSS @media rule(s) and the media rules can be applied to any CSS property via what I refer to as Responsive Array Syntax

I’m going to borrow the Object Syntax example from this post but i’ve added a new breakpoints key to the theme object (note: this is the default breakpoints array from Theme UI)

Src 👇

<Box
  className='demo-box'
  sx={{
    padding: ['xs', 'sm', 'md', 'lg'],
  }}
>
  I'm a Box
</Box>

Theme 👇

// path-to-theme/index.js

export default {
  ...
  space: {
    none: '0px',
    xs: '4px',
    sm: '8px',
    md: '16px',
    lg: '32px',
    xl: '48px',
    xxl: '64px',
  },
  breakpoints: ['40em', '56em', '64em']
}

I’d first like to discuss the Src. Notice instead of padding being a single value it’s an array of values:

Reading the CSS properties from left to right on the <Box /> above for padding the breakdown looks like this

property indexpropertykeyvaluescale
0paddingxs4pxspace
1paddingsm8pxspace
2paddingmd16pxspace
3paddinglg32pxspace

Next have a look at the breakpoints array from the theme object.

It’s important to note here Theme UI works on the CSS min-width principle so what we see in the zero index of the breakpoints array will actually end up being the first breakpoint where CSS will kick in. This is one of the many tenants of mobile first… because we handle the CSS properties for “mobile”, first.

How the breakpoints relate to the properties defined on the <Box /> above breakdown like this.

property indexpropertykeyvaluescalebreakpoint indexbreakpoint value
0paddingxs4pxspacen/an/a
1paddingsm8pxspace040em
2paddingmd16pxspace156em
3paddinglg32pxspace264em

I’d now like to translate the above table into the resulting CSS, I hope this will feel a little more familiar to you since it’s CSS

.demo-box {
  padding: 4px;
}

@media screen and (min-width: 40em) {
  .demo-box {
    padding: 8px;
  }
}

@media screen and (min-width: 52em) {
  .demo-box {
    padding: 16px;
  }
}

@media screen and (min-width: 64em) {
  .demo-box {
    padding: 32px;
  }
}

no breakpoint

In the CSS above you can see that outside of any @media rule the .demo-box padding is set to 4px this will be the default styes applied to the <Box /> until any of the @media rules kick in. It’s resulting CSS property for padding is derived from space.xs which if you refer to the theme object above has a value of “4px”

breakpoint 0

This is the first time the @media rule will modify the styles and kicks in when the browser reaches a minimum width of 40em. The min-width value here is taken from breakpoints index 0 and the resulting CSS property for padding is derived from space.sm which if you refer to the the theme object above as a value of “8px”

breakpoint 1

This @media rule will modify the styles when the browser reaches a minimum width of 56em. The min-width value here is taken from breakpoints index 1 and the resulting CSS property for padding is derived from space.md which if you refer to the the theme object above as a value of “16px”

breakpoint 2

And lastly this @media rule will modify the styles when the browser reaches a minimum width of 64em. The min-width value here is taken from breakpoints index 2 and the resulting CSS property for padding is derived from space.lg which if you refer to the the theme object above as a value of “32px”

Working with responsive values from theme scales is tricky to understand initially because you have to first understand how padding maps to theme.space and then understand how each property from the responsive syntax array is applied via a @media rule which is created based on values from the breakpoints array.

The above explains the principles but now I hope to demonstrate the same approach by using a more digestible example. Again as above you’ll need to resize your browser to see what happens to the <Box /> across the breakpoints.

Src 👇

<Box
  sx={{
    borderColor: ['red', 'green', 'yellow', 'hotpink'],
    borderStyle: ['solid', 'dashed'],
    borderWidth: '6px',
  }}
>
  I'm a Box
</Box>

In this example i’m not using any values from the theme object, instead I’m using web safe colors for borderColor, a hard-coded “px” value for borderWidth and valid border-style CSS properties for the borderStyle

If you resize your browser you’ll notice the borderColor properties change across all breakpoints, the borderStyle only changes when the first @media rule kicks in and borderWidth remains constant across all breakpoints.

From the above you should be able to see that Responsive Values can be applied to any CSS property and the amount of values you add to the Responsive Array Syntax can vary. The only caveat being you can’t have more values applied than you have breakpoints defined.

Personally speaking when I was learning Theme UI I struggled to understand this concept at first but what helped was to have a play with various CSS properties using the Responsive Array Syntax and seeing what effects it had when I resized my browser.

Theme UI has done a hell of a job in abstracting @media rules and it really cleans up your Jsx. If you’re interested in how it works under the hood i’ve written an in depth post explaining how the same approach can be used with Styled Components: [Styled Components Responsive Array Syntax](/posts/2020/08/Styled Components-responsive-array-syntax/)

This is the penultimate post in my Understanding Theme UI series. Next up is: The hacks where I hope to explain how you can target elements using various CSS selectors via the sx prop, how to use the theme function and as a little bonus i’ll be explaining how to use @keyframes so you can add pure CSS keyframe animation to site.

Thanks for reading!

Hey!

Leave a reaction and let me know how I'm doing.

  • 0
  • 0
  • 0
  • 0
  • 0
Powered byNeon