đŸ”ș
1479 Words

Should we use Inline CSS instead of Tailwind?

Isn’t tailwind just basically like writting inline css?

1
2
<!--- This requires bloat, configuration, and complexity just to keep your css "simple" --->
<span class="block">Elegant Block Head</span>

I mean its basically the same thing.

1
2
<!--- This is literally it, no scripts or elegant dependencies needed --->
<span style="display: block;">Annoying Square Minimalist</span>

Or perhaps Im yet another ignorant css dork who doesn’t understand the beautiful elegance of Tailwind.

Spy X Family Spy Family GIFfrom Spy X Family GIFs

Either way, I want to take this question seriously. Im genuinely curious about alternative ways of doing things, and this idea has peaked my intrest.

To be clear Im not here to dunk on tailwind itself.

There is nothing wrong with using tailwind. IT IS a useful TOOL.

Though I will admit that I am unlikely to use it in my own personal projects, mostly because Im a total sicko who likes writting css.

The spirit of tailwind says something like “we should stop doing css the old way”. Like giving every single component unique class names project-card-inner-wrapper, project-card-header, project-card-body, ... and so on.

I agree.

However there are other ‘correct’ ways to do things. And some of the tailwinds precept can become problems when treated like commandments.

but, that’s just my opinion.

Source of truth and Arbitrary values

Lets cherry pick an example that places tailwind in a better lighting.

1
<span class="text-gray-100 my-2 p-2">Elegant Wonder</span>
1
<span style="color: rgb(243 244 246); margin-left: 0.5rem; margin-right: 0.5rem; padding: 0.25rem">Minimalist Grabage</span>

The repetition here is inconvenient and the arbitrary values can become difficult to change with more code. Or perhaps its fine because you can just find and replace %s|0.5rem;|0.4rem;.

Its nice that Tailwind provides a config and source of truth for the colors and sizes. To replicate that advantage we could do something like:

1
2
3
4
5
6
7
8
9
10
11
12
:root {
  --s1: .25rem;
  --s2: .5rem;
  --s3: 1rem;
  --s4: 2rem;
  --s5: 4rem;
  --s6: 8rem;
  --s7: 16rem;
  --s8: 32rem;

  --gray100: rgb(243 244 246);
}
1
2
3
4
5
6
7
<span style="
  color: var(--gray100);
  margin: 0 var(--s2);
  padding: var(--s1)
">
  Minimalist Grabage
</span>

It is certainly more typing than text-gray-100 my-2 p-1. But so far I don’t I hate it.

Inline styles work well for one off simple Properties.

You have to admit, these two lines are basically the same thing. The only real difference is the specificity, and the dependencies involved.

1
<div style="columns: 3;">...</div>
1
<div class="columns-3">...</div>

Keep in mind that we don’t need to be draconian

We don’t have to use inline style for everything. Less say ours styles start getting really long or we find ourself using the same styles repeatedly.

1
2
3
<p style="max-width: 15em; text-indent: 2em; line-height: 1.8em;">...</p>
<p style="max-width: 15em; text-indent: 2em; line-height: 1.8em;">...</p>
<p style="max-width: 15em; text-indent: 2em; line-height: 1.8em;">...</p>

There is nothing stopping us from writting css rules for things we use a lot. Infact it might be a nice way to work.

1
2
3
4
5
p {
  max-width: 15em;
  text-indent: 2em;
  line-height: 1.8em;
}
1
<p>...</p>

Buttons are a good example of styles that are worth abstracting

Most often these styles are used on several kinds of elements. ie <a> <button>. You also want all of you’re buttons to be consistant. And you don’t want to sematically apply it to every button element. They usually also have style variations that you’d like to target. ie :hover, :focus, :active and primary, secondary, tertiary.

1
2
3
4
5
6
7
8
9
.btn {
  color: var(--scribe);
  padding: 0.2em 0.4em;
  border: solid 2px currentColor;
  border-radius: 5px;
} 
.btn:hoer, .btn:focus, .btn:active {
  color: var(--scribe-hover)
}
1
<button class="btn">Reset Sanity</button>

‘Clearly’ its a bad idea to be strict about using inline styles for everything! We should be smart by not treating one particular paradime as the end-all be-all.

