0
(0)

Css came a long way to be where it is today. Now we have variables, filtering(with the :is() pseudo-class), we have mathematics with the calc(). The problem is we don’t have nesting, and mixins, and functions and parent selector. Also everything in CSS is globally scoped.

Styled-components comes with a new approach. Instead of creating a component and applying a class name that has some styles defined, it creates a component, that:

  • gets a generated class name, as a 6 letter combination, that is case-sensitive, this is taken care automatically by the library
  • we can write pure CSS code that will be injected in HTML in a style tag
  • we can write CSS either as object (property-value pairs) or as vanilla CSS in a template literal

Template literal:

Object:

  • since the CSS will not be an inline CSS but it will be embedded in the html’s style tag, you can use media queries, pseudo elements, pseudo classes and so on

The styles of each component is scoped to that component, meaning if you don’t use the component, neither the styles for that component will be loaded. Also since the class names are generated dynamically and they are unique, there will be no class clashing between components.

So let’s recap, styled-components offer the following:

  • unique class names
  • dead styles(unused ones) are eliminated
  • the least amount of code is loaded, using code splitting
  • dynamic theming(Themeprovider)
  • automatic vendor-prefixing
  • you can pass in props values

How about caching ?

Class names will not change from one compilation to another only if some style is changed inside that component in the meantime.

Features in common with css preprocessors

  • nesting of elements
  • accessing parent element
  • using variables
  • Mixins without parameters
  • Mixins with parameters:
  • Any mathematical operation is permited inside the ${ } since that is the portal to Javascript or you can just use simply with the CSS native calc() function.
  • Loops are not that pretty with javascript:

Above I created 2 constants with an array value. Colors array has color values and classes array has the actual selectors. Both arrays should have the same length and same order for the association to work properly. I iterate through the array and combine the generated strings all together.

  • Extending a class with another class

The styled() syntax resolves the extending of one class with another, but the problem is, we don’t want the Button component to be rendered as a link, but as a button tag. Therefore we add the as attribute on the Button component to communicate with the browser to render it as a button.

Instead of as attribute you could use the withComponent, but that feature is getting deprecated and you have to write more code also:

const PrimaryButton = Button.withComponent('button');
  • Media queries that are inside instead of outside of the selector rule:

Extra features in Styled-components

Props

Since components are created when defining a styled component rule, they can be used just like react components with props.

const Button = styled.button`
   background-color: ${props =>
      (props.type === 'primary' && 'blue') || 
      (props.type === 'error' && 'red') ||
      (props.type === 'warning' && 'yellow')
    }
`
<Button type="primary" />
<Button type="error" />
<Button type="warning" />

In the example we created a styled component named Button and we checked what type prop did get and according to that the button got the right background color.

Creating global styles

When you want to style elements on the highest level, like body or html, or just want to style generally elements like paragraphs and so on you can use the createGlobalStyle feature, that you need to import from styled-components to use it.

This way styles are created but no element is rendered as in the previous cases.

const GlobalStyles = createGlobalStyle`
    @import url('https://fonts.googleapis.com/......');
    body {
        color: black;
        font-family: Arial, sans-serif
    }
    p {
        padding-bottom: 20px;
    }
`

Theme provider

const theme = {
    colors: { 
        header: '#ebfbff',
        body: '#fff',
        footer: '#033'
    }    

}

<ThemeProvider theme = {theme}>
    <App />
</ThemeProvider>

export const StyledHeader = styled.header`
    background-color: ${({ theme }) => theme.colors.header}
`

A centralized theme definition that is accessible by the all the components that are wrapped around by this it is just like using variables in CSS. When a variable changes in the theme provider it changes everywhere.

Adding images

import img from '../public/images/cat.png';

const Content = styled.div`
  background-image: url(${img});
  width: 125px;
  height: 110px;
`

Using CSS variables

<Wrapper
    style={{
    '--bgcolor': color,
    '--opacity': opacity,
    }}
>

const Wrapper = styled.div`
  opacity: var(--opacity);
  background-color: var(--bgcolor);
`;    

The attrs method

You can add to all instances of your styled component an attribute(in case you would omit on the comoponent. For example you create a Password Input component but you want to make sure you won’t forget to add the type on each instance:

const PasswordInput = styled.input.attrs(({ type }) => ({
  type:  type || "password"
}))`
  display: flex;
  align-items: center;
  margin: 1.3vh 0;
`
<PasswordInput type="password" />
<PasswordInput />

Specificity

You can add more specificity to an element by repeating the parent selector multiple times, that will repeat the class name several times:

const Button = styled.button`
  &&& {
    color: green;
    font-weight: bold;
  }
`  // This will result in something like .fUdhed.fUdhed.fUdhed { ... }

Animations

Summary:

Styled components is a CSS-in-JS approach, where you write pure css code in template literals and it takes that code and Injects into style tags in the HTML. Of course this means that it will make the HTML more crowded and also the browser will not start interpreting the styles until styled-components have parsed them and added them into the DOM, which could mean a speed factor in rendering. Because your CSS lives inside the javascript files it will be cached like normal js files.

Styled components injects only the styles that you actually need for a component that is actively rendered on the page(is on the screen), nothing more. 6 letter classes are generated for each component, but you can also use the babel macro extension to have more understandable class names.

Honourable mentions

Emotion

In the same group with styled-components we can mention Emotion style library. It does the same things as styled-components, but it has some additional syntax that we can use.

We can use it as a value of className:

Or directly with the css method:

<div css={css`
        margin: 10px;
        padding: 10px;
        background-color: #eee;
`}>

In case you want to stick to the styled-components syntax you can just use the:

const Button = styled.button`
   color: red
`

Linaria

This style library brings the same things to the table as styled components, but there is a major difference. As on their official website promote it, it has zero-runtime, meaning that the CSS does not live in the javascript bundle but instead Linaria creates a javascript file and a css file as an end result. The browser will not load and run javascript first, but css first and javascript after. How cool is that?

The basic syntax for linaria is just like in Emotion using the css method as a value of class name. But if you import the @linaria/react extension then you can write style with template literals just like styled-components.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Categorized in: