Understanding Theme UI: 5 - Media Queries
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 index | property | key | value | scale |
---|---|---|---|---|
0 | padding | xs | 4px | space |
1 | padding | sm | 8px | space |
2 | padding | md | 16px | space |
3 | padding | lg | 32px | space |
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 index | property | key | value | scale | breakpoint index | breakpoint value |
---|---|---|---|---|---|---|
0 | padding | xs | 4px | space | n/a | n/a |
1 | padding | sm | 8px | space | 0 | 40em |
2 | padding | md | 16px | space | 1 | 56em |
3 | padding | lg | 32px | space | 2 | 64em |
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
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!