Q1 ⭐ What is Tailwind CSS and how is it different from traditional CSS frameworks like Bootstrap?
- Tailwind = utility-first CSS framework. Each class = one CSS property.
- Bootstrap = component-based. Pre-built components (buttons, modals) with fixed designs.
- Tailwind: more flexible, no design opinion, smaller production bundle (purged), harder to learn initially.
- Bootstrap: faster to start, consistent components, larger bundle, harder to customize deeply.
🔗 Follow-up: "What does utility-first mean?"
Q2 ⭐ What is the purpose of the content array in tailwind.config.js?
- Tailwind scans these files to find used class names — only those classes appear in final CSS.
- This is how Tailwind achieves tiny production bundles (dead-code elimination / PurgeCSS).
- Must include all files that use Tailwind classes: HTML, JSX, TSX, Vue, Svelte files.
- Missing a file path = those classes stripped from production build → styles missing!
🔗 Follow-up: "Why can't you build class names dynamically with string concatenation in Tailwind?"
Q3 ⭐ How does Tailwind CSS handle responsive design? What does "mobile-first" mean here?
- Breakpoint prefixes: sm: md: lg: xl: 2xl: — each maps to a min-width media query.
- Mobile-first: unprefixed classes apply to ALL screen sizes. sm: means "640px and above".
- Example: <code>text-sm md:text-base lg:text-xl</code> — small on mobile, scales up.
- There is no "xs:" — write mobile styles without prefix, override upward.
Q4: What is the difference between @apply and just using utility classes in HTML?
- @apply: extracts utilities into a CSS class. Use for repeated patterns (buttons, cards).
- HTML utilities: inline, flexible, easier to see what's applied, no switching files.
- @apply should be used sparingly — it re-introduces "semantic class" problem Tailwind solves.
- Best: use @apply only in @layer components for truly reused components. Prefer JS components.
Q5: How do you add a custom color to Tailwind? How would you use brand-500?
- In tailwind.config.js → theme.extend.colors: { brand: { 500: '#7c3aed' } }
- Using extend keeps all default colors. Putting in theme.colors replaces them.
- Then use: bg-brand-500, text-brand-500, border-brand-500, ring-brand-500
- Can define full 50-950 scale or single value. Opacity modifier: bg-brand-500/50
Q6: What is the Tailwind CSS JIT (Just-in-Time) engine? How is it different from the old purge approach?
- Old: generated ALL possible classes (~3MB+), then purged unused in production.
- JIT (now default since v3): generates ONLY the classes you actually use, on demand.
- Benefits: instant dev builds, tiny dev CSS, enables arbitrary values (w-[123px]), all variants everywhere.
- JIT = faster builds + arbitrary value support + no huge dev CSS file.
Q7: What are arbitrary values in Tailwind? Give 3 examples.
- Square bracket syntax for one-off values outside the design scale: <code>w-[350px]</code>, <code>text-[22px]</code>, <code>bg-[#1da1f2]</code>
- Works with any utility: <code>mt-[clamp(1rem,5vw,3rem)]</code>, <code>grid-cols-[1fr_2fr]</code>
- Use sparingly — frequent arbitrary values suggest you should extend your config instead.
Q8 ⭐ Explain group and peer in Tailwind. How do they work?
- <code>group</code>: add class "group" to parent. Then use <code>group-hover:</code>, <code>group-focus:</code> on children to style based on parent state.
- <code>peer</code>: add class "peer" to a sibling. Then use <code>peer-invalid:</code>, <code>peer-checked:</code> on the NEXT sibling.
- Named groups (v3.3): <code>group/name</code> + <code>group-hover/name:</code> for nested groups.
- peer must come BEFORE the element that styles itself based on peer.
🔗 Follow-up: "How would you show a hidden button when hovering a card?"
Q9 ⭐ How does dark mode work in Tailwind? What's the difference between media and class strategy?
- media: uses <code>@media (prefers-color-scheme: dark)</code>. Automatic, follows OS. No JS needed.
- class: requires <code>class="dark"</code> on html element. User-toggleable, controllable, storable in localStorage.
- Usage: <code>dark:bg-gray-900 dark:text-white</code>
- class strategy preferred for apps with manual toggle. media for simple sites.
Q10: Why can't you use dynamic class names like `text-${size}-500` in Tailwind?
- Tailwind scans source files for complete class name strings. It doesn't execute JavaScript.
- Dynamically constructed strings like <code>`text-${color}-500`</code> will never match — the full string never exists in source.
- Solution: use complete class names in conditionals: <code>isRed ? 'text-red-500' : 'text-blue-500'</code>
- Or use safelist in config to always include specific patterns/classes.
Q11: What is tailwind-merge and why do you need it?
- Problem: merging Tailwind classes with conflicts — <code>p-4 p-6</code> → both appear but only last wins (CSS order, not HTML).
- tailwind-merge: intelligently removes conflicting utilities, keeps later ones.
- <code>twMerge('p-4', 'p-6')</code> → <code>'p-6'</code>. <code>twMerge('bg-red-500', 'bg-blue-500')</code> → <code>'bg-blue-500'</code>
- Essential for component libraries where users pass className props. Usually paired with clsx.
Q12: How would you implement a glassmorphism card in Tailwind?
- <code>backdrop-blur-md</code> for the blur effect on background
- <code>bg-white/10</code> or <code>bg-slate-900/50</code> — semi-transparent background
- <code>border border-white/20</code> — subtle border
- Full: <code>backdrop-blur-md bg-white/10 border border-white/20 rounded-xl p-6 shadow-xl</code>
Q13: What are @layer base, @layer components, and @layer utilities?
- base: global reset/default styles. HTML element styles, CSS variables. Low specificity.
- components: reusable component classes (.btn, .card). Used with @apply. Medium specificity.
- utilities: single-purpose utility overrides. Highest specificity — always win.
- Order matters: base → components → utilities. Utilities always beat components.
Q14: How do you add custom fonts in Tailwind? Walk through the full process.
- 1. Import font (Google Fonts link or @font-face in CSS)
- 2. Add to tailwind.config.js: theme.extend.fontFamily: { custom: ['Inter', 'sans-serif'] }
- 3. Use: <code>font-custom</code> in HTML
- Or override default sans: theme.fontFamily.sans = ['Inter', ...defaultTheme.fontFamily.sans]
Q15: What are Tailwind CSS plugins? Give an example of writing a simple custom plugin.
- Plugins extend Tailwind with new utilities, components, or base styles
- Use plugin() function: <code>require('./my-plugin')</code> in plugins array
- Example: addUtilities for .text-shadow, addComponents for .btn, addBase for :root variables
- Official plugins: @tailwindcss/typography, @tailwindcss/forms, @tailwindcss/container-queries
Q16 ⭐ How would you build a reusable component system with Tailwind that allows className prop overrides?
- Use cn() utility (clsx + tailwind-merge) to merge default + user-provided classes
- Default classes defined in component, className prop merged last to allow overrides
- <code>function Button({ className, ...props }) { return <button className={cn('px-4 py-2 bg-blue-600', className)} /> }</code>
- twMerge handles conflicts — user's bg-red-500 beats default bg-blue-600
- Class Variance Authority (CVA) library for variant-based component APIs
Q17 ⭐ What is the safelist in Tailwind config? When would you use it?
- safelist: always include these classes even if not found in content scan
- Use when: classes from API/CMS/database, dynamically constructed strings, third-party templates
- Supports patterns: <code>safelist: [{ pattern: /bg-(red|blue|green)-(100|500|900)/ }]</code>
- Can specify variants: <code>{ pattern: /text-.*/, variants: ['hover', 'focus'] }</code>
Q18: How does Tailwind's spacing scale work internally? Why is everything in multiples of 4?
- 1 unit = 0.25rem = 4px (at browser default 16px). Design systems use 4px or 8px grids.
- Consistent scale prevents arbitrary spacing and keeps layouts harmonious.
- p-1=4px, p-2=8px, p-4=16px, p-8=32px — all multiples of 4.
- Non-scale values exist: px (1px), 0.5 (2px) for fine-tuning borders and dividers.
Q19: How would you integrate Tailwind with CSS-in-JS libraries or styled-components?
- Direct mixing is tricky — styled-components generates CSS at runtime, Tailwind at build time.
- Approach 1: Use Tailwind theme values via resolveConfig() in JS.
- Approach 2: CSS variables — define Tailwind custom properties, use in styled-components.
- Approach 3: twin.macro — converts Tailwind classes to CSS-in-JS at build time. (Babel plugin)
Q20: What are Tailwind CSS v4 key changes? How is it different from v3?
- v4: Configuration in CSS (not JS). No tailwind.config.js needed — use @import "tailwindcss" + CSS variables.
- Built on Lightning CSS (Rust) instead of PostCSS — 5-10x faster builds.
- All CSS features detected natively. No need to configure content paths explicitly.
- Composing utilities with @utility. First-party vite plugin. Much smaller codebase.
Q21: How would you optimize Tailwind for production? What affects bundle size?
- Tailwind production bundle = only used classes. JIT is already optimal by default.
- Ensure content array covers all template files — no missed files = no extra classes.
- Avoid safelist overuse — whitelisted classes always included regardless of use.
- Use CSS layers correctly — base/components/utilities ordering matters.
- @apply in components reduces HTML class bloat but increases CSS. Tradeoff.
- Additional: minify CSS in build pipeline, use Brotli/gzip compression on server.