From 14cecaacd246de1b2600c7b8413f3fef847ad0e1 Mon Sep 17 00:00:00 2001 From: VladaHarbour Date: Mon, 9 Feb 2026 12:33:43 +0200 Subject: [PATCH 1/2] fix: zIndex updates --- .../painters/dom/src/renderer.ts | 23 ++++++++----------- .../layout-engine/painters/dom/src/styles.ts | 10 +++----- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/packages/layout-engine/painters/dom/src/renderer.ts b/packages/layout-engine/painters/dom/src/renderer.ts index 42774924a6..705d493036 100644 --- a/packages/layout-engine/painters/dom/src/renderer.ts +++ b/packages/layout-engine/painters/dom/src/renderer.ts @@ -1634,18 +1634,15 @@ export class DomPainter { pageNumberText: page.numberText, }; - // Separate behindDoc fragments from normal fragments. - // Prefer explicit fragment.behindDoc when present. Keep zIndex===0 as a - // compatibility fallback for older layouts that predate explicit metadata. + // Separate behindDoc fragments (zIndex === 0) from normal fragments. + // behindDoc fragments need to render behind body content, so they must be + // placed directly on the page (not in the header container) with negative z-index. const behindDocFragments: typeof data.fragments = []; const normalFragments: typeof data.fragments = []; for (const fragment of data.fragments) { - let isBehindDoc = false; - if (fragment.kind === 'image' || fragment.kind === 'drawing') { - isBehindDoc = - fragment.behindDoc === true || (fragment.behindDoc == null && 'zIndex' in fragment && fragment.zIndex === 0); - } + const isBehindDoc = + (fragment.kind === 'image' || fragment.kind === 'drawing') && 'zIndex' in fragment && fragment.zIndex === 0; if (isBehindDoc) { behindDocFragments.push(fragment); } else { @@ -3951,7 +3948,8 @@ export class DomPainter { img.style.marginRight = `${run.distRight}px`; } - // Apply z-index to render above tab leaders + // Position and z-index on the image only (not the line) so resize overlay can stack above. + img.style.position = 'relative'; img.style.zIndex = '1'; // Assert PM positions are present for cursor fallback @@ -4282,6 +4280,9 @@ export class DomPainter { throw new Error('DomPainter: document is not available'); } + const lineRange = computeLinePmRange(block, line); + let runsForLine = sliceRunsForLine(block, line); + const el = this.doc.createElement('div'); el.classList.add(CLASS_NAMES.line); applyStyles(el, lineStyles(line.lineHeight)); @@ -4301,16 +4302,12 @@ export class DomPainter { el.style.textAlign = 'left'; } - const lineRange = computeLinePmRange(block, line); - if (lineRange.pmStart != null) { el.dataset.pmStart = String(lineRange.pmStart); } if (lineRange.pmEnd != null) { el.dataset.pmEnd = String(lineRange.pmEnd); } - - let runsForLine = sliceRunsForLine(block, line); const trackedConfig = this.resolveTrackedChangesConfig(block); // Preserve PM positions for DOM caret mapping on empty lines. diff --git a/packages/layout-engine/painters/dom/src/styles.ts b/packages/layout-engine/painters/dom/src/styles.ts index b61016001a..e04a6d079a 100644 --- a/packages/layout-engine/painters/dom/src/styles.ts +++ b/packages/layout-engine/painters/dom/src/styles.ts @@ -77,13 +77,10 @@ export const fragmentStyles: Partial = { }; /** - * Z-index for paragraph text lines, ensuring they render above floating - * OOXML-derived fragments (which typically range 1–10 000). Must stay - * below browser-UI layers (tooltips, menus, overlays) that may live in the - * same stacking context. + * Line container styles. z-index is intentionally not set on the line so that + * the resize overlay (and other UI) can stack above content. Only the image + * element itself gets z-index for layering within the line (e.g. above tab leaders). */ -const TEXT_LINE_Z_INDEX = '100000'; - export const lineStyles = (lineHeight: number): Partial => ({ lineHeight: `${lineHeight}px`, height: `${lineHeight}px`, @@ -95,7 +92,6 @@ export const lineStyles = (lineHeight: number): Partial => // provides defense-in-depth against any remaining sub-pixel rendering // differences between measurement and display. overflow: 'visible', - zIndex: TEXT_LINE_Z_INDEX, }); const PRINT_STYLES = ` From cdc6f91a949a7a7f4a338917b605506e94dd8dfe Mon Sep 17 00:00:00 2001 From: VladaHarbour Date: Mon, 9 Feb 2026 13:34:43 +0200 Subject: [PATCH 2/2] fix: revert behindDoc change --- packages/layout-engine/painters/dom/src/renderer.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/layout-engine/painters/dom/src/renderer.ts b/packages/layout-engine/painters/dom/src/renderer.ts index 705d493036..32bde42e59 100644 --- a/packages/layout-engine/painters/dom/src/renderer.ts +++ b/packages/layout-engine/painters/dom/src/renderer.ts @@ -1634,15 +1634,18 @@ export class DomPainter { pageNumberText: page.numberText, }; - // Separate behindDoc fragments (zIndex === 0) from normal fragments. - // behindDoc fragments need to render behind body content, so they must be - // placed directly on the page (not in the header container) with negative z-index. + // Separate behindDoc fragments from normal fragments. + // Prefer explicit fragment.behindDoc when present. Keep zIndex===0 as a + // compatibility fallback for older layouts that predate explicit metadata. const behindDocFragments: typeof data.fragments = []; const normalFragments: typeof data.fragments = []; for (const fragment of data.fragments) { - const isBehindDoc = - (fragment.kind === 'image' || fragment.kind === 'drawing') && 'zIndex' in fragment && fragment.zIndex === 0; + let isBehindDoc = false; + if (fragment.kind === 'image' || fragment.kind === 'drawing') { + isBehindDoc = + fragment.behindDoc === true || (fragment.behindDoc == null && 'zIndex' in fragment && fragment.zIndex === 0); + } if (isBehindDoc) { behindDocFragments.push(fragment); } else {