Design Technologist · AI-Assisted CSS Engineering

Container-relative notification cards, from viewport assumptions to parent-aware CSS.

This showcase documents the complete assignment from raw semantic HTML through prompt engineering, human auditing, and a verified Interactive Notification Workspace that uses @container and :has() instead of JavaScript state classes.

01Problem
02CSS Concepts
03Raw HTML
04AI Prompt
05Audit
06Final Result
07Verification
01

Why viewport breakpoints were the wrong source of truth

Reusable cards need to adapt to their containing slot, not only to the entire browser window.

Before

A traditional media query can only ask about the viewport. That makes a notification card fragile when the same class appears in a narrow sidebar and a wide main feed at the same time.

Modern approach

Container queries let each .notification-container become the measurement context. The :has() selector then lets the card visually react when its own archive checkbox is checked.

Viewport-only logic Injected state classes JavaScript dependency Collapsed sidebar cards Unverified selectors
02

The CSS systems behind context-aware notification components

Six coordinated ideas turn one repeated card structure into a fluid, state-aware component.

03

The raw HTML before container-aware styling

The assignment starts with two identical notification cards placed into different layout compartments.

before.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Week 06 Lab: Container Queries and :has()</title>
</head>
<body>

  <div class="workspace-grid">
    <!-- Sidebar Container -->
    <aside class="sidebar-region">
      <h2 class="region-title">Sidebar Slot</h2>
      <div class="notification-container">
        
        <!-- Card in narrow sidebar context -->
        <article class="notification-card">
          <div class="card-visual">
            <span class="icon">⚙️</span>
          </div>
          <div class="card-details">
            <h3 class="card-title">System Backup Completed</h3>
            <p class="card-message">Your weekly scheduled system backup finished without warnings.</p>
          </div>
          <div class="card-actions">
            <label class="action-check">
              <input type="checkbox" class="archive-toggle">
              <span class="label-text">Archive</span>
            </label>
          </div>
        </article>

      </div>
    </aside>

    <!-- Main Dynamic Feed Region -->
    <main class="main-region">
      <h2 class="region-title">Main Dynamic Slot</h2>
      <div class="notification-container">
        
        <!-- Identical Card in wide main region context -->
        <article class="notification-card">
          <div class="card-visual">
            <span class="icon">⚙️</span>
          </div>
          <div class="card-details">
            <h3 class="card-title">System Backup Completed</h3>
            <p class="card-message">Your weekly scheduled system backup finished without warnings.</p>
          </div>
          <div class="card-actions">
            <label class="action-check">
              <input type="checkbox" class="archive-toggle">
              <span class="label-text">Archive</span>
            </label>
          </div>
        </article>

      </div>
    </main>
  </div>

</body>
</html>

Browser defaults only

Main Dynamic Slot

⚙️

System Backup Completed

Your weekly scheduled system backup finished without warnings.

04

How the AI prompt became an auditable contract

Each layer turns the assignment’s short prompt blueprint into requirements that can be inspected in CSS.

Layer 1 — Preserve the structure

Keep the supplied workspace, region, card, and checkbox classes intact.

Layer 2 — Register containment

Make each notification container the measurement source with inline-size containment.

Layer 3 — Define the narrow default

Start with a stacked card that remains readable in a sidebar slot.

Layer 4 — Require container response

Use @container (min-width: 500px) for the wide card layout instead of viewport queries.

Layer 5 — Add parent-state styling

Use :has() and :checked so the card archives itself through CSS.

Layer 6 — Demand verification

Require checks for no JavaScript, no card media queries, keyboard access, zoom, and overflow.

AI prompt
Act as a senior CSS systems engineer. Generate a production-ready stylesheet for the supplied semantic Interactive Notification Workspace HTML without replacing its structural class system.

Implementation requirements:

1. Preserve the supplied .workspace-grid, .sidebar-region, .main-region, .notification-container, .notification-card, .card-visual, .card-details, .card-actions, .action-check, and .archive-toggle class names.

2. Register .notification-container as a size containment context with container-type: inline-size so each card responds to the size of its own parent compartment.

3. Style .notification-card with a default narrow layout that stacks the visual, text details, and archive action vertically for sidebar-sized containers.

4. Add @container (min-width: 500px) to convert the same .notification-card structure into a wider horizontal row only when its own .notification-container has enough inline space.

5. Use the relational selector .notification-card:has(.archive-toggle:checked) to dim the archived parent card background, border, and visual treatment without adding JavaScript or external state classes.

6. Keep the checkbox keyboard-accessible, preserve visible focus states, support readable contrast, and prevent long notification text from creating horizontal overflow.

7. Do not use JavaScript, injected classes, floats, absolute positioning for the card layout, or standard viewport @media queries to determine the card's stacked versus horizontal state.

8. Add concise comments explaining the containment context, narrow default card layout, container-query transition, and parent-state :has() rule.

Return only the complete CSS stylesheet.
05

Auditing the generated container-query system

The draft is accepted only when the card state and layout are governed by the right parent contexts.

audited CSS excerpt
.notification-container {
  container-type: inline-size;
}

.notification-card {
  display: grid;
  gap: 1rem;
  align-items: start;
  padding: 1rem;
  border: 1px solid #cbd5e1;
  border-radius: 1rem;
  background: #ffffff;
}

@container (min-width: 500px) {
  .notification-card {
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
  }
}

.notification-card:has(.archive-toggle:checked) {
  border-color: #94a3b8;
  background: #f1f5f9;
  color: #64748b;
}
Containment source

The audited CSS registers .notification-container, not the global workspace, as the query container.

Independent cards

The sidebar card remains stacked while the main-feed card can become horizontal at the same viewport width.

Parent state

The archived style comes from .notification-card:has(.archive-toggle:checked), not from a JavaScript class.

Technique boundary

The card layout has no standard viewport @media breakpoint controlling stacked versus horizontal behavior.

06

The final container-relative notification workspace

Two identical cards now choose their layout from the size of their own parent containers.

Main Dynamic Slot

⚙️

System Backup Completed

Your weekly scheduled system backup finished without warnings.

Same classes

Both cards use the same .notification-card structure, keeping the component reusable.

Different containers

The sidebar container stays narrow, while the main-region container gives the card room to become horizontal.

No script state

Checking Archive dims only that card because :has() evaluates the checkbox inside the parent card.

07

Technical verification before deployment

The final workspace is accepted only after its container behavior and interactive state are tested.

  1. Confirm .notification-container has container-type: inline-size.
  2. Confirm the default card layout is vertically stacked before the container reaches 500px.
  3. Confirm @container (min-width: 500px) switches the card to a horizontal row.
  4. Verify the sidebar card remains stacked while the main-feed card displays horizontally on a wide viewport.
  5. Check Archive on the sidebar card and confirm only that parent card dims.
  6. Check Archive on the main card and confirm no JavaScript class is injected.
  7. Search the assignment CSS for card-sizing viewport @media rules and confirm none are used.
  8. Navigate to both checkboxes with the keyboard and verify visible focus remains readable.
  9. Zoom to 200% and confirm text, controls, and card layout remain usable.
  10. Resize to tablet, mobile, and narrow-mobile widths and confirm there is no horizontal page overflow.
  11. Switch dark/light mode and style families from the Resume page, then return to verify the showcase remains themed and readable.
  12. Use the browser inspector to verify the same card classes are used in both regions.

AI drafted the CSS. Human auditing verified containment, selector state, accessibility, and portfolio consistency.