Adapt a Page with Custom Media

Build a responsive card using named CSS conditions and style query fallbacks.

Introduction

30 Second Summary

A page that feels comfortable with a mouse can become fiddly under a thumb. The same layout can also waste space as the screen grows.

In this project, you will build a product card page that adapts to each visitor using CSS. You will name reusable conditions with @custom-media presets. You will then port those presets to container style queries for consistent behavior across browsers.

What You'll Build

Picture your product card reshaping itself as you move from a touch-sized view to a wide mouse-driven screen in DevTools.

By the end of this project, you'll have:

  • A touch-friendly product card with buttons that grow for coarse pointers. Those controls stay compact for fine pointers.
  • A responsive grid that moves through three layouts as the browser width changes. On suitable hardware, an HDR-aware accent becomes brighter.
  • A reusable preset file that names each condition once. A container style query version carries the same behavior into a second browser.
  • Secret Mission: an optional challenge to push your skills further.

Are there any prerequisites?

You only need a text editor. You also need a modern browser.

Before We Start

Your card page needs to respond to touch, mouse, screen width, plus HDR. A consistent workspace gives you a reliable way to test each condition.

In this step, you'll prepare a code editor plus two modern browsers. You'll also create an empty project folder on your Desktop.

Your primary browser's DevTools will provide device emulation for the pointer checks ahead.

In this step, get ready to:
  • Make a code editor plus two modern browsers available.
  • Prepare an empty adaptive-card-page workspace in your editor.
  • Confirm that device emulation is available in your primary browser.
Check your local tools

A code editor gives you one place to write HTML plus CSS. Two browsers let you compare the same local page later.

  • Check your computer for a code editor that can edit plain-text files.
  • Check your computer for two modern desktop browsers.
  • Confirm that one browser offers developer tools with device emulation.

✔️ I have all three tools

Your local toolkit is ready. It supports the editing plus comparison work ahead.

ⓧ I am missing a tool

Choose tools that cover each role before you continue. Official download websites give you the current installers for your computer.

  • Choose a code editor that supports plain-text HTML plus CSS files.
  • Download the editor from its official website.
  • Install the editor using the installer's default options.
  • Choose two current desktop browsers from different browser makers.
  • Download each browser from its official website.
  • Install each browser using the installer's default options.
  • Check one browser's official developer documentation for a built-in device emulation or responsive testing mode.

Can't find device emulation?

A browser can place device testing inside its developer tools. Check the browser's own developer documentation for its device or responsive testing control.

Get help locating device emulation in your chosen browser.

Create your empty project folder

A dedicated folder keeps every page file together. Starting with an empty folder also gives you a clear baseline for the first build step.

macOS

  • Press Cmd+Space to open system search.
  • Type Finder in the search field.
  • Press Enter to launch Finder.
  • Select Desktop in the Finder sidebar.
  • Click File in the menu bar.
  • Click New Folder.
  • Name the folder adaptive-card-page.
  • Press Enter to create the folder.

Windows

  • Press the Windows key to open system search.
  • Type File Explorer in the search field.
  • Press Enter to launch File Explorer.
  • Select Desktop in the File Explorer sidebar.
  • Right-click a blank area in the Desktop view.
  • Select New in the context menu.
  • Select Folder.
  • Name the folder adaptive-card-page.
  • Press Enter to create the folder.

You should see an empty adaptive-card-page folder on your Desktop. That clean folder is your blank canvas for the card page.

  • Press Cmd+Space on macOS or the Windows key on Windows to open system search.
  • Type the name of your code editor in the search field.
  • Press Enter to launch the editor.
  • Select your editor's folder-opening command from the File menu.
  • Select the adaptive-card-page folder on your Desktop.
  • Confirm the folder selection in the file picker.

You'll see adaptive-card-page in the editor's file sidebar. No project files should appear inside it.

Confirm your browser testing controls

Device emulation can hide behind a small toolbar control, so it is normal if it takes a moment to spot. Once active, it gives you a resizable page viewport for the touch checks ahead.

  • Press Cmd+Space on macOS or the Windows key on Windows to open system search.
  • Type the name of your primary browser in the search field.
  • Press Enter to launch the browser.
  • Open the browser's main menu.
  • Select its developer tools entry.
  • Activate its device emulation or responsive testing control.

