Published 12/2/2025 · 6 min read
Tags: svg
Lesson 22: Responsive SVG
SVGs are inherently scalable — that’s the “S” in SVG. But making them responsive — adapting intelligently to different containers and screen sizes — requires understanding a few key concepts.
The viewBox is Everything
We covered viewBox in Lesson 3, but it’s crucial for responsive SVGs:
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="#3b82f6" />
</svg>
The viewBox defines a coordinate system. The SVG will scale to fit its container while maintaining those internal coordinates.
Without viewBox: The SVG has fixed dimensions. With viewBox: The SVG scales fluidly.
Removing Fixed Dimensions
For a fully responsive SVG, remove width and height:
<svg viewBox="0 0 200 100">
<!-- content scales to container -->
</svg>
Then control size with CSS:
svg {
width: 100%;
height: auto;
}
The SVG now fills its container width and calculates height from the viewBox aspect ratio (2:1 in this case).
preserveAspectRatio
This attribute controls how the viewBox fits into the SVG’s actual dimensions:
<svg viewBox="0 0 100 50" preserveAspectRatio="xMidYMid meet">
Alignment Values
The first part (xMidYMid) sets alignment:
| Value | X Alignment | Y Alignment |
|---|---|---|
xMinYMin | Left | Top |
xMidYMin | Center | Top |
xMaxYMin | Right | Top |
xMinYMid | Left | Middle |
xMidYMid | Center | Middle |
xMaxYMid | Right | Middle |
xMinYMax | Left | Bottom |
xMidYMax | Center | Bottom |
xMaxYMax | Right | Bottom |
Meet vs Slice
The second part controls scaling:
meet (default) — Scale to fit entirely within the viewport (like background-size: contain)
<svg viewBox="0 0 100 50" preserveAspectRatio="xMidYMid meet">
slice — Scale to cover the viewport, cropping if needed (like background-size: cover)
<svg viewBox="0 0 100 50" preserveAspectRatio="xMidYMid slice">
none
Stretch to fill, ignoring aspect ratio:
<svg viewBox="0 0 100 50" preserveAspectRatio="none">
Use sparingly — this distorts the graphic.
Common Responsive Patterns
Full-Width Banner
<svg viewBox="0 0 1200 300" preserveAspectRatio="xMidYMid slice">
<!-- hero graphic that fills width and crops height -->
</svg>
.banner svg {
width: 100%;
height: 200px;
}
Centered Icon
<svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
<!-- icon stays centered and contained -->
</svg>
Fluid Illustration
<div class="illustration-container">
<svg viewBox="0 0 800 600">
<!-- illustration scales proportionally -->
</svg>
</div>
.illustration-container {
max-width: 800px;
width: 100%;
}
.illustration-container svg {
width: 100%;
height: auto;
}
CSS Sizing Techniques
Percentage Width
svg {
width: 50%;
height: auto;
}
Fixed Height, Fluid Width
svg {
width: 100%;
height: 60px;
}
Combine with preserveAspectRatio to control cropping/fitting.
Viewport Units
svg {
width: 50vw;
height: 50vh;
}
Container Queries (Modern CSS)
@container (min-width: 600px) {
svg {
width: 400px;
}
}
Inline SVG vs img Tag
Inline SVG
<div class="hero">
<svg viewBox="0 0 800 400">...</svg>
</div>
.hero svg {
width: 100%;
height: auto;
}
✅ Full CSS control ✅ Can be styled/animated ✅ Responsive by default with viewBox
img Tag
<img src="graphic.svg" alt="Description" class="responsive-svg" />
.responsive-svg {
width: 100%;
height: auto;
max-width: 600px;
}
✅ Cached separately ✅ Simpler HTML ❌ Limited CSS access
CSS Background
.hero {
background-image: url("graphic.svg");
background-size: cover;
background-position: center;
}
✅ Easy positioning ❌ No DOM access ❌ Less accessible
Responsive Breakpoint Strategies
Swap SVGs at Breakpoints
<picture>
<source media="(min-width: 768px)" srcset="graphic-large.svg" />
<img src="graphic-small.svg" alt="Description" />
</picture>
Hide/Show Elements Within SVG
<svg viewBox="0 0 400 200">
<g class="mobile-only">
<!-- simplified version -->
</g>
<g class="desktop-only">
<!-- detailed version -->
</g>
</svg>
.desktop-only {
display: none;
}
@media (min-width: 768px) {
.mobile-only {
display: none;
}
.desktop-only {
display: block;
}
}
Adjust Content Based on Size
<svg viewBox="0 0 100 100">
<text class="label-full">Dashboard</text>
<text class="label-short">Dash</text>
</svg>
.label-short {
display: none;
}
@media (max-width: 480px) {
.label-full {
display: none;
}
.label-short {
display: block;
}
}
Aspect Ratio Control
CSS aspect-ratio Property
.svg-container {
width: 100%;
aspect-ratio: 16 / 9;
}
.svg-container svg {
width: 100%;
height: 100%;
}
Padding Hack (Legacy)
For older browser support:
.svg-container {
position: relative;
width: 100%;
padding-bottom: 56.25%; /* 16:9 ratio */
height: 0;
}
.svg-container svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Practical Example: Responsive Logo
<svg viewBox="0 0 200 60" class="logo" aria-label="Company Name">
<!-- Icon part -->
<g class="logo-icon">
<circle cx="30" cy="30" r="25" fill="#3b82f6" />
</g>
<!-- Text part - hidden on mobile -->
<g class="logo-text">
<text x="70" y="38" font-size="24" font-weight="bold" fill="#1e293b">
Company
</text>
</g>
</svg>
.logo {
height: 40px;
width: auto;
}
@media (max-width: 480px) {
.logo {
height: 32px;
}
.logo-text {
display: none;
}
}
On mobile, only the icon shows. On larger screens, the full logo appears.
Exercises
Exercise 22.1: Fluid Hero
Create an SVG that spans the full width of the page and maintains a 3:1 aspect ratio.
Exercise 22.2: preserveAspectRatio Test
Create a simple SVG and test all combinations of xMinYMin, xMidYMid, xMaxYMax with meet and slice.
Exercise 22.3: Responsive Icon Set
Create a navigation bar with SVG icons that scale proportionally as the viewport changes.
Exercise 22.4: Breakpoint Swap
Create an SVG with detail elements that hide on smaller screens using CSS media queries.
Key Takeaways
- Always include
viewBoxfor responsive SVGs - Remove fixed
width/heightand control size with CSS preserveAspectRatiocontrols how content fits:meet(contain),slice(cover),none(stretch)- Use CSS media queries to show/hide SVG elements at breakpoints
- Inline SVGs offer the most control;
<img>tags are simpler - Modern CSS
aspect-ratiosimplifies container sizing