Advanced Image Optimization in React/Next.js: Device-Based Responsive Images for Peak Performance (Part 1)

Published: (December 4, 2025 at 01:47 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Cover image for Advanced Image Optimization in React/Next.js: Device-Based Responsive Images for Peak Performance (Part 1)

Images account for 50‑70% of a typical web page’s total size. Serving optimized images based on device capabilities and screen density is crucial for performance, user experience, and SEO. In this comprehensive guide, we’ll explore device pixel ratio (DPR) optimization and responsive image techniques using React and Next.js.

Understanding Device Pixel Ratio (DPR)

Device Pixel Ratio represents the relationship between physical pixels and CSS pixels. Modern devices have varying DPRs:

  • Standard displays: DPR 1 (1920×1080 monitors)
  • Retina/HD displays: DPR 2 (MacBook Pro, iPhone)
  • Ultra HD displays: DPR 3+ (iPhone 15 Pro, Samsung Galaxy)

Serving a 1× image to a 3× device results in blurry visuals, while serving a 3× image to a 1× device wastes bandwidth.

Detecting Device Pixel Ratio in JavaScript

// Get current device pixel ratio
const dpr = window.devicePixelRatio || 1;

// Listen for DPR changes (when moving between monitors)
const dprQuery = window.matchMedia(`(resolution: ${dpr}dppx)`);
dprQuery.addEventListener('change', (e) => {
  if (!e.matches) {
    console.log('DPR changed, reload optimized images');
  }
});

React Hook for Device Detection

Create a custom hook to detect device capabilities:

// hooks/useDeviceInfo.js
import { useState, useEffect } from 'react';

export const useDeviceInfo = () => {
  const [deviceInfo, setDeviceInfo] = useState({
    dpr: 1,
    width: 0,
    isMobile: false,
    isTablet: false,
    isDesktop: false,
    connection: 'unknown',
  });

  useEffect(() => {
    const updateDeviceInfo = () => {
      const width = window.innerWidth;
      const dpr = window.devicePixelRatio || 1;
      const connection = navigator.connection?.effectiveType || 'unknown';

      setDeviceInfo({
        dpr: Math.min(dpr, 3), // Cap at 3x for practicality
        width,
        isMobile: width <= 768,
        isTablet: width > 768 && width <= 1024,
        isDesktop: width > 1024,
        connection,
      });
    };

    updateDeviceInfo();
    window.addEventListener('resize', updateDeviceInfo);
    return () => window.removeEventListener('resize', updateDeviceInfo);
  }, []);

  return deviceInfo;
};

Building a Responsive Image Component (React)

// components/OptimizedImage.jsx
import React, { useState, useEffect } from 'react';
import { useDeviceInfo } from '../hooks/useDeviceInfo';

const OptimizedImage = ({
  src,
  alt,
  sizes = '100vw',
  quality = 75,
  className = '',
}) => {
  const { dpr, width, connection } = useDeviceInfo();
  const [imageSrc, setImageSrc] = useState('');
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const adjustedQuality = connection === '2g' ? 50 : quality;
    const imageWidth = calculateImageWidth(width, dpr);
    const optimizedSrc = buildOptimizedUrl(src, {
      width: imageWidth,
      quality: adjustedQuality,
      dpr,
      format: 'auto', // WebP when supported
    });
    setImageSrc(optimizedSrc);
  }, [src, dpr, width, connection, quality]);

  const calculateImageWidth = (viewportWidth, deviceDpr) => {
    const targetWidth = viewportWidth * deviceDpr;
    const standardSizes = [
      320, 640, 750, 828, 1080, 1200, 1920, 2048, 3840,
    ];
    return standardSizes.find((size) => size >= targetWidth) || 3840;
  };

  const buildOptimizedUrl = (originalSrc, options) => {
    const { width, quality, dpr, format } = options;
    return `https://res.cloudinary.com/your-cloud/image/upload/w_${width},q_${quality},dpr_${dpr},f_${format}/${originalSrc}`;
  };

  return (
    <img
      src={imageSrc}
      alt={alt}
      className={className}
      sizes={sizes}
      onLoad={() => setIsLoading(false)}
      style={{ display: isLoading ? 'none' : 'block' }}
    />
  );
};

export default OptimizedImage;

Using Picture Element for Art Direction

Different devices might need different image crops or compositions:

const ResponsiveArtDirectedImage = ({ images, alt }) => {
  const { dpr } = useDeviceInfo();

  const buildOptimizedUrl = (src, opts) => {
    const { dpr } = opts;
    return `https://res.cloudinary.com/your-cloud/image/upload/dpr_${dpr}/${src}`;
  };

  return (
    <picture>
      {/* Mobile – portrait crop */}
      <source
        media="(max-width: 767px)"
        srcSet={buildOptimizedUrl(images.mobile, { dpr })}
      />
      {/* Tablet – landscape crop */}
      <source
        media="(min-width: 768px) and (max-width: 1023px)"
        srcSet={buildOptimizedUrl(images.tablet, { dpr })}
      />
      {/* Desktop – full width */}
      <source
        media="(min-width: 1024px)"
        srcSet={buildOptimizedUrl(images.desktop, { dpr })}
      />
      <img src={buildOptimizedUrl(images.desktop, { dpr })} alt={alt} />
    </picture>
  );
};

Continue to Part 2 for Next.js image optimization, lazy loading strategies, and performance monitoring techniques.

Keywords: React image optimization, device pixel ratio, responsive images, Next.js performance, DPR optimization, lazy loading, web vitals

Back to Blog

Related posts

Read more »

RCE Vulnerability in React and Next.js

Article URL: https://github.com/vercel/next.js/security/advisories/GHSA-9qr9-h5gf-34mp Comments URL: https://news.ycombinator.com/item?id=46136026 Points: 26 Co...