CSS-in-JS Guide

CSS-in-JS Guide

One dilemma developers often face when using JavaScript frameworks is whether to use CSS-in-JS. If you're a React developer, you've most likely used CSS-in-JS before.

CSS vs. CSS-in-JS is a hot topic these days. This is mainly due to concerns over the performance issues of CSS-in-JS. However, there are also new CSS features that may address these issues in the near future.

The purpose of this article is to help you choose between CSS and CSS-in-JS for your upcoming projects, based on the current state of modern CSS and how it may change in the future.

Please note that any JavaScript front-end framework or library can implement the CSS-in-JS idea. This article uses React, by far the most popular JavaScript front-end library, to discuss the use of CSS-in-JS, as well as its significant advantages and disadvantages.

1. CSS rendering blocking

Before we go any further into what's best and what's not, let's discuss the rendering issues caused by CSS.

Traditionally, browsers load HTML first and then CSS from all external resources. Afterwards, the browser creates a CSSOM using all external and internal CSS information. The browser is now ready to style the rendered HTML based on CSS cascading rules.

This process causes CSS to block the rendering of the page and delay the first draw of the requested page. First draw is an event that occurs when the browser prints the first pixel on the screen for the requested page.

A delay of more than half a second on the first draw creates a greater risk of user dissatisfaction and can negatively impact the goals of the application. The faster you deliver CSS to the client, the better you can optimize the time to first paint of the page.

2. Solve CSS rendering blocking

Using HTTP/2-enabled applications, multiple HTML, CSS, and JS files can be loaded in parallel. This capability is limited in HTTP/1.1. Most modern browsers and websites now support HTTP/2, which minimizes rendering blocking caused by waiting for other files to load:

image.png

However, render blocking also involves factors other than file loading speed.

Let's say our application has a page that has a lot of CSS. It may contain selectors that are not used, but exist because we import a main CSS file on each page.

The above scenario basically describes how we are accustomed to directly using CSS UI frameworks or UI toolkits we create to quickly simplify our design systems. Not every page uses all the styles referenced by the framework or toolkit. As a result, we end up with a lot of garbage in the final CSS styling of the page.

The more CSS there is, the longer it will take the browser to build the CSSOM, which will lead to completely unnecessary rendering blocking.

To solve this problem, it is useful to break the CSS into small chunks. In other words, keep global styles and key CSS in a common CSS file, and componentize everything else. This strategy makes more sense and solves the unnecessary blocking problem:

image.png

The above diagram shows the traditional way of creating and managing separate CSS files for different components in React. Because each CSS file is attached directly to its respective component, it is only imported when the related component is imported, and disappears when the component is removed.

There is a drawback to this approach. Let's say we have an application that contains 100 components, and another developer working on the same project accidentally uses the same class name in some of those CSS files.

Here, the scope of each CSS file for each component is global, so these accidentally copied styles will continue to override each other and be applied globally. Such a scenario would lead to serious layout and design inconsistencies.

CSS-in-JS is said to solve this scope problem. The next section will review CSS-in-JS at a high level and discuss whether it can effectively solve the scope problem in one go.

3. What CSS-in-JS provides

CSS-in-JS, simply put, is an external functionality layer that allows you to write CSS properties for components via JavaScript.

It all started in 2015 with a JavaScript library called JSS , which is still actively maintained. You must provide CSS properties to the selector using JavaScript syntax, and the selector will automatically apply these properties to the respective selector once the page loads.

When JavaScript took over rendering and managing the front-end with libraries like React, a CSS-in-JS solution called styled components emerged. Below we will styled-componentsdemonstrate an example use case of CSS-in-JS using the library, since it is the most popular way of using CSS-in-JS in React.

In your React application, use the Yarn command below to install styled-componentsthe library. If you are using a different package manager, see the Styled Components installation documentation to find the appropriate installation command:

yarn add styled-components

