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.
You can install GooberJS with npm or yarn:
npm install goober
# or
yarn add goober
First, we have to set the pragma to match:
import { setPragma } from "goober";
import { createElement } from "react";
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.
// It's a named export
import { styled } from "goober";
// Notice the parathesis.
const Title = styled("h1")`
font-size: 2rem;
color: maroon;
`;
function Header() {
return (
<header>
<Title>Goober</Title>
</header>
);
}
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.
import { styled } from "goober";
const Title = styled("h1")`
font-size: 2rem;
color: ${(props) => props.textColor};
`;
function Header() {
return (
<header>
<Title textColor="red">Goober</Title>
</header>
);
}
import { styled } from "goober";
const Title = styled("h1")`
font-size: 2rem;
color: ${(props) => props.textColor};
`;
const LargeTitle = styled(Title)`
font-size: 4rem;
`;
function Header() {
return (
<header>
<Title textColor="red">Goober</Title>
</header>
);
}
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.
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
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