Modern frontend applications present a constant challenge in the writing of reliable and simple to maintain CSS code. In one of our projects, we used to rely on SCSS modules as a tool to control element styles in a more granular way and to resolve problems related to unexpected class conflicts. However, we found that even with SCSS modules, we were still facing growing code complexity and duplication of code over time.
One of the main issues we faced with SCSS modules was code duplication. When the time comes to update a piece of code that appears in multiple places, it can be easy to forget to change it everywhere, breaking the principle of DRY (Don't Repeat Yourself) programming.
Given these challenges, we decided to explore the atomic CSS approach. This approach is more compatible with our design system and aligns with the principles of atomic design, which we have written about before here. To implement this approach, we chose to use Tailwind CSS as our tool.
Introducing Tailwind CSS
Tailwind CSS is a highly popular CSS framework that utilises atomic design or component-based design principles. It allows developers to build responsive layouts and increases the speed of development by providing built-in classes that do not require starting designs from scratch.
An example of a React component using Tailwind CSS might look like this:
One of the main advantages of using Tailwind CSS is that it provides only one source of truth when it comes to configuration. Also, you don’t need to think of names of classes as it has got own set of utility classes. Alongside, it gives options for customisation of colours, breakpoints or complex styles like gradients.
On the other hand, there are also some downsides to using Tailwind CSS, such as a steeper learning curve, as it has got a lot of pre-defined classes to remember, even if you are familiar with CSS. And it can lead to some cases where the className in some JSX tags can become very long. i.e. sticky bottom-0 flex h-16 w-full items-center justify-between border-t border-t-grayscale-500 bg-white px-4.
Despite these downsides, overall Tailwind CSS offers a powerful and highly customizable solution for working with CSS in modern frontend applications.
As a team, we decided to use Tailwind CSS in the project by utilising utility classes inline everywhere possible, decreasing the count of standalone SCSS files in our project.
One of the things we encountered during development was that if you use any methodology, e.g. BEM (Block Element Modifier), then writing styles using utility classes directly in HTML may not suit you. For this issue, one way to solve it is by combining classes to existing ones by using the @apply directive, which copies original styles of used utility classes into code that it was called. However, Tailwind CSS recommend not to use @apply directive to make code more clearer.
As an example of the usage of Tailwind CSS, we will look at how we styled our switch component. In the original code, we used Tailwind's pre-defined classes directly in the component, which resulted in a very long className.
As an alternative, we could have used the above classes in a separated SCSS file with @apply directive.
Another alternative without using modifiers like before:, after:, or hover:
In this way, you can use the benefits of Tailwind CSS, while still adhering to your preferred methodology and keeping your code organised and readable. By extracting classes, you can make your code more maintainable and easier to understand in the future. It also allows to keep track of changes and updates in a centralized location. This makes it easier to manage complex styling while keeping the design system consistent across the application.
In conclusion, using Tailwind CSS everywhere in the project has been a valuable experience for our team. However, we found that it was an overkill for simple components like a switch. While implementing Tailwind CSS, we realised that using it everywhere where it's possible might not always be the best idea. We should not be so strict with that rule.
We also found that it can be hard to avoid using raw CSS in separate files if we want to have readable code in some cases. Using Tailwind classes can be too complicated for very simple components, which can result in very long className in their JSX tags.
Overall, Tailwind CSS is a great solution for developers who are familiar with CSS and want to speed up the development of their projects. However, sometimes ejecting from the default tool might bring value and can be necessary to create a readable and maintainable solution. This doesn't only apply to Tailwind, but it can apply to all alternatives.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.