Blog

Stylng choices for Gatsby

0 claps earned

Like anything React, there are a bunch of options for styling in Gatsby: inine styling, global SCSS imports, CSS Modules, CSS-in-JS components, and then some. Here’s my exploration into some.

1NOTES (2021-08-22)
2---
3When I first wrote this, I wanted to keep as much of existing SCSS/CSS
4as possible since I was converting an existing Jekyll repo into Gatsby.
5While the post content is still relevant, I’ve since rewritten significant
6portions of this site and kept only to `css-in-js` approaches.

Global (S)CSS and Variables

As I’m keeping most of pre-existing UI styles from the previous site written SCSS, I wanted to reuse as much of the existing code as possible.

So, in my gatsby-browser.js I imported the global base styles from base.scss, which contains bare minimum of global styling and imports _variables.scss for certain values.

You’ll notice the duplicated hex values in SCSS variables and CSS custom properties. I almost wanted to ditch SCSS variables and keep everything only to CSS custom properties, and there was just one reason why: Color Functions. SCSS offers built-in color functions such as lighten(), complement(). While they can easily be accomplished by packages like this one, I didn’t want an extra dependency just for a simple task like this.

jsgatsby-browser.js
1import "./src/styles/base.scss";
2
3// ... and other stuff
scssbase.scss
1@import url("//path.to/webfonts");
2@import "./variables";
3
4html,
5body {
6 font-family: Raleway, Helvetica, Arial, sans-serif;
7 font-size: 10px;
8 margin: 0;
9}
10
11body {
12 padding-top: 4.5rem;
13}
scss_variables.scss
1// Colors
2$cyan: #00a2d9;
3$berry: #b7295a;
4$green: #7ab800;
5$yellow: #f2af00;
6$accentColor: $green;
7$bgColor: #fff;
8
9:root {
10 --cyan: #00a2d9;
11 --berry: #b7295a;
12 --green: #7ab800;
13 --yellow: #f2af00;
14}
15
16// ... and other stuff

(S)CSS Modules

Then importing a clean scss into a component felt natural. I like how style definitions are separated from the markup, so I could organize code neatly with no concerns for accidental overriding .

I started the site Header component with this approach.

scssHeader.module.scss
1header {
2 background: var(--berry);
3 position: fixed;
4 // ... stuff
5
6 .BigB {
7 // ... stuff
8 }
9
10 ul.bigNav {
11 // ... stuff
12 a {
13 color: lighten($berry, 25%);
14 // ... stuff
15 &:hover {
16 transform: translateY(-0.25rem);
17 color: #fff;
18 }
19 &.active {
20 color: #fff;
21 }
22 }
23 }
24}
jsxHeader.JS
1import styles from "./Header.module.scss";
2
3const Header = () => (
4 <>
5 <header className={styles.Header}>
6 <div className={styles.BigB}>
7 <Link to="/">B</Link>
8 </div>
9 <ul className={styles.bigNav}>
10 <li>
11 <Link activeClassName={styles.active} to="/">
12 About
13 </Link>
14 </li>
15 <li>
16 <Link activeClassName={styles.active} to="/portfolio">
17 Portfolio
18 </Link>
19 </li>
20 </ul>
21 </header>
22 </>
23);

Styled-Components

Everything else is a styled-component, which provides most of Sass conventions and enables far more dynamic styling via JavaScript. On the home page, IntroBox.js component that takes a few props and styles itself accordingly.

jsxIntroBox.js
1import React from "react";
2import styled from "styled-components";
3// ... and other import statements
4
5const IntroBox = (props) => {
6 const { iconName, width, back, color, order, mobileOrder, label } = props;
7 const IntroBoxDiv = styled.div`
8 flex-basis: ${width === "1" ? "25%" : "50%"};
9 &:hover .flipper {
10 transform: ${width === "1" ? "rotateY(180deg)" : "rotateX(180deg)"};
11 }
12 span {
13 ${flexUnit(1.3, 13, 26, "vw", "font-size")}
14 color: ${color || "#ffffff"};
15 }
16 // ... and other styling stuff
17 `;
18 return (
19 <IntroBoxDiv>
20 <div className="flipper">
21 <div className="front">
22 <Icon iconName={iconName} />
23 <span>{label}</span>
24 </div>
25 <div className="back">{props.children}</div>
26 </div>
27 </IntroBoxDiv>
28 );
29};
jsxindex.js
1import React, { useState } from "react";
2import styled from "styled-components";
3import Layout from "../components/layout";
4import IntroBox from "../components/IntroBox/IntroBox";
5// ... and other import statements
6
7const IntroBoxContainer = styled.section`
8 background: #282828;
9 display: flex;
10 flex-wrap: wrap;
11`;
12
13const IndexPage = () => {
14 // ... other stuff...
15
16 return (
17 <Layout>
18 <IntroBoxContainer>
19 <IntroBox
20 iconName="IntroShoes"
21 width="2"
22 order="0"
23 back="#475F7D"
24 mobileOrder="5"
25 label="Industry Experience"
26 >
27 .... content ....
28 </IntroBox>
29 <IntroBox
30 iconName="IntroEducation"
31 width="1"
32 order="1"
33 back="#334d5c"
34 label="Education"
35 >
36 .... content ....
37 </IntroBox>
38 </IntroBoxContainer>
39 </Layout>
40 );
41};

While I do love the convenience of having style declarations and markup in the same file which eliminates the need for constantly jumping between files when debugging, I found myself having to constantly jump up and down between sections within a component file as the styling blocks become larger.

Why multiple approaches what next

I’m still figuring out what works for me and how best to approach styling. Certainly I won’t need global SCSS import and perhaps won’t need SCSS modules either, as there are other JS-ways to solve the problem. Just for the sake of getting more procifient, I’m likely to proceed with styled-components only for the most part, and maybe even attempt to get rid of other external (S)CSS files in general, but this has been a practical exercise to build something in different ways in any case.

+0
Clap a few times
if you liked it
© 2023 by Bumhan Yu