Wire background-image url() to ImageId via ImageStore lookup during layout, add canvas background URL resolution for root/body propagation, and verify all background sub-properties end-to-end with 8 golden tests (241-248). Includes code review fixes: deduplicate ImageStore.insert_url, extract apply_styles_to_canvas helper, remove redundant Phase 2 canvas propagation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
299 lines
22 KiB
Markdown
299 lines
22 KiB
Markdown
# Story 1.7: Backgrounds
|
|
|
|
Status: done
|
|
|
|
## Story
|
|
|
|
As a web user,
|
|
I want page and element backgrounds to render correctly with images, patterns, and positioning,
|
|
so that visually rich websites display as intended.
|
|
|
|
## Acceptance Criteria
|
|
|
|
1. **Given** an element with the full `background` shorthand property, **When** the page is rendered, **Then** all background sub-properties (color, image, repeat, attachment, position) are parsed and applied correctly per CSS 2.1 §14.2.1
|
|
2. **Given** an element with `background-image: url(...)` and `background-repeat`, **When** the page is rendered, **Then** the image is tiled according to the repeat value (repeat, repeat-x, repeat-y, no-repeat)
|
|
3. **Given** an element with `background-attachment: fixed`, **When** the page is scrolled, **Then** the background image remains fixed relative to the viewport
|
|
4. **Given** an element with `background-position` using keyword, percentage, or length values, **When** the page is rendered, **Then** the background image is positioned correctly within the element's padding box
|
|
5. Golden tests cover each background property combination, checklist is updated, and `just ci` passes
|
|
|
|
## Tasks / Subtasks
|
|
|
|
> **NOTE:** `background-color` is **fully implemented**. CSS parsing and shorthand expansion for all background properties **already exist**. Computed style fields, layout box fields, display list items, and rasterizer drawing for background images, gradients, repeat, attachment, and position are **all wired**. The main gap is that `background-image: url(...)` images are **not loaded** during layout — only `<img>`/`<object>` elements resolve image URLs to `ImageId`. This story completes the background-image URL loading pipeline and verifies all sub-properties work end-to-end with golden tests.
|
|
|
|
- [x] Task 1: Wire background-image URL resolution to ImageId (AC: #2)
|
|
- [x] 1.1 In `crates/layout/src/engine/box_tree.rs` `build_layout_box()`: after `apply_computed_styles_to_box()`, when `computed.background_image` is `BackgroundImage::Url(url)`, resolve via `image_store.get_by_url(url)` and store as `background_image_id` on the `LayoutBox`
|
|
- [x] 1.2 Used Option B: Added `url_to_image: HashMap<String, ImageId>` to `ImageStore` with `insert_url()` and `get_by_url()` methods
|
|
- [x] 1.3 Background images use URL-based lookup via `ImageStore.get_by_url()`, separate from element images' `NodeId`-based `image_map`
|
|
- [x] 1.4 Extended `run_pipeline_with_images()` in `tests/goldens.rs` to scan computed styles for `BackgroundImage::Url` and load images via `image_store.insert_url()`
|
|
- [x] 1.5 Fallback works: if URL not in ImageStore, `get_by_url` returns `None` and `background_image_id` stays `None` — background-color still renders
|
|
- [x] 1.6 Unit tests: 4 ImageStore URL tests + 4 layout-level background-image URL resolution tests
|
|
|
|
- [x] Task 2: Verify background-repeat works end-to-end (AC: #2)
|
|
- [x] 2.1 `BackgroundRepeat` enum verified in `crates/shared/src/lib.rs`
|
|
- [x] 2.2 Parsing verified in computed styles
|
|
- [x] 2.3 `LayoutBox` `background_repeat` field verified
|
|
- [x] 2.4 Display list builder passes repeat to `DisplayItem::BackgroundImage` verified
|
|
- [x] 2.5 Rasterizer tiling logic verified
|
|
- [x] 2.6 Tiling logic verified correct per CSS 2.1 §14.2.2
|
|
- [x] 2.7 Golden test 242 verifies all 4 repeat modes end-to-end
|
|
|
|
- [x] Task 3: Verify background-attachment works end-to-end (AC: #3)
|
|
- [x] 3.1 `BackgroundAttachment` enum verified
|
|
- [x] 3.2 Parsing and computed style field verified
|
|
- [x] 3.3 Display list builder handles `Fixed` attachment verified
|
|
- [x] 3.4 Rasterizer handles `Fixed` by positioning relative to viewport verified
|
|
- [x] 3.5 `scroll` (default) works — normal behavior verified
|
|
- [x] 3.6 `fixed` works — viewport-relative positioning verified via golden test 245
|
|
- [x] 3.7 `local` (CSS3) — parsing works, implementation deferred
|
|
- [x] 3.8 Golden test 245 verifies `background-attachment: fixed`
|
|
|
|
- [x] Task 4: Verify background-position works end-to-end (AC: #4)
|
|
- [x] 4.1 `BackgroundPositionValue` enum verified
|
|
- [x] 4.2 Keyword, percentage, and length parsing verified
|
|
- [x] 4.3 Position-x/y separate computed fields verified
|
|
- [x] 4.4 Position calculation verified per CSS 2.1 §14.2.1
|
|
- [x] 4.5 Position applies to padding box verified
|
|
- [x] 4.6 Golden tests 243 (keywords) and 244 (percentages) verify positioning
|
|
|
|
- [x] Task 5: Verify background shorthand end-to-end (AC: #1)
|
|
- [x] 5.1 Shorthand parsing verified (1009 lines in background.rs)
|
|
- [x] 5.2 Shorthand correctly expands to all sub-properties verified via golden test 246
|
|
- [x] 5.3 Omitted components reset to initial values verified
|
|
- [x] 5.4 Golden test 246: `background: #f0f0f0 url(image.png) no-repeat center top` — output shows SolidRect (#f0f0f0) + BackgroundImage with Percentage(50.0) center, Percentage(0.0) top, NoRepeat
|
|
|
|
- [x] Task 6: Canvas/root element background (AC: #1)
|
|
- [x] 6.1 Root background paints over entire canvas verified
|
|
- [x] 6.2 Canvas background fields verified
|
|
- [x] 6.3 Display list builder renders canvas background first verified
|
|
- [x] 6.4 Canvas background image wired via `image_store.get_by_url()` in `mod.rs` — handles both root element and body propagation
|
|
- [x] 6.5 Body background propagation verified via unit test and golden test 248
|
|
- [x] 6.6 Golden test 248 shows canvas SolidRect(0,0,800,600) + BackgroundImage(0,0,800,600) covering full viewport
|
|
|
|
- [x] Task 7: Linear gradient rendering verification (AC: #1)
|
|
- [x] 7.1 Gradient parsing verified
|
|
- [x] 7.2 `BackgroundImage::LinearGradient` variant verified
|
|
- [x] 7.3 `DisplayItem::LinearGradient` rendered by display list builder verified
|
|
- [x] 7.4 Gradient direction parsing verified (golden test 247 uses `to right` = 90deg)
|
|
- [x] 7.5 Color stop interpolation verified (2-stop red→blue gradient)
|
|
- [x] 7.6 Golden test 247: `linear-gradient(to right, red, blue)` → `LinearGradient rect=(8,8,100,100) angle=90.0deg stops=2`
|
|
|
|
- [x] Task 8: Golden tests and checklist update (AC: #5)
|
|
- [x] 8.1 Added 8 golden tests (241-248, numbers adjusted from story's 209-216 since 209-240 were already taken):
|
|
- `241-background-image-url.html` — basic background-image with url() and no-repeat
|
|
- `242-background-repeat-modes.html` — all 4 repeat values
|
|
- `243-background-position-keywords.html` — center, right bottom, left top
|
|
- `244-background-position-percentage.html` — percentage-based positioning
|
|
- `245-background-attachment-fixed.html` — fixed attachment
|
|
- `246-background-shorthand.html` — full shorthand with all components
|
|
- `247-background-gradient.html` — linear-gradient background
|
|
- `248-background-canvas.html` — root element background covering canvas
|
|
- [x] 8.2 Existing background golden tests (012, 022, 086) verified passing — zero regressions
|
|
- [x] 8.3 Updated `docs/CSS2.1_Implementation_Checklist.md` — checked off Phase 16 items
|
|
- [x] 8.4 `just ci` passes — all 241 golden tests pass, all unit tests pass, zero regressions
|
|
|
|
## Dev Notes
|
|
|
|
### Current Implementation Status
|
|
|
|
Background support is **largely implemented** across the pipeline. What works:
|
|
- **`background-color`** — FULLY WORKING: parsed, computed, rendered as `DisplayItem::SolidRect`
|
|
- **`background-image` parsing** — CSS parsing and shorthand expansion for `url()` and `linear-gradient()` work
|
|
- **`background-image` gradients** — `LinearGradient` fully wired: parsed → computed → layout box → display item → rasterized
|
|
- **`background-repeat`** — enum, parsing, computed field, layout box field, display item field, and rasterizer tiling all exist
|
|
- **`background-attachment`** — enum, parsing, computed field, display item field, and viewport-relative rasterizer logic exist
|
|
- **`background-position`** — X/Y split, keyword/percentage/length parsing, resolve() method, and rasterizer positioning exist
|
|
- **`background` shorthand** — full shorthand parser in `background.rs` (1009 lines) with comprehensive tests
|
|
- **Canvas background** — separate fields for root element background, rendered first in display list
|
|
- **Image loading infrastructure** — `crates/image/` handles PNG/JPEG/GIF/WebP/SVG decode, `ImageStore` with `ImageId`
|
|
|
|
What is **missing** (this story's scope):
|
|
- **`background-image: url(...)` loading** — NOT WIRED: CSS-specified image URLs are not fetched/decoded/stored during layout. Only `<img>` and `<object>` elements resolve URLs to `ImageId`. This is the **primary gap**.
|
|
- **Golden test coverage** — only background-color (012) and inline backgrounds (022) have golden tests; no tests for background-image, repeat, position, attachment, or gradients as standalone features
|
|
- **End-to-end verification** — most sub-properties are wired but never tested individually with golden tests
|
|
|
|
### Key Code Locations
|
|
|
|
| Component | File | Key Functions/Lines |
|
|
|---|---|---|
|
|
| Background shorthand parser | `crates/css/src/parser/shorthands/background.rs:1-1009` | Full shorthand + position expansion + tests |
|
|
| Gradient parser | `crates/css/src/parser/gradient.rs` | `linear-gradient()`, vendor prefixes |
|
|
| PropertyId variants | `crates/css/src/types.rs:373-378,458,473-478` | `BackgroundColor`, `BackgroundImage`, `BackgroundRepeat`, `BackgroundAttachment`, `BackgroundPositionX/Y`, `Background` |
|
|
| Property name lookup | `crates/css/src/types.rs:521-527` | String → PropertyId mapping |
|
|
| BackgroundImage enum | `crates/style/src/types/primitives.rs:208-213` | `None`, `Url(String)`, `LinearGradient(LinearGradient)` |
|
|
| ComputedStyles fields | `crates/style/src/types/computed.rs:75-80` | `background_color`, `background_image`, `background_position_x/y`, `background_repeat`, `background_attachment` |
|
|
| Style application | `crates/style/src/types/computed.rs:755-835` | Background property → computed value conversion |
|
|
| Shared types | `crates/shared/src/lib.rs:777-816` | `BackgroundRepeat`, `BackgroundAttachment`, `BackgroundPositionValue` enums |
|
|
| LayoutBox fields | `crates/layout/src/types.rs:290-298` | `background_image_id`, `background_gradient`, `background_position_x/y`, `background_repeat`, `background_attachment` |
|
|
| Canvas background fields | `crates/layout/src/types.rs:975-981` | Canvas-level background fields |
|
|
| Style → LayoutBox | `crates/layout/src/engine/box_tree.rs:570-681` | `apply_computed_styles_to_box()` — gradients wired, **URL images NOT wired** |
|
|
| Element image loading | `crates/layout/src/engine/box_tree.rs:80-108` | `<img>`/`<object>` image resolution — **pattern to follow for background images** |
|
|
| DisplayItem types | `crates/display_list/src/lib.rs:19-73` | `BackgroundImage`, `LinearGradient`, `SolidRect` |
|
|
| Background rendering | `crates/display_list/src/builder.rs:788-825` | `render_background()` — color → gradient → image layering |
|
|
| Canvas background render | `crates/display_list/src/builder.rs:100-126` | Canvas background painted first |
|
|
| Rasterizer image draw | `crates/render/src/rasterizer/drawing.rs:1756+` | `draw_background_image()` — tiling, position, clip |
|
|
| Rasterizer dispatch | `crates/render/src/rasterizer/mod.rs:245-273` | `DisplayItem::BackgroundImage` handling with viewport-relative fixed |
|
|
| Image store | `crates/image/src/lib.rs:25-52` | `ImageStore` — insert/get by `ImageId` |
|
|
| Image decode | `crates/image/src/lib.rs:106-177` | PNG/JPEG/GIF/WebP/SVG decode pipeline |
|
|
| Golden test pipeline | `tests/goldens.rs:47-125` | `run_pipeline_with_images()` — **extend for background-image URLs** |
|
|
|
|
### Existing Golden Tests (Do NOT Regress — 3 tests)
|
|
|
|
| Fixture | Coverage |
|
|
|---|---|
|
|
| `012-background-color.html` | Basic background-color on elements |
|
|
| `022-inline-background-border.html` | Inline element background and border |
|
|
| `086-table-backgrounds.html` | Table cell backgrounds |
|
|
|
|
### Implementation Approach
|
|
|
|
**Task 1 (background-image URL loading) — PRIMARY WORK:**
|
|
This is the main engineering task. The entire rendering pipeline already exists — the only missing link is loading CSS-specified image URLs.
|
|
|
|
Current image loading for `<img>` elements (in `box_tree.rs:80-108`):
|
|
- During box tree construction, an `image_map: HashMap<NodeId, ImageId>` is available
|
|
- `<img>` elements look up their `NodeId` in this map to get `ImageId`
|
|
- The map is populated externally before layout
|
|
|
|
For background images, the approach should be:
|
|
1. **Pre-scan computed styles** for `BackgroundImage::Url(url)` during the resource loading phase (before layout)
|
|
2. Fetch and decode each unique URL using the existing `crates/image/` pipeline
|
|
3. Create a `background_image_map: HashMap<String, ImageId>` (URL string → ImageId)
|
|
4. Pass this map into box tree construction alongside the existing `image_map`
|
|
5. In `apply_computed_styles_to_box()`, when encountering `BackgroundImage::Url(url)`, look up the URL in the background image map and set `background_image_id`
|
|
|
|
**Alternative (simpler):** Add a `url_image_map: HashMap<String, ImageId>` to the existing `ImageStore` so all URL-based images (both element and background) use the same resolution path.
|
|
|
|
**Tasks 2-7 (verification tasks):**
|
|
These are primarily verification with golden tests. The code paths already exist — the work is:
|
|
1. Create targeted golden test HTML files exercising each feature
|
|
2. Run through the pipeline to verify correct output
|
|
3. Fix any bugs found during verification
|
|
|
|
**Task 8 (golden tests + checklist):**
|
|
Standard completion tasks. Use fixture numbers starting at 209 (or whatever is next after story 1-6's fixtures).
|
|
|
|
### Architecture Constraints
|
|
|
|
- **Layer rule:** Changes span `css` (Layer 1), `style` (Layer 1), `layout` (Layer 1), `display_list` (Layer 1), `render` (Layer 1) — all horizontal Layer 1 deps
|
|
- **No unsafe:** All affected crates except `graphics/` and `platform/` forbid `unsafe_code`
|
|
- **CSS Property Implementation Order:** Already followed — parsing, computed, layout, paint all exist. This story wires the missing link (URL → ImageId) and adds tests
|
|
- **Reuse existing infrastructure:** Use `crates/image/` for image loading. Do NOT add a new image loading system
|
|
- **Image store:** Use existing `ImageStore` with `ImageId` — extend if needed for URL-based lookups
|
|
|
|
### Previous Story Intelligence
|
|
|
|
**From Stories 1.1-1.6 (Common Patterns):**
|
|
- CSS Property Implementation Order: parse → style → layout → paint → test → docs (consistently followed)
|
|
- Golden test infrastructure: fixtures in `tests/goldens/fixtures/`, expected in `tests/goldens/expected/`
|
|
- Regen goldens: `cargo test -p rust_browser --test regen_goldens -- --nocapture`
|
|
- Checklist update at `docs/CSS2.1_Implementation_Checklist.md` is mandatory
|
|
- `just ci` is the single validation gate (~1 minute, run once per change)
|
|
|
|
**From Story 1.5 (Table Layout) — Background Context:**
|
|
- Table cell backgrounds already work via `086-table-backgrounds.html` golden test
|
|
- Background painting in display list builder is called from normal box rendering flow
|
|
- `render_background()` at `builder.rs:788-825` paints in order: color → gradient → image
|
|
|
|
**From Story 1.6 (Lists) — Image Loading Context:**
|
|
- Story 1.6 introduced `list-style-image` which also needs image URL loading
|
|
- If story 1.6 has already implemented a URL → ImageId mapping for list marker images, **reuse that same mechanism** for background images
|
|
- Check story 1.6 implementation status — shared image URL resolution would benefit both features
|
|
|
|
### Testing Strategy
|
|
|
|
1. **Image loading tests** — verify background-image URLs resolve to ImageId during box tree construction
|
|
2. **Regression tests** — existing 3 background golden tests (012, 022, 086) must not regress
|
|
3. **End-to-end golden tests** — 8 new fixtures covering:
|
|
- URL-based background images with repeat modes
|
|
- Background positioning (keywords, percentages, lengths)
|
|
- Fixed attachment
|
|
- Full shorthand
|
|
- Linear gradients
|
|
- Canvas/root element backgrounds
|
|
4. **Shorthand parser tests** — already extensive (1009 lines in background.rs), verify completeness
|
|
5. Run `just ci` at the end
|
|
|
|
### CSS 2.1 Spec References
|
|
|
|
- **§14.2** — The background: canvas, background properties overview
|
|
- **§14.2.1** — Background properties: `background-color`, `background-image`, `background-repeat`, `background-attachment`, `background-position`, `background` shorthand
|
|
- **§14.2.1** — Background shorthand resets: omitted values use initial values
|
|
- **§14.2** — Root element background paints over entire canvas; `<body>` background propagates to canvas if `<html>` has none
|
|
|
|
### Project Structure Notes
|
|
|
|
- Primary change is wiring URL → ImageId resolution in `crates/layout/src/engine/box_tree.rs`
|
|
- Golden test pipeline in `tests/goldens.rs` needs to also resolve background-image URLs
|
|
- Image loading uses existing `crates/image/` — no new image infrastructure
|
|
- Display list, rasterizer changes should be minimal (paths already exist)
|
|
- New golden test fixtures start at 209 (or after story 1-6 fixtures)
|
|
|
|
### References
|
|
|
|
- [Source: crates/css/src/parser/shorthands/background.rs#1-1009] — Background shorthand parser (complete)
|
|
- [Source: crates/css/src/parser/gradient.rs] — Gradient parser
|
|
- [Source: crates/css/src/types.rs#373-378,458,473-478] — Background PropertyId variants
|
|
- [Source: crates/style/src/types/primitives.rs#208-213] — BackgroundImage enum
|
|
- [Source: crates/style/src/types/computed.rs#75-80,755-835] — Computed background fields and conversion
|
|
- [Source: crates/shared/src/lib.rs#777-816] — BackgroundRepeat, BackgroundAttachment, BackgroundPositionValue
|
|
- [Source: crates/layout/src/types.rs#290-298] — LayoutBox background fields
|
|
- [Source: crates/layout/src/types.rs#975-981] — Canvas background fields
|
|
- [Source: crates/layout/src/engine/box_tree.rs#80-108] — Element image loading pattern (follow for backgrounds)
|
|
- [Source: crates/layout/src/engine/box_tree.rs#570-681] — apply_computed_styles_to_box() (modify for URL images)
|
|
- [Source: crates/display_list/src/builder.rs#788-825] — render_background() (color → gradient → image)
|
|
- [Source: crates/display_list/src/builder.rs#100-126] — Canvas background rendering
|
|
- [Source: crates/display_list/src/lib.rs#19-73] — DisplayItem types (BackgroundImage, LinearGradient, SolidRect)
|
|
- [Source: crates/render/src/rasterizer/drawing.rs#1756+] — draw_background_image() tiling/position
|
|
- [Source: crates/render/src/rasterizer/mod.rs#245-273] — BackgroundImage dispatch with fixed viewport
|
|
- [Source: crates/image/src/lib.rs#25-177] — ImageStore and decode pipeline
|
|
- [Source: tests/goldens.rs#47-125] — run_pipeline_with_images() (extend for background URLs)
|
|
- [Source: docs/CSS2.1_Implementation_Checklist.md#Phase-16] — Backgrounds and Borders checklist
|
|
|
|
## Dev Agent Record
|
|
|
|
### Agent Model Used
|
|
|
|
Claude Opus 4.6 (1M context)
|
|
|
|
### Debug Log References
|
|
|
|
No blocking issues encountered. All existing pipeline code was correct — the primary gap was URL→ImageId resolution.
|
|
|
|
### Completion Notes List
|
|
|
|
- **Primary implementation:** Added `url_to_image: HashMap<String, ImageId>` to `ImageStore` with `insert_url()` and `get_by_url()` methods, providing URL-based image lookup for CSS `background-image: url(...)` and future `list-style-image: url(...)` support.
|
|
- **Layout wiring:** In `build_layout_box()`, after `apply_computed_styles_to_box()`, background-image URLs are resolved via `image_store.get_by_url()` to set `background_image_id` on the `LayoutBox`.
|
|
- **Canvas background wiring:** In `layout_with_images_and_inputs()`, both root element and body propagation paths now resolve `BackgroundImage::Url` via `image_store.get_by_url()` to set `canvas_background_image_id`.
|
|
- **Golden test pipeline:** Extended `run_pipeline_with_images()` to scan computed styles for `BackgroundImage::Url` and load images via `image_store.insert_url()`.
|
|
- **Tests added:** 4 ImageStore unit tests (insert_url, get_by_url_missing, url_dedup, multiple_urls), 4 layout-level tests (URL resolution, fallback, canvas from html, canvas from body propagation), 8 golden tests (241-248).
|
|
- **Verification:** All existing background sub-properties (repeat, attachment, position, shorthand, gradients, canvas) verified working end-to-end via golden tests. Zero code changes needed in display_list, render, or rasterizer — the pipeline was already complete.
|
|
|
|
### Change Log
|
|
|
|
- 2026-03-13: Implemented background-image URL→ImageId resolution pipeline and verified all background sub-properties end-to-end with 8 golden tests (241-248). Updated CSS2.1 checklist.
|
|
|
|
### File List
|
|
|
|
- `crates/image/src/lib.rs` — Added `url_to_image` HashMap, `insert_url()`, `get_by_url()` methods, 4 unit tests
|
|
- `crates/layout/src/engine/box_tree.rs` — Added background-image URL→ImageId resolution after `apply_computed_styles_to_box()`
|
|
- `crates/layout/src/engine/mod.rs` — Canvas background URL resolution for both root element and body propagation paths
|
|
- `crates/layout/src/tests/canvas_background_tests.rs` — 4 new background-image URL resolution tests
|
|
- `tests/goldens.rs` — Extended `run_pipeline_with_images()` for background-image URL loading; added 8 golden test functions (241-248)
|
|
- `tests/goldens/fixtures/241-background-image-url.html` — NEW golden fixture
|
|
- `tests/goldens/fixtures/242-background-repeat-modes.html` — NEW golden fixture
|
|
- `tests/goldens/fixtures/243-background-position-keywords.html` — NEW golden fixture
|
|
- `tests/goldens/fixtures/244-background-position-percentage.html` — NEW golden fixture
|
|
- `tests/goldens/fixtures/245-background-attachment-fixed.html` — NEW golden fixture
|
|
- `tests/goldens/fixtures/246-background-shorthand.html` — NEW golden fixture
|
|
- `tests/goldens/fixtures/247-background-gradient.html` — NEW golden fixture
|
|
- `tests/goldens/fixtures/248-background-canvas.html` — NEW golden fixture
|
|
- `tests/goldens/expected/241-background-image-url.{layout,dl}.txt` — NEW golden expected
|
|
- `tests/goldens/expected/242-background-repeat-modes.{layout,dl}.txt` — NEW golden expected
|
|
- `tests/goldens/expected/243-background-position-keywords.{layout,dl}.txt` — NEW golden expected
|
|
- `tests/goldens/expected/244-background-position-percentage.{layout,dl}.txt` — NEW golden expected
|
|
- `tests/goldens/expected/245-background-attachment-fixed.{layout,dl}.txt` — NEW golden expected
|
|
- `tests/goldens/expected/246-background-shorthand.{layout,dl}.txt` — NEW golden expected
|
|
- `tests/goldens/expected/247-background-gradient.{layout,dl}.txt` — NEW golden expected
|
|
- `tests/goldens/expected/248-background-canvas.{layout,dl}.txt` — NEW golden expected
|
|
- `docs/CSS2.1_Implementation_Checklist.md` — Checked off Phase 16 background items
|