diplodoc-platform / diplodoc-platform/transform

Term definition popup is mispositioned when the rendered YFM container is positioned (position: relative)

Open
#1,011 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
69
Forks
59
Avg merge
1d 21h
Merged PRs (30d)
6

Description

## Problem

The term definition popup (``, `position: absolute`) opens with a constant offset from the clicked term (typically shifted down by ~the height of the consumer's page/file header) on pages where the element that directly contains the rendered YFM HTML is positioned (`position: relative/absolute/sticky`), or when an intermediate ancestor creates a containing block (`transform`, `filter`).

This breaks the term plugin in third-party integrations that wrap rendered HTML in their own layout. The requirement that the YFM container must be non-positioned is not documented anywhere, and consumers have no way to know about it.

## Root cause

`setDefinitionPosition` in `src/js/term/utils.ts` computes inline `top`/`left` for the dfn like this (simplified):

```
customHeaderTop = docY(dfn.parentElement) - dfn.parentElement.offsetTop
top = docY(term) + termHeight + 5 - customHeaderTop
```

i.e. it assumes that the containing block of the absolutely positioned dfn is the `offsetParent` of the dfn's parent. When the dfn's direct parent is itself positioned, the actual containing block is that parent, so the popup is shifted down by exactly `parent.offsetTop` and right by `parent.offsetLeft` relative to the expected position.

## Repro

```html







```

Click the term: the popup appears ~100px below the term. Remove `position: relative` from the `.yfm` element - the popup is positioned correctly.

## Suggested fix

Don't guess the containing block - measure it. The dfn is hidden via `visibility`, so it can be measured without flicker:

```ts
definitionElement.style.top = '0px';
definitionElement.style.left = '0px';
const base = definitionElement.getBoundingClientRect();
const term = termElement.getBoundingClientRect();
definitionElement.style.top = `${term.bottom + 5 - base.top}px`;
definitionElement.style.left = `${term.left - base.left}px`;
```

This works with any containing block (positioned ancestors, transform, sticky, inner scroll containers) and removes the implicit layout requirement for consumers. The existing right-edge overflow / RTL adjustments can be applied on top of this base position.

Related: #723 (another symptom of layout assumptions in the term runtime).

Contributor guide

Open the contributing guide

Research direction

Start in src/js/term/utils.ts at setDefinitionPosition and reproduce the issue with a positioned YFM container or containing-block ancestor. Verify that the popup uses the measured containing block for its base position while preserving the existing right-edge overflow and RTL adjustments; done means the term definition aligns correctly in the provided layouts.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
75/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.