design-to-tailwind
Convert design specifications from Figma, Sketch, or Penpot to HTML with Tailwind CSS utility classes
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Design to Tailwind
Convert design component specifications to HTML with Tailwind CSS.
Overview
This skill transforms design specifications into semantic HTML with Tailwind utility classes, following utility-first best practices.
This skill covers:
- Converting design frames to HTML structure
- Mapping design properties to Tailwind utilities
- Generating responsive variants
- Creating reusable component patterns
This skill does NOT cover:
- Design token extraction (see
design-tokens-extractionskill) - JavaScript interactivity
- Framework-specific components (React, Vue, etc.)
Quick Reference
Design to Tailwind Mapping
| Design Property | Tailwind Utilities |
|---|---|
| Horizontal layout | flex flex-row |
| Vertical layout | flex flex-col |
| Gap/Spacing | gap-{size} |
| Padding | p-{size}, px-{size}, py-{size} |
| Margin | m-{size}, mx-{size}, my-{size} |
| Width | w-{size}, w-full, w-auto |
| Height | h-{size}, h-full, h-auto |
| Background color | bg-{color} |
| Text color | text-{color} |
| Font size | text-{size} |
| Font weight | font-{weight} |
| Border radius | rounded-{size} |
| Shadow | shadow-{size} |
| Opacity | opacity-{value} |
Spacing Scale
| Design Value | Tailwind Class |
|---|---|
| 4px | {p|m|gap}-1 |
| 8px | {p|m|gap}-2 |
| 12px | {p|m|gap}-3 |
| 16px | {p|m|gap}-4 |
| 24px | {p|m|gap}-6 |
| 32px | {p|m|gap}-8 |
Workflow: Convert Design Component
Step 1: Analyze Design Structure
Read the design component and identify:
- Container structure and nesting
- Layout direction and alignment
- Spacing values (map to Tailwind scale)
- Color and typography tokens
Step 2: Generate HTML with Tailwind
Basic Card:
<div class="bg-white rounded-lg shadow-md p-4">
<h3 class="text-lg font-semibold text-gray-900">Card Title</h3>
<p class="text-sm text-gray-600 mt-1">Supporting text content</p>
</div>
With Custom Theme Tokens:
<div class="bg-surface rounded-lg shadow-md p-4">
<h3 class="text-heading-md text-foreground">Card Title</h3>
<p class="text-body-sm text-foreground-muted mt-1">Supporting text</p>
</div>
Step 3: Add Interactive States
<button class="
bg-primary-500 text-white
px-4 py-2 rounded-md
font-medium text-sm
hover:bg-primary-600
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2
active:bg-primary-700
disabled:opacity-50 disabled:cursor-not-allowed
transition-colors duration-150
">
Button Label
</button>
Step 4: Add Responsive Variants
<div class="
flex flex-col gap-4
md:flex-row md:gap-6
lg:gap-8
">
<div class="w-full md:w-1/2 lg:w-1/3">Column 1</div>
<div class="w-full md:w-1/2 lg:w-2/3">Column 2</div>
</div>
Common Patterns
Card Component
<!-- Elevated Card -->
<article class="bg-white rounded-xl shadow-lg overflow-hidden">
<img
src="image.jpg"
alt="Card image"
class="w-full h-48 object-cover"
/>
<div class="p-4 space-y-2">
<h3 class="text-lg font-semibold text-gray-900">Card Title</h3>
<p class="text-sm text-gray-600 line-clamp-2">
Description text that may be truncated...
</p>
<div class="flex items-center justify-between pt-2">
<span class="text-sm font-medium text-primary-600">$29.99</span>
<button class="text-sm text-gray-500 hover:text-gray-700">
View details →
</button>
</div>
</div>
</article>
<!-- Outlined Card -->
<article class="border border-gray-200 rounded-lg p-4 hover:border-gray-300 transition-colors">
<h3 class="font-medium text-gray-900">Card Title</h3>
<p class="text-sm text-gray-600 mt-1">Description text</p>
</article>
Button Variants
<!-- Primary Button -->
<button class="
inline-flex items-center justify-center gap-2
bg-primary-500 text-white
px-4 py-2 rounded-md
font-medium text-sm
hover:bg-primary-600 active:bg-primary-700
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2
transition-colors
">
<svg class="w-4 h-4"><!-- icon --></svg>
Primary Button
</button>
<!-- Secondary Button -->
<button class="
inline-flex items-center justify-center gap-2
bg-gray-100 text-gray-900
px-4 py-2 rounded-md
font-medium text-sm
hover:bg-gray-200 active:bg-gray-300
focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2
transition-colors
">
Secondary
</button>
<!-- Ghost Button -->
<button class="
inline-flex items-center justify-center gap-2
text-primary-600
px-4 py-2 rounded-md
font-medium text-sm
hover:bg-primary-50 active:bg-primary-100
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2
transition-colors
">
Ghost Button
</button>
<!-- Icon Button -->
<button class="
p-2 rounded-full
text-gray-500 hover:text-gray-700
hover:bg-gray-100 active:bg-gray-200
focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2
transition-colors
">
<svg class="w-5 h-5"><!-- icon --></svg>
<span class="sr-only">Action label</span>
</button>
List Items
<ul class="divide-y divide-gray-200">
<li class="flex items-center gap-4 p-4 hover:bg-gray-50 transition-colors">
<div class="flex-shrink-0">
<img src="avatar.jpg" alt="" class="w-10 h-10 rounded-full" />
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-gray-900 truncate">List Item Title</p>
<p class="text-sm text-gray-500 truncate">Supporting text</p>
</div>
<div class="flex-shrink-0">
<svg class="w-5 h-5 text-gray-400"><!-- chevron --></svg>
</div>
</li>
</ul>
Form Input
<div class="space-y-1">
<label for="email" class="block text-sm font-medium text-gray-700">
Email address
</label>
<input
type="email"
id="email"
class="
block w-full px-3 py-2
border border-gray-300 rounded-md
text-gray-900 placeholder-gray-400
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500
disabled:bg-gray-50 disabled:text-gray-500
sm:text-sm
"
placeholder="you@example.com"
/>
<p class="text-sm text-gray-500">We'll never share your email.</p>
</div>
Navigation
<nav class="flex items-center gap-1">
<a href="#" class="
px-3 py-2 rounded-md text-sm font-medium
text-gray-900 bg-gray-100
">
Home
</a>
<a href="#" class="
px-3 py-2 rounded-md text-sm font-medium
text-gray-600 hover:text-gray-900 hover:bg-gray-50
transition-colors
">
Products
</a>
<a href="#" class="
px-3 py-2 rounded-md text-sm font-medium
text-gray-600 hover:text-gray-900 hover:bg-gray-50
transition-colors
">
About
</a>
</nav>
Responsive Design
Breakpoint Prefixes
| Prefix | Min Width | Usage |
|---|---|---|
sm: |
640px | Small screens |
md: |
768px | Medium screens |
lg: |
1024px | Large screens |
xl: |
1280px | Extra large |
2xl: |
1536px | 2x extra large |
Responsive Layout Example
<div class="
grid grid-cols-1 gap-4
sm:grid-cols-2 sm:gap-6
lg:grid-cols-3 lg:gap-8
">
<div class="bg-white rounded-lg shadow p-4">Card 1</div>
<div class="bg-white rounded-lg shadow p-4">Card 2</div>
<div class="bg-white rounded-lg shadow p-4">Card 3</div>
</div>
Dark Mode
<div class="
bg-white dark:bg-gray-800
text-gray-900 dark:text-gray-100
border border-gray-200 dark:border-gray-700
rounded-lg p-4
">
<h3 class="font-medium">Dark mode compatible</h3>
<p class="text-gray-600 dark:text-gray-400 mt-1">
Supporting text with dark mode
</p>
</div>
Component Extraction with @apply
For repeated patterns, use @apply in CSS:
/* components.css */
@layer components {
.btn {
@apply inline-flex items-center justify-center gap-2
px-4 py-2 rounded-md
font-medium text-sm
transition-colors
focus:outline-none focus:ring-2 focus:ring-offset-2;
}
.btn-primary {
@apply btn bg-primary-500 text-white
hover:bg-primary-600 active:bg-primary-700
focus:ring-primary-500;
}
.btn-secondary {
@apply btn bg-gray-100 text-gray-900
hover:bg-gray-200 active:bg-gray-300
focus:ring-gray-500;
}
.card {
@apply bg-white rounded-lg shadow-md p-4;
}
.input {
@apply block w-full px-3 py-2
border border-gray-300 rounded-md
text-gray-900 placeholder-gray-400
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500
sm:text-sm;
}
}
Accessibility
Include accessibility utilities:
<!-- Screen reader only text -->
<span class="sr-only">Description for screen readers</span>
<!-- Focus visible states -->
<button class="focus-visible:ring-2 focus-visible:ring-primary-500">
Button
</button>
<!-- Reduced motion -->
<div class="motion-safe:animate-bounce motion-reduce:animate-none">
Animated element
</div>
See Also
-
design-tokens-extractionskill - Extract tokens first -
design-token-tailwindstyle - Tailwind config generation -
component-specstyle - Documentation format
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-03-11
- Index updated
- 2026-03-11
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!