This small review of different approaches for creating UIs was inspired by a video by Theo from T3. I highly recommend watching this video, as I'll be building on his advice to employ inline styles and create a custom component library for your application.
TailwindUI offers a collection of UI components, not in the traditional sense - as software components - but as a set of HTML code snippets. To utilize a component, simply copy the snippet to your source file and modify it as required. Note that the same snippet can appear in different places in your code, but that's considered to be okay. Here's an example of a snippet for an email form field:
<div class="mb-6">
<label
for="email"
class="mb-2 block text-sm font-medium leading-6 text-gray-900"
>
Email address
</label
>
<div>
<input
id="email" name="email" type="email"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
There are many advantages to this approach:
When it comes to the drawbacks, I would include:
To mitigate the last drawback, I often add descriptive CSS class names to JSX code that uses inline styles (at least, when running in development mode). In most cases these names are not used to style the elements but they make it easier to find that piece of code.
Overall, I think the inline styling approach that is offered by TailwindUI is compelling. As we shall see later, it's the starting point for my hybrid approach.
Before we continue I would like to point out that it can be a good idea to create custom components based on TailwindUI snippets. You can do this on a case-by-case basis. It implies trading some flexibility for increased consistency and reusability.
It may seem counter-intuitive to start with TailwindUI and then go into the direction of components. Shouldn't we just use MaterialUI then? The answer is no, because there is an important difference. Custom components are already shaped to meet the needs of the application. Therefore, there will usually be no need to "break into" them. On the other hand, when using MaterialUI, it can be very challenging to get the component to do exactly what you want.
UIkit is a Javascript framework that offers a collection of UI components. It takes an interesting approach:
Here is an example of creating a drop-down. Note that the button is followed by a div that has the uk-dropdown
attribute.
This tells UIkit that the button must be converted into a drop-down button.
<div class="uk-inline">
<button class="uk-button uk-button-default" type="button">Hover</button>
<div uk-dropdown>I'm a dropdown.</div>
</div>
Interestingly, there is no separate drop-down component in this code snippet. Instead, you turn the button into a drop-down by
mixing in the uk-dropdown
attribute. Since this is somewhat analogous to using inline styles, you could call it an "inline components" approach.
It suggests a more loose concept of what a component is. Instead of an object or function, it can also be a collection of utilities
that add styles and behaviours to a JSX structure.
This is a very flexible approach. For example, if you want to add an icon to the drop-down button, then instead of having to extend a DropDownButton component function you can just add the icon directly to the inlined code. In my hybrid approach, I will build on this idea.
Advantages of UIkit:
Disadvantages are:
Initially, I was a fan of UIkit, because I was impressed by the philosophy behind it. In practice, I have found it annoying to work with the large set of SCSS variables. Still, the idea of creating components as sets of utilities has been an inspiration to me.
Since we all know what SCSS is, let's go straight to the advantages and disadvantages. Here, I should add that much depends on how SCSS is used. Some of its features are an advantage if used in the right way, and a disadvantage if used wrongly.
Disadvantages are:
I think SCSS offers a very powerful approach, that is also risky. For my own styling system, I would like to use the power of SCSS, but put some restrictions in place to limit the risk.
I have limited experience with CSS-in-JS. In part, this is because I like SCSS and have not found a compelling reason to switch. One could say that - apart from the isolation aspect, which is important - SCSS and CSS-in-JS provide a similar developer experience. For developing my hybrid approach, the difference between SCSS and CSS-in-JS is not that relevant.
I haven't used MaterialUI much but the consensus seems to be that it offers a pleasant and efficient developer experience, as long as you are not trying to do things that are too far outside of what MaterialUI offers. Since my priority is nice and clean code, I will usually not choose MaterialUI, because I want to avoid a situation where hacks are needed to overcome the limits of the framework.