Overview
The portfolio uses CSS Modules for component-scoped styling and CSS custom properties (CSS variables) for theme management. This approach provides both flexibility and maintainability.
CSS Modules Architecture
Each component has its own .module.css file that is imported and scoped to that component:
import styles from './Hero.module.css' ;
export default function Hero () {
return (
< section className = { styles . hero } >
< h1 className = { styles . headline } > BUILDING ROBUST SYSTEMS </ h1 >
</ section >
);
}
CSS Modules automatically scope class names to components, preventing style conflicts. The class .hero in Hero.module.css won’t clash with .hero in other files.
Color Theme System
All colors are defined as CSS custom properties in src/index.css:
:root {
/* Dark Amethyst palette */
--dark-amethyst : #23003a ;
--dark-amethyst-2 : #270040 ;
--dark-amethyst-3 : #340452 ;
--dark-amethyst-4 : #3d0c5c ;
--indigo : #451365 ;
--dark-amethyst-5 : #4c1c62 ;
--dark-amethyst-6 : #41005b ;
--neon-violet : #bf40ff ;
/* Semantic aliases */
--color-primary : var ( --indigo );
--color-bg-dark : #0D0D0D ;
--color-bg-mid : var ( --dark-amethyst-2 );
--color-black-cherry : var ( --dark-amethyst );
--color-accent : var ( --dark-amethyst-5 );
--color-neon : var ( --neon-violet );
}
Customizing Your Color Theme
Open index.css
Navigate to src/index.css in your source directory.
Modify Color Variables
Change the hex values in the :root selector. For example, to switch to a blue theme: :root {
--color-primary : #0066ff ;
--color-neon : #00ccff ;
--color-bg-mid : #001a33 ;
--color-black-cherry : #000d1a ;
}
Test Your Changes
Run npm run dev and check that colors update across all components.
Keep sufficient contrast between text and background colors to maintain accessibility. Aim for at least a 4.5:1 contrast ratio for body text.
Shadow System
The portfolio uses a neomorphic shadow system for depth:
:root {
--shadow-neo : 4 px 4 px 0 px 0 px var ( --color-primary );
--shadow-neo-sm : 2 px 2 px 0 px 0 px var ( --color-primary );
--shadow-neo-white : 4 px 4 px 0 px 0 px #ffffff ;
--shadow-neo-green : 6 px 6 px 0 px 0 px var ( --neon-violet );
--shadow-neo-black : 6 px 6 px 0 px 0 px var ( --dark-amethyst );
--shadow-neo-purple : 6 px 6 px 0 px 0 px var ( --neon-violet );
}
Example usage in component:
.descBox {
border : 2 px solid var ( --color-primary );
box-shadow : var ( --shadow-neo );
}
.imageCard {
box-shadow : var ( --shadow-neo-green );
}
Glassmorphism Effects
The portfolio uses overlay layers to create glassmorphic and cyberpunk effects on the hero image:
.gridOverlay {
position : absolute ;
inset : 0 ;
z-index : 10 ;
background-image : url ( "data:image/svg+xml;base64,..." );
opacity : 0.2 ;
pointer-events : none ;
}
.colorOverlay {
position : absolute ;
inset : 0 ;
z-index : 10 ;
background-color : rgba ( 173 , 40 , 49 , 0.35 );
mix-blend-mode : color ;
pointer-events : none ;
}
.scanlines {
position : absolute ;
inset : 0 ;
z-index : 10 ;
background-image : linear-gradient (
transparent 50 % ,
rgba ( 0 , 0 , 0 , 0.5 ) 50 %
);
background-size : 100 % 4 px ;
opacity : 0.2 ;
pointer-events : none ;
}
Customizing Glassmorphism
To adjust the glassmorphism effect intensity:
Stronger Effect
Subtle Effect
.colorOverlay {
background-color : rgba ( 173 , 40 , 49 , 0.6 ); /* Increase alpha */
opacity : 0.8 ;
}
.scanlines {
opacity : 0.4 ; /* More visible scanlines */
}
Animations & Transitions
Buttons use a “push down” animation on hover:
.btnPrimary {
background-color : var ( --color-primary );
border : 2 px solid var ( --color-primary );
box-shadow : var ( --shadow-neo-white );
transition : all 0.15 s ;
}
.btnPrimary:hover {
box-shadow : none ;
transform : translate ( 4 px , 4 px );
}
Marquee Animation
The skills marquee uses infinite scroll:
@keyframes marquee {
0% {
transform : translateX ( 0 );
}
100% {
transform : translateX ( -50 % );
}
}
.animate-marquee {
animation : marquee 20 s linear infinite ;
}
Adjust animation speed by changing the duration:
/* Faster */
.animate-marquee {
animation : marquee 10 s linear infinite ;
}
/* Slower */
.animate-marquee {
animation : marquee 30 s linear infinite ;
}
Image Card Hover
The hero image card has a lift effect:
.imageCard {
box-shadow : var ( --shadow-neo-green );
transition : transform 0.3 s , box-shadow 0.3 s ;
}
.imageCard:hover {
transform : translate ( -4 px , -4 px );
box-shadow : 8 px 8 px 0 px 0 px var ( --color-neon );
}
Font Customization
The portfolio uses Space Grotesk from Google Fonts, loaded in index.html:
< link rel = "preconnect" href = "https://fonts.googleapis.com" >
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin >
< link rel = "stylesheet"
href = "https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap" >
Set globally in index.css:
:root {
--font-display : 'Space Grotesk' , sans-serif ;
}
body {
font-family : var ( --font-display );
}
Changing the Font
Update index.html
Replace the Google Fonts link: < link rel = "stylesheet"
href = "https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" >
Update CSS Variable
Change the font family in src/index.css: :root {
--font-display : 'Inter' , sans-serif ;
}
Background Patterns
Utility classes for grid patterns:
.bg-grid-pattern {
background-image :
linear-gradient ( to right , rgba ( 69 , 19 , 101 , 0.35 ) 1 px , transparent 1 px ),
linear-gradient ( to bottom , rgba ( 69 , 19 , 101 , 0.35 ) 1 px , transparent 1 px );
background-size : 40 px 40 px ;
}
.tech-overlay {
background-image :
linear-gradient ( rgba ( 173 , 40 , 49 , 0.15 ) 1 px , transparent 1 px ),
linear-gradient ( 90 deg , rgba ( 173 , 40 , 49 , 0.15 ) 1 px , transparent 1 px );
background-size : 20 px 20 px ;
}
Customize grid density by adjusting background-size:
/* Denser grid */
.bg-grid-pattern {
background-size : 20 px 20 px ;
}
/* Wider grid */
.bg-grid-pattern {
background-size : 60 px 60 px ;
}
Responsive Design
The portfolio uses CSS custom properties with media queries:
.headline {
font-size : clamp ( 3.5 rem , 10 vw , 7 rem );
line-height : 0.9 ;
}
@media ( min-width : 1024 px ) {
.inner {
flex-direction : row ;
gap : 4 rem ;
}
}
The clamp() function creates fluid typography that scales smoothly between a minimum and maximum size.
Next Steps
Content Customization Update text, links, and personal information
Projects Data Add and manage your portfolio projects