Converting Tailwind CSS to Vanilla CSS: When and How
This guide has a free tool → Open Color Converter
# Converting Tailwind CSS to Vanilla CSS: When and How
Why Convert Tailwind to Vanilla CSS
Tailwind CSS is widely used and for good reason. The utility-first approach speeds up prototyping, enforces consistency through a shared design system, and eliminates the naming problem that plagues traditional CSS architectures. But Tailwind is not the right tool for every situation, and there are valid technical reasons to convert Tailwind-based markup to vanilla CSS.
Removing the Build Dependency
Tailwind requires a build step. The CLI scans your templates, generates a stylesheet containing only the classes you use, and outputs a CSS file. This works seamlessly in modern frameworks like Next.js, Vite, or Astro. But if you are shipping a component, widget, or embeddable script that others will drop into arbitrary environments, requiring a Tailwind build step is a burden on your consumers.
A vanilla CSS component can be included with a single <link> tag. A Tailwind component requires the consumer to either run the Tailwind CLI, copy your entire utility stylesheet, or include Tailwind's CDN build (which is large and includes all utilities). For distributable code, vanilla CSS is a better citizen.
Handing Off to Non-Tailwind Teams
If you build a prototype in Tailwind and hand it to a design or development team that does not use Tailwind, they face a learning curve just to make CSS changes. Tailwind's utility classes are meaningful to developers who know the system, but opaque to those who do not.
Converting to semantically named vanilla CSS classes gives the receiving team something they can immediately understand and modify without learning Tailwind's conventions.
Extracting Components as a Framework-Agnostic Library
Component libraries published to npm need to work across React, Vue, Svelte, Angular, and plain HTML. If your library's styles depend on Tailwind classes in the markup, every consumer needs to configure Tailwind. This is a non-starter for many users.
Publishing components with scoped vanilla CSS (or CSS modules) creates zero friction. The styles work everywhere without any build tool configuration.
Understanding What Utilities Actually Do
Learning exercise: if you have been writing Tailwind for a year and want to sharpen your raw CSS skills, convert a component to vanilla CSS without looking anything up. You will quickly identify which utilities you understand deeply and which you have been using by convention without fully knowing the underlying CSS.
This is especially useful for developers transitioning from Tailwind to a codebase that uses BEM, CSS modules, or styled-components. The conversion exercise bridges the gap between utility-first and traditional CSS approaches.
Bundle Size in Edge Cases
Tailwind's build system is very good at tree-shaking. The output CSS only contains classes you actually use. But in some edge cases - content generated dynamically at runtime, CSS-in-JS patterns that construct class names programmatically, or projects where the scanner does not cover all template sources - Tailwind may include unnecessary utilities.
For very small, focused projects (a landing page, a form widget, a documentation site) where you only use 15-20 distinct utility values, the overhead of Tailwind's configuration and scanning infrastructure may exceed the benefit. Hand-writing CSS for those specific declarations can be lighter.
---
Color Converter
Free online color converter - convert colors between HEX, RGB, HSL formats with live preview
Tailwind to CSS
Free online tailwind to CSS - convert Tailwind CSS classes to vanilla CSS properties
CSS Minifier
Free online CSS minifier - minify your CSS code to reduce file size and improve load times
How Tailwind Classes Map to CSS: Complete Reference
Every Tailwind utility class corresponds to one or a small number of CSS declarations. The mapping is deterministic and documented, but looking it up for each class takes time. Here is a comprehensive reference for the most commonly used utilities.
Spacing (Padding and Margin)
Tailwind uses a spacing scale where 1 = 0.25rem (4px at default font size). So p-4 is padding: 1rem, and p-8 is padding: 2rem.
| Tailwind | CSS |
|---|---|
p-0 | padding: 0 |
p-1 | padding: 0.25rem |
p-2 | padding: 0.5rem |
p-3 | padding: 0.75rem |
p-4 | padding: 1rem |
p-6 | padding: 1.5rem |
p-8 | padding: 2rem |
p-10 | padding: 2.5rem |
p-12 | padding: 3rem |
p-16 | padding: 4rem |
px-4 | padding-left: 1rem; padding-right: 1rem |
py-4 | padding-top: 1rem; padding-bottom: 1rem |
pt-4 | padding-top: 1rem |
pr-4 | padding-right: 1rem |
pb-4 | padding-bottom: 1rem |
pl-4 | padding-left: 1rem |
m-0 | margin: 0 |
m-auto | margin: auto |
m-4 | margin: 1rem |
mx-auto | margin-left: auto; margin-right: auto |
mx-4 | margin-left: 1rem; margin-right: 1rem |
my-4 | margin-top: 1rem; margin-bottom: 1rem |
mt-4 | margin-top: 1rem |
mr-4 | margin-right: 1rem |
mb-4 | margin-bottom: 1rem |
ml-4 | margin-left: 1rem |
-mt-4 | margin-top: -1rem |
gap-4 | gap: 1rem |
gap-x-4 | column-gap: 1rem |
gap-y-4 | row-gap: 1rem |
space-x-4 | margin-left: 1rem (on all children except first) |
space-y-4 | margin-top: 1rem (on all children except first) |
The space-x-* and space-y-* utilities use a CSS selector pattern:
/* space-y-4 */
.space-y-4 > * + * {
margin-top: 1rem;
}Layout and Display
| Tailwind | CSS |
|---|---|
block | display: block |
inline | display: inline |
inline-block | display: inline-block |
flex | display: flex |
inline-flex | display: inline-flex |
grid | display: grid |
inline-grid | display: inline-grid |
hidden | display: none |
contents | display: contents |
table | display: table |
flow-root | display: flow-root |
Flexbox
| Tailwind | CSS |
|---|---|
flex-row | flex-direction: row |
flex-col | flex-direction: column |
flex-row-reverse | flex-direction: row-reverse |
flex-col-reverse | flex-direction: column-reverse |
flex-wrap | flex-wrap: wrap |
flex-nowrap | flex-wrap: nowrap |
flex-wrap-reverse | flex-wrap: wrap-reverse |
items-start | align-items: flex-start |
items-end | align-items: flex-end |
items-center | align-items: center |
items-baseline | align-items: baseline |
items-stretch | align-items: stretch |
justify-start | justify-content: flex-start |
justify-end | justify-content: flex-end |
justify-center | justify-content: center |
justify-between | justify-content: space-between |
justify-around | justify-content: space-around |
justify-evenly | justify-content: space-evenly |
self-auto | align-self: auto |
self-start | align-self: flex-start |
self-end | align-self: flex-end |
self-center | align-self: center |
self-stretch | align-self: stretch |
flex-1 | flex: 1 1 0% |
flex-auto | flex: 1 1 auto |
flex-initial | flex: 0 1 auto |
flex-none | flex: none |
grow | flex-grow: 1 |
grow-0 | flex-grow: 0 |
shrink | flex-shrink: 1 |
shrink-0 | flex-shrink: 0 |
order-first | order: -9999 |
order-last | order: 9999 |
order-1 | order: 1 |
CSS Grid
| Tailwind | CSS |
|---|---|
grid-cols-1 | grid-template-columns: repeat(1, minmax(0, 1fr)) |
grid-cols-2 | grid-template-columns: repeat(2, minmax(0, 1fr)) |
grid-cols-3 | grid-template-columns: repeat(3, minmax(0, 1fr)) |
grid-cols-4 | grid-template-columns: repeat(4, minmax(0, 1fr)) |
grid-cols-5 | grid-template-columns: repeat(5, minmax(0, 1fr)) |
grid-cols-6 | grid-template-columns: repeat(6, minmax(0, 1fr)) |
grid-cols-none | grid-template-columns: none |
grid-rows-1 | grid-template-rows: repeat(1, minmax(0, 1fr)) |
grid-rows-2 | grid-template-rows: repeat(2, minmax(0, 1fr)) |
col-span-1 | grid-column: span 1 / span 1 |
col-span-2 | grid-column: span 2 / span 2 |
col-span-full | grid-column: 1 / -1 |
row-span-1 | grid-row: span 1 / span 1 |
row-span-2 | grid-row: span 2 / span 2 |
col-start-1 | grid-column-start: 1 |
col-end-3 | grid-column-end: 3 |
auto-cols-auto | grid-auto-columns: auto |
auto-cols-fr | grid-auto-columns: minmax(0, 1fr) |
auto-rows-auto | grid-auto-rows: auto |
grid-flow-row | grid-auto-flow: row |
grid-flow-col | grid-auto-flow: column |
grid-flow-dense | grid-auto-flow: dense |
Typography
| Tailwind | CSS |
|---|---|
text-xs | font-size: 0.75rem; line-height: 1rem |
text-sm | font-size: 0.875rem; line-height: 1.25rem |
text-base | font-size: 1rem; line-height: 1.5rem |
text-lg | font-size: 1.125rem; line-height: 1.75rem |
text-xl | font-size: 1.25rem; line-height: 1.75rem |
text-2xl | font-size: 1.5rem; line-height: 2rem |
text-3xl | font-size: 1.875rem; line-height: 2.25rem |
text-4xl | font-size: 2.25rem; line-height: 2.5rem |
text-5xl | font-size: 3rem; line-height: 1 |
text-6xl | font-size: 3.75rem; line-height: 1 |
font-thin | font-weight: 100 |
font-extralight | font-weight: 200 |
font-light | font-weight: 300 |
font-normal | font-weight: 400 |
font-medium | font-weight: 500 |
font-semibold | font-weight: 600 |
font-bold | font-weight: 700 |
font-extrabold | font-weight: 800 |
font-black | font-weight: 900 |
italic | font-style: italic |
not-italic | font-style: normal |
text-left | text-align: left |
text-center | text-align: center |
text-right | text-align: right |
text-justify | text-align: justify |
leading-none | line-height: 1 |
leading-tight | line-height: 1.25 |
leading-snug | line-height: 1.375 |
leading-normal | line-height: 1.5 |
leading-relaxed | line-height: 1.625 |
leading-loose | line-height: 2 |
tracking-tighter | letter-spacing: -0.05em |
tracking-tight | letter-spacing: -0.025em |
tracking-normal | letter-spacing: 0em |
tracking-wide | letter-spacing: 0.025em |
tracking-wider | letter-spacing: 0.05em |
tracking-widest | letter-spacing: 0.1em |
uppercase | text-transform: uppercase |
lowercase | text-transform: lowercase |
capitalize | text-transform: capitalize |
normal-case | text-transform: none |
underline | text-decoration-line: underline |
line-through | text-decoration-line: line-through |
no-underline | text-decoration-line: none |
truncate | overflow: hidden; text-overflow: ellipsis; white-space: nowrap |
text-ellipsis | text-overflow: ellipsis |
text-clip | text-overflow: clip |
whitespace-normal | white-space: normal |
whitespace-nowrap | white-space: nowrap |
whitespace-pre | white-space: pre |
whitespace-pre-line | white-space: pre-line |
whitespace-pre-wrap | white-space: pre-wrap |
break-words | overflow-wrap: break-word |
break-all | word-break: break-all |
Sizing
| Tailwind | CSS |
|---|---|
w-0 | width: 0px |
w-px | width: 1px |
w-auto | width: auto |
w-full | width: 100% |
w-screen | width: 100vw |
w-min | width: min-content |
w-max | width: max-content |
w-fit | width: fit-content |
w-1/2 | width: 50% |
w-1/3 | width: 33.333333% |
w-2/3 | width: 66.666667% |
w-1/4 | width: 25% |
w-3/4 | width: 75% |
h-0 | height: 0px |
h-auto | height: auto |
h-full | height: 100% |
h-screen | height: 100vh |
h-min | height: min-content |
h-max | height: max-content |
h-fit | height: fit-content |
min-w-0 | min-width: 0px |
min-w-full | min-width: 100% |
min-h-0 | min-height: 0px |
min-h-full | min-height: 100% |
min-h-screen | min-height: 100vh |
max-w-xs | max-width: 20rem |
max-w-sm | max-width: 24rem |
max-w-md | max-width: 28rem |
max-w-lg | max-width: 32rem |
max-w-xl | max-width: 36rem |
max-w-2xl | max-width: 42rem |
max-w-3xl | max-width: 48rem |
max-w-4xl | max-width: 56rem |
max-w-5xl | max-width: 64rem |
max-w-6xl | max-width: 72rem |
max-w-7xl | max-width: 80rem |
max-w-full | max-width: 100% |
max-w-screen-sm | max-width: 640px |
max-w-screen-md | max-width: 768px |
max-w-screen-lg | max-width: 1024px |
max-w-screen-xl | max-width: 1280px |
max-w-screen-2xl | max-width: 1536px |
Borders and Radius
| Tailwind | CSS |
|---|---|
border | border-width: 1px |
border-0 | border-width: 0px |
border-2 | border-width: 2px |
border-4 | border-width: 4px |
border-t | border-top-width: 1px |
border-r | border-right-width: 1px |
border-b | border-bottom-width: 1px |
border-l | border-left-width: 1px |
border-solid | border-style: solid |
border-dashed | border-style: dashed |
border-dotted | border-style: dotted |
border-none | border-style: none |
rounded-none | border-radius: 0px |
rounded-sm | border-radius: 0.125rem |
rounded | border-radius: 0.25rem |
rounded-md | border-radius: 0.375rem |
rounded-lg | border-radius: 0.5rem |
rounded-xl | border-radius: 0.75rem |
rounded-2xl | border-radius: 1rem |
rounded-3xl | border-radius: 1.5rem |
rounded-full | border-radius: 9999px |
rounded-t-lg | border-top-left-radius: 0.5rem; border-top-right-radius: 0.5rem |
rounded-b-lg | border-bottom-left-radius: 0.5rem; border-bottom-right-radius: 0.5rem |
Colors
Tailwind uses a named color palette with shade levels 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, and 950. Here are the exact hex values for frequently used colors:
| Tailwind | CSS Value |
|---|---|
text-blue-500 | color: #3b82f6 |
text-blue-600 | color: #2563eb |
text-gray-500 | color: #6b7280 |
text-gray-700 | color: #374151 |
text-gray-900 | color: #111827 |
text-white | color: #ffffff |
text-black | color: #000000 |
text-red-500 | color: #ef4444 |
text-green-500 | color: #22c55e |
bg-white | background-color: #ffffff |
bg-gray-50 | background-color: #f9fafb |
bg-gray-100 | background-color: #f3f4f6 |
bg-gray-200 | background-color: #e5e7eb |
bg-gray-800 | background-color: #1f2937 |
bg-gray-900 | background-color: #111827 |
bg-blue-500 | background-color: #3b82f6 |
bg-blue-600 | background-color: #2563eb |
border-gray-200 | border-color: #e5e7eb |
border-gray-300 | border-color: #d1d5db |
border-blue-500 | border-color: #3b82f6 |
The complete Tailwind color palette contains hundreds of values. Use the Color Converter to translate between hex, RGB, and HSL formats when working with extracted color values.
Opacity, Shadows, and Transforms
| Tailwind | CSS |
|---|---|
opacity-0 | opacity: 0 |
opacity-25 | opacity: 0.25 |
opacity-50 | opacity: 0.5 |
opacity-75 | opacity: 0.75 |
opacity-100 | opacity: 1 |
shadow-sm | box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05) |
shadow | box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1) |
shadow-md | box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1) |
shadow-lg | box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1) |
shadow-xl | box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1) |
shadow-2xl | box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25) |
shadow-none | box-shadow: 0 0 #0000 |
rotate-0 | transform: rotate(0deg) |
rotate-45 | transform: rotate(45deg) |
rotate-90 | transform: rotate(90deg) |
rotate-180 | transform: rotate(180deg) |
-rotate-45 | transform: rotate(-45deg) |
scale-75 | transform: scale(.75) |
scale-100 | transform: scale(1) |
scale-110 | transform: scale(1.1) |
translate-x-4 | transform: translateX(1rem) |
translate-y-4 | transform: translateY(1rem) |
-translate-y-1/2 | transform: translateY(-50%) |
Positioning
| Tailwind | CSS |
|---|---|
static | position: static |
relative | position: relative |
absolute | position: absolute |
fixed | position: fixed |
sticky | position: sticky |
inset-0 | inset: 0px |
top-0 | top: 0px |
right-0 | right: 0px |
bottom-0 | bottom: 0px |
left-0 | left: 0px |
top-4 | top: 1rem |
top-1/2 | top: 50% |
left-1/2 | left: 50% |
z-0 | z-index: 0 |
z-10 | z-index: 10 |
z-20 | z-index: 20 |
z-30 | z-index: 30 |
z-40 | z-index: 40 |
z-50 | z-index: 50 |
z-auto | z-index: auto |
Overflow, Cursor, and Pointer Events
| Tailwind | CSS |
|---|---|
overflow-auto | overflow: auto |
overflow-hidden | overflow: hidden |
overflow-scroll | overflow: scroll |
overflow-visible | overflow: visible |
overflow-x-auto | overflow-x: auto |
overflow-y-auto | overflow-y: auto |
cursor-auto | cursor: auto |
cursor-default | cursor: default |
cursor-pointer | cursor: pointer |
cursor-wait | cursor: wait |
cursor-not-allowed | cursor: not-allowed |
cursor-grab | cursor: grab |
pointer-events-none | pointer-events: none |
pointer-events-auto | pointer-events: auto |
select-none | user-select: none |
select-text | user-select: text |
select-all | user-select: all |
select-auto | user-select: auto |
---
Converting Responsive Prefixes
Tailwind responsive classes use breakpoint prefixes that translate directly to CSS media queries. Tailwind uses a mobile-first approach, so breakpoint prefixes activate styles at the specified width and above.
Tailwind Default Breakpoints
| Prefix | Min-width | CSS |
|---|---|---|
| (none) | 0px | Default (mobile) |
sm: | 640px | @media (min-width: 640px) |
md: | 768px | @media (min-width: 768px) |
lg: | 1024px | @media (min-width: 1024px) |
xl: | 1280px | @media (min-width: 1280px) |
2xl: | 1536px | @media (min-width: 1536px) |
Converting a Responsive Element
<!-- Tailwind -->
<div class="hidden md:block lg:flex lg:items-center">/* Vanilla CSS */
.element {
display: none;
}
@media (min-width: 768px) {
.element {
display: block;
}
}
@media (min-width: 1024px) {
.element {
display: flex;
align-items: center;
}
}A Responsive Grid Layout
<!-- Tailwind: single column mobile, two columns tablet, three columns desktop -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">/* Vanilla CSS */
.card-grid {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: 1rem;
}
@media (min-width: 640px) {
.card-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (min-width: 1024px) {
.card-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}---
Converting State Variants
Tailwind handles hover, focus, active, and other states through prefixed utilities. Each prefix adds a CSS pseudo-class or pseudo-element.
| Tailwind Prefix | CSS Equivalent |
|---|---|
hover: | :hover |
focus: | :focus |
focus-within: | :focus-within |
focus-visible: | :focus-visible |
active: | :active |
visited: | :visited |
disabled: | :disabled |
checked: | :checked |
placeholder: | ::placeholder |
first: | :first-child |
last: | :last-child |
odd: | :nth-child(odd) |
even: | :nth-child(even) |
group-hover: | .group:hover .element |
peer-focus: | .peer:focus ~ .element |
dark: | @media (prefers-color-scheme: dark) or .dark .element |
State Variant Examples
<!-- Tailwind -->
<button class="bg-blue-500 hover:bg-blue-600 focus:ring-2 focus:ring-blue-300 disabled:opacity-50">
Submit
</button>/* Vanilla CSS */
.btn-primary {
background-color: #3b82f6;
}
.btn-primary:hover {
background-color: #2563eb;
}
.btn-primary:focus {
box-shadow: 0 0 0 2px #93c5fd;
outline: none;
}
.btn-primary:disabled {
opacity: 0.5;
}Group Hover Pattern
<!-- Tailwind: change child element on parent hover -->
<div class="group">
<h3>Card Title</h3>
<span class="text-gray-400 group-hover:text-blue-500">Read more</span>
</div>/* Vanilla CSS */
.card:hover .card-link {
color: #3b82f6;
}The group and peer patterns in Tailwind are sophisticated state management. When converting, you replace them with standard CSS sibling and descendant selectors.
---
Converting Dark Mode
Tailwind supports two dark mode strategies: class (toggle by adding a dark class to <html>) and media (responds to prefers-color-scheme). The conversion differs for each.
Media Strategy
<!-- Tailwind with dark: prefix -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">/* Vanilla CSS - media strategy */
.container {
background-color: #ffffff;
color: #111827;
}
@media (prefers-color-scheme: dark) {
.container {
background-color: #111827;
color: #ffffff;
}
}Class Strategy
/* Vanilla CSS - class strategy */
.container {
background-color: #ffffff;
color: #111827;
}
.dark .container {
background-color: #111827;
color: #ffffff;
}Using CSS Custom Properties for Dark Mode
Rather than duplicating every rule in a dark media query, use CSS custom properties:
:root {
--color-bg: #ffffff;
--color-text: #111827;
--color-border: #e5e7eb;
--color-primary: #3b82f6;
}
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #111827;
--color-text: #ffffff;
--color-border: #374151;
--color-primary: #60a5fa;
}
}
.container {
background-color: var(--color-bg);
color: var(--color-text);
border-color: var(--color-border);
}This approach makes the converted CSS much more maintainable than the Tailwind-class-per-element approach.
---
Automated Conversion
Manually converting hundreds of utility classes is tedious and error-prone. Tailwind to CSS handles this automatically. Paste any HTML with Tailwind classes and the tool:
- Parses every class applied to each element
- Resolves the CSS declarations for each utility
- Groups related declarations into semantic class names
- Handles responsive prefixes as media queries
- Handles state variants as pseudo-classes
- Outputs clean, formatted CSS you can use directly
A Realistic Conversion Example
Input HTML:
<div class="flex flex-col gap-6 p-6 max-w-md mx-auto">
<h2 class="text-2xl font-bold text-gray-900">Account Settings</h2>
<div class="flex flex-col gap-4">
<label class="text-sm font-medium text-gray-700">Email</label>
<input class="w-full px-3 py-2 border border-gray-300 rounded-md
text-sm placeholder:text-gray-400
focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<button class="w-full py-2 px-4 bg-blue-600 hover:bg-blue-700
text-white font-semibold rounded-md
disabled:opacity-50 cursor-pointer">
Save Changes
</button>
</div>Output CSS from the converter:
.container {
display: flex;
flex-direction: column;
gap: 1.5rem;
padding: 1.5rem;
max-width: 28rem;
margin-left: auto;
margin-right: auto;
}
.heading {
font-size: 1.5rem;
line-height: 2rem;
font-weight: 700;
color: #111827;
}
.form-group {
display: flex;
flex-direction: column;
gap: 1rem;
}
.form-label {
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
color: #374151;
}
.form-input {
width: 100%;
padding-left: 0.75rem;
padding-right: 0.75rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.875rem;
line-height: 1.25rem;
}
.form-input::placeholder {
color: #9ca3af;
}
.form-input:focus {
outline: none;
box-shadow: 0 0 0 2px #3b82f6;
}
.btn-primary {
width: 100%;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
background-color: #2563eb;
color: #ffffff;
font-weight: 600;
border-radius: 0.375rem;
cursor: pointer;
}
.btn-primary:hover {
background-color: #1d4ed8;
}
.btn-primary:disabled {
opacity: 0.5;
}---
Best Practices for Writing the Converted CSS
1. Group Properties Semantically
The direct result of conversion is often verbose - one CSS declaration per Tailwind utility. Combine related properties into coherent, semantically named classes rather than leaving them in one giant rule:
/* Less readable - everything dumped into one class */
.everything {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1.5rem;
border-radius: 0.5rem;
border: 1px solid #e5e7eb;
background-color: #ffffff;
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
max-width: 28rem;
margin-left: auto;
margin-right: auto;
}
/* More maintainable - split into logical concerns */
.card {
background-color: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
padding: 1.5rem;
}
.card-layout {
display: flex;
flex-direction: column;
gap: 1rem;
}
.card-container {
max-width: 28rem;
margin-left: auto;
margin-right: auto;
}2. Replace Color Values with CSS Custom Properties
Hardcoded hex values from Tailwind make theming difficult. Replace them immediately with CSS variables:
:root {
--color-primary: #3b82f6;
--color-primary-dark: #2563eb;
--color-text: #111827;
--color-text-muted: #6b7280;
--color-border: #e5e7eb;
--color-surface: #ffffff;
--color-bg: #f9fafb;
}
/* Now use the variables */
.btn {
background-color: var(--color-primary);
color: var(--color-surface);
}
.btn:hover {
background-color: var(--color-primary-dark);
}
p {
color: var(--color-text);
}
.caption {
color: var(--color-text-muted);
}3. Use a Consistent Naming Convention
Pick a CSS naming methodology and apply it consistently to the converted output:
BEM (Block, Element, Modifier):
.card { ... }
.card__header { ... }
.card__body { ... }
.card__footer { ... }
.card--featured { ... }
.card--compact { ... }Utility + Component hybrid:
/* Low-level utilities */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.gap-4 { gap: 1rem; }
/* Component-level rules for unique combinations */
.product-card { ... }
.nav-item { ... }4. Organize the Stylesheet Structure
A well-organized converted stylesheet is easier to maintain than the original Tailwind markup (which has ordering determined by element position in the HTML):
/* 1. Custom Properties */
:root { ... }
/* 2. Reset / Base */
*, *::before, *::after { box-sizing: border-box; }
body { ... }
/* 3. Typography */
h1, h2, h3 { ... }
p { ... }
/* 4. Layout */
.container { ... }
.grid { ... }
/* 5. Components */
.card { ... }
.btn { ... }
.form-input { ... }
/* 6. Utilities */
.sr-only { ... }
.visually-hidden { ... }
/* 7. Media Queries */
@media (min-width: 768px) { ... }5. Preserve the Accessible Patterns
Tailwind has several utilities for accessibility that must be converted correctly:
/* sr-only - visually hidden but accessible to screen readers */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
/* not-sr-only - makes an sr-only element visible again */
.not-sr-only {
position: static;
width: auto;
height: auto;
padding: 0;
margin: 0;
overflow: visible;
clip: auto;
white-space: normal;
}
/* focus-visible - shows focus ring only for keyboard navigation */
.input:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}---
When Conversion Is Not the Right Answer
Converting Tailwind to vanilla CSS is sometimes the wrong tool for the problem.
If you just want smaller bundles: Tailwind's build process already ships only the utilities you use. The output is already optimized. You will not save significant bundle size by converting.
If the receiving team will continue developing the UI: Handing off raw vanilla CSS is worse than handing off Tailwind if the team knows Tailwind. Give them the Tailwind source.
If you are maintaining both versions: Keeping Tailwind source and vanilla CSS output in sync is a maintenance burden. Any change in the Tailwind version must be manually reflected in the CSS. This creates drift over time.
If the project might add Tailwind later: Converting now means re-adding Tailwind later will require re-converting. If there is a reasonable chance the project will adopt Tailwind, wait.
The best candidates for conversion are: distributable components, code that needs to outlive any particular CSS framework trend, handoffs that are genuinely final with no further Tailwind usage, and learning exercises.
---
CSS Tools to Support the Conversion
The Tailwind to CSS converter handles the primary conversion automatically. Once you have the raw CSS output, several other tools help you refine and optimize it:
- CSS Minifier - Remove whitespace and comments from the converted CSS for production
- Color Converter - Translate Tailwind hex colors to HSL or other formats
- Box Shadow Generator - Visually create and fine-tune shadow values
- Border Radius Generator - Preview and adjust border radius values
- Gradient Generator - Create gradient backgrounds to replace Tailwind gradient utilities
- CSS Grid Generator - Build and visualize CSS Grid layouts visually
- CSS Flexbox Generator - Configure flexbox layouts with a visual editor
- Color Contrast Checker - Verify that converted color combinations meet WCAG contrast requirements
---
Convert Instantly
Paste your Tailwind HTML into the Tailwind to CSS converter and get clean CSS output in seconds. The tool handles the full range of Tailwind utilities including responsive prefixes, state variants, and dark mode. No signup required, runs entirely in your browser.
After conversion, use the CSS Minifier to optimize the output for production. For color work, the Color Converter and Color Palette tools help you build a consistent design token system from the Tailwind color values in your converted CSS.
Related Tools
Free, private, no signup required
CSS Flexbox Generator
Flexbox generator - visual CSS flexbox layout builder with live preview and ready-to-copy CSS code
CSS Grid Generator
Free online CSS grid generator - visual CSS grid layout builder with live preview and code export
CSS Animation Generator
Free online CSS animation generator - generate CSS keyframe animations visually
CSS Formatter
Free online CSS formatter - format and beautify CSS code with configurable options
You might also like
Want higher limits, batch processing, and AI tools?