Turbo CSS is Tailwind on steroids

 

I've built Turbo CSS because I have some requirements that were not met by any of the existing CSS frameworks / languages out there. Tailwind came closest, hence I'm comparing them here. Note that I did not want to write it. I actively fought it. I explained my ideas in this blog post, published it in a few places including on the Tailwind subreddit and even direct messaged the Tailwind authors. I wanted to give them my ideas for free. I messaged them on two occasions, never got a reply. In the end, I gave in to only write a throwaway prototype - which turned out to be too good so I kept going. Now Turbo is tested, documented, used in production.

Turbo takes inspiration from utility first CSS, functional programming, Tailwind, my experience and my requirements building a website builder / web application platform.

I do respect to the Tailwind authors and hope Adam and Steve are not going to hate me for this. That said, as explained, I believe I have tried my best to try to collaborate with them, or simply give them my ideas. Except they never responded.

 

1. Use any size you want, in any unit

Tailwind has a default spacing scale that you can customize to your needs if you want. Sounds good in theory but I found it extremely limiting in practice.

Let's see a couple of examples on how to use certain sizes.

 

Size Tailwind Turbo
0px00
1pxpx1
2px0.52
3pxnot available by default3
4px14
5pxnot available by default5
6px1.56
7pxnot available by default7
8px28
9pxnot available by default9
10px2.510
11pxnot available by default11
12px312
13pxnot available by default13
14px3.514
15pxnot available by default15
16px416
17pxnot available by default17
18pxnot available by default18
19pxnot available by default19
20px520

 

What if you need special units in a certain situation?

 

Size Tailwind Turbo
37%not available by default37%
37emnot available by default37em
13remnot available by default13rem
17vhnot available by default17vh
91vwnot available by default91vw

 

You can certainly configure all these above. Not in advance because you could not compile Tailwind in finite time and space - but you could do it on demand. The question is, do you want to? Do you want to recompile Tailwind, Excel and Photoshop every time you use a number you have not used before?

As Turbo is a compiler, it will parse whatever number you entered and just use it. You can even use fractions like 16.6667% if you want.

Additionally, to type less in the common scenario, most utilities have a default unit. Thus, for margins, you can use both m-1px and the unitless m-1.

 

2. Simpler scale system

Tailwind has the philosophy that constrains are good. Thus, to achieve a universal design, they introduce a very limited scale for various utilities. Typically, they have the names xs, sm, md, lg, xl.

I'm sure it started with good reasons but it quickly grew out of hands. Now there is 2xl, 3xl, 4xl, 5xl, 6xl, 7xl, 8xl and even 9xl in the default config.

So, in their default spacing system, 1 means 4px (technically it is defined as 0.25rem), now here we face a new unit called xl! Let's reverse engineer what it means in translated to px unit. Let's extract some example values.

 

Utility Tailwind unit CSS value
screen sizexl1280px
screen size2xl1536px
border-radiusxl12px
border-radius2xl16px
font-sizexl20px
font-size2xl24px
max-widthxl576px
max-width2xl672px

 

It's clearly pointless to try to understand the meaning of xl, it's just a dummy variable name. I think it would make sense for button sizes and other complex elements where you only need a few different sizes, but for base units like font-size and max-width, I really don't see the benefit.

In particular, why is 7xl easier to remember than 112px? The alias 7xl only adds extra mental complexity. Now every time I see it, I have to translate it to 112px and vica versa.

Additionally, if you are working on multiple projects that defines different sizes, you will really start to feel the pain. In that case, I certainly wouldn't want to be you.

Turbo CSS uses the perfect scaling system by not inventing a new one. Just use whatever size you want. If you want to have a finite style guide for a cohesive design, just create a document and write them down. I mean, come on, designers manage to do the same. You don't need to recompile Photoshop to use 37px, then why do programmers have to? Just because we can?

If you really insist a finite scale is better, then why not define a finite scale and throw an error for anything that's not on the scale? There is really no need for meaningless variable names like xl.

Let's see some Tailwind CSS vs Turbo CSS examples.

 

Utility Tailwind CSS Turbo CSS
screen size 1280pxxl:w12:
screen size 1536px2xl:w15:
border-radius 12pxrounded-xlrounded-12
border-radius 16pxrounded-2xlrounded-16
font-size 20pxtext-xlfont-20
font-size 24pxtext-2xlfont-24
max-width 576pxmax-w-xlmax-w-576
max-width 672pxmax-w-2xlmax-w-672

 

Sidenote one: the breakpoints have shortened values in Turbo CSS too. w12: stands for viewport min-width of 1280px. It's good enough, as you typically don't need a granularity finer than that, so we just chop off the last 2 digits from 1280 to arrive at the number 12 in w12:. That's better at future-proofing the system, so we won't end up with screen sizes like xl. Turbo CSS aims to minimize your mental load.

Sidenote two: in Tailwind, you can't really set font-size on its own. It automatically sets the line-height as well.

 

3. Copy paste code, even across projects

Turbo CSS has zero config options that would affect its API, by design. This means that you can copy-paste code snippets from one project to another and it will just work.

