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.
keyframes
that enables us to reuse animations across componentsstyled.tag
to a goober’s understandable format, something like styled(“tag”)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:
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.
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.
Let’s quickly set up a React app using Facebook’s create-react-app project. To do so, follow the below steps.
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:
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.
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> ); }
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.
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; } `;
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.
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:
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.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
3 Replies to "Goober: A lightweight CSS-in-JS solution"
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!
“they’re CSS in JS” <- What that is an issue?
Awesome article, thanks! Just an FYI, the benchmarks for Goober have been updated. It is now performing ~2x ops/sec than emotion.