Skip to content

Practice: Build an animated responsive interface

Continue the task board from the Web interaction assignment. Keep its event-state-render behavior intact while you make the page composition and task components adapt to available space. Add short, finite motion that reinforces one user-triggered state change and provide an equivalent reduced-motion result.

This is Stage 2 of the same source-code project. Do not create another product or repository.

What you will practice

  • Separate viewport-responsive page composition from container-responsive component behavior.
  • Build a complete narrow-first fallback before adding wider arrangements.
  • Use a transition and finite keyframe animation to reinforce existing interaction states.
  • Verify responsive, keyboard, motion-preference, and Stage 1 behavior against one commit.

An interactive feature is not complete when it works at only one width or depends on motion to communicate state. This stage treats layout, wrapping, focus, static state, and motion preferences as parts of the feature’s technical contract.

  • New: A responsive test matrix, a wider page composition, one container-responsive task component, one finite state-change animation, and explicit reduced-motion behavior.
  • Reused: The same product brief, repository, HTML landmarks, form controls, JavaScript state object, task renderer, keyboard route, status output, visual tokens, and verified Stage 1 behavior.
  • Not reopened: Do not redesign the data model or add optional task features while the responsive and motion contract is active.

Starting point

Before you start

  • Complete the interactive task-board assignment and preserve its final verified commit in the private repository.
  • Complete the responsive-components and web-animation lessons.
  • Use the same level-2-task-board folder, Git repository, and private GitHub remote.
  • Use a current browser that can emulate viewport widths and prefers-reduced-motion.
Current state
The task board passes its Stage 1 interaction tests and has a complete narrow single-column baseline, but it has no deliberate wide composition, container query, project motion, or responsive test report.
First action
Open level-2-task-board, run git status, and reload the Stage 1 application before changing any file.
First checkpoint
The identified Stage 1 commit is clean, every interaction still passes, and responsive-test-report.md records the baseline at 320 and 1280 CSS pixels.
Help trigger
Return to the last passing Stage 1 commit or ask for help when an interaction fails before responsive work begins; do not style around an unconfirmed regression.

Requirements

The required assignment is complete when every applicable criterion below is met.

Required responsive behavior

  • The complete application works without horizontal page scrolling at 320 CSS pixels, 1280 CSS pixels, and 200% browser zoom.
  • The base CSS provides the complete narrow layout without depending on a media query or container query.
  • One viewport media query changes the page-level composition when the page has enough space. The breakpoint follows the content rather than a named device.
  • The task-list region establishes an inline-size query container, and each task card has one wider arrangement controlled by that container.
  • The task card remains complete when placed in a narrow container inside an otherwise wide viewport.
  • Long task titles and long category labels wrap without overlap, clipping, inaccessible content, or page overflow.

Required motion behavior

  • One short CSS transition gives feedback for a control state such as hover or active.
  • One finite keyframe animation reinforces a user-triggered task completion or reopening event.
  • The animation runs once, does not flash, does not move a large page area, and does not delay the state update or keyboard focus result.
  • The completed or open state remains visible through text, checkbox state, decoration, or another static cue when animation is unavailable.
  • A prefers-reduced-motion: reduce rule removes the project transition and keyframe motion while preserving the same content, state, focus, and function.
  • No required motion starts automatically, repeats indefinitely, or requires a time-sensitive response.

Accessibility and interaction

  • Every Stage 1 form, validation, checkbox, status, and focus-restoration path still passes with the keyboard.
  • Focus indicators remain visible in narrow and wide arrangements and are not clipped by task-card overflow.
  • Source order remains logical when CSS changes visual arrangement.
  • No information or active state depends only on color, position, or motion.
  • Text can reflow at 200% browser zoom without forcing two-dimensional scrolling for the application content.

