fix(hillshade): apply mix-blend-mode per tile to fix max-zoom dropouts (#168)#169
Conversation
…t max zoom The blend was applied to .hillshade-blend (the Leaflet layer's outer container). That element shares the tile pane's stacking context with the base layer below it, but its inner .leaflet-tile-container uses translate3d for hardware-accelerated zoom animation, which can intermittently establish its own stacking context that isolates a container-level blend from siblings — visible as the multiply blend "sometimes not applying" at the closest zoom levels (most noticeable on the topo basemap, where Esri's hillshade upscales from z=16). Targeting img.leaflet-tile under .hillshade-blend keeps the blend on the leaf elements that render directly under the transform, avoiding the isolation. Each tile image blends individually with the base map. Closes #168 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code ReviewOverviewThis PR fixes an intermittent bug where Code CorrectnessThe fix is technically sound. This is a well-known CSS compositing edge case — One alternative worth knowing about: adding Minor concern: Inline Comment WeightThe added comment block (3 lines) is heavier than CLAUDE.md's convention of a single brief line only when the WHY is non-obvious. The stacking context issue is non-obvious, so a comment is justified — but the detail level here duplicates the PR description. Consider trimming to a single line: /* Each tile blends individually — a container-level blend isolates under translate3d zoom animation. */
.hillshade-blend img.leaflet-tile { mix-blend-mode: multiply; }Test Checklist DiscrepancyThe PR description checks off:
Per Summary
The core change is a clean 1-line fix with solid reasoning. Addressing the checklist discrepancy and trimming the comments would bring it fully in line with project conventions. |
- Trim hillshade comment to one line per project convention. - Refresh CLAUDE.md: vitest is now in use (628 tests), recording is replaced by guidance, file-structure entry expanded with the new guidance / routing / geo modules, and the test-claim staleness flagged by the reviewer is resolved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Cycle-2 fixes in the latest push:
|
Code ReviewOverviewThis PR fixes a visual bug (#168) where the hillshade multiply blend drops out at max zoom levels. The fix moves CSS Fix (
|
| Area | Assessment |
|---|---|
| Correctness | ✅ Fix targets the exact root cause |
| Code style | ✅ Follows project conventions (minimal comments, targeted selectors) |
| Performance | ✅ No meaningful overhead |
| Security | ✅ No concerns (CSS-only change) |
| Test coverage | ✅ Unit tests pass; manual visual check is appropriately flagged as pending |
Verdict: Ready to merge after manual verification is completed. The CSS change is minimal, well-reasoned, and the documentation updates are a net positive.
🤖 Generated with Claude Code
…#171) (#172) * fix(hillshade): revert per-tile blend; use isolation: isolate on #map instead PR #169 moved mix-blend-mode from .hillshade-blend (the layer container) to .hillshade-blend img.leaflet-tile (individual tile images). I had the stacking-context reasoning backwards: applying the blend AT the tile image places it INSIDE the transformed .leaflet-tile-container's stacking context. That context contains only the hillshade tiles — nothing to multiply against — so the blend has no backdrop and renders source pixels opaque, hiding the base map entirely. Correct placement is at .hillshade-blend, which is a peer of the base-layer container under .leaflet-tile-pane. There the multiply blend has the base map as the sibling backdrop. To address the original "sometimes not applied" symptom from #168, add isolation: isolate to #map. This makes the map a clean stacking- context root so the blend can reliably composite against base-layer tiles without ancestor compositing layers isolating it from the intended backdrop. Closes #171 Re-opens #168 conceptually but the new fix targets the actual root cause. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: trim hillshade comments per CLAUDE.md convention Single-line comments capturing only the non-obvious WHY; no PR refs that rot as the codebase evolves. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Closes #168
Why this is the right level
The Leaflet pane structure is:
```
.leaflet-tile-pane
.leaflet-layer (className: 'hillshade-blend')
.leaflet-tile-container (transform: translate3d(...))
img.leaflet-tile (each tile)
```
The transform on the middle container is what creates the isolation risk. Targeting the tile images keeps the blend on the leaf rendered content; the base layer's tile images are siblings (in the parent tile-pane stacking context) and the blend pairs with them as expected.
Test plan
🤖 Generated with Claude Code