You need working code, not another definition page. Use screen.width for the display, window.innerWidth for the layout viewport, and devicePixelRatio when physical pixels matter (Retina canvas, sharp images).
The snippets below detect each value and show where they matter for responsive images and canvas scaling.
The Three Values Every Front-End Dev Should Know
Before the snippets, a 10-second mental model:
| API | What it is | Typical use |
|---|---|---|
| screen.width | Physical display width in CSS pixels (often the same as device width on mobile) | Device capability, analytics, "is this a phone?" |
| window.innerWidth | Width of the browser viewport in CSS pixels (scrollbar included) | Layout breakpoints, responsive CSS, "how much space do I have?" |
| window.devicePixelRatio | Ratio of physical pixels to CSS pixels | Sharp images, canvas resolution, "do I need @2x assets?" |
On a 1920×1080 monitor at 100% zoom, you might see screen.width === 1920 and innerWidth smaller if the window isn’t fullscreen.
On an iPhone 15 with a 393×852 logical viewport, innerWidth === 393 and devicePixelRatio === 3—so the physical pixel width is 393 × 3 = 1179.
Get these three in your head, then use the code below to detect them.
1. Detecting Screen Width (screen.width)
screen.width is the width of the user’s screen in CSS pixels. It usually doesn’t change when they resize the browser; it describes the display. Use it when you care about device class (e.g. phone vs desktop), not layout.
// Basic read
const screenWidth = window.screen.width;
console.log('Screen width (CSS px):', screenWidth);
// Optional: guard for SSR / non-browser
const screenWidthSafe = typeof window !== 'undefined' ? window.screen.width : 0;
When to use it: Analytics, feature flags (“show desktop-only feature”), or A/B tests by device size. Don’t use it for responsive layout—use viewport (innerWidth or media queries) instead.
2. Detecting Viewport Width (window.innerWidth)
window.innerWidth is the width of the browser viewport in CSS pixels, including the scrollbar. It changes when the user resizes the window. This is what you want for breakpoints and “how much horizontal space do I have?”
// Current viewport width
const viewportWidth = window.innerWidth;
console.log('Viewport width (CSS px):', viewportWidth);
// React to resize (e.g. for layout or logging)
function logViewport() {
console.log('Viewport:', window.innerWidth, 'x', window.innerHeight);
}
window.addEventListener('resize', logViewport);
// Don’t forget to removeListener when cleaning up (e.g. in useEffect return).
Getting layout width without scrollbar: If you need the “layout” width (what CSS sees in a media query), use a resize observer or match a media query in JS:
// Match a media query (same as CSS (min-width: 768px))
const isTabletOrLarger = window.matchMedia('(min-width: 768px)').matches;
const mediaQueryWidth = 768;
if (viewportWidth >= mediaQueryWidth) {
// Tablet/desktop layout
}
Use innerWidth (or media queries) for responsive layout, breakpoints, and conditional UI—not screen.width.
3. Detecting Device Device Pixel Ratio (DPR) (DPR)
devicePixelRatio is the ratio of physical pixels to CSS pixels. On a Retina Mac or modern phone it’s often 2 or 3; on a standard 1080p monitor it’s usually 1. You need this for crisp images and canvas.
// Basic read
const dpr = window.devicePixelRatio || 1;
console.log('DPR:', dpr);
// Typical buckets for responsive images
const density = dpr >= 3 ? '3x' : dpr >= 2 ? '2x' : '1x';
console.log('Asset density:', density);
Why || 1? Older or headless environments might not define devicePixelRatio; defaulting to 1 avoids NaN and keeps math safe.
Use Case 1: Responsive Images (srcset + sizes + DPR)
You want the right image for viewport size and pixel density: small viewport + high DPR (e.g. phone) gets a smaller logical size but high-res file; large viewport gets a wider image. Here’s the logic in JS so you can build URLs or pick sources yourself (e.g. for a React component or a CMS).
function getImageSuffix() {
if (typeof window === 'undefined') return '1x';
const dpr = Math.min(window.devicePixelRatio || 1, 3);
const w = window.innerWidth;
// Example breakpoints: mobile < 768, tablet < 1280, else desktop
const widthBucket = w < 768 ? 'sm' : w < 1280 ? 'md' : 'lg';
const dprSuffix = dpr >= 3 ? '@3x' : dpr >= 2 ? '@2x' : '';
return `${widthBucket}${dprSuffix}`;
}
// Use with your CDN or path: `/img/hero-${getImageSuffix()}.webp`
In HTML you’d typically use srcset and sizes and let the browser choose; the snippet above is the same logic in JS for when you control the URL (e.g. dynamic or component-driven images). Pair it with pixel density so you serve 2x/3x only where DPR justifies it. Test live DPR on our DPR checker.
Use Case 2: Canvas Scaling (Sharp on Retina)
Canvas has a drawing buffer size and a display size. If you set only the CSS size, the buffer is often 1:1 with CSS pixels, so on a 2x or 3x display the canvas looks soft. Scale the internal size by DPR, then use CSS to show it at the desired layout size.
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const dpr = window.devicePixelRatio || 1;
// Desired size in CSS pixels (e.g. match a container)
const cssWidth = 400;
const cssHeight = 300;
// Set display size (what user sees)
canvas.style.width = `${cssWidth}px`;
canvas.style.height = `${cssHeight}px`;
// Set buffer size (actual pixels: sharp on Retina)
canvas.width = cssWidth * dpr;
canvas.height = cssHeight * dpr;
ctx.scale(dpr, dpr);
// Now draw in CSS pixel coordinates (0..cssWidth, 0..cssHeight)
// The context scales everything up; the canvas stays sharp.
ctx.fillRect(10, 10, 100, 50);
After this, always draw in CSS pixel coordinates (0 to cssWidth, 0 to cssHeight). The context’s scale(dpr, dpr) handles the rest. Resize handling: on resize, recompute cssWidth/cssHeight (e.g. from getBoundingClientRect), set style and width/height again, then redraw.
One Snippet to Log All Three
Drop this in the console or a debug script to see the full picture at once:
function reportScreenViewportDPR() {
const screenW = window.screen?.width ?? 0;
const innerW = window.innerWidth ?? 0;
const dpr = window.devicePixelRatio ?? 1;
const physicalWidth = Math.round(innerW * dpr);
console.log({
'screen.width (CSS px)': screenW,
'window.innerWidth (CSS px)': innerW,
'devicePixelRatio': dpr,
'viewport physical width (px)': physicalWidth,
});
}
reportScreenViewportDPR();
window.addEventListener('resize', reportScreenViewportDPR);
Use this when debugging layout vs asset choices or when teaching the difference between viewport width and screen width.
Common Gotchas (So You Don’t Waste an Hour)
A few traps that bite even senior devs:
- Browser zoom changes everything. At 150% zoom,
window.innerWidthdrops anddevicePixelRatiocan change in some browsers. Test at 100% and at 125%/150% if your app is zoom-sensitive. - screen.width can “lie” on multi-monitor. It usually reports the primary screen; on Linux or exotic setups you may get the wrong monitor. Prefer viewport (innerWidth) for layout.
- SSR and Node have no window. Any snippet that touches
windoworscreenmust run in the browser or be guarded withtypeof window !== 'undefined'(or run only inuseEffect/onMounted). - Canvas: set width/height in pixels, not style. The buffer size is
canvas.widthandcanvas.height(numbers); the display size iscanvas.style.widthandstyle.height(strings with units). Mix them up and you get stretch or blur.
Get these right once and your responsive images and canvas code stay predictable across devices.
Quick Reference: What to Use When
- Responsive layout / breakpoints →
window.innerWidthor CSS media queries. - “Is this a small device?” →
screen.width(or innerWidth) with a threshold. - Responsive images (size + density) →
innerWidth(or sizes) +devicePixelRatio. - Canvas sharp on Retina → Set canvas width/height to
cssSize * devicePixelRatio, thenctx.scale(dpr, dpr)and draw in CSS coordinates. - Analytics / device class →
screen.width(and optionally DPR) is fine; prefer viewport for layout-related metrics.
Wrap-Up
Viewport width, screen width, and DPR each answer a different question. Use screen.width for device capability, window.innerWidth for layout and breakpoints, and devicePixelRatio for resolution-aware assets and canvas. The snippets above are the code angle devs search for—drop them into your project, adapt the thresholds to your breakpoints, and you’ll have responsive images and sharp canvas without the guesswork.
For a live readout of your current screen and viewport, use our viewport checker and DPR checker. For the conceptual stack (CSS pixels, scaling, zoom), see DPR, CSS pixels, and Retina explained; for how resolution and density affect design, see how screen size impacts web design and UX.
Related Articles
Continue reading with these related posts

iPhone 17, Air & Pro Max Screen Sizes: Inches, Resolution, PPI
The iPhone 17 is 6.3 inches, the iPhone Air 6.6 inches, and the iPhone 17 Pro Max 6.9 inches. This chart lists every iPhone 17 model's screen size, resolution, pixel density, aspect ratio, and approximate CSS viewport width.
Best Laptop Screen Size for Students, Office Work, and Travel
Choose 13–14 inch for travel and campus life, 14–15 inch as the daily all-rounder, and 16 inch when the laptop mostly stays on a desk. Screen size is a portability tax as much as a comfort upgrade.

Samsung Galaxy S25 & S26 Screen Sizes: Inches, Resolution, PPI
The Galaxy S25 measures 6.2 inches and the S25 Ultra 6.9 inches. This guide lists every Galaxy S25 and S26 model's screen size, resolution, pixel density, aspect ratio, refresh rate, and approximate CSS viewport width in one chart.
