DEV Community

Artclick
Artclick

Posted on

10 CSS Tips and Tricks for Better Responsive Web Design

Modern CSS gives you tools that make most of your old media queries unnecessary. Here are ten practical techniques worth adding to your toolkit in 2026.

Responsive design used to mean picking a handful of breakpoints, 768px, 1024px, maybe 1440px, and writing a media query for each one. That approach still works, but it's not really how modern CSS wants you to think anymore. A lot of the layout and typography work that used to require careful breakpoint math can now just... respond on its own, because the properties themselves understand context: viewport size, container size, even the user's own OS-level preferences.

Here are ten techniques I'd consider close to essential for anyone building responsive interfaces today. Some of these will be familiar, some are newer than you'd expect.

1. Fluid Typography

Fixed font sizes don't hold up well across different screen sizes. Something that reads comfortably on a laptop can feel oversized on a phone, or too small on an ultrawide monitor. Fluid typography lets text scale with the viewport instead of jumping between fixed values at each breakpoint.

rem is relative to the root font size:

h1 {
  font-size: 2rem;
}
Enter fullscreen mode Exit fullscreen mode

If the root size is 16px, that 2rem works out to 32px, consistent, but static. It doesn't know or care how wide the screen is.

vw is relative to the viewport width instead:

h1 {
  font-size: 5vw;
}
Enter fullscreen mode Exit fullscreen mode

This scales smoothly as the browser resizes, but on its own it's risky. On a small phone, 5vw might shrink your heading down to something barely legible. On a huge monitor, the same rule can blow it up to a size that looks absurd.

clamp() is the fix, and it's the one you actually want to reach for in production. It takes a minimum, a flexible preferred value, and a maximum:

h1 {
  font-size: clamp(1.5rem, 4vw, 3rem);
}
Enter fullscreen mode Exit fullscreen mode

Now the heading grows smoothly with the viewport, but it will never shrink below 1.5rem or grow past 3rem. One line replaces what used to take three or four separate media query overrides.

2. Fluid Spacing, Not Just Fluid Type

Once you've got clamp() in your toolkit, don't stop at font sizes. Padding, margins, and gaps benefit from the exact same treatment, and it's an easy thing to overlook since most tutorials only demonstrate clamp() on headlines.

.card {
  padding: clamp(1rem, 3vw, 2.5rem);
}

.section {
  margin-block: clamp(2rem, 6vw, 6rem);
}
Enter fullscreen mode Exit fullscreen mode

Without this, it's common to see a layout where the text scales beautifully but the whitespace around it stays exactly the same at every screen size, which ends up looking cramped on large screens and oddly spacious on small ones. Scaling your spacing alongside your type keeps the overall proportions of a layout feeling consistent, not just the words on the page.

3. Intrinsic Grids That Don't Need Breakpoints At All

A huge chunk of "responsive design" work used to be writing media queries just to change how many columns a card grid has. CSS Grid's auto-fit and minmax() combination removes that need almost entirely:

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.5rem;
}
Enter fullscreen mode Exit fullscreen mode

Read that as: fit as many columns as will comfortably hold at least 240px each, and let them share the remaining space evenly. Resize the browser and the grid reflows on its own, four columns, then three, then two, then one, without a single @media block. This is usually called intrinsic or content-aware layout, and once you've built a grid this way, going back to hardcoded breakpoint columns feels like doing more work for a worse result.

4. Container Queries

Media queries respond to the viewport. But a component doesn't always know how much space it actually has, a card might be full-width in one layout and squeezed into a narrow sidebar in another, and a viewport-based media query has no way to tell the difference.

Container queries fix this by letting an element respond to the size of its actual container, not the screen:

.card-wrapper {
  container-type: inline-size;
}

.card {
  display: flex;
  flex-direction: column;
}

@container (min-width: 400px) {
  .card {
    flex-direction: row;
  }
}
Enter fullscreen mode Exit fullscreen mode

Here, the card stacks vertically by default and switches to a horizontal layout once its container, not the viewport, is at least 400px wide. Drop that same card into a wide main content area or a narrow sidebar on the exact same page, and it adapts correctly in both places. This is the piece that finally makes truly reusable, drop-anywhere components possible, which viewport media queries were never really able to deliver.

5. The aspect-ratio Property

Responsive images and video embeds used to rely on a padding-percentage hack, wrapping the media in a container with padding-top set to some calculated percentage just to reserve the right amount of space before the media loaded. It worked, but nobody found it intuitive, and it's not something you'd guess how to write from scratch.

