React Development With Styled Components
Let’s talk about CSS and React!
It can make your React and HTML & CSS development experience quite a bit smoother if you define your CSS and styles directly in the React component (.tsx) files. Some people say it’s heretical to bake CSS styles directly inside React components. But in reality, it improves your productivity quite a bit when you don’t suffer from the headache of constantly switching between CSS files and their React components. I believe that the firmly rooted ideology of keeping them separate is based on the assumption that other people, such as UX designers, would be responsible for updating the styles whereas the developers would take care of the code part of the components.
I haven’t seen a single project where this would be the case. It was always the developer who would do the both. It turns out, the styles typically are quite deeply entangled with the DOM structure, which is defined by the component. How you organize your React components deeply affects the structure of the accompanied CSS files. Therefore it generally does not make sense for UX designers to go into such detail that they directly edit CSS files.
As writing the final CSS for the React components goes tightly hand-in-hand with creating the actual components, it feels quite obvious to place every component’s style in the same file with the component.
There are quite some nice React libaries that make your styles in React code look really neat, such as Styled Components.
Some Practices With Styled Components
Styled Compoents is a great way to smoothly embed CSS into your code and also improve readability by giving some semantic meaning to your elements.
Let’s have a look at a sample implementation of a styled component:
const Div = styled.Div({
backgroundColor: 'black',
display: 'flex',
flexDirection: 'row'
});
const SomeLabel = styled.span({
verticalAlign: 'left'
});
const MyCustomInput = styled.input({
color: 'white',
border: 'none'
});
export const MyInfoField = (props: {
label: string;
value: string;
}): ReactNode => (
<Div>
<SomeLabel>{props.label}</SomeLabel>
<MyCustomInput type={'text'} value={props.value} />
</Div>
);
(See also the complete example on my GitHub repo!)
The greatness of this approach is that you can easily “label” underlying basic elements with your own names and thereby make the code more self-documenting. That helps other coders understand the purpose of each element just by reading the code. You can also easily export these component snippets and reuse them elsewhere in your application!
I’ve been writing styled components this way since about half a year now on a very professional customer project with extremely high quality requirements. I can tell you, writing React code with styled components this way makes you feel like having a grip like it never was in the past when the styles were placed in separate files. I have used separate plain CSS files and pre-compiled CSS files in the past, such as Sass, PostCSS etc. And I have been doing it a lot - since decades! The guideline by the Wise of the Internet always was that embedding styles directly in the JavaScript code is a bad practice. But once you take your first steps to the ‘dark side’ and start embedding styles in the code in the way described above, there’s no turning back!
About Bootstrap and Other ‘CSS Frameworks’
There are many CSS frameworks, such as Bootstrap, Materialize etc. I think such CSS frameworks can be a good starting point to get something look proper without a lot of hassle. However, the problem is that while Bootstrap provides a proper looking default layout, the reality is that the customer usually comes up with a design that deviates from the standard Bootstrap style. Then you start entering problems because you will need to code your own styles on top of the default Bootstrap styles. You end up partially rewriting and covering up underlying Bootstrap styles and that isn’t a beautiful thing by definition. It’s sort of a hack that you have to start ‘fixing’ the default sauce by mixing in your own flavors. There will be maintainability problems in the long term. If the customer has their own unique design for the UI, you would be better off writing your vanilla styles from scratch and get rid of the underlying ‘framework’ mess that does not quite fit into what you are really doing. So it depends on the use case whether you should use a CSS framework like Bootstrap or not. For a standardish looking UI, it is great. For unique designs, you may want to start from a clean slate!
Applying Skins to Components
With Styled Components you can have an approach to CSS that integrates it smoothly to your TypeScript & React code. Without this approach, CSS will always appear like a cumbersome separate attachment to your code. When your CSS definitions fit your code just as if they were only some more code, this can be a quite neat experience. To get a grip of this, let’s create a nicely layered button component. The component is organized layer-wise. As the first layer we have the base lase layer that defines the fundamental style features that your compnent is going to have:
const BaseButton = styled.button({
all: "unset",
borderRadius: "5px",
color: "white",
});
The baseButton style defines the properties that our button will have. No matter what, we want this button to have all default settings unset and it definitely must have slightly rounded corners (border radius 5px) and white text color.
Then, we can extend the base button and define how the button must look when it is enabled or disabled:
export const Enabledbutton = styled(Basebutton)({
backgroundcolor: "blue",
cursor: "pointer",
});
export const DisabledButton = styled(BaseButton)({
backgroundColor: "gray",
cursor: "default",
});
I’ll be back to these exciting topics very soon. Cheers!