diplodoc-platform / diplodoc-platform/transform
Term definition popup is mispositioned when the rendered YFM container is positioned (position: relative)
- 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
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