You should see a page viewport inside the developer tools. You should also see controls for changing the emulated device or viewport.

Don't see a device viewport?

Make sure the developer tools are open in your primary browser. Look for a control that switches the page into device or responsive testing mode.

Ask for help with the testing controls you see.

  • Return to system search.
  • Type the name of your second browser in the search field.
  • Press Enter to launch the second browser.

Before you check, do you expect the editor sidebar to list any files yet?

  • Return to your code editor.
  • Inspect the editor's file sidebar.
  • Return to your primary browser.
  • Confirm that device emulation remains active.
  • Return to your second browser.
  • Confirm that its browser window is ready.

You'll see the empty adaptive-card-page folder open in your editor. That empty state matches the project starting point exactly.

Your primary browser shows its device testing viewport. Your second browser is ready for the cross-browser check later.

Your testing workspace is ready. Next up, you'll build the plain card page and see its unstyled baseline.

Build the Card Page

Adaptive behavior is easier to judge when you have a stable starting point. A plain card page gives every later touch, screen size, and display test the same content.

You’ll create the page structure with HTML. You’ll link a CSS file that contains no styling rules yet.

In this step, get ready to:
  • Create the linked stylesheet for your adaptive rules.
  • Build a product grid with content and controls.
  • Load the page to capture its unstyled baseline.
Create the linked stylesheet

A linked stylesheet needs to exist before the browser requests it. Keeping the file comment-only preserves the unstyled baseline.

  • Create a file named styles.css inside the open project folder using the editor sidebar.
  • Add a placeholder comment by pasting the code below:
/* Adaptive rules are added in the next steps. */

What does this stylesheet do?

The comment keeps styles.css valid without adding visual rules. The browser can resolve the stylesheet while showing its default rendering.

  • Save styles.css.
  • Confirm that styles.css remains listed in the editor sidebar.

Don’t see styles.css?

  • Check that the file sits directly inside the open project folder.
  • Check that the filename ends with .css.

Help me find my stylesheet in the editor.

✔️ Awesome, I've got everything!

Your stylesheet exists with no visual rules, which keeps the baseline clean.

ⓧ I'd like to double check the full code

/* Adaptive rules are added in the next steps. */

What should match?

Your complete styles.css file contains this single comment. No responsive, input, display range, or container rules belong here yet.

Build the product card grid

The product grid needs repeated cards so later layout changes are easy to spot. Each article keeps one product’s content and controls together.

  • Create a file named index.html inside the open project folder using the editor sidebar.
  • Build the product page by pasting the code below into index.html:
<!doctype html>
<html lang="en">
<head>
  <!-- Keep document settings together so the cards render consistently. -->
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Adaptive Product Cards</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <main class="product-grid" aria-label="Featured products">
    <!-- Each card keeps its content and controls together for later layout tests. -->
    <article class="product-card"><h2>Trail Bottle</h2>
      <p>A steel bottle for long walks and busy commutes.</p>
      <p class="product-card__price">$28</p>
      <div class="product-card__actions"><button type="button">Add to cart</button><button type="button">View details</button></div></article>
    <article class="product-card"><h2>Desk Lamp</h2>
      <p>A compact light with a warm reading mode.</p>
      <p class="product-card__price">$46</p>
      <div class="product-card__actions"><button type="button">Add to cart</button><button type="button">View details</button></div></article>
    <article class="product-card"><h2>Travel Pack</h2>
      <p>A lightweight pack with space for daily essentials.</p>
      <p class="product-card__price">$72</p>
      <div class="product-card__actions"><button type="button">Add to cart</button><button type="button">View details</button></div></article>
  </main>
</body>
</html>

What does this code do?

  • The stylesheet link connects index.html to styles.css.
  • The product-grid class provides one shared layout hook for every card.
  • Each product-card groups a product name, description, price, and controls.
  • The product-card__actions class gives both buttons a shared target for later input changes.
  • Save index.html.
  • Confirm that index.html appears beside styles.css in the editor sidebar.

Don’t see index.html?

  • Check that you created the file directly inside the open project folder.
  • Check that the filename ends with .html.

Help me check my page files.

✔️ Awesome, I've got everything!

Your page structure is saved with three products and two controls per card.

ⓧ I'd like to double check the full code

<!doctype html>
<html lang="en">
<head>
  <!-- Keep document settings together so the cards render consistently. -->
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Adaptive Product Cards</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <main class="product-grid" aria-label="Featured products">
    <!-- Each card keeps its content and controls together for later layout tests. -->
    <article class="product-card"><h2>Trail Bottle</h2>
      <p>A steel bottle for long walks and busy commutes.</p>
      <p class="product-card__price">$28</p>
      <div class="product-card__actions"><button type="button">Add to cart</button><button type="button">View details</button></div></article>
    <article class="product-card"><h2>Desk Lamp</h2>
      <p>A compact light with a warm reading mode.</p>
      <p class="product-card__price">$46</p>
      <div class="product-card__actions"><button type="button">Add to cart</button><button type="button">View details</button></div></article>
    <article class="product-card"><h2>Travel Pack</h2>
      <p>A lightweight pack with space for daily essentials.</p>
      <p class="product-card__price">$72</p>
      <div class="product-card__actions"><button type="button">Add to cart</button><button type="button">View details</button></div></article>
  </main>
</body>
</html>

What should match?

Your complete index.html file links to styles.css. It contains the Trail Bottle, Desk Lamp, and Travel Pack cards.

View the unstyled baseline

Browser-default rendering gives you a control sample for every adaptive change that follows. The page should look plain because the stylesheet contains no visual rules.

Before you load the page, which parts do you expect the browser to place on separate lines?

  • Load index.html in the browser using the local-page method from your setup.

You’ll see three product names in one vertical browser-default flow.

Under each price, you’ll see two plain buttons labelled Add to cart and View details.

Page blank or missing content?

  • Refresh the browser after saving index.html.
  • Check that the opening and closing main tags surround all three cards.
  • Check that index.html and styles.css sit in the same project folder.

Help me debug my local product page.

Your unstyled baseline is ready. Next, you’ll make the controls respond to touch and mouse input.

Add Input Presets

Your product card is open in the browser. Its controls currently stay the same size for every input device.

A finger needs a roomier target than a mouse pointer. Custom media queries let you name each input condition once. Your stylesheet can reuse those names wherever controls need to adapt.

In this step, get ready to:
  • Enable experimental custom media support for this browser test.
  • Create the two input presets in presets.css.
  • Verify the button sizing with touch and mouse emulation.
Enable experimental custom media support

The @custom-media at-rule has limited browser support. Firefox provides it as an experimental feature from version 148.

Changing an experimental preference can feel risky. This preference controls custom media parsing. You can return it to false after the project.

  • Switch to Firefox 148 or later from your two-browser setup.
  • Enter about:config in the address bar.

Firefox shows a configuration warning before exposing its experimental preferences.

  • Continue past the configuration warning.
  • Search for layout.css.custom-media.enabled.

You will see the matching preference with a Boolean value.

  • Toggle layout.css.custom-media.enabled to true.

That preference is active. Firefox can now parse the named conditions you add next.

Preference missing?

  • Confirm that your Firefox release is version 148 or later.
  • Search for the complete preference name without extra spaces.
  • Ask for help checking your Firefox custom media preference.
Build the preset file

The pointer media feature describes the accuracy of the primary input. A coarse pointer represents limited accuracy such as a finger. A fine pointer represents precise input such as a mouse.

  • In the code editor's file sidebar, create presets.css inside the local project folder.
  • Add both named input conditions by pasting this code:
/* Primary input mechanism is mouse or an emulated mouse */
@custom-media --mouse (hover: hover) and (pointer: fine);

/* Primary input mechanism is touch */
@custom-media --touch (hover: none) and (pointer: coarse);

What do these presets do?

  • The --mouse preset requires hover support plus a fine primary pointer.
  • The --touch preset requires no hover support plus a coarse primary pointer.
  • Each name now represents its complete capability check.
  • Save presets.css.
  • Confirm that presets.css appears beside index.html and styles.css in the file sidebar.

