Skip to content

web: Fix canvas sizing with CSS-driven layout and container resizes - #170

Merged
timzifer merged 1 commit into
mainfrom
claude/fix-canvas-button-layout-EHSeE
Apr 21, 2026
Merged

timzifer merged 1 commit into
mainfrom
claude/fix-canvas-button-layout-EHSeE

Conversation

@timzifer

Copy link
Copy Markdown
Owner

Summary

This PR fixes canvas sizing issues when the canvas is embedded in a container with CSS-driven layout (e.g., width: 100% !important). The changes address two main problems:

  1. Incorrect size detection during initialization: The code was using clientWidth/clientHeight, which round to integer CSS pixels and don't account for transforms or container-imposed sizing. Now it uses getBoundingClientRect() which reflects the actual rendered size.

  2. Missing resize detection for container changes: When a container resizes (e.g., window resize, parent layout change), the canvas wasn't being notified. Now a ResizeObserver detects CSS-driven size changes, complementing the existing window resize listener which only catches DPR changes.

  3. Stale inline styles fighting CSS layout: When no explicit size was configured, the code was still setting inline pixel values that would conflict with container CSS. Now inline styles are only set when an explicit size is requested.

  4. Incorrect pointer event coordinates: The canvasPos() function was using offsetX/offsetY which don't account for CSS transforms or when the rendered size diverges from cached values. Now it derives coordinates from getBoundingClientRect() and scales them to backing-store pixels.

Type of change

  • Bug fix (non-breaking change that fixes an issue)

Testing

  • Code review of DOM API usage and resize handling logic
  • Verified ResizeObserver fallback for older browsers
  • Pointer event coordinate calculation updated to match actual rendered geometry

Checklist

  • I have read CONTRIBUTING.md
  • Documentation updated (inline comments added explaining the layout behavior)
  • Related to container-based canvas embedding scenarios

https://claude.ai/code/session_01EAVzQWyPG186aRQoR1AHfF

When the canvas is embedded in a container styled with
`#lux-canvas { width: 100% !important; height: 100% !important; }`, the
rendered CSS size is driven by the surrounding layout and can change
without a window resize. The old listener only watched `window.resize`
and our inline `style.width/height` was overridden by the user CSS,
so the backing store went stale. That stretched the framebuffer
(squashed buttons) and `offsetX * dpr` no longer matched the rendered
size (wrong hitboxes).

- Attach a `ResizeObserver` to the canvas and route both window and
  observer events through a shared `handleResize` that reads the
  post-layout size from `getBoundingClientRect`.
- Map pointer coordinates via `getBoundingClientRect` + `canvas.width/
  height` so the scale factor is derived from the DOM on every event
  and stays correct even mid-resize.
- Skip inline `style.width/height` in `Init` when the caller didn't
  request an explicit size, so embedding CSS controls layout.
- Emit an initial `OnResize` from `Run` so the app's first frame has
  the actual framebuffer size.
@github-actions

Copy link
Copy Markdown

Thank you for your contribution to lux! Before we can merge this pull request, we need you to agree to the Contributor License Agreement (CLA). It grants the Project the rights needed to distribute your contribution under both the noncommercial and commercial licenses.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@timzifer
timzifer merged commit 663fabf into main Apr 21, 2026
3 of 4 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants