|

CSS 34 ๐Ÿ’ป display-mode and dynamic-range media features

These two media features let you adapt styles based on how the app is displayed and the visual capabilities of the screen โ€” from standalone PWA mode to HDR displays.


Overview of Features

FeatureDescriptionValues
display-modeHow the document is displayedbrowser, standalone, minimal-ui, fullscreen, picture-in-picture
dynamic-rangeBrightness, contrast, and color depthstandard, high

1. display-mode

The display-mode media feature queries how the document is being displayed โ€” whether it’s in a browser tab, installed as an app, in fullscreen, etc.

@media (display-mode: standalone) {
    body {
        background-color: #f0f8ff;
        color: #036;
    }
}

Values

ValueDescription
browserIn a normal browser tab or window
standaloneInstalled as a standalone app (PWA)
minimal-uiLike standalone, but with minimal browser UI
fullscreenUses the full screen (no browser chrome)
picture-in-pictureIn a picture-in-picture window
window-controls-overlayPWA with window controls overlay (desktop)

How It’s Set

The display mode is controlled by:

  1. The manifest file’s display property (for PWAs)
  2. The Fullscreen API (requestFullscreen())
  3. The Picture-in-Picture API

Manifest example:

{
    "display": "standalone",
    "name": "My PWA",
    "short_name": "PWA"
}

JavaScript example:

// Enter fullscreen
document.documentElement.requestFullscreen();

// Check current display mode
if (window.matchMedia('(display-mode: standalone)').matches) {
    console.log('Running as standalone app');
}

2. dynamic-range

The dynamic-range media feature queries the combination of brightness, contrast, and color depth capabilities of the display.

@media (dynamic-range: high) {
    body {
        background-color: #f5f5f5;
        color: #000;
    }
}

Values

ValueDescription
standardStandard dynamic range (SDR) โ€” typical displays
highHigh dynamic range (HDR) โ€” supports HDR content

HDR requirements:

  • Color depth greater than 24-bit (usually 30-bit or 36-bit)
  • High contrast ratio
  • High peak brightness (typically 1000+ nits)

Key Points:

  • A device that matches high also matches standard (HDR is a superset)
  • A device that matches standard may or may not support high
  • Use high to enhance visuals on capable displays
  • Always provide a standard fallback