.video-embed {
  aspect-ratio: 16 / 9;
  width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

That's the whole thing now. The browser reserves the correct proportional space immediately, which also means no layout shift while an image or iframe is still loading, a detail that matters for Core Web Vitals as much as it does for how polished a page feels while it's rendering.

6. min() and max() for Flexible Constraints

clamp() gets most of the attention, but its two simpler siblings are worth knowing on their own. min() picks the smallest of the values you give it, max() picks the largest.

A common pattern: let content take up most of the width on small screens, but stop it from stretching too wide on large ones.

.container {
  width: min(90%, 1200px);
}
Enter fullscreen mode Exit fullscreen mode

On a phone, 90% is the smaller value, so the container hugs the screen with a bit of breathing room on either side. On a wide desktop monitor, 1200px becomes the smaller value, so the container caps out there instead of stretching edge to edge. One line, no media query, and it reads almost like plain English once you're used to it.

7. Dynamic Viewport Units: dvh, svh, lvh

If you've ever set height: 100vh on a mobile site and watched content get cut off behind the browser's address bar, this one's for you. The classic vh unit is based on the largest possible viewport, ignoring the fact that mobile browser chrome, the address bar, the bottom toolbar, expands and collapses as someone scrolls, changing how much space is actually visible.

Newer units account for this directly:

.hero {
  min-height: 100dvh;
}
Enter fullscreen mode Exit fullscreen mode

dvh stands for dynamic viewport height, and it adjusts live as the browser's UI shows or hides. There's also svh (small viewport height, calculated assuming the browser UI is fully expanded) and lvh (large viewport height, assuming it's fully collapsed), for cases where you specifically want one behavior or the other instead of the dynamically adjusting version. For most full-height hero sections and mobile layouts, dvh is the one you want, and switching to it fixes a genuinely common and annoying mobile bug in one word.

8. Logical Properties Instead of Physical Ones

This one's less about screen size and more about a different axis of "responsive", to writing direction and layout context, but it belongs on this list because it prevents a specific category of layout bug that only shows up once you're supporting more than one language or more than one layout direction.

Instead of physical directions like margin-left or padding-right, logical properties describe position relative to the flow of the content:

.card {
  margin-inline-start: 1rem;
  padding-block: 1.5rem;
}
Enter fullscreen mode Exit fullscreen mode

margin-inline-start means "the start edge in the inline direction", which is the left in English, but automatically becomes the right in Arabic or Hebrew, without you writing a single RTL-specific override. padding-block covers top and bottom together as one shorthand. If there's any chance your site ever ships in a right-to-left language, or you just want spacing rules that are correct by construction rather than by accident, this is worth adopting as your default habit rather than something you retrofit later.

9. Responsive Images With srcset and sizes

CSS handles how big an image displays, but it can't reduce how many bytes get downloaded in the first place. That's what srcset and sizes are for, letting the browser choose the most appropriately sized image file for the current viewport, instead of shipping one large image to every device regardless of screen size:

<img
  src="hero-800.jpg"
  srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1600.jpg 1600w"
  sizes="(max-width: 600px) 100vw, 50vw"
  alt="A wide shot of the product lineup"
/>
Enter fullscreen mode Exit fullscreen mode

srcset lists the available image files along with their actual widths. sizes tells the browser how much space the image will occupy at different viewport widths, and the browser combines that with the device's pixel density to pick the smallest file that will still look sharp. A phone downloads the 400w version instead of the same 1600w file a desktop gets, which is a meaningful difference in load time on a mobile connection, and it's handled declaratively, no JavaScript resizing or lazy-loading library required for this part.

10. Respecting User Preferences, Not Just Screen Size

Responsive design started out being entirely about screen dimensions, but modern CSS can respond to the person on the other end too, not just their device. Two media features are worth building in as defaults rather than afterthoughts.

prefers-color-scheme lets you offer a dark theme automatically, based on the operating system setting the user already chose, rather than making them find a toggle on your site:

:root {
  color-scheme: light dark;
}

body {
  background: #ffffff;
  color: #111827;
}

@media (prefers-color-scheme: dark) {
  body {
    background: #0f172a;
    color: #e5e7eb;
  }
}
Enter fullscreen mode Exit fullscreen mode

prefers-reduced-motion respects a genuinely important accessibility setting for people with vestibular disorders who can get real physical discomfort from large animated motion:

.hero-animation {
  animation: slide-in 0.6s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .hero-animation {
    animation: none;
  }
}
Enter fullscreen mode Exit fullscreen mode

Neither of these has anything to do with screen width, but both are about the same underlying idea every technique on this list shares: a layout that adapts to the actual conditions it's being viewed under, rather than assuming one fixed context for every visitor.

Putting it together

None of these ten replace each other, and in a real project they mostly stack. A card grid might use auto-fit/minmax() for its columns, clamp() for its internal padding, aspect-ratio on its thumbnail images, and a container query to switch its internal layout once it's dropped into a narrower sidebar, all at the same time, on the same component. That's really the shift modern CSS represents: less time spent enumerating every breakpoint by hand, more time spent describing the actual relationship you want, and letting the browser handle the arithmetic.


We're ArtClick, a web development agency based in Kyoto. We build company websites, WordPress sites, and custom systems — with a focus on sites that are fast, well-designed, and easy to maintain long-term. Learn more at artclickdev.

Follow us for more CSS tutorials, web dev tips, and resources.

Top comments (0)