Styled components - introduction

Possible that you noticed that in previous articles I did not use standard HTML tags only used some strange notation with the prefix “Styled.”. Today I will try to explain where it came from, and what is more important - why it appeared.
Styling components in React
Several techniques can be used to style components. Below you will find their list, so that those more interested know what they can read about:
- CSS
- CSS Preprocessors (LESS, SASS, …)
- CSS-in-JS (e.g. styled-components)
- CSS Modules
In the article, however, we will focus only on one of them.
Why use styled-components?
There is a range of benefits resulting from using the mentioned library. We will focus, however, on the most important ones, which are actually worth spending some time on.
It is worth starting from the fact that components written using styled-components receive unique class names, to which styles are assigned. Thanks to this, we do not have to worry about their overlapping, which in turn allows focusing on the code itself instead of watching over methodologies facilitating structuring of style sheets. Such an approach significantly facilitates development and maintenance of code, and also secures us against difficult to find errors related to overlapping style definitions.
Another key aspect is the simplicity of linking a React component with a style. As programmers guided by good practices, we usually do not like to "bind" anything in the code. Trust me that in this case it is nothing bad and it is hard to make things difficult for yourself. What exactly do I mean, speaking about binding? Styled-components allows passing values directly to style definitions, using props for this. This means that we can pass any value through them, and then use it in the style definition.
Among significant advantages I would mention two more issues: code expressiveness and optimization.
The first of them means nothing else than increasing code readability by giving specific names to constructions composed of HTML tags. In short - describing a button for sending a form we do not use HTML "button," only we can define a constant SubmitButton, which we will then use in our JSX. In classic HTML and CSS similar effect we often achieved by using id and class attributes.
The second issue happens "underneath" and does not require additional contribution from us. Optimization consists in the fact that styled-components loads style definitions only for components currently rendered on the screen. From the classic approach it differs in that if the user does not see one of the views, then we will not load its style. Using CSS the client entering the page had to download all definitions of style sheets regardless of whether they visited a given path or not.
So that you better understand the above advantages, a bit further I will support them with examples, but first...
I am styled… styled-component
Before we go further, first let's install the package:
npm install --save styled-components
<br />
If you use TypeScript, you will also need type definitions:
npm install --save @types/styled-components
So, to code!
A good practice is to separate styles into a separate file. I have a habit of naming them identically as the component they refer to - adding the suffix ".styles". For example - component "Dashboard.jsx" and styles referring to it - "Dashboard.styles.js".
And now let's create our first styled component!
import styled from 'styled-components';
export const Button = styled.button``;
Believe it or not, but this is already a correct styled-component. It does not bring anything to the appearance of our button, true, but it allows us to use the benefits written in previous paragraphs.
Note that I defined a constant which I exported. We will need it in a moment, but first let's create one more component - this time making slightly more sense. It will be a container wrapping our whole example:
export const Container = styled.div`
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
`;
As you can see it is a simple div, which will watch over the arrangement of our elements inside itself. If you do not know flexbox, then be calm - at the end of the article you will surely find links that are worth checking to get acquainted with it.
Let's use our components now inside React. First we must import them:
import * as Styled from './App.styles';
And now let's use them when rendering:
const App = () => {
return (
<Styled.Container>
<Styled.Button>Push me!</Styled.Button>
</Styled.Container>
);
}
Note that with such use of styled-components we know exactly which components are styled by us and it is easier to search for definition of their styles (most IDEs allow direct transition to definition of a given style).
Extending existing components
There is one more thing that is worth knowing starting work with styled-components. It is the possibility of extending existing components. It applies to both those defined by ourselves, as well as components coming from external libraries. The only condition of operation for the latter is returning by them the className prop to the DOM element.
To illustrate this it will be easiest to use an example. Let's use the Button defined above for this. Let's add a few new values to it, so that we can observe that components extending it will inherit its definition.
export const Button = styled.button`
border: 0;
border-radius: 3px;
font-weight: bold;
padding: 1rem;
margin: 1rem;
:hover {
filter: invert(25%);
}
`;
Note that without the slightest problems we used the pseudo-class hover nesting it in our component. It will help show the user that a given button is interactive. Let's go a step further now and extend this button with two color variants. To achieve this goal we will use slightly different syntax than the one we used so far. Instead of defining style using "styled.element name" we will use the styled function to which, as a parameter we will give our component. See for yourself:
export const BlueButton = styled(Button)`
color: #fff;
background: #00f;
`;
export const RedButton = styled(Button)`
background: #f00;
`;
All styles defined inside Button will be inherited to BlueButton and RedButton, moreover we added to them font and background color respectively. If in the basic component we had defined one of these fields, then it would be replaced by the value specified inside the inheriting component.
Back to theory
I will return for a moment to the advantages that I outlined at the beginning of the article. regarding readability itself, you are able to state yourself, how component definitions fall compared to classic CSS. I would like to show you, to what form the components created by us are generated, to better outline the first of the advantages - protection against style overlapping. Below you will find a screenshot presenting the DOM structure of our component:

Note how the classes of each element look. They were generated by styled-components, and to each of the classes the definitions written by us are assigned. In this way we are sure that none of the styles will overlap with another.
regarding the other advantages described at the beginning of the article, we will use passing values through props in the next article, which will appear next week.
In the matter of optimization, however, if you do not want to take my word for it (which I sincerely recommend ;) ) then you are able to very easily check it yourself. Just add any new component using styled-components, but do not use it in any view. To verify, start the application, enter the browser developer tools (I recommend Firefox), and then "Style Editor". You will find there a list of all CSS classes our application uses. They will have strange names - like those on the screen above. Even if you search them very carefully, I am sure that you will not find the style definition of the unused component there.
Small warning at the end
However you use styled-components, remember not to define them inside functional components (unless you use memoization), nor inside the render method of class components. If you do this, they will be defined at each render, which may negatively affect the performance of your application. Best however to stick to extracting styles to a separate file. In this way you will be sure that you will not harm yourself, and in addition you will maintain code cleanliness.
And in this way we close our introduction to styled-components. Next week we will move on to more advanced issues. Today's example you will find on the repository. If so far you have not had contact with this way of styling applications, then I sincerely recommend facing it. It will definitely be worth it!
Useful links
Styled-components:
Flexbox:
- MDN Documentation
- Great article from CSS Tricks
- Flexbox Froggy - interactive game teaching flex