Complete Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>display-mode and dynamic-range Media Features</title>
    <style>
        *, *::before, *::after {
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            padding: 20px;
            background: #f8f9fa;
            max-width: 1200px;
            margin: 0 auto;
            line-height: 1.6;
            transition: background 0.3s, color 0.3s;
        }

        h1 {
            color: #007bff;
            border-bottom: 3px solid #007bff;
            padding-bottom: 10px;
        }

        h2 {
            color: #28a745;
            border-left: 4px solid #28a745;
            padding-left: 15px;
            margin-top: 30px;
        }

        h3 {
            color: #333;
            margin-top: 20px;
        }

        section {
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            margin: 20px 0;
            transition: background 0.3s;
        }

        .code-block {
            background: #1e1e1e;
            color: #d4d4d4;
            padding: 15px;
            border-radius: 8px;
            overflow-x: auto;
            font-family: 'Courier New', monospace;
            font-size: 0.9rem;
            line-height: 1.8;
            margin: 10px 0;
        }

        .reference-table {
            width: 100%;
            border-collapse: collapse;
            margin: 15px 0;
        }

        .reference-table th,
        .reference-table td {
            padding: 10px;
            border: 1px solid #ddd;
            text-align: left;
        }

        .reference-table th {
            background: #007bff;
            color: white;
        }

        .reference-table tr:nth-child(even) {
            background: #f8f9fa;
        }

        .note {
            font-size: 0.9rem;
            color: #6c757d;
            margin-top: 5px;
        }

        .highlight {
            background: #ffc107;
            color: #333;
            padding: 2px 6px;
            border-radius: 4px;
            font-weight: bold;
        }

        /* ====== DISPLAY MODE DEMOS ====== */
        @media (display-mode: browser) {
            .display-browser {
                background: #cce5ff;
                border-color: #007bff;
            }
            .display-browser .value {
                color: #007bff;
            }
        }

        @media (display-mode: standalone) {
            body {
                background-color: #f0f8ff;
                color: #036;
            }
            a {
                color: #00f;
            }
            .display-standalone {
                background: #d4edda;
                border-color: #28a745;
            }
            .display-standalone .value {
                color: #28a745;
            }
        }

        @media (display-mode: minimal-ui) {
            .display-minimal-ui {
                background: #fff3cd;
                border-color: #ffc107;
            }
            .display-minimal-ui .value {
                color: #856404;
            }
        }

        @media (display-mode: fullscreen) {
            body {
                background-color: #fff;
                color: #000;
            }
            a {
                color: #03f;
            }
            .display-fullscreen {
                background: #f8d7da;
                border-color: #dc3545;
            }
            .display-fullscreen .value {
                color: #dc3545;
            }
        }

        @media (display-mode: picture-in-picture) {
            .display-pip {
                background: #e2d9f3;
                border-color: #6c5ce7;
            }
            .display-pip .value {
                color: #6c5ce7;
            }
        }

        /* ====== DYNAMIC RANGE DEMOS ====== */
        @media (dynamic-range: standard) {
            body {
                background-color: #e5e5e5;
                color: #333;
            }
            p {
                font-size: 1em;
            }
            .dynamic-standard {
                background: #e9ecef;
                border-color: #6c757d;
            }
            .dynamic-standard .value {
                color: #6c757d;
            }
        }

        @media (dynamic-range: high) {
            body {
                background-color: #f5f5f5;
                color: #000;
            }
            p {
                font-size: 1.2em;
            }
            .dynamic-high {
                background: #fff3cd;
                border-color: #ffc107;
            }
            .dynamic-high .value {
                color: #856404;
            }
        }

        /* ====== DETECTION CARDS ====== */
        .detection-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin: 20px 0;
        }

        .detection-card {
            padding: 15px;
            border-radius: 8px;
            text-align: center;
            border: 2px solid #ddd;
            background: #f8f9fa;
            transition: all 0.3s;
        }

        .detection-card .label {
            font-size: 0.85rem;
            color: #666;
            display: block;
            margin-bottom: 5px;
        }

        .detection-card .value {
            font-size: 1.1rem;
            font-weight: bold;
            color: #007bff;
        }

        /* ====== BUTTONS ====== */
        .btn-group {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin: 15px 0;
        }

        .btn {
            padding: 10px 20px;
            border: none;
            border-radius: 8px;
            font-size: 1em;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s;
            color: white;
        }

        .btn-primary {
            background: #007bff;
        }
        .btn-primary:hover {
            background: #0056b3;
            transform: translateY(-2px);
        }

        .btn-success {
            background: #28a745;
        }
        .btn-success:hover {
            background: #1e7e34;
            transform: translateY(-2px);
        }

        .btn-danger {
            background: #dc3545;
        }
        .btn-danger:hover {
            background: #a71d2a;
            transform: translateY(-2px);
        }

        .btn-warning {
            background: #ffc107;
            color: #333;
        }
        .btn-warning:hover {
            background: #d39e00;
            transform: translateY(-2px);
        }

        /* ====== HDR VISUAL DEMO ====== */
        .hdr-demo {
            border-radius: 12px;
            overflow: hidden;
            margin: 20px 0;
            position: relative;
        }

        .hdr-demo .image-container {
            width: 100%;
            height: 300px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.5rem;
            font-weight: bold;
            color: white;
            text-shadow: 0 2px 10px rgba(0,0,0,0.3);
            transition: all 0.3s;
            /* Standard dynamic range */
            background: linear-gradient(135deg, #007bff, #6c5ce7);
        }

        /* High dynamic range enhancement */
        @media (dynamic-range: high) {
            .hdr-demo .image-container {
                background: linear-gradient(135deg, 
                    oklch(69% 0.27 240), 
                    oklch(69% 0.27 300),
                    oklch(69% 0.27 30));
                box-shadow: 0 0 40px rgba(108, 92, 231, 0.5);
            }
            .hdr-demo .image-container::after {
                content: " (HDR Enhanced โœจ)";
                font-size: 1rem;
                font-weight: normal;
            }
        }

        /* ====== LIVE INDICATOR ====== */
        .live-indicator {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: #007bff;
            color: white;
            padding: 12px 20px;
            border-radius: 50px;
            font-weight: bold;
            font-size: 0.85rem;
            box-shadow: 0 4px 15px rgba(0,123,255,0.4);
            z-index: 1000;
            transition: all 0.3s;
        }

        /* ====== PWA MANIFEST NOTE ====== */
        .manifest-note {
            background: #e2d9f3;
            padding: 20px;
            border-radius: 8px;
            border-left: 4px solid #6c5ce7;
            margin: 15px 0;
        }

        .manifest-note code {
            background: rgba(0,0,0,0.08);
            padding: 2px 6px;
            border-radius: 4px;
            font-family: 'Courier New', monospace;
        }
    </style>
</head>
<body>

    <h1>display-mode and dynamic-range Media Features</h1>

    <!-- ====== 1. DISPLAY-MODE DEMO ====== -->
    <section>
        <h2>1. display-mode</h2>
        <p>Queries how the document is being <strong>displayed</strong> โ€” browser tab, standalone app, fullscreen, etc.</p>

        <div class="btn-group">
            <button class="btn btn-primary" onclick="enterFullscreen()">๐Ÿ–ฅ๏ธ Enter Fullscreen</button>
            <button class="btn btn-danger" onclick="exitFullscreen()">๐Ÿšช Exit Fullscreen</button>
            <button class="btn btn-success" onclick="showDisplayMode()">๐Ÿ“ฑ Detect Display Mode</button>
            <button class="btn btn-warning" onclick="requestPiP()">๐Ÿ“บ Picture-in-Picture</button>
        </div>

        <div id="display-mode-result" class="detection-card" style="margin: 15px 0;">
            <span class="label">Current display mode:</span>
            <span class="value" id="current-display-mode">Click "Detect Display Mode"</span>
        </div>

        <div class="code-block">
            /* Browser tab or window */
            @media (display-mode: browser) {
                body { background-color: #f8f9fa; }
            }

            /* Installed as a standalone PWA */
            @media (display-mode: standalone) {
                body { background-color: #f0f8ff; }
            }

            /* Minimal UI (browser controls hidden) */
            @media (display-mode: minimal-ui) {
                body { background-color: #fff3cd; }
            }

            /* Fullscreen (no browser chrome) */
            @media (display-mode: fullscreen) {
                body { background-color: #fff; }
            }

            /* Picture-in-Picture window */
            @media (display-mode: picture-in-picture) {
                body { background-color: #e2d9f3; }
            }
        </div>

        <div class="manifest-note">
            <strong>๐Ÿ“‹ How display-mode is set:</strong>
            <ul>
                <li>In a <strong>manifest.json</strong> file: <code>"display": "standalone"</code></li>
                <li>With the <strong>Fullscreen API</strong>: <code>document.documentElement.requestFullscreen()</code></li>
                <li>With the <strong>Picture-in-Picture API</strong>: <code>video.requestPictureInPicture()</code></li>
            </ul>
        </div>
    </section>

    <!-- ====== 2. DYNAMIC-RANGE DEMO ====== -->
    <section>
        <h2>2. dynamic-range</h2>
        <p>Queries the <strong>brightness, contrast, and color depth</strong> capabilities of the display.</p>

        <div class="hdr-demo">
            <div class="image-container">
                ๐ŸŽจ Dynamic Range Demo
            </div>
        </div>

        <div id="dynamic-range-result" class="detection-card" style="margin: 15px 0;">
            <span class="label">Current dynamic range:</span>
            <span class="value" id="current-dynamic-range">Detecting...</span>
        </div>

        <div class="code-block">
            /* Standard Dynamic Range (SDR) โ€” most displays */
            @media (dynamic-range: standard) {
                body {
                    background-color: #e5e5e5;
                    color: #333;
                }
                p {
                    font-size: 1em;
                }
            }

            /* High Dynamic Range (HDR) โ€” HDR displays */
            @media (dynamic-range: high) {
                body {
                    background-color: #f5f5f5;
                    color: #000;
                }
                p {
                    font-size: 1.2em;
                }
            }
        </div>

        <p class="note"><strong>Note:</strong> HDR requires color depth > 24-bit, high contrast, and high peak brightness (1000+ nits). A device that matches <code>high</code> also matches <code>standard</code>.</p>
    </section>

    <!-- ====== 3. DETECTION SUMMARY ====== -->
    <section>
        <h2>3. Your Device's Capabilities</h2>
        <p>Below is a live detection of your display's capabilities.</p>

        <div class="detection-grid">
            <div class="detection-card" id="dm-browser">
                <span class="label">display-mode: browser</span>
                <span class="value" id="dm-browser-value">Detecting...</span>
            </div>
            <div class="detection-card" id="dm-standalone">
                <span class="label">display-mode: standalone</span>
                <span class="value" id="dm-standalone-value">Detecting...</span>
            </div>
            <div class="detection-card" id="dm-minimal-ui">
                <span class="label">display-mode: minimal-ui</span>
                <span class="value" id="dm-minimal-ui-value">Detecting...</span>
            </div>
            <div class="detection-card" id="dm-fullscreen">
                <span class="label">display-mode: fullscreen</span>
                <span class="value" id="dm-fullscreen-value">Detecting...</span>
            </div>
            <div class="detection-card" id="dm-pip">
                <span class="label">display-mode: picture-in-picture</span>
                <span class="value" id="dm-pip-value">Detecting...</span>
            </div>
            <div class="detection-card" id="dr-standard">
                <span class="label">dynamic-range: standard</span>
                <span class="value" id="dr-standard-value">Detecting...</span>
            </div>
            <div class="detection-card" id="dr-high">
                <span class="label">dynamic-range: high</span>
                <span class="value" id="dr-high-value">Detecting...</span>
            </div>
        </div>

        <div class="code-block">
            /* Detect display-mode */
            @media (display-mode: browser) { /* Normal browser tab */ }
            @media (display-mode: standalone) { /* Installed PWA */ }
            @media (display-mode: fullscreen) { /* Fullscreen */ }
            @media (display-mode: picture-in-picture) { /* PiP */ }

            /* Detect dynamic-range */
            @media (dynamic-range: standard) { /* SDR display */ }
            @media (dynamic-range: high) { /* HDR display */ }
        </div>
    </section>

    <!-- ====== 4. PRACTICAL EXAMPLE ====== -->
    <section>
        <h2>4. Practical Example: PWA-Aware Styling</h2>
        <p>Styles that adapt when your site is installed as a standalone app.</p>

        <div class="detection-card" id="pwa-status" style="background: #e9ecef; border-color: #6c757d;">
            <span class="label">PWA Status</span>
            <span class="value" id="pwa-status-value">Checking...</span>
        </div>

        <div class="code-block">
            /* Hide browser-specific UI in standalone mode */
            @media (display-mode: standalone) {
                .browser-only {
                    display: none;
                }
                .standalone-only {
                    display: block;
                }
            }

            @media (display-mode: browser) {
                .standalone-only {
                    display: none;
                }
            }
        </div>

        <p class="browser-only" style="display: block; padding: 15px; background: #cce5ff; border-radius: 8px; margin-top: 15px;">
            ๐ŸŒ You're viewing this in a <strong>browser tab</strong>. Install this site as a PWA to see standalone styles!
        </p>
        <p class="standalone-only" style="display: none; padding: 15px; background: #d4edda; border-radius: 8px; margin-top: 15px;">
            ๐Ÿ“ฑ You're viewing this as a <strong>standalone app</strong>! Enjoy the app-like experience.
        </p>
    </section>

    <!-- ====== 5. REFERENCE TABLES ====== -->
    <section>
        <h2>5. Reference Tables</h2>

        <h3>display-mode Values</h3>
        <table class="reference-table">
            <tr>
                <th>Value</th>
                <th>Description</th>
                <th>How to Set</th>
            </tr>
            <tr>
                <td><code>browser</code></td>
                <td>Normal browser tab or window</td>
                <td>Default</td>
            </tr>
            <tr>
                <td><code>standalone</code></td>
                <td>Installed as a standalone app (PWA)</td>
                <td>Manifest: <code>"display": "standalone"</code></td>
            </tr>
            <tr>
                <td><code>minimal-ui</code></td>
                <td>Standalone with minimal browser UI</td>
                <td>Manifest: <code>"display": "minimal-ui"</code></td>
            </tr>
            <tr>
                <td><code>fullscreen</code></td>
                <td>Full screen (no browser chrome)</td>
                <td>Fullscreen API</td>
            </tr>
            <tr>
                <td><code>picture-in-picture</code></td>
                <td>Picture-in-Picture window</td>
                <td>PiP API</td>
            </tr>
            <tr>
                <td><code>window-controls-overlay</code></td>
                <td>PWA with window controls overlay</td>
                <td>Manifest: <code>"display_override"</code></td>
            </tr>
        </table>

        <h3>dynamic-range Values</h3>
        <table class="reference-table">
            <tr>
                <th>Value</th>
                <th>Description</th>
                <th>Requirements</th>
            </tr>
            <tr>
                <td><code>standard</code></td>
                <td>Standard Dynamic Range (SDR)</td>
                <td>Typical displays (8-bit color)</td>
            </tr>
            <tr>
                <td><code>high</code></td>
                <td>High Dynamic Range (HDR)</td>
                <td>Color depth > 24-bit, high contrast, high peak brightness</td>
            </tr>
        </table>

        <h3>HDR Requirements</h3>
        <table class="reference-table">
            <tr>
                <th>Requirement</th>
                <th>Minimum</th>
                <th>Typical HDR</th>
            </tr>
            <tr>
                <td>Color depth</td>
                <td>> 24-bit</td>
                <td>30-bit or 36-bit</td>
            </tr>
            <tr>
                <td>Peak brightness</td>
                <td>โ€”</td>
                <td>1000+ nits</td>
            </tr>
            <tr>
                <td>Contrast ratio</td>
                <td>โ€”</td>
                <td>High (10000:1+)</td>
            </tr>
        </table>
    </section>

    <!-- ====== 6. BEST PRACTICES ====== -->
    <section>
        <h2>6. Best Practices</h2>

        <div style="background: #d4edda; padding: 20px; border-radius: 8px; border-left: 4px solid #28a745;">
            <h3 style="margin-top: 0; color: #155724;">โœ… Do This:</h3>
            <ul>
                <li>Use <code>display-mode</code> to adapt your PWA's UI in standalone mode</li>
                <li>Hide browser-specific UI (like "Add to Home Screen" prompts) in standalone mode</li>
                <li>Use <code>dynamic-range</code> to enhance visuals on HDR displays</li>
                <li>Always provide a <code>standard</code> fallback for SDR displays</li>
                <li>Test your PWA in both browser and standalone modes</li>
                <li>Use the Fullscreen API to test <code>fullscreen</code> mode</li>
            </ul>
        </div>

        <div style="background: #f8d7da; padding: 20px; border-radius: 8px; border-left: 4px solid #dc3545; margin-top: 15px;">
            <h3 style="margin-top: 0; color: #721c24;">โŒ Don't Do This:</h3>
            <ul>
                <li>Don't assume all users are in <code>browser</code> mode</li>
                <li>Don't forget to handle the <code>standalone</code> case for PWAs</li>
                <li>Don't use HDR colors without a <code>standard</code> fallback</li>
                <li>Don't rely on <code>display-mode</code> for critical functionality</li>
                <li>Don't confuse <code>dynamic-range</code> with <code>color-gamut</code> (they're different!)</li>
            </ul>
        </div>
    </section>

    <!-- ====== LIVE INDICATOR ====== -->
    <div class="live-indicator" id="live-indicator">Detecting...</div>

    <!-- ====== SCRIPT FOR DETECTION ====== -->
    <script>
        // Display mode detection
        const displayModes = [
            { id: 'dm-browser', value: 'browser' },
            { id: 'dm-standalone', value: 'standalone' },
            { id: 'dm-minimal-ui', value: 'minimal-ui' },
            { id: 'dm-fullscreen', value: 'fullscreen' },
            { id: 'dm-pip', value: 'picture-in-picture' }
        ];

        function updateDisplayModes() {
            displayModes.forEach(mode => {
                const card = document.getElementById(mode.id);
                const valueEl = card.querySelector('.value');
                const query = `(display-mode: ${mode.value})`;

                if (window.matchMedia(query).matches) {
                    valueEl.textContent = 'Active โœ…';
                    card.style.background = '#d4edda';
                    card.style.borderColor = '#28a745';
                    valueEl.style.color = '#28a745';
                } else {
                    valueEl.textContent = 'Inactive';
                    card.style.background = '#e9ecef';
                    card.style.borderColor = '#6c757d';
                    valueEl.style.color = '#6c757d';
                }
            });
        }

        // Dynamic range detection
        function updateDynamicRange() {
            const standardCard = document.getElementById('dr-standard');
            const highCard = document.getElementById('dr-high');
            const indicator = document.getElementById('live-indicator');

            const isStandard = window.matchMedia('(dynamic-range: standard)').matches;
            const isHigh = window.matchMedia('(dynamic-range: high)').matches;

            if (isStandard) {
                standardCard.querySelector('.value').textContent = 'Supported โœ…';
                standardCard.style.background = '#cce5ff';
                standardCard.style.borderColor = '#007bff';
                standardCard.querySelector('.value').style.color = '#007bff';
            }

            if (isHigh) {
                highCard.querySelector('.value').textContent = 'Supported โœ…';
                highCard.style.background = '#fff3cd';
                highCard.style.borderColor = '#ffc107';
                highCard.querySelector('.value').style.color = '#856404';
                indicator.textContent = 'โœจ HDR Display';
                indicator.style.background = '#ffc107';
                indicator.style.color = '#333';
            } else {
                highCard.querySelector('.value').textContent = 'Not supported';
                highCard.style.background = '#e9ecef';
                highCard.style.borderColor = '#6c757d';
                highCard.querySelector('.value').style.color = '#6c757d';
                indicator.textContent = '๐ŸŽจ SDR Display';
                indicator.style.background = '#007bff';
                indicator.style.color = 'white';
            }
        }

        // Current display mode detection
        function showDisplayMode() {
            const modes = ['browser', 'standalone', 'minimal-ui', 'fullscreen', 'picture-in-picture'];
            let current = 'unknown';
            for (const mode of modes) {
                if (window.matchMedia(`(display-mode: ${mode})`).matches) {
                    current = mode;
                    break;
                }
            }
            document.getElementById('current-display-mode').textContent = current;
        }

        // Fullscreen API
        function enterFullscreen() {
            document.documentElement.requestFullscreen().catch(err => {
                alert('Fullscreen not supported or denied: ' + err.message);
            });
        }

        function exitFullscreen() {
            if (document.fullscreenElement) {
                document.exitFullscreen();
            }
        }

        // Picture-in-Picture (needs a video element)
        function requestPiP() {
            alert('Picture-in-Picture requires a video element. Open a video in PiP mode to see this display mode!');
        }

        // PWA status
        function updatePWAStatus() {
            const el = document.getElementById('pwa-status-value');
            if (window.matchMedia('(display-mode: standalone)').matches) {
                el.textContent = '๐Ÿ“ฑ Standalone (Installed)';
                el.style.color = '#28a745';
            } else {
                el.textContent = '๐ŸŒ Browser Tab';
                el.style.color = '#007bff';
            }
        }

        // Update all
        function updateAll() {
            updateDisplayModes();
            updateDynamicRange();
            updatePWAStatus();
            showDisplayMode();
        }

        window.addEventListener('load', updateAll);
        window.addEventListener('resize', updateAll);

        // Listen for fullscreen changes
        document.addEventListener('fullscreenchange', updateAll);

        // Listen for PiP changes
        document.addEventListener('enterpictureinpicture', updateAll);
        document.addEventListener('leavepictureinpicture', updateAll);

        updateAll();
    </script>

</body>
</html>

Quick Reference

FeatureDescriptionValues
display-modeHow the document is displayedbrowser, standalone, minimal-ui, fullscreen, picture-in-picture
dynamic-rangeBrightness, contrast, color depthstandard, high

display-mode Values

ValueDescriptionHow to Set
browserNormal browser tabDefault
standaloneInstalled PWAManifest: "display": "standalone"
minimal-uiStandalone with minimal UIManifest: "display": "minimal-ui"
fullscreenFull screenFullscreen API
picture-in-picturePiP windowPiP API

dynamic-range Values

ValueDescriptionRequirements
standardStandard Dynamic Range (SDR)Typical displays (8-bit)
highHigh Dynamic Range (HDR)Color depth > 24-bit, high contrast, high brightness

Best Practices

โœ… Do This:

/* Adapt PWA UI in standalone mode */
@media (display-mode: standalone) {
    .browser-only {
        display: none;
    }
    .standalone-only {
        display: block;
    }
}

/* Enhance visuals on HDR displays */
@media (dynamic-range: high) {
    .hero {
        background: linear-gradient(135deg, oklch(69% 0.27 240), oklch(69% 0.27 300));
    }
}

/* Standard fallback */
.hero {
    background: linear-gradient(135deg, #007bff, #6c5ce7);
}

โŒ Don’t Do This:

/* Don't assume all users are in browser mode */
.browser-only {
    display: block; /* May show in standalone too */
}

/* Don't use HDR without fallback */
.hero {
    background: oklch(69% 0.27 240); /* May look wrong on SDR */
}

/* Don't confuse dynamic-range with color-gamut */
@media (dynamic-range: high) {
    /* HDR is about brightness/contrast, not just color */
}

Pro Tip: display-mode is essential for Progressive Web Apps (PWAs). Use it to hide browser-specific UI (like “Add to Home Screen” prompts) when your app is installed as a standalone app. dynamic-range is your key to HDR-enhanced visuals โ€” but remember, HDR is about brightness and contrast, not just color. Always provide a standard fallback first, then enhance for high dynamic range displays. The two features work great together: one for app-like experiences, the other for visually stunning displays!


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!