After installing styled-componentsthe library, import styledthe function and use it as follows:

import styled from "styled-components";

const StyledButton = styled.a`
  padding: 0.75em 1em;
  background-color: ${
      
       ({
       
        primary }) => ( primary ? "#07c" : "#333" ) };
  color: white;

  &:hover {
    background-color: #111;
  }
`;

export default StyledButton;

This styled component can now be imported anywhere and used directly to build functional components without having to worry about styling:

import StyledButton from './components/styles/Button.styled';

function App() {
    
    
  return (
    <div className="App">
      ...
      <StyledButton href="...">Default Button</StyledButton>
      <StyledButton primary href="...">Primary Button</StyledButton>
    </div>
  );
}

export default App;

The effect is as follows:

image.png

Note that styles applied to styled components are locally scoped, which eliminates the need to pay attention to CSS class naming and global scope. Additionally, we can dynamically add or remove CSS based on the provided to the component propsor any other logic required for the functionality of the application.

4. Advantages of CSS-in-JS

JavaScript developers may prefer to use CSS-in-JS styles rather than CSS classes. The biggest problem the CSS-in-JS approach solves is global scope. For JavaScript developers, it has some other advantages.

Now let’s explore these advantages.

4.1 No scope and priority issues

Because styles are available locally, they are less likely to conflict with styles from other components. You don't even have to worry about naming things strictly to avoid style conflicts.

Styles are written specifically for a component, with no child selectors pre-set, so there are rarely issues with priority.

4.2 Dynamic styles

Conditional CSS is another highlight of CSS-in-JS. As the button example above demonstrates, check propthe value and add appropriate styles.

4.3 Simple themes

It's easy to theme your application with custom CSS properties. Finally, you will have to move to the JavaScript side and write logic to switch and remember themes based on user input.

CSS-in-JS allows you to write theme logic entirely in JavaScript. Using styled-components ThemeProviderwrappers, you can quickly color-code a component's theme.

4.4 Ease of maintenance

Considering the features and benefits provided by CSS-in-JS, JavaScript developers may find CSS-in-JS more convenient than managing hundreds of CSS files. However, one must have a good understanding of both JavaScript and CSS to effectively manage and maintain large projects powered by CSS-in-JS.

5. Disadvantages of CSS-in-JS

CSS-in-JS solves the scope problem really well. But as we initially discussed, we face bigger challenges - things like render blocking, which directly impacts the user experience. In addition to this, the concept of CSS-in-JS also needs to solve some other problems.

5.1 Delayed rendering

CSS-in-JS will execute JavaScript to parse CSS from JavaScript components and then inject these parsed styles into the DOM. The more components there are, the more time it takes the browser to draw them the first time.

5.2 Caching issues

CSS caching is often used to improve sequential page load times. Since no CSS files are involved when using CSS-in-JS, caching is a big issue. Additionally, dynamically generated CSS class names compound this problem.

5.3 No support for CSS preprocessors

Using regular componentized CSS methods, it's easy to add support for preprocessors such as Sass, Less, and PostCSS. This is not possible in CSS-in-JS.

5.4 Chaotic DOM

CSS-in-JS is based on the idea of ​​parsing all style definitions from JavaScript into plain CSS, and then using style blocks to inject these styles into the DOM.

For every component styled with CSS-in-JS, there may be 100 style blocks that must be parsed and then injected. Simply put, there will be more indirect costs.

5.5 Learning Curve

Many native CSS and SCSS features are missing from CSS-in-JS. For developers accustomed to CSS and SCSS, adapting to CSS-in-JS may take some time.

5.6 No widespread support

Most UI and component libraries now don't support the CSS-in-JS approach because it still has a lot of problems to solve. The issues discussed above can collectively result in a low-performance, difficult-to-maintain product with multiple UI and UX inconsistencies.

Guess you like

Origin blog.csdn.net/p1967914901/article/details/129015231