Replacing Styled Components with a 1KB alternative Goober

Posted on February 12, 2020

Styled Components and EmotionJS are two of the most popular CSS-in-JS libraries for the React land. But both of these do come with a cost, anywhere between 10KB to 20KB is how much any of these libraries would add to the your bundle.

What if we could replace the same with a 1KB library? That is the promise of GooberJS that uses the same styled(element) paradigm styled-components and emotion popularised but at much lesser size.

Goober does this by utilising a custom pragma pattern which is already used in cases like the css prop in emotion or sx prop in ThemeUI.

TLDR; JSX Pragma is a way of customising how JSX is compiled to React elements (React.createElement) and adding our own thing in there.

Installation

You can install GooberJS with npm or yarn:

npm install goober
# or
yarn add goober

Usage

First, we have to set the pragma to match:

import { createElement } from 'react';
import { setPragma } from 'goober';
setPragma(createElement);

Note that this has to be performed only once in the whole application and would probably go in index.js file in your application.

How do I styled an HTML element?

1// It's a named export
2import { styled } from 'goober';
3
4// Notice the parathesis.
5const Title = styled('h1')`
6 font-size: 2rem;
7 color: maroon;
8`;
9
10function Header() {
11 return (
12 <header>
13 <Title>Goober</Title>
14 </header>
15 );
16}

Goober also supports nesting and SASS like &:hover kind pseudo selectors as it’s predecessors. You can also add media templates inside styled components to make it work.

How do I customise it with props?

1import { styled } from 'goober';
2
3const Title = styled('h1')`
4 font-size: 2rem;
5 color: ${props => props.textColor};
6`;
7
8function Header() {
9 return (
10 <header>
11 <Title textColor="red">Goober</Title>
12 </header>
13 );
14}

How do I extend a component?

1import { styled } from 'goober';
2
3const Title = styled('h1')`
4 font-size: 2rem;
5 color: ${props => props.textColor};
6`;
7
8const LargeTitle = styled(Title)`
9 font-size: 4rem;
10`;
11
12function Header() {
13 return (
14 <header>
15 <Title textColor="red">Goober</Title>
16 </header>
17 );
18}

Global Styles?

Goober exposes glob function for this. It is not to be imported/used anywhere else, just using this function would add the global styles as necessary.

import { glob } from 'goober';
glob`
body {
margin: 0;
}
`;

I do feel that styled components API did it better here with the createGlobalStyle function. But if you have been with the project for long, you will know this is how it started off.

Missing styled.tag?

If you are feeling attached to styled.tag format from Styled Components, Goober team has a babel plugin that can help so that you can keep writing styled.tag but the plugin will convert the references for you.

npm i --save-dev babel-plugin-transform-goober
# or
yarn add --dev babel-plugin-transform-goober

What’s pending now?

  • Goober does not automatically prefix styles as of now, but they are proactively working on it.
  • Goober does not support theming at the moment. Here is the PR they are working on.

But this should not discourage you from using theming at all. You can always fallback to using CSS variables (or create a Theme Context and work with it if you miss JavaScript theming)

Here is a kitchen sink of everything mentioned in this article: CodeSandbox

Buy me a coffeeBuy me a coffee