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:
@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:
Light Theme
Dark Theme
Retro Theme
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 */
}
A sophisticated dark theme with subtle color accents and high contrast. .dark {
--background : oklch ( 0.2136 0.0483 257.95 );
--foreground : oklch ( 0.9636 0.0328 106.9994 );
--primary : oklch ( 0.922 0 0 );
--secondary : oklch ( 0.7872 0.096 181.8426 );
/* ... more colors */
}
A nostalgic retro theme inspired by DaisyUI’s retro palette with warm tones. .retro {
--background : oklch ( 91.637 % 0.034 90.515 );
--foreground : oklch ( 44 % 0.011 73.639 );
--primary : oklch ( 0.58 0.15 35 );
--secondary : oklch ( 0.52 0.08 120 );
/* ... more colors */
}
Color System
The theme uses a semantic color system based on OKLCH color space for perceptual uniformity:
Main background color for the page
Primary brand color used for important UI elements
Secondary accent color for highlights and links
Muted background color for subtle elements
Accent color for emphasis
Border color for dividers and outlines
Background color for cards and elevated surfaces
Customizing Colors
To customize your theme colors, edit the CSS variables in 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:
Slide Animations
Fade Animations
Scale Animations
@keyframes slide-in-bottom {
from {
opacity : 0 ;
transform : translateY ( 30 px );
}
to {
opacity : 1 ;
transform : translateY ( 0 );
}
}
/* Usage */
.animate-slide-in-bottom {
animation : slide-in-bottom 0.6 s 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:
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
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
Use CSS Variables
Always use CSS variables for colors to maintain theme consistency
Test All Themes
Test your customizations in all three themes (light, dark, retro)
Maintain Accessibility
Ensure sufficient color contrast ratios for text readability
Use Semantic Colors
Use semantic color names (primary, secondary) instead of specific colors (blue, red)