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.
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.
â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.