The Problem With Modern Responsive Design
Most responsive design today means one thing: CSS media queries and hope. You write a breakpoint, maybe slap some clamp() on a font size, and call it done. The page looks fine on a 27-inch monitor and passes the Lighthouse audit on desktop. Nobody tests it on a $120 phone on a 3G connection in a basement apartment. That is the gap responsible responsive design tries to close. Responsible Responsive Design by Scott Jehl is not a library you npm install. It is a design philosophy and a set of pragmatic techniques that treat user conditions as first-class citizens instead of afterthoughts. The core idea is straightforward: your site should behave differently depending on what the user actually has, not just what their viewport width happens to be. This covers network speed, device memory, screen pixel density, battery state, and even whether the user has requested reduced data. It pushes back against the assumption that every visitor deserves the same heavy experience. Sometimes the responsible thing is to give them less. Scott Jehl has been talking about this for over a decade, and the Responsible Responsive Design Scott Jehl philosophy shows up in projects like fitvids.js, respond.js, and much of what the modern web performance movement owes to him.
How It Works in Practice
Start measuring what matters. Device memory and connection type are available through the Navigator API. Network Information API gives you effectiveType, downlink, and rtt. Battery Status API exists but is deprecated in most browsers now, so use it sparingly if at all. The real work is in acting on that data before you dump assets into the page. Here is a concrete setup. You detect slow connections early, then swap heavy resources for lighter alternatives. You do not wait for paint. You do not block the main thread to check.
Network-Based Asset Substitution
I built a project last year where we were loading hero images at 2MB each for users on 2G connections in parts of Southeast Asia. The page was rendering, but it was doing it at roughly 1.4 seconds before first contentful paint because the browser was downloading these monsters over a connection that could barely chew through 200KB per second. We added a simple detection block: If navigator.connection.effectiveType is 2g or slow-2g, we swap the hero for a 180KB WebP version. If it is 4g, we serve the full-resolution image. This cut average hero image payload by about 90 percent for the users who needed it most without affecting anyone on decent connections. The code looks like this. Put it in the head, not in a JS bundle loaded after paint.
Get the Full Details

const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (conn && (conn.effectiveType === '2g' || conn.effectiveType === 'slow-2g')) {
document.querySelector('.hero-img').srcset = '/images/hero-small.webp';
} That is it. No frameworks needed. Just run the check and adjust the DOM before the browser starts fetching.
Responsive Images Done Right
srcset and sizes solve half the problem. They make the browser choose between multiple image resolutions based on viewport width and pixel density. But they do not account for network conditions or device memory. If you only use srcset, a high-DPI phone on a terrible connection still requests the 2x image because the browser does not know the network is slow. The fix is either JavaScript-based substitution or using the picture element with media queries that also consider device memory. Device memory is accessible via navigator.deviceMemory, though support is Chrome and Edge only right now. Here is a pattern that works for most cases: <picture>
<source media="(min-width: 800px)" srcset="hero-lg.webp 1x, hero-lg-2x.webp 2x">
<img src="hero-md.webp" alt="...>
</picture>
Then layer JavaScript on top to override the source list for low-memory devices. A phone with 2GB RAM does not benefit from a 2x image at all. The browser will downscale it anyway, and the user wastes bandwidth downloading something they never see.

A Real Edge Case I Hit
I ran into a problem where users on Android with the Data Saver feature enabled were still getting full-resolution images. The Network Information API reports effectiveType as 4g even when Data Saver is on because Data Saver does not change the connection type. It changes how the browser itself handles resources. There is no reliable API signal for Data Saver being active. What I ended up doing was detecting user-agent strings for Samsung Internet and Chrome on Android, then applying a heuristic based on the presence of the save-data request header that the browser sends automatically. If save-data is in the headers, serve lower-res images. This caught roughly 95 percent of the Data Saver cases without needing a server-side UA parser, which is always a mess. The server-side check in Express looks like this: if (req.headers['save-data'] === 'on') {
// serve thumbnail or compressed variant
}
It is not perfect. Some proxies strip the header. But it is the best signal we have right now.
When This Approach Breaks Down
Responsible responsive design does not solve everything. The biggest limitation is that network information APIs are still inconsistent across browsers. Safari does not fully support the Network Information API. Firefox supports effectiveType but hides some details. The Battery Status API is dead. You cannot rely on any single signal. The second limitation is that this adds JavaScript to what should be a purely CSS-driven pipeline in many cases. You are trading a cleaner architecture for better user experience on constrained devices. That trade-off is usually worth it, but do not pretend it is free. If you are building a static site or a mostly CSS-heavy layout, adding JS detection can feel wrong. In that case, consider server-side detection via User-Agent parsing or A/B testing at the CDN level. Cloudflare Workers or Vercel Edge Functions can read headers and serve different image URLs before the request ever hits your origin. This keeps the client free of logic and moves the responsibility to the edge where it belongs for this kind of thing.

Practical Steps to Implement This
First, audit your heaviest resources. Find the top three assets that cause the most pain on slow connections. Usually it is images, video, and JavaScript bundles. Second, add network detection early in the page lifecycle. Third, create fallback versions of those assets at lower resolutions and smaller file sizes. Fourth, wire up the swapping logic. Fifth, test on actual slow connections, not just in DevTools. DevTools network throttling is useful but it does not simulate the same behavior as a real 2G connection on a real device. The browser prefetching and preload behavior changes under real throttling in ways the simulator does not always replicate. For fonts, this is where most people fail. Self-hosted fonts on slow connections are a disaster. Use font-display: swap. Consider serving only the Latin subset if your audience does not need Devanagari or Cyrillic glyphs. A full-weight font file can be 400KB. A subset with just the characters you need can be under 50KB. That is a ten times difference for something the user might never notice visually but will feel immediately in terms of page load time. Video is the other place where responsible design matters most. Most sites embed 10MB videos in an iframe and expect them to play everywhere. They do not. Serve a poster image instead. Load the video only when the user explicitly asks for it or when the connection is fast enough. A simple intersection observer that checks connection type before loading a video element can cut video-related bandwidth by roughly 70 percent on pages where video is present but not always viewed.
What Not to Do
Do not use device memory or connection APIs to show or hide UI elements like navigation menus. That is not what they are for. Those APIs are meant for resource optimization, not for degrading the interface. A user with a slow phone still needs to navigate your site. They just need it to load faster. Do not create a second-class experience based on device specs. Serve less data, not fewer features. Do not rely on a single detection method. Combine Network Information API with header-based detection and UA sniffing as a last resort. Each method has gaps. Together they cover most of the real-world surface area. Do not assume that serving less is always the right answer for every user. Some users on slow connections are in situations where they need every bit of information available to them, like a healthcare worker checking a medical app on a spotty hospital Wi-Fi. The goal is to give them access without frustration, not to withhold content. Compress and lazy-load instead of omitting.
The Bottom Line
Responsible responsive design is about matching the experience to the reality of the user's device and connection. It is not about building two versions of your site. It is about building one site that knows when to hold back. Scott Jehl's work has pushed the industry toward this thinking for years, and the tools are better now than they were even three years ago. The APIs are more widely supported, the image formats are more efficient, and the edge computing options make server-side optimization cheaper to implement. The people who will benefit most are the ones you are least likely to test for. If your QA team only tests on company iPhones and home WiFi, you are missing the majority of your global audience. Build for them. Test on a real slow connection if you can borrow a phone and walk outside your office. The difference between a page that loads in two seconds on 4G and one that loads in twelve on 2G is the difference between a user staying and a user leaving. That is the point of all of this.
