Step 9: Improve Visual Design
Time: ~10 minutes | Type: Styling | Concepts: Spacing, hover states, shadows, mobile responsiveness
What We're Building
Visual polish to make your app look professional:
- Consistent spacing scale (4/8/16/24px)
- Hover states on interactive elements
- Focus states for keyboard navigation
- Subtle shadows for depth
- Basic mobile responsiveness
The Prompt for AI
💡 Ask AI to help you improve visual design:
I want to improve the visual design of my todo app. Current issues: - Inconsistent spacing between elements - No hover states on buttons - No focus indicators - Flat design (no depth) - Doesn't work well on mobile I need CSS improvements for: 1. Consistent spacing scale (4px increments) 2. Hover states (buttons, links, cards) 3. Focus states for accessibility 4. Subtle shadows on cards/buttons 5. Mobile responsive layout (smaller screens) 6. Better typography (font sizes, line height) Can you provide CSS updates to make the app look more polished? Don't change HTML structure, just improve CSS.
Wait for AI's response, then apply the CSS updates.
Part 1: Create Spacing Scale
Add CSS variables for consistent spacing:
/* src/index.css or src/App.css */
/* Spacing Scale */
:root {
--spacing-1: 4px;
--spacing-2: 8px;
--spacing-3: 12px;
--spacing-4: 16px;
--spacing-5: 20px;
--spacing-6: 24px;
--spacing-8: 32px;
--spacing-10: 40px;
--spacing-12: 48px;
/* Colors */
--color-primary: #3b82f6;
--color-primary-hover: #2563eb;
--color-danger: #ef4444;
--color-danger-hover: #dc2626;
--color-success: #10b981;
--color-border: #e5e7eb;
--color-text: #1f2937;
--color-text-light: #6b7280;
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
}Use spacing in your layouts:
/* Container spacing */
.container {
padding: var(--spacing-6);
max-width: 800px;
margin: 0 auto;
}
/* Form spacing */
form {
display: flex;
flex-direction: column;
gap: var(--spacing-4);
}
/* List spacing */
.todo-list {
display: flex;
flex-direction: column;
gap: var(--spacing-3);
}Part 2: Add Hover States
Make interactive elements respond to hover:
/* Button Hover States */
button {
padding: var(--spacing-2) var(--spacing-4);
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s ease;
}
button:hover:not(:disabled) {
transform: translateY(-1px);
box-shadow: var(--shadow-md);
}
button:active:not(:disabled) {
transform: translateY(0);
}
button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* Primary Button */
.button-primary {
background: var(--color-primary);
color: white;
}
.button-primary:hover:not(:disabled) {
background: var(--color-primary-hover);
}
/* Danger Button */
.button-danger {
background: var(--color-danger);
color: white;
}
.button-danger:hover:not(:disabled) {
background: var(--color-danger-hover);
}
/* Link Hover */
a {
color: var(--color-primary);
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
color: var(--color-primary-hover);
text-decoration: underline;
}
/* Card Hover */
.todo-card {
padding: var(--spacing-4);
background: white;
border: 1px solid var(--color-border);
border-radius: 8px;
transition: all 0.2s ease;
}
.todo-card:hover {
box-shadow: var(--shadow-md);
border-color: var(--color-primary);
}Part 3: Add Focus States
Ensure keyboard navigation is visible:
/* Focus Styles for Accessibility */
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
a:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* Remove default focus outline, replace with better one */
*:focus {
outline: none;
}
*:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}What this does:
- Removes default browser outline (often ugly)
- Adds visible blue outline when navigating with keyboard
:focus-visibleonly shows when using keyboard (not mouse clicks)
Part 4: Add Shadows for Depth
Add subtle shadows to create visual hierarchy:
/* Card Shadows */
.card {
background: white;
padding: var(--spacing-6);
border-radius: 8px;
box-shadow: var(--shadow-sm);
}
/* Elevated Card (on hover or important) */
.card-elevated {
box-shadow: var(--shadow-lg);
}
/* Input Shadows */
input,
textarea {
padding: var(--spacing-2) var(--spacing-3);
border: 1px solid var(--color-border);
border-radius: 6px;
font-size: 14px;
transition: all 0.2s ease;
}
input:focus,
textarea:focus {
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}Part 5: Mobile Responsiveness
Make the app work on smaller screens:
/* Mobile Responsive Layout */
/* Container adapts to screen size */
.container {
padding: var(--spacing-4);
max-width: 100%;
}
/* Responsive breakpoint for tablets and phones */
@media (max-width: 768px) {
/* Smaller spacing on mobile */
.container {
padding: var(--spacing-3);
}
/* Stack buttons vertically on mobile */
.button-group {
flex-direction: column;
width: 100%;
}
.button-group button {
width: 100%;
}
/* Smaller font sizes on mobile */
h1 {
font-size: 24px;
}
h2 {
font-size: 20px;
}
/* Full-width forms on mobile */
form {
width: 100%;
}
input,
textarea {
width: 100%;
font-size: 16px; /* Prevent zoom on iOS */
}
/* Smaller todo cards */
.todo-card {
padding: var(--spacing-3);
}
/* Toast notifications - smaller on mobile */
.toast {
min-width: auto;
max-width: 90%;
}
}Part 6: Typography Improvements
Better font sizing and spacing:
/* Typography */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
color: var(--color-text);
line-height: 1.6;
}
h1 {
font-size: 32px;
font-weight: 700;
margin: 0 0 var(--spacing-6) 0;
color: var(--color-text);
}
h2 {
font-size: 24px;
font-weight: 600;
margin: 0 0 var(--spacing-4) 0;
color: var(--color-text);
}
h3 {
font-size: 18px;
font-weight: 600;
margin: 0 0 var(--spacing-3) 0;
color: var(--color-text);
}
p {
margin: 0 0 var(--spacing-4) 0;
color: var(--color-text-light);
}Verification
Test visual improvements:
Test 1: Spacing Consistency
- Open your app
- Look at spacing between elements
- Expected:
- [ ] Consistent gaps (not random)
- [ ] Form inputs evenly spaced
- [ ] Cards have consistent padding
- [ ] Page margins look balanced
Test 2: Hover States
Hover over buttons
Expected:
- [ ] Button lifts slightly (translateY)
- [ ] Shadow appears
- [ ] Color darkens
- [ ] Smooth transition (not instant)
Hover over links
Expected:
- [ ] Color changes
- [ ] Underline appears
- [ ] Smooth transition
Hover over todo cards
Expected:
- [ ] Shadow appears
- [ ] Border color changes to blue
- [ ] Smooth transition
Test 3: Focus States (Keyboard Navigation)
- Press Tab to navigate
- Expected:
- [ ] Blue outline appears on focused element
- [ ] Outline visible and clear
- [ ] Can navigate through all interactive elements
- [ ] Current focus always visible
Test 4: Shadows
- Look at cards, buttons, inputs
- Expected:
- [ ] Subtle shadows (not too harsh)
- [ ] Creates sense of depth
- [ ] Shadows darken on hover
- [ ] Looks polished
Test 5: Mobile Responsiveness
- Open browser DevTools (F12)
- Toggle device toolbar (Ctrl+Shift+M)
- Set to "iPhone SE" or similar small screen
- Expected:
- [ ] Content fits screen (no horizontal scroll)
- [ ] Buttons stack vertically
- [ ] Font sizes readable
- [ ] Touch targets large enough (44px minimum)
- [ ] Form inputs full width
- [ ] Spacing appropriate for mobile
Test 6: Typography
- Check all text on the page
- Expected:
- [ ] Headings have clear hierarchy
- [ ] Body text readable (not too small)
- [ ] Line height comfortable (not cramped)
- [ ] Colors have good contrast
Common Issues
Hover States Not Working
Problem: Missing transition or selector wrong.
Fix:
button {
transition: all 0.2s ease; /* Must be on base element */
}
button:hover:not(:disabled) { /* Don't forget :not(:disabled) */
/* hover styles */
}Focus Outline Not Showing
Problem: Using :focus instead of :focus-visible.
Fix:
*:focus-visible { /* Use focus-visible, not just focus */
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}Mobile Layout Broken
Problem: Missing max-width: 100% or viewport meta tag.
Fix:
- Check HTML has viewport meta tag:
<meta name="viewport" content="width=device-width, initial-scale=1.0" />- Make sure elements don't exceed screen:
.container {
max-width: 100%;
padding: var(--spacing-4);
}Shadows Too Harsh
Problem: Shadow opacity too high.
Fix: Lower opacity in shadow definition:
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1); /* 0.1 is subtle */Understanding Check
Before moving on, make sure you understand:
💡 Ask yourself:
- Why use CSS variables for spacing? (Consistency, easy to change)
- What does transition: all 0.2s ease do? (Smooths all property changes)
- Why use :focus-visible instead of :focus? (Only shows for keyboard, not mouse)
- How do media queries make sites responsive? (Apply different CSS at different screen sizes)
- Why use translateY for hover effect? (Creates subtle lift, feels interactive)
What You Learned
At this point you should have:
- ✅ Consistent spacing scale (CSS variables)
- ✅ Hover states on all interactive elements
- ✅ Focus states for keyboard navigation
- ✅ Subtle shadows for depth
- ✅ Mobile responsive layout
- ✅ Better typography
- ✅ Professional visual design
- ✅ Smooth transitions
Next Step
Now let's add basic accessibility improvements for screen readers and keyboard users: