Skip to main content

Overview

The portfolio uses CSS animations to create engaging, smooth interactions without any JavaScript. Animations are applied to:
  • Navigation links - Hover underline effect
  • Skills icons - Fade-in on page load
  • Icon hover states - Scale and brightness effects
  • Focus states - Accessibility indicators
All animations use CSS keyframes and transitions, ensuring smooth 60fps performance.
When hovering over navigation links, a blue underline animates in from left to right.

The Effect

styles.css:96-104
.nav-link:hover::after {
    content: '';
    width: 100%;
    height: 3px;
    background-color: #003ba8;
    display: block;
    animation-name: ampliar-anchura;
    animation-duration: 0.5s;
}

The Keyframes

styles.css:106-114
@keyframes ampliar-anchura {
    from {
        width: 0%;
    }

    to {
        width: 100%;
    }
}
  1. A ::after pseudo-element is created on hover
  2. It starts at width: 0%
  3. Animates to width: 100% over 0.5 seconds
  4. Creates a 3px tall blue bar
  5. When hover ends, the element disappears (no reverse animation)
The animation name “ampliar-anchura” means “expand width” in Spanish.

Skills Icons Fade Animation

The technology icons in the Habilidades section fade in and slide up when the page loads.

Icon Styling

styles.css:192-203
.img {
    width: 50px;
    height: 50px;
    transition: 0.3s ease-out;
    box-sizing: content-box;
    animation: fadeSlide 0.8s both;
    scale: 1;
}
The animation-fill-mode: both (the “both” keyword) keeps the initial opacity: 0 until animation starts and maintains the final state after completion.

FadeSlide Keyframes

styles.css:213-223
@keyframes fadeSlide {
    from {
        opacity: 0;
        transform: translateY(20px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}
Animation breakdown:
  • Initial state: Icons are invisible (opacity: 0) and 20px below their final position
  • Duration: 0.8 seconds
  • End state: Icons are fully visible (opacity: 1) at their natural position
  • Effect: Icons smoothly fade in while sliding upward

Staggered Animation Delays

Each icon animates with a different delay, creating a wave effect:
styles.css:225-251
.img:nth-child(1) { animation-delay: 0.2s; }  /* HTML */
.img:nth-child(2) { animation-delay: 0.3s; }  /* CSS */
.img:nth-child(3) { animation-delay: 0.4s; }  /* JavaScript */
.img:nth-child(4) { animation-delay: 0.5s; }  /* Tailwind */
.img:nth-child(5) { animation-delay: 0.4s; }  /* SQL Server */
.img:nth-child(6) { animation-delay: 0.3s; }  /* MongoDB */
.img:nth-child(7) { animation-delay: 0.2s; }  /* MySQL */
The delays create a center-out wave pattern:
0.2s → 0.3s → 0.4s → 0.5s → 0.4s → 0.3s → 0.2s
HTML   CSS    JS     TW     SQL    Mongo  MySQL

  ░     ░░    ░░░    ████   ░░░    ░░     ░
       ⬅ Earlier          Later ➡
The middle icon (Tailwind) animates last, creating symmetry.
If you add or remove skill icons, update both the desktop (lines 225-251) and mobile (lines 254-280) animation delays.

Icon Hover Effects

When hovering over skill icons, they scale up and brighten:
styles.css:205-211
.img:hover {
    scale: 1.15;
    filter: brightness(1.5) contrast(1.1);
}
Effects breakdown:
  • scale: 1.15 - Icon grows to 115% size (57.5px × 57.5px)
  • brightness(1.5) - Colors become 50% brighter
  • contrast(1.1) - Slightly increased contrast makes colors pop
The scale property is a shorthand for transform: scale(1.15) and has better performance.

Transition Timing

styles.css:195
transition: 0.3s ease-out;
The hover effect transitions over 0.3 seconds with an ease-out timing function (fast start, slow end).
┌────────┐
│        │
│  [🔷]  │  50×50px, normal brightness
│        │
└────────┘

Focus States (Accessibility)

Keyboard navigation triggers focus styles with a blue outline:
styles.css:88-93
.nav-link a:focus {
    outline: 4px solid #003ba8;
    border-radius: 8px;
    outline-offset: 3px;
    transition-delay: 125ms;
}
Features:
  • 4px solid outline in brand blue (#003ba8)
  • 8px border radius for softer corners
  • 3px offset creates space between text and outline
  • 125ms delay prevents flashing when rapidly tabbing
This ensures the portfolio is fully accessible via keyboard (Tab key navigation).

Profile Image Effect

The profile photo has a glowing drop shadow:
styles.css:141
filter: drop-shadow(1px 1px 30px #0094a8);
Parameters:
  • 1px horizontal offset
  • 1px vertical offset
  • 30px blur radius (creates glow effect)
  • #0094a8 light blue color
Unlike box-shadow, drop-shadow follows the alpha channel of PNG images, creating a true glow around the subject rather than a rectangular shadow.

Performance Considerations

GPU-Accelerated Properties

These animations use GPU-accelerated properties for smooth performance: Animating (fast):
  • transform (translateY, scale)
  • opacity
  • filter
Avoid animating (slow):
  • width, height
  • margin, padding
  • top, left
The navigation underline animation uses width, which can cause minor performance issues on very low-end devices. Consider using transform: scaleX() instead:
.nav-link::after {
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.5s ease-out;
}

.nav-link:hover::after {
    transform: scaleX(1);
}

Animation Performance Tips

Some users prefer reduced motion. Add this media query:
@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}
For frequently animated elements, hint to the browser:
.img {
    will-change: transform, filter;
}
But don’t overuse it - only for elements that animate often.

Customization Examples

Slower Fade Animation

.img {
    animation: fadeSlide 1.5s both;  /* Was 0.8s */
}

Different Hover Scale

.img:hover {
    scale: 1.3;  /* Bigger growth */
}

Reverse Navigation Animation

Make the underline animate out when hover ends:
.nav-link::after {
    content: '';
    width: 0;
    height: 3px;
    background-color: #003ba8;
    display: block;
    transition: width 0.3s ease-out;
}

.nav-link:hover::after {
    width: 100%;
}

Add Bounce Effect

@keyframes fadeSlide {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    
    60% {
        transform: translateY(-5px);  /* Slight bounce */
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

Next Steps

Responsive Design

Learn how animations adapt to mobile

CSS Architecture

Understand the overall CSS structure

Navigation

Explore the navigation HTML and CSS

Customization

Customize animation colors and timing