Styling React App - Stylify vs Styled Components

machy8

Vladimír Macháček

Posted on August 21, 2022

Styling React App - Stylify vs Styled Components

Stylify generates utility-first CSS based on what you write. It works with any framework and with any tool. Styled Components is a library for styling React components.

This article is not about which tool is better but about comparing approaches when styling the app with these tools.

Setup

For all the examples below, I am going to use the vite-react setup.

Stylify requires the installation and a bit of configuration. It's because the CSS is generated during a build before the app is initialized:

npm i -D @stylify/unplugin
Enter fullscreen mode Exit fullscreen mode

And the vite.config.js:

const stylifyPlugin = vitePlugin({
    transformIncludeFilter: (id) => {
        return id.endsWith('js') || id.endsWith('jsx');
    },
    bundles: [{
        outputFile: './src/stylify.css',
        files: ['./src/**/*.js', './src/**/*.jsx'],
    }],
    extend: {
        bundler: {
            compiler: {
                selectorsAreas: [
                    '(?:^|\\s+)className="([^"]+)"',
                    '(?:^|\\s+)className=\'([^\']+)\'',
                    '(?:^|\\s+)className=\\{`((?:.|\n)+)`\\}'
                ]
            }
        }
    }
});

export default defineConfig({
    plugins: [stylifyPlugin, react()]
});
Enter fullscreen mode Exit fullscreen mode

You can try to edit the Stylify+Vite+React and Stylify+Next examples on Stackblitz.

Styled Components only requires to install the library and it can be used right away.

npm i styled-components
Enter fullscreen mode Exit fullscreen mode

Syntax and usage

When you want to style an element with the Styled Components, you can use the CSS API or create a component:

const Title = styled.div`
  color: blue 
  font-weight: bold
`;
<Title>Hello World!🎉</Title>
Enter fullscreen mode Exit fullscreen mode

The generated CSS looks like this:

.sc-bdVaJa {} .knKEua{color:blue;font-weight:bold;}
Enter fullscreen mode Exit fullscreen mode

Stylify on the other hand takes file content and generates CSS for each matched selector. Each selector is by default a utility and is generated only once.

The syntax is by default native CSS property:value. Also, when writing values, you can use __ (two underscores) instead of space and ^ (a hat) for a quote. It is similar to Tailwind, but without having to learn and remember the custom selectors and shortcuts. If you know CSS you already know the Stylify selectors. In case you need want shorter or custom selectors, you can add your own macros.

The selectors can be written right away without defining a component.

<div className="color:blue font-weight:bold">Hello World!🎉</div>
Enter fullscreen mode Exit fullscreen mode

CSS output:

.color\:blue {color:blue}
.font-weight\:bold {font-weight:bold}
Enter fullscreen mode Exit fullscreen mode

However, nobody wants bloated templates with utilities. Sometimes the components are necessary. They can be defined globally in a config or locally in a file (through content options), where they are used. In the file, it expects a javascript object without the surrounding brackets. The definition is recommended within comments because almost any file format can handle comments. In Stylify the component is a CSS class and it can be used on any element:

/*
stylify-components
  title: 'color:blue font-weight:bold'
/stylify-components
*/
<div className="title">Hello World!🎉</div>
Enter fullscreen mode Exit fullscreen mode

The title selector in the CSS is attached to each selector it requires. Because of that, there are fewer selectors/duplicates and the CSS is smaller.

.color\:blue,.title{color:blue}
.font-weight\:bold,.title{font-weight:bold}
Enter fullscreen mode Exit fullscreen mode

When it comes to production, the selectors can be minified:

<div class="_88io">Hello World!🎉</div>
Enter fullscreen mode Exit fullscreen mode
._asder,._88io{color:blue}
._a4fv7,._88io{font-weight:bold}
Enter fullscreen mode Exit fullscreen mode

Media queries

When we need a different style for various media queries, we can do that like this in Styled Components:

const Title = styled.div`
  color:blue
  @media (max-width: 768px) {
    color:red
  }
`;
Enter fullscreen mode Exit fullscreen mode

With Stylify, you can use predefined screens or dynamic ones:

/*
stylify-components
  title: `
    color:blue
    md:color:red
    minw640px:color:orange
  `
/stylify-components
*/
<div className="title">Hello World!🎉</div>
Enter fullscreen mode Exit fullscreen mode

Variables

Variables can be used within the Styled Components directly in the styles:

const Title = styled.div`
  color: ${props => props.color || "red"}
`;
Enter fullscreen mode Exit fullscreen mode

Stylify allows you to define variables and then use them within the selectors:

/*
stylify-variables
  blue: '#005EB8',
  red: '#8b0000'
/stylify-variables

stylify-components
  title: 'color:$blue'
/stylify-components
*/
<div className="color:$red"></div>
Enter fullscreen mode Exit fullscreen mode

When there is a case that we need various types of one button, we need to write the full selectors in stylify

<div className={`wrapper searchDiv ${isOrangeButton ? 'color:orange' : 'color:blue'}`}></div>
Enter fullscreen mode Exit fullscreen mode

Keyframes

The keyframes in the Styled Components can be defined like this:

const rotate = keyframes`
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
`;

const Rotate = styled.div`
  animation: ${rotate} 2s linear infinite;
`;
Enter fullscreen mode Exit fullscreen mode

In Stylify it looks a bit different

/*
stylify-keyframes
  rotate: `
     from { transform: rotate(0deg); }
     to { transform: rotate(360deg); }
  `
/stylify-keyframes
*/
<div class="animation:rotate__2s__linear__infinite"></div>
Enter fullscreen mode Exit fullscreen mode

A simple animation example:
Stylify animation keyframe

Plain selectors

When it comes to global styles and simple selectors, they can be defined within the Styled Components using createGlobalStyle:

import { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
  button { color:red }
`;

<React.Fragment>
  <GlobalStyle />
</React.Fragment>
Enter fullscreen mode Exit fullscreen mode

In Stylify, the same thing is achieved using plain selectors. The selectors are directly injected into the generated CSS file.

/*
stylify-plainSelectors
   button: 'color:red'
/stylify-plainSelectors
*/
<button></button>
Enter fullscreen mode Exit fullscreen mode

Splitting CSS

The Styled Components doe's a good job when it comes to optimization as it automatically splits the CSS into critical and noncritical and injects the CSS of those components that are used. However, the compilation is done when the app is running.

Stylify doesn't work that way.
It generates CSS files according to your configuration and you have to tell the app when the CSS should be loaded.
You can configure a bundle for each page/component/layout separately. Even though you can split the CSS however you want, thanks to the utilities/components combination the CSS size is going to be relatively small as the selectors are generated only once. So sometimes it makes sense to have only Front + Admin CSS. Stylify website has less then 20 Kb and other websites are between 30-50 Kb.
One more feature is, that it doesn't slow down the app because the CSS is generated before the app is initialized.

Let me know what you think!

If you like the idea, let me know that by starring Stylify repo ❤️.

I will also be happy for any feedback! The Stylify is still a new Library and there is a lot of space for improvement 🙂.

Also a big thanks goes to Luke Shiru for reviewing the information about the Styled Components.

Stay in touch:

👉 @stylifycss
👉 stylifycss.com
👉 @8machy
👉 dev.to/machy8
👉 medium.com/@8machy

💖 💪 🙅 🚩
machy8
Vladimír Macháček

Posted on August 21, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related