One experience does not fit all
Device hardware and network quality vary enormously across the web. A page that runs smoothly on a flagship phone can become unusable on a budget device, and an experience tuned for a fast fiber connection may crawl on 2G. The cost of JavaScript and heavy media is not uniform: users on constrained devices pay a much higher price for the same resources.
Adaptive loading is a pattern for addressing this by serving different experiences based on a user's specific network and hardware constraints. The core idea is to always deliver a fast, functional baseline experience. Then, progressively add enhancements—like higher-quality media or more interactive features—only when the user's device and connection can handle them without a performance penalty.
In practice, this can mean several things:
- Delivering lower quality images and video on slower network connections.
- Throttling animation frame rates on low-end devices to save CPU work.
- Avoiding expensive operations, like heavy client-side computations, on underpowered hardware.
- Deferring or blocking third-party scripts and non-critical JavaScript on constrained devices.
Available platform signals
The web platform provides a set of APIs that developers can use to make these decisions at runtime. Browser support for each signal was highlighted in the Chrome Dev Summit talk by Google's Addy Osmani and Facebook's Nate Schloss.
navigator.deviceMemory
This property reports the approximate amount of device RAM. It allows you to reduce memory consumption by lowering image quality or loading fewer rich components on low-memory devices. It is supported in Chrome 63+ and Edge 79+.
navigator.hardwareConcurrency
This returns the number of logical processor cores available. It can be used to limit CPU-intensive JavaScript logic on devices with few cores. This API is broadly supported, with availability in Chrome 37+, Edge 15+, and Firefox 48+, among others.
navigator.connection.effectiveType
This property from the Network Information API provides the effective connection type (slow-2g, 2g, 3g, or 4g). It's useful for tuning data transfer to consume less bandwidth. Support is present in Chrome and Edge, while Firefox has yet to fully ship it.
navigator.connection.saveData
This boolean property reflects the user's preference for reduced data usage, such as the Data Saver feature on Android or Chrome. When enabled, you can proactively serve lower-quality or fewer resources. Support currently covers Chrome and Edge.
These JavaScript APIs are available on the client. On the server, you can use Client Hints to receive related signals—like device memory and network conditions—in HTTP request headers, enabling content negotiation before the initial page load.
Simplifying with React hooks
The React Adaptive Loading Hooks & Utilities suite provides a set of tools to incorporate these APIs into React applications more easily:
useNetworkStatus()to adapt based on the effective connection type.useSaveData()to adapt based on the user's Data Saver preference.useHardwareConcurrency()to adapt based on the CPU core count.useMemoryStatus()to adapt based on the device's RAM.
Each hook takes an optional initial value argument. This is especially relevant for server-side rendering, where you can populate the hook's initial state with Client Hint data on the server. When the hook runs in the browser, it can then update its value if the relevant signal changes, such as a shift in the effective network type.
Because the underlying implementation relies solely on the web platform APIs described above, the same adaptive loading logic can be replicated in other frameworks, including Angular and Vue.
Adaptive loading in practice
Several real-world implementations mentioned during the talk demonstrate how these patterns can improve experiences.
The approach of using network awareness to serve media can be seen in a sample movie browsing app that shows posters, summaries, and cast lists. In this demo, the application serves high-resolution poster images to users on fast connections, while users on slower networks receive lower-quality versions.
Twitter's Data Saver preference is a well-known example. When enabled, the app loads low-resolution preview images and only fetches a high-resolution version once a user taps on the preview. This approach has reportedly saved a substantial amount of data for image loading across their iOS, Android, and web clients.
eBay demonstrates conditional enhancement through code-splitting. Features like zooming can be toggled on and off based on user conditions. Heavier, more interactive components are loaded and run only on higher-end devices, while those scripts are not sent to users who might suffer from executing them. React.lazy() and Suspense provide a mechanism to facilitate this type of conditional loading.
Tinder applies several adaptive patterns to both its web app and Lite app. If a user is on a slow network or has Data Saver enabled, the app disables video autoplay, limits route prefetching, and constrains the carousel to load images incrementally rather than those ahead. After implementing these changes, the company saw noticeable improvements in swiping activity in markets with more constrained networks.
Device classification at Facebook
A persistent challenge in this space is grouping devices into performance tiers. Mobile device names from the user-agent string allow classification based on known device characteristics. Desktop devices offer less information through the UA string, providing essentially just the operating system.
At Facebook, a different strategy is used for desktop. The company logs data about the operating system, CPU core count from navigator.hardwareConcurrency, and device memory from navigator.deviceMemory in its performance monitoring. This data revealed correlations between hardware configurations and user-facing performance, leading to the creation of five distinct hardware classes. These classes can then be used for targeted, adaptive delivery of features such as specific animation complexity or the amount of JavaScript to load.
Designing for inclusivity
Adaptive loading is an inclusive design strategy that puts the default experience quality on the minimum viable hardware. It uses available APIs to build a core experience that performs well everywhere. From that foundation, you can then selectively layer in additional features for richer experiences on devices with more capability. Several demo applications and code examples from the Chrome Dev Summit talk are available for teams looking to experiment with and learn from this pattern.