Technical constraints

  • Continue the existing index.html, styles.css, app.js, README.md, repository, and private remote.
  • Use CSS Grid or Flexbox for layout. Do not use absolute positioning to create the main page or task-card arrangement.
  • Use one page-level media query and at least one component-level @container query for different layout responsibilities.
  • Use intrinsic and flexible sizing. Do not make the required layout depend on fixed task-card widths or fixed text heights.
  • Keep the event → state update → render sequence from Stage 1. JavaScript can expose the changed task state, but CSS owns the required motion.
  • Add responsive-test-report.md and record every required environment, action, expected result, actual result, and final status.

Design freedom

  • Choose the page grid, task-card wider arrangement, breakpoint values, transition properties, keyframe properties, and exact motion duration.
  • Refine the existing color, type, spacing, border, and elevation system while preserving contrast and state visibility.
  • Choose whether the completion confirmation uses a small emphasis, border, background, opacity, or short transform, provided it meets every motion constraint.

Out of scope

  • A new product brief, new repository, CSS framework, JavaScript framework, build tool, and component library are not required.
  • Task removal, filtering, editing, persistence, APIs, deployment, CMS integration, SEO changes, and analytics changes are not required in this stage.
  • Parallax, scroll-jacking, autoplay sequences, infinite animation, large zoom effects, and flashing content are outside the required motion contract.
  • Pixel-perfect matching to a reference design is not assessed.

The required assignment is complete when one identified commit passes the full Stage 1 regression, responsive matrix, keyboard route, standard-motion result, and reduced-motion result. The commit must exist on the private remote, responsive-test-report.md and README.md must identify it, and git status must be clean.

Open a terminal in level-2-task-board and run:

Confirm the Stage 1 recovery point
git status
git log -1 --oneline
git remote -v

Stop if the working tree contains changes you cannot explain. Preserve them in an intentional commit or ask for help before continuing. Do not reset or discard work to make the output look clean.

Run the Stage 1 self-check from a fresh reload. Record the commit ID and results at the top of a new responsive-test-report.md:

Responsive report header
# Responsive and motion test report
## Baseline
- Product:
- Brief:
- Stage 1 commit:
- Browser and version:
- Baseline interaction result:
- Known limits:

The Stage 1 commit is the recovery point. Keep it in the existing history. A new branch or tag is optional and does not replace the required checkpoint commits.

Checkpoint 1: Record the narrow and wide baseline

Section titled “Checkpoint 1: Record the narrow and wide baseline”

Before changing CSS, test the current application with at least three fictional tasks:

  1. a short title;
  2. a title long enough to wrap across several lines;
  3. a title that contains one uninterrupted test string such as AccessibilityReviewCheckpoint.

Use developer tools to inspect these environments:

ID Environment Expected baseline evidence
BASE-01 320 × 640 CSS pixels No horizontal page scroll; form and task controls remain usable
BASE-02 1280 × 800 CSS pixels Current single-column layout remains complete, even if space is not used well
BASE-03 1280 × 800 at 200% browser zoom Content reflows; focus and text remain available
BASE-04 Narrow task-list host in a wide viewport Record how the current task card uses its own available width

For each row, record Pass, Fail, or Blocked and one actual observation. A failure is baseline evidence, not a reason to hide the row.

Confirm that the report names the Stage 1 commit, browser, four baseline rows, long-content values, and the first responsive problem you will address.

Assistance 1 — Separate a viewport from a component container

The viewport is the browser’s layout area. The task-list region is the component’s containing context. A wide viewport can still give the task list a narrow column, so record both widths when they differ.

Assistance 2 — Find the first element that creates overflow

In developer tools, inspect the element whose right edge extends beyond the visible page. Check fixed widths, min-content sizing, long strings, padding under border-box sizing, and flex or grid children that need min-width: 0.

Checkpoint: The responsive baseline is explicit

What now works
The original application still passes Stage 1, and the report records its actual narrow, wide, zoom, and component-host behavior against one commit.
Files changed
responsive-test-report.md
What remains
Build the complete narrow foundation and a wider page composition without changing application behavior.
Next action
Open styles.css and group the existing base rules before any responsive condition.
If it does not work
If Stage 1 fails, stop responsive work and repair or recover the interaction baseline before editing layout rules.

Record responsive checkpoints in the same repository

Section titled “Record responsive checkpoints in the same repository”

Use focused commits after each passing behavior. Suitable outcomes include:

Example Stage 2 commit messages
Build responsive task board composition
Add container-responsive task cards
Add reduced-motion completion feedback
Document responsive application tests

Each commit must preserve the earlier interaction paths. Push after a checkpoint so the remote remains a usable recovery route.

Checkpoint 2: Build the page composition narrow first

Section titled “Checkpoint 2: Build the page composition narrow first”

Review styles.css and arrange its layers in this order:

  1. design tokens and box sizing;
  2. base type and element behavior;
  3. complete narrow page and component styles;
  4. control states;
  5. page-level media query;
  6. task-card container query;
  7. motion layer;
  8. reduced-motion override.

The order makes the fallback visible and reduces conflicts between unrelated conditions.

In the base layer:

  • keep the page in one column;
  • let inputs, selects, buttons, list items, titles, and categories shrink and wrap;
  • use a flexible content width rather than a fixed page width;
  • keep controls at least 44 CSS pixels high;
  • keep the complete form, summary, task list, and status in source order.

Add one viewport media query only after the narrow route passes. At the chosen content-based breakpoint, arrange the task-entry region and task-list region into a deliberate wider page grid. The status output can span the complete grid.

Choose column proportions from the content. A form often needs a stable readable minimum while the list can use the remaining space. Use minmax() if it helps the grid shrink without overflow.

Test at 1 CSS pixel below and above the page breakpoint. Confirm:

  • the narrow layout is complete below the breakpoint;
  • the wide layout uses space without changing the DOM source order;
  • no control or task text overlaps during the switch;
  • Tab order follows the source order in both arrangements;
  • Stage 1 add and complete behavior still passes.
Assistance 2 — Choose a page breakpoint from a visible failure

Start narrow and increase the viewport. Choose the first width where the two main regions can sit side by side with readable content and control sizes. Record that observation in the test report instead of choosing a device label.

Assistance 3 — Build the page grid without changing component rules

Keep task-card styles unchanged. First name the two main regions with classes. Make main a one-column grid. At one media query, define the wider columns and place the status across them. Verify the page grid before opening the task-card container query.

Checkpoint: The page composition adapts

What now works
The complete narrow page reflows into a deliberate wider composition at a content-based breakpoint while source order, focus order, and Stage 1 behavior remain stable.
Files changed
index.html, styles.css, responsive-test-report.md
What remains
Make task cards respond to the task-list container instead of the viewport.
Next action
Open index.html and identify the task-list wrapper that will establish container-type: inline-size.
If it does not work
If the wide grid overflows, remove explicit column placement, confirm the narrow base, then restore one minmax column definition at a time.

Checkpoint 3: Make task cards respond to their container

Section titled “Checkpoint 3: Make task cards respond to their container”

The page media query and component container query answer different questions:

Condition Responsibility
Viewport media query Can the page arrange the form and task-list regions side by side?
Task-list container query Does this specific list give a task card enough space for a wider internal arrangement?

Add a class to the stable task-list region or wrapper. In styles.css, establish an inline-size query container:

Container boundary pattern
.task-list-region {
container-type: inline-size;
}

Keep the base task card stacked and complete. Then add one container query that rearranges existing task-card content only when the list region is wide enough. For example, the title can use the flexible column while the category occupies an auto-sized column.

Do not query the card’s own size when the card is the element you want to style. Query the stable parent container and change descendants inside it.

Use developer tools to test the same card in both of these conditions:

  • a narrow list column inside a wide page;
  • a wide list region when the page gives it enough space.

Long content must determine whether the chosen threshold works. Adjust the container breakpoint when the category or title becomes cramped.

Add these rows to responsive-test-report.md:

ID Condition Expected result
RESP-01 320 CSS-pixel viewport Stacked page and stacked task cards; no overflow
RESP-02 1 pixel below page breakpoint Complete one-column page
RESP-03 1 pixel above page breakpoint Wide page composition appears without overlap
RESP-04 Narrow list container in wide viewport Task card keeps its stacked internal layout
RESP-05 Wide list container Task card uses its wider internal arrangement
RESP-06 Long title and category Text wraps; control, label, and focus remain available
RESP-07 200% browser zoom Reflow works without horizontal application scrolling

Record the container’s measured width for RESP-04 and RESP-05. This evidence shows that the component responds to its host rather than a remembered viewport value.

Assistance 1 — Identify the query container and changed descendant

The task-list region establishes container-type. The task card or its internal content receives the conditional layout rules. Write those two selectors beside each other before debugging the threshold.

Assistance 2 — Diagnose a container query that never matches

Inspect the intended parent in developer tools. Confirm its computed container-type is inline-size, the @container rule is valid, and the measured container width crosses the threshold. Confirm that the conditional selector targets a descendant of that container.

Assistance 3 — Prove container behavior independently of the viewport

Keep the viewport wide. Temporarily change only the page-grid column allocation so the list becomes narrow and then wide. If the task card changes at its container threshold in both cases, the component boundary works. Remove temporary values after recording the result.

Checkpoint: Task cards adapt to their host

What now works
The task component has a complete stacked fallback and one wider arrangement controlled by the measured task-list container width.
Files changed
index.html, styles.css, responsive-test-report.md
What remains
Add finite interaction feedback and an equivalent reduced-motion result.
Next action
Open app.js and expose which rendered task changed during the completion event.
If it does not work
If only viewport resizing triggers the component, inspect whether the rule is an @media query or whether the container always receives the same width from the page grid.

Checkpoint 4: Add motion after the static state works

Section titled “Checkpoint 4: Add motion after the static state works”

The task’s checkbox, completion text treatment, summary, and status message already communicate the state. Keep those static results. Motion can reinforce the change but cannot become its only evidence.

Choose one small control property, such as background color, border color, or a short button transform. Define the transition on the control’s base rule so both entry and exit states use the same timing. Keep the duration short and the affected area local.

Let renderTasks know which task triggered the completion render. On the matching new list item, add a data attribute such as data-changed="true". Other tasks must not receive that value.

This attribute is temporary interface state for the new render. The task’s persistent completion state remains in the state object.

Target only the changed task card. Use one animation name, one short duration, a finite iteration count of 1, and no start delay. Prefer local emphasis over large movement. The effect must end in the normal static open or completed appearance.

At the end of styles.css, add:

Reduced-motion contract
@media (prefers-reduced-motion: reduce) {
/* Name the project controls that normally transition. */
.project-control {
transition: none;
}
/* Keep the changed task state but remove the effect. */
.task-card[data-changed="true"] {
animation: none;
}
}

Replace .project-control with the actual selector or selectors. Do not use a global rule that changes unrelated browser or extension behavior.

Run these paths with the keyboard:

ID Preference Action Expected result
MOTION-01 No preference Complete one open task Static state updates immediately; local animation runs once; focus returns to its checkbox
MOTION-02 No preference Reopen the same task Static state updates immediately; effect runs once; focus remains useful
MOTION-03 Reduced motion Complete one open task Same checkbox, text, summary, status, and focus results; no project transition or keyframe motion
MOTION-04 Reduced motion Reopen the task Same open-state result; no delay and no motion
MOTION-05 Either preference Wait after the event No animation repeats or continues

Use the browser rendering or emulation controls to change prefers-reduced-motion. Record the exact tool and setting in the report.

Assistance 2 — Trace a state change that animates every task

Inspect the rendered data attributes. Only the task whose ID matches the event’s task ID should receive data-changed="true". Keep data-completed separate because several tasks can be complete at once.

Assistance 3 — Separate static state, event emphasis, and preference

First confirm the checkbox, completion decoration, summary, status, and focus without animation. Then add the changed-task attribute and finite keyframe. Last, emulate reduced motion and disable the transition and animation while leaving all static results unchanged.

Checkpoint: Motion reinforces but does not own the result

What now works
One local effect runs once after a user-triggered task change, while standard and reduced-motion modes provide the same state, content, function, and focus result.
Files changed
styles.css, app.js, responsive-test-report.md
What remains
Run the complete regression, document decisions and limits, and record the verified Stage 2 commit.
Next action
Reload the application and execute the self-check from the first interaction path through the final reduced-motion path.
If it does not work
If reduced motion still moves, inspect computed animation-name and transition-duration on the exact changed task and control while emulation is active.

For every required ID, record:

  • environment or preference;
  • precondition;
  • action;
  • expected result;
  • actual result;
  • Pass, Fail, or Blocked;
  • evidence or focused repair commit when applicable.

Add a final regression section for the Stage 1 paths. Identify any test limit. A result observed in one browser is evidence for that browser and version, not every browser or assistive technology.

Update README.md with:

  • page-level and component-level responsive responsibilities;
  • the page and container breakpoint values and why content supports them;
  • the static completion cues;
  • the motion trigger, duration, affected properties, and iteration count;
  • the reduced-motion result;
  • how to reproduce the responsive and motion tests;
  • the final verified commit;
  • known limits and the next quality-planning step.

Record and push the final checkpoint:

Record the verified Stage 2 application
git status
git diff
git add index.html styles.css app.js README.md responsive-test-report.md
git diff --staged
git commit -m "Complete responsive animated task board"
git push
git status

Self-check

Complete these checks against the required result.

  1. The final commit begins from the verified Stage 1 repository and preserves its product brief, state model, private remote, and history.
  2. Every Stage 1 form, validation, add-task, completion, summary, status, safe-text, and focus-restoration path still passes.
  3. The complete narrow layout works at 320 CSS pixels without a media query or horizontal page scrolling.
  4. One content-based viewport breakpoint changes the page composition without changing source or focus order.
  5. The task-list region is an inline-size query container, and a task card changes its internal layout at a measured container threshold.
  6. The same task card stays stacked in a narrow host inside a wide viewport and uses its wider arrangement in a wide host.
  7. Long task titles, long categories, and 200% browser zoom pass without clipping, overlap, lost controls, or inaccessible content.
  8. One control transition and one changed-task keyframe effect remain local, short, finite, and user-triggered.
  9. The completed or open state is fully understandable from static checkbox, text, summary, and status evidence.
  10. Reduced-motion emulation removes the project transition and keyframe motion without delaying or removing state, content, focus, or function.
  11. responsive-test-report.md records every BASE, RESP, MOTION, and regression result against the final identified commit.
  12. README.md explains the responsive boundaries, motion contract, test route, limits, and next step.
  13. The final commit exists on the private remote, the Console has no unresolved errors, and git status reports a clean working tree.
Area Evidence
Responsive foundation Narrow-first CSS, intrinsic sizing, long-content behavior, zoom reflow, and page composition pass
Component responsiveness The task card responds to a measured container boundary independently of viewport width
Motion design Static state remains primary; the transition and finite effect have a clear trigger and bounded scope
Motion accessibility Reduced-motion mode preserves content, state, interaction, timing, and focus without project motion
Regression safety Every Stage 1 interaction path passes after the CSS and motion changes
Development evidence Focused commits, report rows, README decisions, private remote, and clean final state identify one verified result

The review does not reward more breakpoints or more animation. One well-supported page breakpoint, one well-supported component threshold, and one meaningful finite effect meet the required technical scope.

Assistance 4 — Review a responsive and motion CSS structure

Adapt selectors and values to your application. The comments identify responsibility boundaries; they are not a required visual design.

