TailwindCSS

architecture

TailwindCSS

Definition

TailwindCSS is a utility-first CSS framework that fundamentally changes how developers approach styling by providing a comprehensive set of low-level, single-purpose utility classes that are composed directly in HTML markup to build custom designs. Rather than writing semantic CSS class names like .card-header or .navigation-menu and then defining their styles in separate stylesheet files, TailwindCSS developers apply atomic utilities like flex, pt-4, text-center, rounded-lg, and bg-gray-900 directly to elements, constructing any design without ever leaving the HTML template.

This approach eliminates several categories of problems that plague traditional CSS development: specificity conflicts (where multiple rules compete to style the same element), dead CSS accumulation (where unused styles bloat production bundles), naming debates (where teams spend time arguing over BEM, SMACSS, or other naming conventions), and context switching (where developers constantly jump between template and stylesheet files). The utility-first philosophy treats CSS as a design API rather than a separate programming concern, and the resulting markup is self-documenting---any developer can look at a component's HTML and immediately understand its visual presentation without tracing through cascading stylesheets.

TailwindCSS uses a JIT (Just-In-Time) compiler that scans all configured template files (HTML, JSX, Elixir HEEx, ERB, or any other format) at build time, identifies which utility classes are actually used, and generates a minimal CSS bundle containing only those classes. This means a production build typically produces a CSS file of 10-30KB (gzip-compressed), regardless of how many utility classes TailwindCSS offers in total. The JIT compiler also enables arbitrary value support (e.g., w-[137px], bg-[#1da1f2]), making the framework infinitely flexible without custom configuration.

Utility-First Philosophy

The utility-first approach represents a paradigm shift from component-based CSS frameworks like Bootstrap or Material UI:

ApproachExampleProsCons
Semantic CSS.btn-primary { ... }Clean HTML, reusable namesNaming fatigue, specificity wars
CSS Modules.Button_primary__3Kx2Scoped, no conflictsBuild complexity, no sharing
CSS-in-JSstyled.button\...``Dynamic, scopedRuntime cost, bundle size
Utility-Firstclass="bg-blue-600 px-4 py-2 rounded"No naming, no dead CSSVerbose markup
<!-- Traditional CSS approach -->
<button class="btn-primary">Submit</button>
<!-- Requires: .btn-primary { background: blue; padding: 0.5rem 1rem; border-radius: 0.25rem; } -->

<!-- TailwindCSS utility-first approach -->
<button class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition-colors">
  Submit
</button>
<!-- No separate CSS file needed -->

When patterns repeat across multiple components, TailwindCSS provides two extraction mechanisms:

  1. Component extraction: Create reusable LiveView function components that encapsulate utility classes
  2. @apply directive: Extract utility combinations into named CSS classes (used sparingly, as it defeats the utility-first advantage)

Responsive Design System

TailwindCSS implements a mobile-first responsive design system through breakpoint prefix modifiers that apply styles conditionally based on viewport width:

PrefixMin WidthCSS Media QueryCommon Use
(none)0pxDefault (mobile)Base styles
sm:640px@media (min-width: 640px)Small tablets
md:768px@media (min-width: 768px)Tablets, small laptops
lg:1024px@media (min-width: 1024px)Laptops, desktops
xl:1280px@media (min-width: 1280px)Large desktops
2xl:1536px@media (min-width: 1536px)Extra-large screens
<!-- Responsive grid: 1 column on mobile, 2 on tablet, 3 on desktop -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
  <div class="bg-gray-800 rounded-lg p-6">
    <h3 class="text-lg sm:text-xl font-semibold text-white">Asset Card</h3>
    <p class="mt-2 text-sm text-gray-400">Security rating: A</p>
  </div>
</div>

The mobile-first approach means that unprefixed utilities target all screen sizes, and breakpoint prefixes progressively enhance the layout for larger viewports. This produces more maintainable code because the base mobile layout is defined first, and larger screens add complexity incrementally.

Dark Mode

TailwindCSS provides built-in dark mode support through the dark: prefix variant, with two activation strategies:

StrategyConfigurationActivationUse Case
Class-baseddarkMode: 'class'class="dark" on <html>Manual toggle, SSR
Media-baseddarkMode: 'media'prefers-color-scheme: darkOS preference
<!-- Dark mode styling (class strategy) -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
  <h2 class="text-xl font-bold">Security Dashboard</h2>
  <p class="text-gray-600 dark:text-gray-400">Current threat level: Low</p>
</div>

The Prismatic Platform uses the class-based strategy with a forced-dark theme---the <html> element always has class="dark" applied, and all UI is designed exclusively for dark mode. This eliminates the need for dark: conditional prefixes on the promo site frontpage, where direct dark classes (bg-gray-950, text-white, text-gray-400) are used instead.

JIT Compilation and Build Process

The JIT compiler is the engine that makes TailwindCSS practical for production use. It operates in three phases:

  1. Content scanning: Parse all configured template files to extract class names
  2. CSS generation: Generate only the CSS for classes that actually appear in templates
  3. Optimization: Apply PostCSS plugins (autoprefixer, cssnano) for cross-browser compatibility and minification
// tailwind.config.js
module.exports = {
  content: [
    "./templates/**/*.html",
    "./templates/**/*.html.heex",
    "../lib/*_web/**/*.*ex",
    "../lib/*_web/**/*.html.heex",
    "../deps/flowbite/**/*.js"
  ],
  darkMode: 'class',
  theme: {
    extend: {
      colors: {
        prismatic: {
          900: '#0f172a',
          800: '#1e293b',
          700: '#334155',
        }
      }
    }
  },
  plugins: [
    require('flowbite/plugin')
  ]
}

The content configuration is critical: any class name that does not appear in a scanned file will be excluded from the generated CSS. This is why dynamically constructed class names (e.g., bg-${color}-500) do not work---the JIT compiler performs static analysis and cannot resolve runtime expressions. Instead, use complete class strings with conditional logic.

Configuration and Customization

TailwindCSS's default design system is fully customizable through tailwind.config.js:

Configuration AreaPurposeExample
theme.colorsColor paletteCustom brand colors
theme.spacingSpacing scaleAdditional spacing values
theme.fontFamilyTypographyCustom font stacks
theme.extendAdditive customizationExtend without overriding defaults
pluginsFeature extensionsFlowbite, typography, forms
contentTemplate file pathsFiles to scan for class usage

TailwindCSS ships with a carefully crafted default design system that includes:

  • A 22-shade color palette across 22 color families (50-950 shades per color)
  • A spacing scale from 0 to 96 (0px to 24rem) in consistent increments
  • A type scale with 10 font sizes from xs to 9xl
  • 7 font weights from thin (100) to black (900)
  • 6 border radius values from rounded-sm to rounded-full
  • Shadow, opacity, and transition utilities with sensible defaults

Context in Prismatic

Within the Prismatic Platform, TailwindCSS is the mandatory and exclusive styling approach enforced by platform policy. This is a hard requirement with zero exceptions---inline styles and custom CSS files are explicitly forbidden across all applications.

Enforcement Scope: All UI across LiveView dashboards, the Perimeter EASM interface, administrative panels, and the public promo site must use TailwindCSS utilities combined with Flowbite 2.3 components. This mandate ensures visual consistency across 92 umbrella applications and eliminates CSS specificity conflicts.

Build Integration: TailwindCSS is integrated into Phoenix's asset pipeline through esbuild configuration. The JIT compiler watches template files during development and generates optimized CSS for production releases. Docker container builds include a TailwindCSS compilation step as part of the multi-stage build process.

Promo Site Rebuild Requirement: The promo site at sites/promo/ requires explicit TailwindCSS rebuilds after any template changes:

cd sites/promo
npx tailwindcss -i static/css/tailwind-input.css -o static/css/tailwind.css --minify

Failure to rebuild after template changes causes newly used classes to be absent from the generated CSS, resulting in invisible text or broken layouts. This is a known operational requirement documented in the platform's deployment procedures.

Platform UI Stack:

LayerTechnologyRole
StylingTailwindCSS 3.4Utility classes for all visual presentation
ComponentsFlowbite 2.3Pre-built accessible UI components
InteractivityAlpine.js 3.13.5Client-side behavior (dropdowns, modals)
RenderingPhoenix LiveViewServer-rendered reactive UI
ThemeForced dark modeclass="dark" on <html>, no toggle

TailwindCSS Anti-Patterns

Anti-PatternProblemCorrect Approach
Dynamic class constructionbg-${color}-500 not scanned by JITUse complete strings: bg-red-500, bg-blue-500
Inline stylesBypasses design system, no responsiveUse TailwindCSS utilities exclusively
Custom CSS filesSpecificity conflicts, maintenance burdenExtract to components or use @apply sparingly
!important overridesBreaks utility predictabilityUse proper specificity ordering
Unused @apply extractionDefeats utility-first benefitsExtract only when truly repeated 3+ times
  • Flowbite - TailwindCSS component library providing pre-built UI elements
  • LiveView - Server-side rendering framework consuming TailwindCSS for reactive UI
  • Phoenix - Web framework integrating TailwindCSS via asset pipeline
  • Clean Run - Quality standard extending to UI code consistency
  • Docker - Container builds that include TailwindCSS compilation step
  • EASM - Perimeter dashboard built entirely with TailwindCSS utilities
  • Plug - Middleware serving compiled TailwindCSS assets
  • Metrics - Dashboard visualizations styled with TailwindCSS
  • Observability - Monitoring UI built with TailwindCSS components

See Also

  • Architecture - Platform UI architecture and component strategy
  • Technologies - Technology stack details
  • Apps - Applications using TailwindCSS for their interfaces

Connect & Contribute

Created by Tomáš Korcak (korczis) | Open Source under GHL