Skip to content

CSS Architecture

CSS architecture guide for Talent Finder

Table of Contents

Overview

The project uses a modern CSS architecture combining:

TechnologyUsageProportion
Tailwind CSS 4.1Utilities (layout, spacing)~70%
CSS Custom PropertiesCentralized design tokensGlobal
Scoped StylesComplex components with variants~30%
OKLCH Color SpacePerceptually uniform color system100%

Key Files

src/
├── app.css              # Global design system (~775 lines)
└── lib/
    └── ui/
        └── *.svelte     # Components with scoped styles

Design Tokens

All tokens are defined in src/app.css and accessible via CSS custom properties.

Colors (OKLCH)

The system uses the OKLCH color space to generate consistent shades:

css
/* Base parameters */
:root {
  --hue-primary: 250;    /* Primary hue (0-360) */
  --hue-accent: 180;     /* Accent hue */
  --hue-neutral: 260;    /* Neutral hue */
  --chroma: 0.15;        /* Saturation (0-0.3) */
}

/* Automatically generated shades */
--color-primary-50   /* Lightest */
--color-primary-100
--color-primary-200
--color-primary-300
--color-primary-400
--color-primary-500  /* Base */
--color-primary-600
--color-primary-700
--color-primary-800
--color-primary-900
--color-primary-950  /* Darkest */

Color categories:

CategoryUsageTokens
primaryMain actions, links, CTA50-950 (11 shades)
accentSecondary highlighting50-950 (11 shades)
secondaryText, neutral backgrounds50-950 (11 shades)
successPositive feedback50, 500, 600, 700
warningAlerts, warnings50, 500, 600, 700
errorErrors, critical states50, 500, 600, 700

Typography

css
/* Font families */
--font-sans: var(--font-body), ui-sans-serif, system-ui, sans-serif;
--font-heading: var(--font-heading-family), ui-sans-serif, system-ui, sans-serif;
--font-mono: var(--font-mono-family), ui-monospace, monospace;

/* Sizes */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */

Spacing

css
--spacing-xs: 0.25rem; /* 4px */
--spacing-sm: 0.5rem; /* 8px */
--spacing-md: 1rem; /* 16px */
--spacing-lg: 1.5rem; /* 24px */
--spacing-xl: 2rem; /* 32px */
--spacing-2xl: 3rem; /* 48px */

Other Tokens

css
/* Border Radius */
--radius-sm: 0.25rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
--radius-full: 9999px;

/* Shadows */
--shadow-sm: 0 1px 2px 0 oklch(0% 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px oklch(0% 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px oklch(0% 0 0 / 0.1);

/* Transitions */
--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300ms ease;

Hybrid Approach

When to Use Tailwind

Use Tailwind (utility classes) for:

  • Layout (flex, grid, positioning)
  • Spacing (margin, padding)
  • Responsive design (breakpoints)
  • Simple and direct styles
svelte
<!-- Good: Tailwind for layout and spacing -->
<div class="flex items-center gap-4 p-6 md:p-8">
	<h2 class="text-2xl font-semibold">Title</h2>
</div>

When to Use Scoped Styles

Use scoped styles (<style>) for:

  • Components with multiple variants (data-variant)
  • Complex animations
  • Multiple dynamic states
  • Integration with CSS custom properties
svelte
<!-- Good: Scoped styles for complex variants -->
<div class="alert" data-variant={variant}>
	<slot />
</div>

<style>
	.alert {
		--alert-bg: var(--color-primary-50);
		--alert-border: var(--color-primary-200);
		background-color: var(--alert-bg);
		border: 1px solid var(--alert-border);
	}

	.alert[data-variant='success'] {
		--alert-bg: var(--color-success-50);
		--alert-border: var(--color-success-500);
	}

	.alert[data-variant='error'] {
		--alert-bg: var(--color-error-50);
		--alert-border: var(--color-error-500);
	}
</style>

Theme System

Color Palettes (18)

The system offers 18 predefined palettes via the data-palette attribute:

CategoryPalettes
Professionalcorporate, executive
Natureforest, ocean, earth
Vibrantneon, electric, tropical
Minimalpaper, slate, stone
Warmamber, rose, terracotta
Coolarctic, indigo, mint
html
<!-- Apply a palette -->
<body data-palette="ocean"></body>

Typography Pairings (30)

30 font combinations via the data-font attribute:

CategoryFonts
Sans-serifmodern, humanist, geometric, minimal, startup, etc.
Serifeditorial, classic, literary, magazine, academic, etc.
Displaybold-statement, creative, luxe, vintage, urban, etc.
Technicaltechnical, developer, terminal, data, science, etc.
html
<!-- Apply a pairing -->
<body data-font="editorial"></body>

Dark Mode

Implementation

Dark mode uses the .dark class on the <html> element:

css
/* Tailwind custom variant */
@custom-variant dark (&:where(.dark, .dark *));

/* Color scheme */
html {
	color-scheme: light;
}
html.dark {
	color-scheme: dark;
}

Pattern for Scoped Styles

css
/* Light styles (default) */
.component {
	--bg: var(--color-secondary-50);
	--text: var(--color-secondary-900);
	background-color: var(--bg);
	color: var(--text);
}

/* Dark styles */
:global(.dark) .component {
	--bg: var(--color-secondary-800);
	--text: var(--color-secondary-100);
}

OKLCH Pattern for Dark Mode

For colors with preserved hue:

css
:global(.dark) .alert[data-variant='success'] {
	--alert-bg: oklch(from var(--color-success-500) 20% 0.05 h);
}

Standard Dark Mode Colors

ElementLightDark
Backgroundsecondary-50secondary-900
Surface/Cardswhitesecondary-800
Primary textsecondary-900secondary-100
Secondary textsecondary-600secondary-400
Borderssecondary-200secondary-700
Primary actionsprimary-600primary-400

Components

Global Utility Classes

Defined in app.css via @layer components:

Buttons:

  • .btn-primary - Primary action
  • .btn-secondary - Secondary action
  • .btn-accent - Accent action
  • .btn-outline - Outline button
  • .btn-ghost - Transparent button
  • .btn-sm, .btn-lg - Sizes

Cards:

  • .card - Card with shadow
  • .card-bordered - Card with border

Forms:

  • .input - Input field
  • .input-error - Error state
  • .label - Form label

Badges:

  • .badge-primary, .badge-accent
  • .badge-success, .badge-warning, .badge-error

Alerts:

  • .alert-info, .alert-success
  • .alert-warning, .alert-error

Variant System (data-attributes)

Complex components use data-* attributes for variants:

svelte
<!-- Style variants -->
<Section data-variant="surface" />
<Section data-variant="card" />
<Section data-variant="transparent" />

<!-- Sizes -->
<Badge data-size="sm" />
<Badge data-size="md" />
<Badge data-size="lg" />

<!-- Spacing -->
<Section data-spacing="sm" />
<Section data-spacing="md" />
<Section data-spacing="lg" />

Best Practices

1. Single Source of Truth

Always use design tokens:

css
/* Good */
color: var(--color-primary-600);
padding: var(--spacing-md);
border-radius: var(--radius-lg);

/* Bad */
color: #4f46e5;
padding: 16px;
border-radius: 8px;

2. Semantic Colors

Never use descriptive colors:

css
/* Good */
@apply bg-primary-600 text-success-500;

/* Bad */
@apply bg-blue-600 text-green-500;

3. Mobile-First Responsive

Always start from mobile:

svelte
<!-- Good: mobile-first -->
<div class="flex-col md:flex-row lg:gap-8">

<!-- Bad: desktop-first -->
<div class="flex-row max-md:flex-col">

4. Accessibility

Always include:

css
/* Focus visible */
:focus-visible {
	@apply outline-2 outline-offset-2 outline-primary-500;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
	* {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
	}
}

5. No Magic Numbers

css
/* Good */
gap: var(--spacing-md);
font-size: var(--text-lg);

/* Bad */
gap: 16px;
font-size: 18px;

6. Minimal Scoped Styles

Scoped styles should only contain what cannot be done with Tailwind:

svelte
<!-- Good: Tailwind for layout, scoped for variants -->
<div class="flex items-center gap-4 p-4" data-variant={variant}>

<style>
  /* Only complex variants */
  [data-variant='success'] { --icon-color: var(--color-success-500); }
  [data-variant='error'] { --icon-color: var(--color-error-500); }
</style>

PR Checklist

Before Submitting CSS

  • [ ] Tokens: Uses design tokens (no hardcoded values)
  • [ ] Dark mode: Component supports dark mode
  • [ ] Responsive: Mobile-first with appropriate breakpoints
  • [ ] Accessibility: Visible focus states, sufficient contrasts
  • [ ] Semantic: Semantic colors (primary, success, error)
  • [ ] Minimal scoped: No duplication with Tailwind
  • [ ] Variants: Uses data-* attributes if multiple variants

Automated Checks

bash
# CSS Linting (if Stylelint configured)
pnpm lint

# Build to verify CSS purge
pnpm build

Audit and Quality

Resources