Partial Stage 2 stylesheet structure
/* 1. Complete narrow page and component fallback */
.app-layout {
display: grid;
gap: var(--space-5);
}
.task-list-region {
container-type: inline-size;
min-width: 0;
}
.task-card,
.task-copy {
min-width: 0;
}
/* 2. Page composition responds to the viewport */
@media (min-width: 56rem) {
.app-layout {
grid-template-columns: minmax(16rem, 0.75fr) minmax(0, 1.25fr);
}
.status {
grid-column: 1 / -1;
}
}
/* 3. Task internals respond to their list container */
@container (min-width: 34rem) {
.task-copy {
grid-template-columns: minmax(0, 1fr) auto;
align-items: baseline;
}
}
/* 4. Optional motion reinforces an existing static state */
.project-control {
transition: background-color 180ms ease, transform 180ms ease;
}
.task-card[data-changed="true"] {
animation: confirm-task 240ms ease-out 1;
}
@keyframes confirm-task {
50% {
outline: 0.2rem solid var(--accent);
outline-offset: 0.2rem;
}
}
/* 5. Preference removes motion, not the result */
@media (prefers-reduced-motion: reduce) {
.project-control {
transition: none;
}
.task-card[data-changed="true"] {
animation: none;
}
}

Complete and test one numbered layer before you open the next.

Assistance 5 — Review one complete Stage 2 change patternExample solution

This pattern assumes the Stage 1 reference classes. Adapt it to your own DOM. It is complete for the responsive and motion changes, not a replacement for your existing application files.

Add class="app-layout" to the element that contains the task-entry section, task-list section, and status. Add class="task-list-region" to the task-list section. Keep the existing semantic source order.

In the render loop, add the changed-task state after the item receives its task-card class:

Expose only the task that triggered this render
item.dataset.changed = String(task.id === focusTaskId);

The existing checkbox handler already passes task.id to renderTasks. The valid submit handler calls renderTasks() without an ID, so adding a task does not receive the completion effect.

Append this tested layer after the complete Stage 1 base CSS. Adjust only a breakpoint that your content evidence shows is unsuitable:

Reference Stage 2 CSS layer
.app-layout {
display: grid;
gap: var(--space-5);
}
.task-list-region {
container-type: inline-size;
min-width: 0;
}
.task-card,
.task-control,
.task-copy {
min-width: 0;
}
.task-copy {
display: grid;
gap: var(--space-1);
}
button {
transition: background-color 180ms ease, transform 180ms ease;
}
button:hover {
background: #18594d;
}
button:active {
transform: translateY(0.1rem);
}
@media (min-width: 56rem) {
.site-header,
main {
width: min(100% - 3rem, 70rem);
}
.app-layout {
grid-template-columns: minmax(16rem, 0.75fr) minmax(0, 1.25fr);
align-items: start;
}
.status {
grid-column: 1 / -1;
}
}
@container (min-width: 34rem) {
.task-copy {
grid-template-columns: minmax(0, 1fr) auto;
align-items: baseline;
gap: var(--space-3);
}
}
.task-card[data-changed="true"] {
animation: confirm-task 240ms ease-out 1;
}
@keyframes confirm-task {
0%,
100% {
outline: 0 solid transparent;
outline-offset: 0;
}
50% {
outline: 0.2rem solid var(--accent);
outline-offset: 0.2rem;
}
}
@media (prefers-reduced-motion: reduce) {
button {
transition: none;
}
button:active {
transform: none;
}
.task-card[data-changed="true"] {
animation: none;
}
}

Run the complete responsive and motion matrix after adapting the pattern. A matching screenshot does not prove container independence, keyboard focus, or reduced-motion behavior.

Stop after a passing checkpoint and push the commit. Add this current-state note to responsive-test-report.md before a longer interruption:

Stage 2 resume note
## Resume here
- Last passing commit:
- Page widths that pass:
- Container widths that pass:
- Motion preference last tested:
- First failing or unfinished test ID:
- Exact next action:
- File and selector or function to open:

When Stage 2 is complete, leave the task-board repository intact. The Quality, SEO, and analytics lessons and final project will use this verified application and its existing history.