Make It Feel Alive
Hover states tell users “this is interactive.” A button that changes on hover invites clicking. A card that lifts suggests it leads somewhere. These micro-interactions make applications feel responsive and professional.
What You’ll Learn
- Create effective hover states
- Use transitions for smooth effects
- Apply transforms for visual depth
- Handle focus states for accessibility
The Basics of Hover
The :hover pseudo-class applies styles when the cursor is over an element:
.card {
background: white;
border: 1px solid #e5e7eb;
}
.card:hover {
border-color: #3b82f6;
} But abrupt changes feel jarring. Add transitions:
.card {
background: white;
border: 1px solid #e5e7eb;
transition: border-color 0.2s ease;
}
.card:hover {
border-color: #3b82f6;
} Now the border color smoothly shifts over 0.2 seconds.
Transition Properties
Control what animates and how:
/* Specific property */
transition: background-color 0.2s ease;
/* Multiple properties */
transition: background-color 0.2s ease, transform 0.2s ease;
/* All properties (use carefully) */
transition: all 0.2s ease;
/* Different timing for different properties */
transition:
background-color 0.15s ease,
transform 0.3s ease-out,
box-shadow 0.2s ease; Common timing functions:
ease— Starts slow, speeds up, slows downease-in— Starts slowease-out— Ends slowease-in-out— Slow start and endlinear— Constant speed
Button Hover States
Make buttons feel clickable:
.btn {
padding: 0.75rem 1.5rem;
background: #3b82f6;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.15s ease, transform 0.1s ease;
}
.btn:hover {
background: #2563eb;
}
.btn:active {
transform: scale(0.98);
} The :active state gives feedback during the click — a subtle scale creates a “press” effect.
Card Hover Effects
Lift cards to suggest clickability:
.service-card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 12px;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease,
transform 0.2s ease;
}
.service-card:hover {
border-color: #3b82f6;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform: translateY(-4px);
} The card lifts (translateY), gains shadow depth, and highlights its border.
Image Hover Effects
Zoom images on hover for visual interest:
.card-image {
overflow: hidden;
border-radius: 8px;
}
.card-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.card:hover .card-image img {
transform: scale(1.05);
} Note: The hover is on the parent .card, but the effect is on the nested img. This creates a more accessible experience.
Link Hover States
Make links clearly interactive:
.nav-link {
color: #4b5563;
text-decoration: none;
padding: 0.5rem 0;
position: relative;
transition: color 0.15s ease;
}
.nav-link:hover {
color: #3b82f6;
}
/* Animated underline */
.nav-link::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: #3b82f6;
transition: width 0.2s ease;
}
.nav-link:hover::after {
width: 100%;
} The underline slides in from the left on hover.
Focus States for Accessibility
Don’t forget keyboard users. Focus states should be visible:
.btn:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.4);
}
/* Modern approach: visible only for keyboard */
.btn:focus-visible {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.4);
} :focus-visible only shows for keyboard navigation, not mouse clicks. This keeps the UI clean while maintaining accessibility.
Apply to BookIt Components
ServiceCard Hover
<!-- filename: src/lib/components/ServiceCard.svelte -->
<style>
.card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 12px;
overflow: hidden;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease,
transform 0.2s ease;
}
.card:hover {
border-color: #3b82f6;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
.card-image img {
transition: transform 0.3s ease;
}
.card:hover .card-image img {
transform: scale(1.05);
}
.card-title a {
color: #1f2937;
text-decoration: none;
transition: color 0.15s ease;
}
.card-title a:hover {
color: #3b82f6;
}
</style> Navigation Hover
<!-- filename: src/lib/components/Header.svelte -->
<style>
nav a {
color: #4b5563;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 6px;
transition: background-color 0.15s ease, color 0.15s ease;
}
nav a:hover {
background: #f3f4f6;
color: #1f2937;
}
nav a.active {
background: #eff6ff;
color: #3b82f6;
}
</style> Price Badge Hover
<!-- filename: src/lib/components/PriceBadge.svelte -->
<style>
.price {
display: inline-block;
padding: 0.25rem 0.5rem;
background: #eff6ff;
color: #3b82f6;
border-radius: 4px;
font-weight: 600;
transition: background-color 0.15s ease;
}
.price:hover {
background: #dbeafe;
}
</style> Hover State Guidelines
Do:
- Use subtle effects (don’t go overboard)
- Keep transitions short (0.15s - 0.3s)
- Match hover to the element’s purpose
- Include focus states for accessibility
Don’t:
- Make hover effects too dramatic
- Forget to transition (abrupt changes feel broken)
- Use hover for essential information (touch devices can’t hover)
- Remove focus outlines without alternatives
Touch Device Considerations
Hover doesn’t exist on touch devices. Don’t rely on it for critical interactions:
/* This info is only visible on hover — bad! */
.card .details {
opacity: 0;
}
.card:hover .details {
opacity: 1;
} Better: Show the info by default, or use a tap/click to reveal.
For effects that are purely decorative, hover is fine — they just won’t appear on touch devices.
Common Mistakes
Too Much Movement
/* ❌ Too dramatic */
.card:hover {
transform: scale(1.2) rotate(5deg);
box-shadow: 0 20px 50px rgba(0,0,0,0.5);
}
/* ✅ Subtle and professional */
.card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(0,0,0,0.1);
} Missing Transitions
/* ❌ Abrupt change */
.btn:hover {
background: #2563eb;
}
/* ✅ Smooth transition */
.btn {
transition: background-color 0.15s ease;
}
.btn:hover {
background: #2563eb;
} Forgetting Keyboard Users
/* ❌ Only hover, no focus */
.btn:hover {
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.4);
}
/* ✅ Both hover and focus */
.btn:hover,
.btn:focus-visible {
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.4);
} Summary
Hover states make interfaces feel responsive. Use transitions for smooth effects, keep movements subtle, and always include focus states for accessibility. The goal is feedback, not distraction.
Key takeaways:
- Add
transitionbefore:hoverstyles - Keep effects subtle (0.15s-0.3s, small transforms)
- Include
:focus-visiblefor keyboard users - Don’t hide essential info behind hover
Next Steps
Component styles are scoped, but some styles need to be global. Continue with Global Styles to set up typography, colors, and base styles for all of BookIt.