css • Responsive media queries and pixels - martindubenet/wed-dev-design GitHub Wiki
Viewport units for relative dimensions
Because mobile phone browsers reserve some height for the GUI of their browser app, when setting the viewport height unit value to 100% { vh: 100%; }
makes the element heigher then the actual viewport, displaying a scrollbar on the Y axes.
To fix the issue, use instead the Dynamic Viewport Height unit (dvh
).
.example {
height: 100vh; /* as backup for legacy browsers */
height: 100dvh;
}
Media queries
CSS properties for responsive layout
From best to worst.
Rating | Property | Explanations | Link |
---|---|---|---|
★★★ | @media screen |
A CSS media type property very useful if your HTML is well formated since most CSS are done for screen disply only, when this boolean property is false it is the under lying basic HTML that will render the content. Making it as eazy to read printed documents as if it was a PDF. |
⌝ |
★★★ | @media print |
A CSS media type property that is useful to debug style issues on printer devices. | ⌝ |
★★★ | (min-width/max-width: *px) |
The basic media query to use, the saffer. It gets the job done. | ⌝ |
★★☆ | (min-resolution: *dpi) |
The official W3C approved property that rely on dpi units used to refer to PPI (Pixels Per Inch). ⚠ This property is NOT supported by Safari browsers! | ⌝ |
★★☆ | (orientation: portrait/landscape) |
A standard boolean property usefull for mobile devices (only), allowing to fix granular layout issues. The only options are either portrait or landscape . |
⌝ |
★★☆ | @media(pointer: fine/coarse) |
This media query allows you to detect whether the device has a precise pointing device (mouse device = fine ) or not (touchscreen = coarse ), which can influence the user interface design. |
⌝ |
★☆☆ | (-webkit-min-device-pixel-ratio: *) |
A non-standard boolean property for both Google Chrome and Apple Safari (mobile and regular) browsers. It rely on absolute values. ⚠ They only reason we still use this property is beacause Safari browsers does NOT support the min-resolution as approved by W3C. So you should always duplicate your values in both (1st) -webkit-min-device-pixel-ratio then cascade down to min-resolution . Test your device⌝ |
⌝ |
★☆☆ | (aspect-ratio: *) |
Detect mobile device orientation, either horizontal or vertical. It rely on absolute values. ⚠ You should rely on orientation if you only need boolean result. |
⌝ |
☆☆☆ | (min-device-width: *px) |
🚫 Obsolete! Developers should use the min-width media feature instead. |
⌝ |
As of the this Screen Resolutions Market Share the common large computer screens size to target would be the 1920 x 1080 of 1080i HDTVs.
Implicitly the mobile first design approach implies the use of minimal values (
min-width
) in our CSS.
/* PHONES */
@media screen and (min-width: 320px) and (pointer: coarse) { … }
@media screen and (min-width: 600px) and (pointer: coarse) and (orientation: landscape) { … }
/* TABLETS */
@media screen and (min-width: 800px) and (pointer: coarse) and (orientation: portrait) { … }
@media screen and (min-width: 1024px) and (pointer: coarse) and (orientation: landscape) { … }
/* LAPTOPS with touchscreen feature enable */
@media screen and (min-width: 1024px) and (pointer: coarse) { … }
/* LAPTOPS without touchscreen feature */
@media screen and (min-width: 1024px) and (pointer: fine) { … }
/* DESKTOPS */
@media screen and (min-width: 1200px) { … }
/* LARGE DESKTOPS */
@media screen and (min-width: 1800px) { … }
/* PRINTERS */
@media print { … }
Device's display specifications
Device | Resolution (px) | Browser viewport (px) | PPI | Resolution |
---|---|---|---|---|
🖥 UHD 8K | 7680 × 4320 | |||
🖥 32in Pro XDR Display (Retina 6K) | 6016 x 3384 | |||
🖥 32in iMac Pro 5K (UHD+) | 5120 × 2880 | 3200 x 1800 | ||
🖥 27in UHD 4K LG monitor | 3840 x 2160 | 1860 | ~140dpi | 1.5 |
💻 16in Macbook Pro | 3072 x 1920 | 1536 | 226dpi | 2.26 |
💻 13in Macbook Air | 2560 x 1600 | 1280 | 113dpi | 2 |
Tablet iPad Air 4 (2020) | 1640 x 2360 | 820 x 1180 | 264dpi | 2 |
Tablet iPad Mini | 1536 x 2048 | 768 x 1024 | 324dpi | 2 |
Tablet Pixel C (2015) | 2560 x 1800 | 1280 x 900 | 308dpi | 2 |
📱iPhone 12 Pro Max | 1284 x 2778 | 428 x 926 | 458dpi | 3 |
📱iPhone 12 | 1170 x 2532 | 390 x 844 | 460dpi | 3 |
📱iPhone 12 Mini | 1080 x 2340 | 360 x 780 | 476dpi | 3 |
📱iPhone SE (2020) | 750 x 1334 | 375 x 667 | 326dpi | 2 |
📱Pixel 4 XL | 1440 x 3040 | 412 x 869 | 537dpi | 3.5 |
📱Pixel 5 | 1080 x 2340 | 393 x 851 | 432dpi | 2.75 |
📱Pixel 2 | - | 412 x 732 | - | 2.625 |
Television specifications
TV standards | Resolution (px) | PPI |
---|---|---|
📺 UHD 4K | 3840 x 2160 | ~140dpi |
📺 HDTV 1080i | 1920 x 1080 | 72dpi |
📺 HDTV 720p | 1280 x 720 | 72dpi |
📺 TV 480p | 640 x 480 | 72dpi |
⚠ Do not rely on resolution values alone!
For displaying contents within web browsers we rely ONLY on the viewport values. Not the screen resolution specifications of the device itself. Because the resolution does not directly reflect the physical size of the screen. A device may have a high resolution but a small screen, making content difficult to read based on resolution alone.
-webkit-device-pixel-ratio)
@media (The -webkit-device-pixel-ratio is a non-standard boolean CSS media feature which is an alternative to the standard
resolution
media feature.resolution)
@media (The resolution CSS media feature can be used to test the pixel density of the output device. ⚠ This property is NOT supported by Safari browsers
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi) { /* 4K/UHD/Retina devices */ }
Breakpoint helper for developers and QA
- JsFiddle demo: Get Bootstrap 4 Responsive Breakpoint on window resize
Design for Device
Is mouse device available?
For a public (marketing type) website relying on viewport dimensions is a good enough approach. But for (Saas) web applications with dense dashboard templates where customers always request more details per pixels, a good practice would be to add the possibility to toggle between (Phone/Tablet) touch devices VS mouse devices. The first requiring a 48x48
pixels hitzone for fingers where a smaller 20x20
pixels is good enough for mouse device users.
To differenciate small laptops from large tablets (or laptops with touch screens) it makes sense to identify if the device has a mouse device enabled since this is the real features that differenciate the type of design to propose/support.
See Javascript example based on matchMedia()
in this StackOverflow post.
matchMedia()
JavaScript method
The The Window interface's matchMedia() method returns a new MediaQueryList object that can then be used to determine if the document matches the media query string, as well as to monitor the document to detect when it matches (or stops matching) that media query.
— MDN
Gemini 2.5 Flash prompt:
« Generate the javascript code te get confirmation that the user of my website page as a mouse device available based on
(matchMedia('(pointer:fine)').matches)
»
Gemini 2.5 Flash code:
/** * Checks if the user's primary input device is a "fine" pointer, * which typically indicates the presence of a mouse or similar high-precision device. * * @returns {boolean} True if a fine pointer is detected, false otherwise. */ function hasMouseDevice() { // The 'pointer: fine' media query evaluates to true if the primary input mechanism // of the user is accurate enough to target a small area, like a mouse. // 'pointer: coarse' would typically indicate touchscreens. // 'pointer: none' would indicate no pointing device. return window.matchMedia('(pointer:fine)').matches; } // --- Examples of usage: --- // 1. On page load: if (hasMouseDevice()) { console.log("Mouse device detected: Yes, a fine pointer is available."); // You might add a class to the body for CSS adjustments document.body.classList.add('has-mouse'); } else { console.log("Mouse device detected: No, or a coarse/no pointer is available."); document.body.classList.add('no-mouse'); } // 2. You can also use it to conditionally enable/disable features: function enableMouseSpecificFeatures() { if (hasMouseDevice()) { console.log("Enabling features for mouse users (e.g., hover effects, complex drag-and-drop)."); // Example: Add hover effects (if not handled purely by CSS) const hoverElements = document.querySelectorAll('.hover-effect'); hoverElements.forEach(el => { el.addEventListener('mouseenter', () => { el.style.backgroundColor = 'lightblue'; }); el.addEventListener('mouseleave', () => { el.style.backgroundColor = ''; }); }); } else { console.log("Disabling/adjusting features for touch/keyboard users."); // Example: Provide alternative interaction for touch const clickableElements = document.querySelectorAll('.clickable'); clickableElements.forEach(el => { el.addEventListener('click', () => { alert("This element was clicked!"); }); }); } } // Call this function when the DOM is ready document.addEventListener('DOMContentLoaded', enableMouseSpecificFeatures); // 3. Listening for potential changes (less common for 'pointer:fine', but possible if input devices change) // While 'pointer:fine' is generally static for a session, you can technically listen for changes. // This is more relevant for dynamic device changes (e.g., connecting a mouse to a tablet). const mediaQuery = window.matchMedia('(pointer:fine)'); function handlePointerChange(e) { if (e.matches) { console.log("Pointer changed to fine (mouse detected)."); // Re-enable mouse-specific features or adjust UI } else { console.log("Pointer changed to coarse or none (mouse no longer primary)."); // Disable mouse-specific features or adjust UI } } // Add the listener mediaQuery.addEventListener('change', handlePointerChange); // Initial check for the listener handlePointerChange(mediaQuery);
Device orientation?
Modern SaaS applications are based on modular components that can be trought within different slots of different templates. Not all components requires a to be adapted accross all breakpoints. Of course using CSS container queries is THE best practice but in real life we don't always have the time required to (re)design on component from scratch based on @container
instead of @media
queries based on viewport dimensions like we do since years.
So knowing the orientation of a device to style it is a good solution for fixing CSS issues. And, since it is not often that a computer screen is vertically installed, this is also a hint that the user is on a mobile device.
Gemini 2.5 Flash prompt:
« Generate the javascript code of a function that set
deviceOrientation
as either Landscape, Portrait or Square values based on the comparaison ofwindow.innerWidth
andwindow.innerHeight
»
Gemini 2.5 Flash code:
/** * Determines the device orientation (Landscape, Portrait, or Square) based on window dimensions. * * @returns {string} The orientation: 'Landscape', 'Portrait', or 'Square'. */ function getDeviceOrientation() { const width = window.innerWidth; const height = window.innerHeight; if (width > height) { return 'Landscape'; } else if (height > width) { return 'Portrait'; } else { // width === height return 'Square'; } } // --- Examples of usage: --- // Get the current orientation let currentOrientation = getDeviceOrientation(); console.log("Current Device Orientation:", currentOrientation); // You can also listen for changes in orientation (e.g., when the user rotates their device or resizes the browser window) window.addEventListener('resize', () => { const newOrientation = getDeviceOrientation(); if (newOrientation !== currentOrientation) { console.log("Device Orientation Changed to:", newOrientation); currentOrientation = newOrientation; // Update the current orientation } }); // Another example: Use it to apply specific CSS classes or logic function applyOrientationSpecificStyles() { const orientation = getDeviceOrientation(); const body = document.body; // Remove any previously set orientation classes body.classList.remove('orientation-landscape', 'orientation-portrait', 'orientation-square'); // Add the new orientation class if (orientation === 'Landscape') { body.classList.add('orientation-landscape'); } else if (orientation === 'Portrait') { body.classList.add('orientation-portrait'); } else { body.classList.add('orientation-square'); } console.log("Applied style for orientation:", orientation); } // Call it initially and on resize applyOrientationSpecificStyles(); window.addEventListener('resize', applyOrientationSpecificStyles);
References:
- Designer's guide to DPI by Sébastien Gabriel.
- YesViz.com
- Wikipedia's Computer display standard.