Skip to content

[Bug] Cell editor sizing is incorrect when Univer is embedded in a scrollable page (non-fullscreen container) #6603

@ycwang-dev

Description

@ycwang-dev

Environment

  • Univer version: 0.15.3
  • Browser: Chrome (latest)
  • OS: macOS

Description

When Univer is embedded inside a scrollable page (e.g., documentation site, dashboard, or any page where the Univer container does NOT occupy the full browser viewport), the cell editor's maximum height calculation is incorrect. This causes the editing border/overlay to extend beyond the actual canvas boundaries, resulting in visual distortion when editing cells in lower rows (e.g., starting around row 17 in a 600px-tall container).

Root Cause Analysis

The issue is in packages/sheets-ui/src/services/editor/cell-editor-resize.service.ts, specifically the _getEditorMaxSize method (lines 249-254):

const clientHeight =
    document.body.clientHeight -
    startY -
    footerBarHeight -
    canvasOffset.top -
    EDITOR_BORDER_SIZE * 2;

This calculation uses document.body.clientHeight (browser viewport height) to determine the available space for the cell editor. However, this assumes Univer occupies the full viewport, which is NOT true in embedded scenarios.

Example calculation (600px container on a scrollable doc page):

Variable Value Description
document.body.clientHeight 720px Browser viewport height
startY 324px Cell E17 position in canvas coordinates
canvasOffset.top 68px Canvas position relative to viewport (varies with scroll)
footerBarHeight 28px Sheet footer bar height
EDITOR_BORDER_SIZE * 2 4px Editor border
Calculated clientHeight 296px What Univer thinks is available
Actual remaining canvas space 171px canvas.height(495) - startY(324)

The calculated clientHeight (296px) is 125px larger than the actual remaining canvas space (171px), causing the editor to render beyond the canvas boundaries.

Why document.body.clientHeight is incorrect here:

  1. When the page is scrollable, canvasOffset.top changes with scroll position (via getBoundingClientRect()), but document.body.clientHeight remains constant
  2. The formula assumes document.body.clientHeight - canvasOffset.top gives the distance from canvas top to viewport bottom, which is only valid when Univer fills the entire viewport
  3. In embedded scenarios, the actual available space should be constrained by the canvas container height, not the body height

Steps to Reproduce

  1. Create a scrollable HTML page
  2. Embed a Univer Sheets instance inside a container with a fixed height (e.g., height: 600px)
  3. Ensure the page has content above and below the Univer container, making the page scrollable
  4. Double-click on a cell in a lower row (e.g., row 17 or beyond)
  5. Observe that the cell editor border/overlay extends beyond the visible canvas area

Minimal reproduction:

<!DOCTYPE html>
<html>
<body style="height: 2000px; padding: 200px 50px;">
  <h1>Content above Univer</h1>
  <div id="univer-container" style="height: 600px; width: 800px;"></div>
  <h1>Content below Univer</h1>
  <script type="module">
    import { createUniver, defaultTheme, LocaleType, UniverSheetsCorePreset } from '@univerjs/presets';
    import '@univerjs/presets/lib/styles/preset-sheets-core.css';

    const { univerAPI } = createUniver({
      locale: LocaleType.EN_US,
      theme: defaultTheme,
      presets: [UniverSheetsCorePreset()],
    });
    univerAPI.createWorkbook({ sheets: [{ id: 'sheet1', name: 'Sheet1', rowCount: 100, columnCount: 26 }] });
  </script>
</body>
</html>

Expected Behavior

The cell editor should be constrained within the actual canvas area, regardless of where Univer is positioned on the page. The editor should NOT extend beyond the canvas boundaries.

Actual Behavior

The cell editor's height calculation overestimates available space, causing the editor overlay to extend beyond the canvas boundaries. This results in:

  • Editor border appearing outside the spreadsheet area
  • Visual distortion when editing lower rows
  • The issue worsens the further down the row is (more rows below = more overflow)

Suggested Fix

Replace document.body.clientHeight with the actual canvas container's available height:

// Current (broken in embedded scenarios):
const clientHeight = document.body.clientHeight - startY - footerBarHeight - canvasOffset.top - EDITOR_BORDER_SIZE * 2;

// Suggested fix:
const canvasContainerHeight = canvasElement.parentElement.getBoundingClientRect().height;
const clientHeight = canvasContainerHeight - startY - footerBarHeight - EDITOR_BORDER_SIZE * 2;

This would correctly constrain the editor within the canvas boundaries regardless of the page layout.

Metadata

Metadata

Assignees

Labels

bug 🐛Something isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions