Goober: A lightweight CSS-in-JS solution

5 min read 1458

Goober: a lightweight CSS-in-JS solution

CSS was originally created to style entire web pages. But, over time the complexity of websites has grown, which makes it very difficult to manage designs. CSS doesn’t have any concept of modules through which we could divide the code into separate chunks.

Even JavaScript doesn’t have the modules initially. But, with the passing of time, web development has significantly evolved. We now use component-based libraries like React and Vue.js to design the frontend of web apps. It highlighted the need for a similar solution for CSS. But, the standard CSS doesn’t provide any programming concepts. So, we use a solution called CSS-in-JS.

There are some popular CSS-in-JS libraries like emotion and styled-components. But, their main issue is that they take around 10KB to 20KB of space. As you probably know that heavy files make a significant impact on the page load time and therefore on the ranking of a website in search engines. So, Cristian Bote created a lightweight alternative, goober. It takes less than 1KB of space which makes it a preferred choice for high-performance sites.

Features of goober

  • The major feature that attracts developers to goober is its size. Its lightweight footprint of less than 1KB makes it stand out from other CSS-in-JS solutions
  • It is designed to work with vanilla JavaScript as well as its frontend libraries/frameworks like React, Vue.js, Angular, Svelte, etc.
  • Support for server-side rendering
  • Growing community size with around 24 active contributors
  • Different ways to customize CSS properties. For example, by providing props to CSS tagged templates or by using CSS with JSON. Here, an important thing to note is that using JSON/Object to write CSS code significantly reduces the bundle size
  • Ability to specify a target node to append the style tag
  • It allows us to separate code for the entire document and specific sections
  • Reuse code with ease
  • goober has a method called keyframes that enables us to reuse animations across components
  • It has a babel plugin to transform codes like styled.tag to a goober’s understandable format, something like styled(“tag”)
  • Integrate goober with Gatsby using an official plugin
  • Ability to parse CSS code
  • goober has nested rules with pseudo selectors. It even has nested styled-components
  • It enables us to extend styles. For example, we can either overwrite with another set of CSS rules or use “as” prop
  • Support for media queries (@media) and keyframes (@keyframes)
  • An interesting feature of goober is that it comes with smart(lazy) client-side hydration
  • Helpful autoprefixer that makes sure the CSS code will work on all web browsers. This functionality is also known as vendor prefixing. The team behind goober has created a separate package to handle auto prefixing

Benchmarks

Since its inception, goober has seen significant adaptation from the developer community. It encouraged the contributors behind goober to make a performance comparison between its popular competitors.

So, they selected goober, emotion, and styled-components. Then, executed 85 samples with each library to find out how much time on average it takes to complete the task.

The benchmark results were quite phenomenal:

  • styled-components processed 21,469 ops/sec
  • goober processed 39,348 ops/sec
  • emotion processed 46,504 ops/sec

Clearly, the winner here is the emotion library. But, the point to be noted is that emotion and styled-components have well-established APIs and both have 200+ contributors. Whereas, goober is a new contender among CSS-in-JS libraries. Still, it beats the styled-components in speed and gives a close run compared to the emotion library.

Comparison between goober, emotion, and styled-components

Before writing any code for goober, let’s compare it with its popular competitors (i.e. emotion and styled-components). It will answer your question, “why should I use goober?”

Features goober emotion styled-components
Tagged template literals Yes Yes Yes
Composition Yes Yes Yes
Global styles Yes Yes Yes
Theming support Yes Yes Yes
Media queries Yes Yes Yes
Nested selectors Yes Yes Yes
Attaching props Yes Yes Yes
Server-side rendering Yes Yes Yes
Average number of operations per second 39,348 46,504 21,469
Library size Less than 1kB ~11kB ~12kB
Number of contributors 24 211 283

In the above table, you can see that all three CSS-in-JS libraries have common features. But, the way they are implemented decides the performance of the library. emotion is faster than both but the small footprint of goober could give an advantage to its users.

Getting started with goober

Let’s quickly set up a React app using Facebook’s create-react-app project. To do so, follow the below steps.

We made a custom demo for .
No really. Click here to check it out.

At first, create the project inside the “my-app” folder:

npx create-react-app my-app

And then move inside the folder:

cd my-app

Now, we need to install the goober library:

npm install goober

At this point, we are ready to write the code to integrate goober with React. We will start by creating a simple web page that contains one heading and three paragraphs.

The heading style is very straightforward as we directly target the <h1> tag. Whereas, for paragraphs, we’ll define all the common code once. And then, extend it separately for each paragraph. Paste the below code inside src/index.js:

import React from "react";
import ReactDOM from "react-dom";
import { styled, setup } from "goober";

setup(React.createElement);

const Title = styled("h1")`
  font-weight: bold;
  color: #00f;
`;

const P = styled("p")`
  font-weight: bold;
`;

const P1 = styled(P)`
  color: #f00;
  font-style: italic;
  font-weight: normal;
`;

const P2 = styled(P)`
  color: pink;
  text-decoration: underline;
`;

const P3 = styled(P)`
  color: #bb0276;
`;

function App() {
  return (
    <div className="App">
      <Title>Hello World</Title>

      <P1>This is paragraph # 1 that is designed with goober.</P1>

      <P2>This is paragraph # 2 that is designed with goober.</P2>

      <P3>This is paragraph # 3 that is designed with goober.</P3>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

You may now test this code by executing the below command in the console window:

npm start

It will look something like this:
'hello world' goober

Explanation of above code

First of all, we imported the required packages React, ReactDOM, and goober to make everything work correctly. We then have to call the setup() method once in the beginning. It is important to note that setup() must be called before using the styled() function.

After that, we will create different CSS rules for headings and paragraphs using tagged template literals.

Customize the style with props

There are different ways to customize the style in goober. One of them is to use props. Basically, we set the desired values using props and access them inside the template literals of the desired styled() function.

For example:

const Title = styled('h1')`
  color: ${props => props.textColor};
  font-size: 3rem;
`;

function App() {
  return (
    <div className="App">
      <Title textColor="red">Hello World</Title>
    </div>
  );
}

Explanation of above code

Here, you can see that we added props called textColor and assign it a value “red”. We then used the props inside the template literals of styled() function to assign the value to the “color” property of CSS.

Global styles

goober is packed with a function called glob. It is used to specify global styles that will be applied to the entire document. It is pretty useful in web design there is a lot of code that is common between different elements.

For example, the glob function is very suitable to include any external fonts that will be used on the whole web page. Most people even use it to write the “CSS Reset” rules. To get started, we first need to import glob from goober. Like this:

glob`
  body {
    margin: 0;
  }
`;

Missing styled.tag

If you ever worked with styled-components library then you might be familiar with its styled.tag functionality. It is very popular among developers who work with CSS-in-JS solutions.

goober doesn’t support this format by default. But, the contributors and the team have developed a babel plugin. This plugin is used to convert all styled.tag references into a format that is understandable by goober.

Conclusion

The main idea behind the development of goober was to introduce a lightweight alternative for popular CSS-in-JS libraries like emotion and styled-components. So, you should use it in scenarios:

  • When you want your web pages to load faster
  • Your website receives heavy traffic (i.e. millions of users every month). Such as a news website, blog, SaaS application, or a social media network, etc. It is because goober has less than 1 kB size so it will not eat up much bandwidth as compared to its competitors

I didn’t find any significant disadvantages of goober because the team has really done well to offer almost all the features that its competitors have. And all using a very small codebase.

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.

2 Replies to “Goober: A lightweight CSS-in-JS solution”

  1. I think the main issue with CSS-in-JS solutions so far isn’t the bundle size, but rather…. That they’re CSS in JS. In a few years we’ll look back at this trend and shudder!

Leave a Reply