Your reusable input conditions now have their own file. Future styles can refer to their names instead of repeating the full capability checks.

Preset file not listed?

  • Check that you created presets.css inside the same local project folder as index.html.
  • Check that the filename ends in .css.
  • Ask for help finding the new preset file.

✔️ Awesome, I've got everything!

Your preset file is complete. Both primary input conditions have reusable names.

ⓧ I'd like to double check the full code

/* Primary input mechanism is mouse or an emulated mouse */
@custom-media --mouse (hover: hover) and (pointer: fine);

/* Primary input mechanism is touch */
@custom-media --touch (hover: none) and (pointer: coarse);

This reference should match the complete contents of presets.css.

Adapt the buttons

The preset file defines the conditions. Your linked stylesheet now needs to import those definitions before using their names.

  • Switch back to styles.css from earlier.
  • Place the preset import plus the mouse sizing rule at the top of the file by adding this code:
/* Load the reusable media condition aliases first */
@import "presets.css";

/* Use compact controls for a precise primary pointer */
@media (--mouse) {
  button {
    min-height: 36px;
    padding: 8px 12px;
  }
}

What does this code do?

  • The @import rule loads the named conditions before the rest of the stylesheet.
  • The --mouse branch gives each button a 36px minimum height.
  • The smaller padding keeps the controls compact for precise input.
  • Save styles.css.
  • Return to the product card in Firefox.
  • Reload the product card page.

With a mouse as the primary input, you will see compact buttons that are taller than the unstyled controls.

Buttons still unstyled?

  • Check that @import "presets.css"; is above every other rule in styles.css.
  • Confirm that layout.css.custom-media.enabled still reads true.
  • Ask for help tracing the missing mouse styles.
  • Return to the bottom of styles.css.
  • Add the larger touch sizing by pasting this code:
/* Give touch controls a larger target */
@media (--touch) {
  button {
    min-height: 44px;
    padding: 12px 16px;
  }
}

How does the touch branch help?

  • The --touch branch activates for a coarse primary pointer without hover support.
  • The 44px minimum height gives a finger a larger target.
  • The larger padding creates more space around each button label.
  • Save styles.css.

Before you switch input modes, which branch do you expect to produce the larger buttons?

  • Return to the product card page in Firefox.
  • Press Cmd+Opt+M on macOS or Ctrl+Shift+M on Windows to enter Responsive Design Mode.
  • Click the Enable/Disable touch simulation control in the Responsive Design Mode toolbar.
  • Reload the product card page.

The touch simulation control turns blue. You will see the buttons grow to the larger touch-friendly size.

  • Click the Enable/Disable touch simulation control again.
  • Reload the product card page.

The control returns to black. You will see the buttons return to their compact mouse size.

Button size does not change?

  • Confirm that touch simulation is blue during the touch check.
  • Check that @media (--touch) contains the 44px minimum height.
  • Check that the closing braces match the full reference below.
  • Ask for help testing the input presets.

✔️ Awesome, I've got everything!

Your stylesheet imports both presets. The product card now responds to the primary input mechanism.

ⓧ I'd like to double check the full code

/* Load the reusable media condition aliases first */
@import "presets.css";

/* Use compact controls for a precise primary pointer */
@media (--mouse) {
  button {
    min-height: 36px;
    padding: 8px 12px;
  }
}

/* Give touch controls a larger target */
@media (--touch) {
  button {
    min-height: 44px;
    padding: 12px 16px;
  }
}

This reference should match the complete input-related contents of styles.css.

You have proved that one card can adapt to touch and mouse input. Next up, you will name the viewport breakpoints that reshape its grid.

Add Responsive Grid Presets

Your buttons already respond to touch and mouse input. The card grid now needs to respond as the browser window grows.

A responsive breakpoint marks the width where a layout changes. You will name three viewport conditions with @custom-media before connecting each one to a grid layout.

In this step, get ready to:
  • Add three named viewport conditions to presets.css.
  • Apply three responsive grid layouts in styles.css.
  • Resize the browser through every grid layout.
Name the viewport conditions

The presets.css file keeps reusable conditions in one place. Descriptive breakpoint names let the stylesheet refer to each width without repeating its condition.

  • In the code editor from earlier, select presets.css in the project sidebar.
  • Keep the existing coarse-pointer preset unchanged.
  • Keep the existing fine-pointer preset unchanged.
  • Add three named viewport conditions below the input presets in ascending width order.
  • Save presets.css.
  • Open your editor's search panel.
  • Search for @custom-media.

You should see five declarations in the search results. Two declarations describe input mechanisms. Three declarations describe viewport widths.

Only seeing the input presets?

  • Check that all three viewport conditions are saved inside presets.css.
  • Use this breakpoint check to find a missing declaration.
Connect presets to the grid

The named conditions control the grid when styles.css references them. The CSS cascade lets wider matching sections replace the earlier layout as the window expands.

  • Select styles.css in the project sidebar.
  • Find the rule that controls the product-card grid.
  • Keep the existing coarse-pointer button sizing unchanged.
  • Keep the existing fine-pointer button sizing unchanged.
  • Update the responsive grid rules in ascending threshold order to reference all three viewport presets across three distinct layouts.
  • Save styles.css.
Resize through every layout

Each breakpoint should produce an observable change in the grid. Testing every width confirms that all three preset references are active.

Before you resize, do you expect the grid to change at every named threshold?

  • Return to the page already open in your browser.
  • Resize the window until only the first viewport condition matches.

You should see the grid use its compact arrangement.

  • Widen the window until the second viewport condition matches.

You should see the cards move into the middle arrangement.

  • Widen the window until the third viewport condition matches.

You should see the grid use its widest arrangement.

  • Move the window back and forth across each breakpoint boundary.

The cards should switch cleanly among all three layouts. Each change proves that a named viewport condition is controlling the grid.

Grid staying in one layout?

  • Compare each preset name in presets.css with its reference in styles.css.
  • Check that the responsive grid rules appear after the base grid rule in styles.css.
  • Use this responsive grid check to trace a mismatch.

That responsive system is now working across the full window range. Your grid can move through three layouts without repeating its width conditions.

Next, you will give the page accent a display-aware branch for screens with a wider visual range.

Add the HDR Preset

Your grid now responds at all three viewport breakpoints. The final device signal is HDR, which lets the page brighten its accent when the screen supports the extra display range.

An HDR check depends on real display hardware. You will add the condition to your presets before checking which styling branch your screen receives.

In this step, get ready to:
  • Add an HDR display-range condition to presets.css.
  • Apply a brighter button accent from styles.css.
  • Identify which display-range branch your screen receives.
Name the HDR condition

True HDR combines high dynamic range with a P3 color gamut. A custom media query gives that two-part test one reusable name.

  • Switch back to presets.css in your code editor.
  • Place your cursor after the three viewport breakpoint conditions.
  • Add the HDR preset by pasting this code:
/* True HDR needs high dynamic range plus a wide P3 color gamut. */
@custom-media --true-hdr (dynamic-range: high) and (color-gamut: p3);

What does this preset check?

  • The dynamic-range: high condition checks whether the browser and screen support high dynamic range visuals.
  • The color-gamut: p3 condition checks whether the display supports the wider P3 color range.
  • The --true-hdr name keeps both requirements together wherever you use the preset.
  • Save presets.css.
  • Confirm that the new --true-hdr condition appears after your viewport presets.

Is the preset marked as unsupported?

Some editors flag experimental CSS syntax even when the line is valid. Check that the preset starts with @custom-media and ends with a semicolon.

Help me check why my HDR custom media preset is marked as unsupported.

Brighten the accent on HDR screens

The base button style remains the standard-range presentation. The HDR rule adds extra brightness only when --true-hdr matches.

  • Switch back to styles.css in your code editor.
  • Place your cursor after the existing media rules.
  • Add the HDR accent override by pasting this code:
@media (--true-hdr) {
  /* Brighten the existing button accent on HDR-capable displays. */
  button {
    filter: brightness(1.2);
  }
}

What does this rule do?

  • The @media rule activates only when the named HDR condition matches.
  • The button keeps its existing accent while brightness(1.2) increases its visible brightness.
  • Standard-range displays continue using the base button treatment.
  • Save styles.css.
  • Refresh the product card page in the browser from earlier.

On an HDR-capable display, the button accent gains extra brightness. A standard-range display preserves the base accent.

Does the button look unchanged?

Your screen may be receiving the standard-range branch. The next check reads the display condition directly.

Help me check why my HDR rule is not brightening the button accent.

Check your display branch

The display hardware decides whether the HDR condition matches. The browser console can report that decision as a boolean value.

  • Return to DevTools from your earlier input tests.
  • Select the browser console panel.

Before you run the check, do you expect your screen to match the HDR condition?

  • Check the live display condition by pasting this expression:
window.matchMedia("(dynamic-range: high) and (color-gamut: p3)").matches

What does this check do?

  • The matchMedia() method evaluates the same two display conditions used by your preset.
  • The matches property reports whether the current browser and screen satisfy both conditions.

You will see true on an HDR-capable P3 display. You will see false when your screen receives the standard-range styling branch.

  • Return to the product card page while keeping the console result visible.
  • Compare the button accent with the branch reported by the console.

That check settles it. Your page now selects the brighter accent only when the display meets both HDR requirements.

Does the console reject the expression?

Make sure you pasted the expression into the console input area. Check that both media conditions remain inside the quotation marks.

Help me diagnose my display-range console check.

Your page now responds to input method, viewport width, and display range. Next, you will port these named conditions to the cross-browser version.

Port to Container Style Queries

Your product card already responds to pointer type, viewport width, and HDR display range. The remaining problem is browser reach.

Container style queries can reproduce those behaviors without relying on native @custom-media support. You will keep presets.css as a reusable reference while you port the working branches.

In this step, get ready to:
  • Keep the named-condition preset file reusable.
  • Port the pointer, layout, and HDR branches to container style queries.
  • Confirm the page behaves the same way in a second browser.
Port the input conditions

The fallback separates condition detection from the styles that use each condition. The root element records a match through inherited custom properties.

Each container style query reads one matching property. The existing button declarations stay attached to their original pointer condition.

  • In index.html, locate the existing stylesheet link for styles.css.
  • Add presets.css as a linked stylesheet immediately before that link.
  • Save index.html.
  • Reload the page in the first browser.

You should see the same product card. This confirms that the reusable preset file loads without changing the current page.

How Does the Port Work?

Each root-level media rule uses a condition expression from presets.css. A match sets a custom property with the corresponding condition name.

Descendants inherit that property. A container style query can then activate the declarations associated with that condition.

  • In styles.css, rewrite both pointer branches as root-level condition flags consumed by matching container style queries.
  • Keep the touch-friendly button declarations inside the coarse-pointer branch.
  • Keep the compact button declarations inside the fine-pointer branch.
  • Save styles.css.

Before you switch pointer profiles, do you expect the button to keep changing size after the port?

  • Return to the DevTools device emulation view from earlier.
  • Select the coarse-pointer profile.

You should see the button grow to its touch-friendly size.

  • Select the fine-pointer profile.

You should see the button return to its compact mouse-friendly size. Both input branches now work through container style queries.

Button Size Staying the Same?

Compare each root flag name with the name read by its container style query. A spelling mismatch prevents the query from seeing the active condition.

Confirm that each set of button declarations stayed inside the correct pointer branch. Help me troubleshoot my pointer style queries.

Port the layout and HDR conditions

The same flag pattern can represent each viewport condition. Every layout query keeps the grid declarations from its matching named branch.

  • In presets.css, locate the three viewport condition expressions.
  • In styles.css, rewrite all three layout branches as root-level flags consumed by matching container style queries.
  • Save styles.css.

Before you resize the browser, which of the three grid layouts do you expect to see at its current width?

  • Resize the first browser through the same three viewport ranges you tested earlier.

You should see the grid move through all three layouts. Each transition should occur at the same width as before.

Grid Missing a Layout?

Confirm that every viewport condition creates its own root flag. Check that every layout query reads the corresponding flag name.

Keep each set of grid declarations inside its original layout branch. Help me trace the missing responsive branch.

