In 2025, we still design mobile-first—but with better tools:
dvh
, svh
, lvh
) fix mobile address-bar jumps.image-set()
for responsive background images.Pick breakpoints where your layout needs them—not by device names.
/* Mobile-first breakpoints */
@media (min-width: 600px) { /* tablet */ }
@media (min-width: 900px) { /* small laptop */ }
@media (min-width: 1200px) { /* desktop */ }
.card { container-type: inline-size; container-name: card; }
@container card (min-width: 28rem) {
.card--media-right { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
}
Tip: Keep your typography and spacing fluid with clamp()
and size components using %
, rem
, vw
, cqw
(container query units), not fixed px
.
width: min(100% - 2rem, 68rem); margin-inline: auto;
img, video { max-width: 100%; height: auto; } /* intrinsic sizing */
:root { --content: 68rem; } /* ~1088px */
.wrapper { width: min(100% - 2rem, var(--content)); margin-inline: auto; }
Use AVIF when possible (best compression), WebP as a widely-supported modern default, JPG for photo fallback, PNG for transparency/UI art (only when SVG isn’t suitable).
<picture>
with srcset
+ sizes
<picture>
<source type="image/avif"
srcset="/img/card-400.avif 400w, /img/card-800.avif 800w, /img/card-1200.avif 1200w">
<source type="image/webp"
srcset="/img/card-400.webp 400w, /img/card-800.webp 800w, /img/card-1200.webp 1200w">
<img src="/img/card-800.jpg" alt="Responsive demo" width="800" height="533"
sizes="(max-width:600px) 92vw, (max-width:1200px) 50vw, 600px"
loading="lazy" decoding="async">
</picture>
width
/height
to avoid CLS.loading="lazy"
for non-critical images; consider fetchpriority="high"
for the LCP/hero image.image-set()
.hero {
min-height: 60vh;
background: center/cover no-repeat image-set(
url("/img/hero-m.webp") 1x, url("/img/hero-m@2x.webp") 2x
);
}
@media (min-width: 48rem) {
.hero { background: center/cover no-repeat image-set(
url("/img/hero-d.webp") 1x, url("/img/hero-d@2x.webp") 2x
);}
}
Use SVG for logos, icons, and diagrams:
fill
/stroke
or inherit currentColor
.<title>
and ARIA; inline when you need stateful styling.Do not use SVG for photographs or complex textured art (raster is better).
<!-- once per page (server/layout include), hidden off-layout -->
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true"
style="position:absolute;width:0;height:0;overflow:hidden">
<symbol id="icon-check" viewBox="0 0 24 24">
<path d="M20.3 5.7a1 1 0 0 1 0 1.4l-10 10a1 1 0 0 1-1.4 0l-5-5a1 1 0 1 1 1.4-1.4L9.3 15l9.3-9.3Z"/>
</symbol>
</svg>
<button class="btn">
<span class="icon" aria-hidden="true">
<svg width="1em" height="1em"><use href="#icon-check"/></svg>
</span>
Save
</button>
Pick the tool that fits your team and UI, then ship only what you use.
// app.scss
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/utilities";
content
paths tight to avoid bloat.// tailwind.config.js
module.exports = { content: ["./**/*.{html,md,js}"], theme:{}, plugins:[] }
Choice | Use when | Pros | Cons |
---|---|---|---|
CDN | Prototypes, internal tools, quick spikes | Zero setup, edge-cached, simple version pinning + SRI | Third-party dependency, privacy/logging, cache partitioning weakens cross-site reuse |
Self-host | Production sites/apps, compliance, perf budgets | Deterministic builds, tree-shaking/purge, full CSP, no third-party outages | CI setup, you own caching/versioning |
Rule of thumb: marketing sites & apps → self-host and purge. Demos and PoCs → CDN with SRI and pinned versions.
<link rel="stylesheet"
href="https://cdn.example.com/bootstrap/5.3.3/css/bootstrap.min.css"
integrity="sha384-…"
crossorigin="anonymous">
prefers-reduced-motion
./assets/css/responsive-starter.css
with fluid type/spacing, helpers, and container queries._includes/svg-sprite.html
with icons (<use href="#icon-…">
).index.md
shows <picture>
/srcset
and background image-set()
patterns.Live demo & repo:
Starter → https://michalferber.me/responsive-starter-repo/
GitHub → https://github.com/MichalAFerber/responsive-starter-repo
Don’t chase devices. Build fluid components, test across ranges, and ship only what users need on the network they have. That’s responsive design in 2025.