Skip to main content

Overview

Astro Portfolio v3 uses Tailwind CSS v4 with a modern theming system that supports light, dark, and retro modes. The styling is managed through CSS custom properties (CSS variables) for easy theme customization.

Tailwind CSS v4 Setup

The project uses the new Tailwind CSS v4 syntax with inline configuration in the global stylesheet.

Global Styles Location

All styles are defined in src/styles/global.css:
src/styles/global.css
@import 'tailwindcss';
@import 'tw-animate-css';

@custom-variant dark (&:is(.dark *));
@custom-variant retro (&:is(.retro *));

Theme System

The portfolio includes three built-in themes:
The default light theme with a clean, minimal aesthetic using neutral colors.
:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
  --primary: oklch(0.205 0 0);
  --secondary: oklch(0.55 0.15 250);
  /* ... more colors */
}

Color System

The theme uses a semantic color system based on OKLCH color space for perceptual uniformity:
background
color
Main background color for the page
foreground
color
Main text color
primary
color
Primary brand color used for important UI elements
secondary
color
Secondary accent color for highlights and links
muted
color
Muted background color for subtle elements
accent
color
Accent color for emphasis
border
color
Border color for dividers and outlines
card
color
Background color for cards and elevated surfaces

Customizing Colors

To customize your theme colors, edit the CSS variables in src/styles/global.css:
src/styles/global.css
:root {
  --primary: oklch(0.205 0 0);     /* Change primary color */
  --secondary: oklch(0.55 0.15 250); /* Change secondary color */
  --background: oklch(1 0 0);       /* Change background */
}
The project uses OKLCH color space for better color consistency. Use tools like OKLCH Color Picker to generate colors.

Custom Utilities

The project includes several custom utility classes:

Container Fluid

A responsive container with consistent padding:
.container-fluid {
  @apply px-4 sm:px-6 w-full mx-auto max-w-6xl;
}
Usage:
<div class="container-fluid">
  <h1>Content with consistent padding</h1>
</div>

First Letter Color

Applies accent color to the first letter of text:
.first-letter-color {
  @apply first-letter:text-secondary retro:first-letter:text-primary;
}
Usage:
<h1 class="first-letter-color">Beautiful Typography</h1>

Custom Animations

The theme includes several custom animations for smooth transitions:
@keyframes slide-in-bottom {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Usage */
.animate-slide-in-bottom {
  animation: slide-in-bottom 0.6s ease-out;
}

Staggered Animations

Create beautiful staggered entrance animations:
<div class="animate-stagger">
  <div>Item 1</div> <!-- Animates with 0.1s delay -->
  <div>Item 2</div> <!-- Animates with 0.2s delay -->
  <div>Item 3</div> <!-- Animates with 0.3s delay -->
</div>

Theme-Specific Styling

Use custom variants to apply styles based on the active theme:
<!-- Light theme only -->
<div class="bg-white dark:bg-transparent">

<!-- Dark theme only -->
<div class="hidden dark:block">

<!-- Retro theme only -->
<div class="retro:border-4 retro:border-primary">

<!-- Multiple themes -->
<p class="text-primary retro:text-secondary dark:text-accent">

Custom Border Radius

The theme includes a flexible border radius system:
--radius: 0.625rem; /* Base radius */
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
Usage:
<div class="rounded-[var(--radius-lg)]">
  <button class="rounded-[var(--radius-sm)]">Click me</button>
</div>

Typography

The site uses the Inter font family loaded through Astro’s Font API:
src/layouts/Layout.astro
import { Font } from 'astro:assets';

<Font cssVariable='--font-inter' />
Apply it globally:
body {
  font-family: var(--font-inter), sans-serif;
}
Be careful when modifying animation durations, as they’re synchronized with Astro’s view transitions. Changes may cause visual glitches during page navigation.

Class Utility Function

The project includes a cn() utility function for merging Tailwind CSS classes intelligently. This function combines clsx and tailwind-merge to handle conditional classes and resolve Tailwind conflicts. Location: src/lib/utils.ts
src/lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
Usage:
---
import { cn } from '@/lib/utils';

const isActive = true;
const customClass = 'my-custom-class';
---

<div class={cn(
  'base-class',
  isActive && 'active-class',
  customClass,
  'text-blue-500 text-red-500' // text-red-500 wins
)}>
  Content
</div>
This utility is particularly useful for:
  • Conditional class application
  • Resolving conflicting Tailwind classes
  • Building dynamic class strings for components

Best Practices

1

Use CSS Variables

Always use CSS variables for colors to maintain theme consistency
2

Test All Themes

Test your customizations in all three themes (light, dark, retro)
3

Maintain Accessibility

Ensure sufficient color contrast ratios for text readability
4

Use Semantic Colors

Use semantic color names (primary, secondary) instead of specific colors (blue, red)

Build docs developers (and LLMs) love