Just imagine trying to manage button hover states, and other variants, with inline styles! :weary: You’d end up adding or removing styles with javascript based on


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function Button({children,disabled,kind,className,...rest}): ButtonProps {
  cosnt [isHovering, setIsHovering] = useState<boolean>(false)

  return (
    <button
    className={
      clsx(
        className, 
        kind === PRIMARY && 'text-white py-1 px-2 border-white',
        isHovering && kind === PRIMARY && 'text-gray-100 border-gray-100',
        kind === PRIMARY && isDisabled && 'border-red-400 text-red-400 bg-none',
        kind === SECONDARY && ...,
        ...,
      )
    }
    disabled={disabled}
    onMouseEnter={()=>{ setIsHover(true) }}
    onMouseLeave={()=>{ setIsHover(false) }}
    onClick{()=>{ alert("oh no...") }}
    {...rest}
    >
      {children}
    </button>
  )
}

// I've seen things I wish to unsee.
This Is Fine GIFfrom This Is Fine GIFs

“Whoever wrote that code was doing tailwind wrong!”

I mean
 yes, but the fellow also explained that he was following tailwind recommendations.

Don’t rely on [custom] CSS classes to extract complex components

Avoiding premature abstraction, don’t use @apply just to make things look “cleaner”

“He should have used tailwind selectors like hover:border-gray-100 or data-[disabled]:border-red-400.”

Take a good long look at your dangling rope of tailwind tokens, on your ‘clean’ reuseable button and tell me that its nicer than this:

1
<button class="btn btn-primary btn-jumbo-size">This is Excessive</button>

Its not!

There is a point of complexity that tailwind utilities stop being convenient and start getting in the way.

Don’t be draconian about it. There is nothing wrong with writting custom css to extend your utilities.

Css Grid

One place I’ve been loving inline styles is for basic grids.

1
2
3
4
5
6
7
8
9
<div style="
  display: grid;
  grid-template-columns: repeat(3, minmax(15rem, auto));
">
  <div style="
    column: 1 / span 2;
  ">
  ...
</div>

It feels really good to have the grid layout right where im editing it. And I don’t need to figure out how the flork to write grid-template-columns: repeat(3, minmax(15rem, auto)); in tailwind logic. Im sure you can, I just don’t want to spend my time thinking about it.

Using grid with inline styles was the nicest time I’ve ever had using grid.

In this scenario, I think inline styles win.

The exception to this finding has been for grids with media queries. However I suspect that using var()s could help.

I found a trick for utilizing media queries with inline styles

I used a --gutter variable to place fixed elements where I wanted them.

1
2
3
4
5
6
7
8
9
10
:root {
  --gutter: 0px;
}

@media screen and (min-aspect-ratio: 1/1) {
  :root {
    --gutter: calc( -2px + (100vw - 100vh) / 2 );
  }
}

1
2
3
4
5
6
7
8
<nav
style="
  position: fixed;
  bottom: 0;
  right: var(--gutter);
">
  ...
</nav>

I was able to reuse the same variable for an <aside> as well.

This probably wont be useful for every media query situation, but I think its a nice tool for this one.

Space-y-n

One thing from tailwind I frequently use us the space-y-n utility. Its used to generate a margin based gap between a list of elements.

I wanted a suitable replacement, and this is what I came up with.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
* { --s: var(--s3); }

.s\>1 > *, .s1 { --s: var(--s1)}
.s\>2 > *, .s2 { --s: var(--s2)}
.s\>3 > *, .s3 { --s: var(--s3)}
.s\>4 > *, .s4 { --s: var(--s4)}
.s\>5 > *, .s5 { --s: var(--s5)}
.s\>6 > *, .s6 { --s: var(--s6)}
.s\>7 > *, .s7 { --s: var(--s7)}
.s\>8 > *, .s8 { --s: var(--s8)}


.space-y > * + * {
  margin-top: var(--s);
}
1
2
3
<div class="space-y s>2">
  ...
</div>

Im using --s as a generic size variable. s>2 sets all of the direct childrens --s to the specified size.

Then the space-y class applies a margin-top with that size to all of its direct children except the first one.

I don’t know if this is good or not, its interesting though.

Conclusion

While im not sure why, initially I had written off the idea of using inline styles as bad practice. Im glad that tailwind has caused me to question that idea.

Im finding inline css to be more useful than I expected. I think it can replace a lot of my need for tailwind style token utilities.

While I am bias, I am also honesly finding this more convenient than using tailwind. That this mostly due to familiarly. Its rare for me to lookup css properties anymore. In comparason whenever I’m using tailwind I have to keep the docs open. css_knowledge !== tailwind_knowledge

Time will tell if I make this a part of my process or if im just temporarily enamored with this new shinny perspective.

Thank you for reading!

And here are some more intresting articles you can enjoy or ignore.