ScottSpence.com

Scott's Digital Garden.

Linaria - Getting Started

I had a work colleague introduce me to Linaria last week and I’ve used it on a project and I quite like it.

Linaria is like styled-components but different as in there’s no runtime cost and some other gotchas I’ve found along the way.

What does that mean though? I’m going to take the headings from the Linaria Docs for benefits and list them here, for more detail on them I suggest checking the links in the list.

Advantages Over other CSS-in-JS solutions

Example Me Up Yo!

TL;DR to the video if you like, or read on…

Getting started with Linaria, I’m using the Gatsby default starter (no surprises there I guess 🤣).

I like styled-components because you’re writing CSS not camelCase style keys.

To start I’ll spin up a new project with the Gatsby CLI:

1# with the Gatsby CLI
2gatsby new gatsby-starter-linaria
3# or with npx
4npx gatsby new gatsby-starter-linaria

Add Linaria and the Gatsby plugin as dependencies:

1yarn add linaria@next gatsby-plugin-linaria

Error: Cannot find module ‘core-js/…’

I’m using @next because there’s a known issue between Linaria and Gatsby’s version of core-js.

I’ll add the .linaria-cache folder to bottom of the .gitignore file as that’s not needed in source control.

1# linaria
2.linaria-cache

Add gatsby-plugin-linaria to the gatsby-config.js file in the plugins array:

1plugins: [
2 `gatsby-plugin-linaria`,
3 `gatsby-plugin-react-helmet`,
4 {
5 resolve: `gatsby-source-filesystem`,
6 ...

The ... represents the reset of the items in the array, I’ve shortend it for brevity.

I’ll delete the layout.css file in the components directory and remove the import "./layout.css" line from the layout.js component.

Now that the reset is removed (when I deleted the layout.css file) there’s a bit of a margin showing and everything looks a bit meh!

Global Style

With CSS-in-JS the styles can be scoped to specific components, more on this in a bit.

Sometimes there’s a need to write some global styles, to get rid of that margin and to normalise browser inconsistencies.

I’ll straight up jack the example given in the Linaria docs and add that to a theme folder in the src directory. The file structure will look like this.

1gatsby-starter-linaria/
2├─ src/
3│ ├─ components
4│ ├─ images
5│ ├─ pages
6│ └─ theme
7│ └─ globals.js

In the globals.js file, I’ll import the css tag from Linaria and paste in the example.

Add a body tag to remove that margin and add a background colour with a bit of contrast so that I can see the styles have been applied.

1import { css } from 'linaria'
2
3export const globals = css`
4 :global() {
5 html {
6 box-sizing: border-box;
7 }
8
9 *,
10 *:before,
11 *:after {
12 box-sizing: inherit;
13 }
14
15 body {
16 margin: 0;
17 background: red;
18 }
19 }
20`

Ok, cool, so that’s nice, but wtf do I do with it? Right??

So, from what I can glean the css tag will append the global style to the body element of the project no matter where you put it. 🙃

For me it’ll make sense to add it to the layout component as this is where all the main styles for this project live and it’s what wraps every other component and page in the project.

For now I’ll change the empty fragment (<></>) wrapping the layout component to a div and add a className to it to pass the globals to:

1...
2import { globals } from "../theme/globals"
3...
4
5return (
6 <div className={globals}>
7 <Header siteTitle={data.site.siteMetadata.title} />
8 <div
9 style={{
10 margin: `0 auto`,
11 maxWidth: 960,
12 padding: `0 1.0875rem 1.45rem`,
13 }}
14 >
15 <main>{children}</main>
16 ...

I can now take some of the styles from the reset I deleted and add those to the globals file:

1import { css } from 'linaria'
2
3export const globals = css`
4 :global() {
5 html {
6 box-sizing: border-box;
7 font-family: sans-serif;
8 -ms-text-size-adjust: 100%;
9 -webkit-text-size-adjust: 100%;
10 }
11
12 *,
13 *:before,
14 *:after {
15 box-sizing: inherit;
16 }
17
18 body {
19 margin: 0;
20 -webkit-font-smoothing: antialiased;
21 -moz-osx-font-smoothing: grayscale;
22 }
23 }
24`

Now the styles are back to what they were but I’m now using Linaria.

Using the styled tag

Now I can use the Linaria styled tag much in the same way I’d use it with styled-components.

I’m going to convert the components from using the inline style tag to using the Linaria styled tag.

I’ll work through the components that have styles in them.

Header: I’ll import the Linaria styled tag and make a StyledHeader component:

1import { styled } from 'linaria/react'
2
3const StyledHeader = styled.header``

From here I can add all the styles in that wrapping component to the styled Linaria tag component.

So I’ll add a div a h1 and an a tag (the Gatsby Link component is an a element) like this:

1const StyledHeader = styled.header`
2 background: rebeccapurple;
3 margin-bottom: 1.45rem;
4 div {
5 margin: 0 auto;
6 max-width: 960px;
7 padding: 1.45rem 1.0875rem;
8 }
9 h1 {
10 margin: 0;
11 }
12 a {
13 color: white;
14 text-decoration: none;
15 }
16`

Now the component is cleaner with all the inline styling moved to the styled Linaria component.

1const Header = ({ siteTitle }) => (
2 <StyledHeader>
3 <div>
4 <h1 style={{ margin: 0 }}>
5 <Link to="/">{siteTitle}</Link>
6 </h1>
7 </div>
8 </StyledHeader>
9)

Layout: same again, import the Linaria styled tag and make a StyledLayout component:

1import { styled } from 'linaria/react'
2
3const StyledLayout = styled.main``

As this is wrapping the whole project I’ll need to define a class for the div on this component:

1const StyledLayout = styled.main`
2 .page-wrapper {
3 margin: 0 auto;
4 max-width: 960px;
5 padding: 0 1.0875rem 1.45rem;
6 }
7`

Apply the class to the div in the component and remove the main tag wrapping the components children:

1return (
2 <StyledLayout className={globals}>
3 <Header siteTitle={data.site.siteMetadata.title} />
4 <div className="page-wrapper">
5 <>{children}</>
6 <footer>
7 © {new Date().getFullYear()}, Built with
8 {` `}
9 <a href="https://www.gatsbyjs.org">Gatsby</a>
10 </footer>
11 </div>
12 </StyledLayout>
13)

That’s it for the components and taking a look at the pages none of them have any styles in them.

So now the StyledLayout is where I could apply the styles to the h1 and p elements in the pages. If I wanted to I could style the rest of the projects elements here.

But I’m not! That’s it for this one.

Video Detailing the Process

Here’s a video of me detailing the process.

Resources

Here’s some resources on CSS-in-JS performance I found interesting.

Back to Top