Don't worry, this doesn't mean that you can't configure your colors and fonts! You certainly can! For example, there is a default color named blue with a default value. You can customize what exact color blue shall mean on your project, but you can't remove the existence of blue. That way, templates written against the Turbo CSS API will be completely portable.

Copy-paste is our old friend! :)

To elaborate, if you copy-paste a code snippet from a template into your own project, it will automatically pick up your color and font configurations to seamlessly fit into the design of your site.

 

5. Much easier to set up

You not only need to install Tailwind CSS which requires NodeJS but to set up some complex CSS purging mechanism. That's a step that's parsing your entire codebase looking for the occurrence of any Tailwind utility class names. Those that are found are kept, the rest are not included in your production build.

That's actually quite tricky to get right. What if you are storing dynamic content in a database? What if you are dynamically gluing together utility class names?

You will have to hack your way through these issues. Except you will not know about them. If a class name is not defined in production, it will just look ugly on unreadable, you will not know about it.

 

6. Composable

As Turbo CSS is a compiled language, we can combine selectors in any way.

Set width 4px conditionally:

  • When parent is hovered: hover:/w-4

  • When grand-grand-grand-parent is hovered: hover:////w-4

  • When parent's previous sibling is hovered: hover:~/w-4

Think these never come up? Wrong. For example, to apply custom designs to a file input field that is also correctly accessible via keyboard and mouse, you will need to apply styles like focus:~/outline-2-blue and hover:~/outline-2-blue. I don't know of any CSS framework that handles these - except for the official Boomla uikit built on Turbo CSS.

Turbo CSS also supports ad-hoc uses of colors like:

  • color-hex-AB1234

  • color-rgb-12-34-56

  • color-rgb-12-34-56-78 (last segment is alpha)

  • color-hsl-90-50-100

  • color-hsl-90-50-100-66 (last segment is alpha)

     

These are just impossible in Tailwind due to the CSS file size issues.

 

7. Language independent

Turbo CSS takes an API first approach: it is primarily a suite of test cases. The Turbo CSS compiler can be implemented in any programming language to minimize the integration complexity. It is already implemented in two programming languages, Go and Javascript. 

Tailwind is NodeJS based. If you don't already have NodeJS integrated into your workflow, Tailwind will add significant complexity.

 

8. Write less

Because Turbo is a language, it can support shorthand functions (and it does). For example, you can write b-1-red. The equivalent Tailwind CSS expression is border-1 border-red.

Tailwind CSS takes the approach of introducing sane defaults. The problem is, some utility classes have unexpected side-effects. The official stance is that this is a trade-off.

I disagree, that's accidental complexity. The Turbo solution is to use shorthand utilities instead. No side-effects.

 

9. Utility names are closer to CSS

Turbo utility class names are closer to CSS, thus it's easier to learn and work with them. For example, in Turbo, the line-height can be set with the line utility, while in Tailwind it can be set via the leading utility.

I have a really hard time figuring out what things like leading-tight and tracking-wider mean.

Motto: don't make me think.

 

10. Compile in the browser

Turbo provides the easiest onboarding experience ever: just drop a JS file into your site and it does everything. It will compile all the CSS before the first paint event so that users will not see any flickers. It will also watch the DOM for changes (via MutationObserver) and add any CSS definitions required.

This means you can even use it on a static website, without any server-side support.

And, it's only 18KB minified gzipped. Tiny!

 

11. Better browser support

Lots of Tailwind uses CSS variables, which has almost good browser support.

That's not bad, but why use it when you don't have to? That again is accidental complexity. As 

Turbo is a compiler, thus it can take a way cleaner approach. Pretty much like if you would hand-craft your CSS. No CSS variables needed.

 

12. Much faster compile times

Tailwind first generates all the possible classes based on your configs and then works hard on trimming it down. This is called the purge step: getting rid of the unused classes. Unfortunately, it's not trivial to figure out what is used and what is not. What if it comes from the DB? What if it is dynamically genrated.

Turbo only generates the required classes, period. If you have dynamic content, you can generate the relevant CSS dynamically, when serving the request. Everything else is just a hack and will bite you, sooner or later.

 

13. Catches typos

Because Turbo is a type-safe compiled language, it will tell you if you make a typo, so you can fix it.

Not Tailwind. If you make a typo in the class names you use, bad luck. Let's hope it won't happen to the pricing page.

 

14. Conditionally apply user-defined classes

In Tailwind, you can define custom classes via an @apply keyword. They are not first-class citizens, as in, you can't use all the language features with them.

In Turbo, you define custom classes similar to CSS class definitions. Crucially though, every language feature is always available with all your user-defined classes. You can also use any language feature within your class definitions. It's true composability.

 

15. Don't fight your configs

In Tailwind, you constantly battle your config file to access the features you need.

Turbo doesn't have a config file, as in, not for customizing the API and what language features shall be available. The only config options are for customizing your fonts and colors. This doesn't affect the API though.

 

16. Style any pseudo elements

Tailwind doesn't allow you to style pseudo-elements, it would make its CSS file size sky-rocket.

Turbo doesn't have this issue. As it is a language, it can provide a few selectors like before:, after:, selection:, placeholder:, etc. These compose well with all the other language features, making all utilities available for them.

 

If you like Turbo CSS, please consider spreading the word!

 


Cheers,

you can follow me on Twitter