Slicing UI Lebih Cepat: Memaksimalkan Potensi Tailwind CSS
Mengapa Tailwind Mengubah Cara SayaBerfikir UI
Saya awalnya skeptis dengan utility-first CSS. "Kenapa harus ketik text-primary-600 font-bold mb-4 di setiap h1?" Saya suka separates HTML dan CSS dengan BEM.
Lalu coba 2 minggu proyek production dengan Tailwind. Hasilnya: 40% faster delivery, CSS bundle lebih kecil, dan zero style conflicts. Saya ter-transformasi.
1. Utility-First Mindset
Tailwind mengubah mindset "buatk class semantik" menjadi "gunakan utility classes dengan komposisi".
<!-- Sebelum (BEM): -->
<button class="btn btn--primary btn--large">Save</button>
<!-- CSS file terpisah dengan ratusan baris -->
<!-- Tailwind: -->
<button
class="inline-flex items-center px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors"
>
Save
</button>
Keuntungan: tidak perlu context-switching ke file CSS. Semua yang memengaruhi tampilan ada di tempat yang sama.
2. @apply: Ketika Utility Berlebihan
Untuk pola yang berulang dengan banyak utility, gunakan @apply di CSS final.
/* components/buttons.css */
@layer components {
.btn-primary {
@apply inline-flex items-center px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors;
}
.btn-secondary {
@apply inline-flex items-center px-6 py-3 border-2 border-blue-600 text-blue-600 font-medium rounded-lg transition-colors;
}
}
<button class="btn-primary">Save</button>
<button class="btn-secondary">Cancel</button>
Gunakan ini untuk hal yang benar-benar reusable (> 3 tempat pemakaian). Jangan untuk satu-dua lokasi.
3. Tailwind Config yang Tepat
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx,vue,html}',
],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
900: '#1e3a8a',
},
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
animation: {
'fade-in': 'fadeIn 0.5s ease-out',
'slide-up': 'slideUp 0.3s ease-out',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(20px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
},
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
],
};
4. Komposisi yang Baik
Trik pimpinan saya: pisahkan komponen ke 3 layer — primitive, composite, page.
Layer 1: Primitives (> 95% reuse)
<!-- Button.vue, Input.vue, Card.vue -->
<button class="inline-flex items-center gap-2 px-4 py-2 rounded-lg transition-colors font-medium">
<slot />
</button>
Variants:
- Warna: gunakan parent-class override
- Ukuran: gunakan
sizeprop
Layer 2: Composites (5-95% reuse)
<!-- SearchBar.vue -->
<div class="flex items-center gap-2">
<Input placeholder="Search..." v-model="query" class="flex-1" />
<Button variant="primary">Search</Button>
</div>
Layer 3: Pages (< 5% reuse)
Semua utility classes inline ditempatkan langsung.
<div class="min-h-screen bg-gray-50 flex flex-col">
<header class="h-16 bg-white border-b flex items-center px-6">
...
</header>
<main class="flex-1 container mx-auto py-8">
...
</main>
</div>
5. Responsive Design Tanpa Media Queries
Tailwind memakai prefix mobile-first.
<!-- Mobile first: default 1 kolom, sm ke atas 2 kolom, lg 3 kolom -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
...
</div>
Prefix yang tersedia: sm, md, lg, xl, 2xl. Lebih intuitive dari media queries manual.
6. Dark Mode yang Terintegrasi
<div class="bg-white dark:bg-slate-800 text-gray-900 dark:text-slate-100">
Dark-aware component
</div>
// tailwind.config.js
module.exports = {
darkMode: 'class', // atau 'media'
}
Toggle dark mode otomatis dengan prefers-color-scheme atau user toggle.
7. Tips Performance
PurgeCSS Built-in
Tailwind hanya meng-keep utility classes yang ditemukan di content. Final CSS bisa < 10 KB.
// Kalau Anda lupa purge, hasil CSS bisa ratusan KB!
content: ['./src/**/*.{html,js,jsx,vue,astro}'],
Just-In-Time Mode (Tailwind 3+)
Semenjak Tailwind 3, JIT mode default. Build time turun drastis dan arbitrary values work:
<!-- Arbitrary value, tidak perlu config -->
<div class="top-[117px] bg-[#bada55] grid-cols-[200px_1fr_1fr]">
Arbitrary values
</div>
8. Plugin yang Berguna
@tailwindcss/forms: style form element konsisten cross-browser@tailwindcss/typography: prose styling untuk konten markdown (yang Anda baca ini pakai ini!)@tailwindcss/aspect-ratio: ratio boxes tanpa CSS hacks@tailwindcss/line-clamp: truncate text multi-line
9. Trik Slicing Lebih Cepat
Mental checklist saya saat slicing Figma ke Tailwind:
- Identifikasi layout utama — flex atau grid?
- Spacing antar elemen — pakai
gap, jangan margin satu per satu - Container utama —
max-w-sesuai konten (max-w-7xluntuk dashboard,max-w-3xluntuk blog) - Warna border — gunakan
border-gray-200 dark:border-slate-700 - Shadows subtle —
shadow-smlebih elegan darishadow-lguntuk card umum - Transitions — selalu tambahkan
transition-colorske elemen hover
10. Ekstract Components yang Reusable
Pola yang sering ulang saya ekstract ke komponen:
<!-- Card.vue -->
<template>
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-md border border-gray-100 dark:border-slate-700 p-6">
<slot />
</div>
</template>
<!-- Badge.vue -->
<script setup>
const props = defineProps({
variant: { type: String, default: 'gray' }
});
const variants = {
gray: 'bg-gray-100 text-gray-700',
blue: 'bg-blue-100 text-blue-700',
red: 'bg-red-100 text-red-700',
};
</script>
<template>
<span :class="['px-2 py-1 text-xs font-medium rounded', variants[variant]]">
<slot />
</span>
</template>
Kesimpulan
Tailwind bukan"ganti className". Tailwind adalah pengubah cara berpikir tentang UI. Setelah 2 tahun pengalaman, saya tidak akan kembali ke BEM murni. Manfaat: kecepatan delivery, konsistensi desain, dan mantenability (counter-intuitive tapi benar — utility class lebih mudah refactor dari spread CSS rules).
Mulailah dengan proyek kecil. Rasakan productivitasnya, lalu extract components yang benar-benar reusable. Jangan over-engineer setup awal.