Author: Richard Haines

Posted: 25 Feb 2020

take me there

  • With media queries
  • Using the sx prop
  • Extraction

When i started using theme-ui i was already an avid emotion user. I would splatter my files with styled components without really thinking about if they could (or should) be shared. It was a well drilled operation that i felt was giving me the results i wanted.

For example, i would generally use css grid for my sites base layout, this would be wrapped around the whole app using gatsby-plugin-layout.

With media queries

1const Container = styled.div`
2 display: grid;
3 grid-template-columns: 1fr;
4 grid-template-areas:
5 "nav"
6 "main"
7 "footer";
8 height: 100%;
9 width: fit-content;
10
11 /* 48em = 768px */
12 @media (min-width: 48em) {
13 display: grid;
14 grid-template-columns: repeat(6, 1fr);
15 grid-template-rows: 0.5fr 4fr 0.5fr;
16 grid-template-areas:
17 "nav nav nav nav nav nav"
18 "main main main main main main"
19 "footer footer footer footer footer footer";
20 height: 100vh;
21 width: auto;
22 }
23`;
24
25const Layout = ({ children }) => {
26 return (
27 <>
28 <Global
29 styles={css`
30 * {
31 margin: 0;
32 padding: 0;
33 box-sizing: border-box;
34 }
35 body {
36 scroll-behavior: smooth;
37 overflow-y: scroll;
38 -webkit-overflow-scrolling: touch;
39 width: 100%;
40 overflow-x: hidden;
41 }
42 `}
43 />
44 <Container>
45 <Header>
46 <Nav />
47 </Header>
48 {children}
49 <Footer />
50 </Container>
51 </>
52 );
53};
54
55export default Layout;

Using the sx prop

This worked perfectly fine, but i had learned through discussions with other devs, and through seeing their work that mixing both emotion and theme-ui not only wasn't really necessary but also a bit clunky to say the least. Thats without going into how theme-ui uses emotion under the hood (what was i thinking?)

When i decided to do a complete redesign of my website i wanted to try and use theme-ui only to style my site, and more specifically the sx prop. The problem i faced was not how to add the grid system via the sx prop, but how to make it responsive, that is, how to do what i was doing with media queries but via the sx prop.

The solution was surprisingly simple. With css variables on the sx prop you can use an array format to give different values depending on the browser width. With this knowledge in hand i converted the above code to the following:

1const Layout = ({ children }) => {
2 return (
3 <>
4 <Global
5 styles={css`
6 * {
7 margin: 0;
8 padding: 0;
9 box-sizing: border-box;
10 }
11 body {
12 scroll-behavior: smooth;
13 overflow-y: scroll;
14 -webkit-overflow-scrolling: touch;
15 width: 100%;
16 overflow-x: hidden;
17 }
18 `}
19 />
20 <div
21 sx={{
22 display: "grid",
23 gridTemplateRows: "auto",
24 gridTemplateColumns: [
25 "repeat(4, 1fr)",
26 "repeat(6, 1fr)",
27 "repeat(8, 1fr)"
28 ],
29 gridTemplateAreas: [
30 `
31 'nav nav nav nav'
32 'main main main main'
33 'footer footer footer footer'
34 `,
35 `
36 'nav nav nav nav nav nav'
37 'main main main main main main'
38 'footer footer footer footer footer footer'
39 `,
40 `
41 '. nav nav nav nav nav nav .'
42 '. main main main main main main .'
43 '. footer footer footer footer footer footer .'
44 `
45 ],
46 padding: "0 1em"
47 }}
48 >
49 <Header>
50 <Nav />
51 </Header>
52 {children}
53 <Footer />
54 </div>
55 </>
56 );
57};
58
59export default Layout;

Extraction

This was a great improvement and when looking at it with the understanding that the array notation works like so ['mobile', 'tablet', 'desktop'] it becomes really easy to read and understand what is going on. Having all those long strings in there was kinda messy though so i moved them out into another file and replaced them:

1<div
2 sx={{
3 display: "grid",
4 gridTemplateRows: "auto",
5 gridTemplateColumns: ["repeat(4, 1fr)", "repeat(6, 1fr)", "repeat(8, 1fr)"],
6 gridTemplateAreas: [
7 PhoneTemplateAreas,
8 TabletTemplateAreas,
9 DesktopTemplateAreas
10 ],
11 padding: "0 1em"
12 }}
13>
14 <Header>
15 <Nav />
16 </Header>
17 {children}
18 <Footer />
19</div>

Much better! 😎

Edit on GitHub.Next: How to make a gatsby ecommerce theme. Part 1