The HDR branch follows the same pattern. Its brighter accent remains tied to the display-range condition from presets.css.

  • In styles.css, rewrite the HDR branch as a root-level flag consumed by a matching container style query.
  • Keep the brighter accent declaration inside that query.
  • Save styles.css.

Before you reload, do you expect your display to receive the brighter accent or the standard-range accent?

  • Reload the page in the first browser.

You should see the same accent branch that your display received earlier. The display-range behavior has survived the port.

Accent Branch Changed?

Compare the HDR condition in styles.css with its condition in presets.css. Confirm that both expressions match.

Check the root flag name against the name read by the HDR style query. Help me troubleshoot the HDR branch.

Check the page in a second browser

A second browser provides the final portability check. The card should react to the same conditions without depending on native custom-media support.

  • Switch to the second browser from earlier.
  • Drag index.html from the local project folder into the browser window.

Before you compare the two browsers, do you expect the pointer controls, grid layouts, and accent branch to match?

  • Resize the second browser through the same three viewport ranges.

You should see the grid move through the same three layouts at the same widths.

  • Return to device emulation in the second browser.
  • Select the coarse-pointer profile.

You should see the same touch-friendly button size as in the first browser.

  • Select the fine-pointer profile.

You should see the button return to the same compact size.

  • Compare the accent branch with the one shown in the first browser.

You should see the same accent branch in both browsers. This proves that the port preserves every behavior across the two browsers.

Browsers Showing Different Results?

Confirm that both browsers loaded the saved files from the same local project folder. Reload each page after correcting any unsaved changes.

Compare the pages at the same window width with the same pointer profile. Help me compare the browser results.

That completes the portability check. Your product card now preserves its touch controls, responsive layouts, and HDR accent in a second browser.

Secret mission

Build a Cross-Browser Test Matrix

Turn your adaptive card into a repeatable quality check. Test every pointer-layout combination in both browsers. Capture proof that the states agree.

Clean Up Your Resources

Clean Up Your Resources

Your local HTML and CSS page has no running services or ongoing costs. Decide whether to keep the files, pause by closing your tools, or delete the page files.

Resources you used:

  • The local index.html file that holds your product card page.
  • The reusable presets.css file that holds your named conditions.
  • The local styles.css file that controls the adaptive card styles.

Keep everything running

No action is needed. This option fits if you want to reuse the page or its named conditions in another project.

  • Keep index.html, presets.css, and styles.css together in the local project folder.
  • Reuse presets.css as a drop-in source of named conditions for a future page.
  • Open index.html in either browser whenever you want to test the adaptive card again.

Pause - I'll come back to this later

Pausing leaves your local files intact while your tools remain closed. Your finished page stays ready for another session.

  • Save any open changes to index.html, presets.css, and styles.css.
  • Close the product card page in each browser.
  • Close the code editor from earlier.

Delete - I don't want to use this again

Deleting your finished page can feel drastic. This option removes only index.html, presets.css, and styles.css from the local project.

Your code editor may ask you to confirm each deletion.

  • Delete index.html through the context menu in the code editor's file sidebar.
  • Approve the deletion if your editor asks for confirmation.
  • Delete presets.css through the context menu in the code editor's file sidebar.
  • Approve the deletion if your editor asks for confirmation.
  • Delete styles.css through the context menu in the code editor's file sidebar.
  • Approve the deletion if your editor asks for confirmation.
  • Confirm that index.html, presets.css, and styles.css no longer appear in the file sidebar.

Nice Work!

Nice Work!

You made it! Your product card now adapts itself to each visitor's hardware.

The controls respond to pointer type. The layout responds to screen size. The accent responds to display range.

You've learned how to:

  • Build adaptive controls that grow for coarse pointers. The same controls stay compact for fine pointers.
  • Create reusable named conditions in presets.css with CSS @custom-media presets for pointer input. The file also captures three viewport breakpoints. It includes an HDR display condition.
  • Port the named conditions to container style queries. You confirmed the same touch behavior in a second browser. You also confirmed the same grid behavior. The HDR branch stayed consistent too.
  • Secret Mission: Apply the same condition-first approach in an optional project extension that pushes your adaptive styling skills further.

Ready to quiz yourself?