Environment: Safari (desktop + iOS/iPadOS). Not reproducible in Chromium/Firefox.
Symptom: After incremental edits near a wrap boundary, Safari leaves the <textarea> glyph layout stale. Because OverType overlays the invisible textarea on the styled preview, the caret and wrapping visibly desync from the preview (the "hanging cursor", the word stays wrapped).
Repro (overtype.dev homepage, 2nd "WITH TOOLBAR" editor):
- Click at the end of
Use the toolbar or keyboard shortcuts:
- Type
x until the word wraps to the next line.
- Press
Backspace once.
- The word stays on the next line and the caret hangs. Safari only.
Root cause: This is a Safari text-shaping cache bug, not line-break recalculation. Confirmed with console probes on the live editor:
- Forcing a full re-layout via
textarea.value = textarea.value does not fix it.
- Toggling the
wrap attribute (line-break invalidation) does not fix it.
- Toggling
letter-spacing (glyph-shaping invalidation) does fix it.
So only something that invalidates text shaping clears the stale state.
Fix (implemented locally): a Safari-gated, requestAnimationFrame-coalesced nudge after edits: set letter-spacing: -0.001px !important inline, read offsetHeight to force a synchronous reflow, then remove it. Wired into handleInput and setValue, cancelled in destroy().
Note: the inline value needs !important because OverType's stylesheet pins letter-spacing: normal !important; the raw snippet without !important is a silent no-op.
Reported by a contributor, who also supplied the letter-spacing workaround.
Environment: Safari (desktop + iOS/iPadOS). Not reproducible in Chromium/Firefox.
Symptom: After incremental edits near a wrap boundary, Safari leaves the
<textarea>glyph layout stale. Because OverType overlays the invisible textarea on the styled preview, the caret and wrapping visibly desync from the preview (the "hanging cursor", the word stays wrapped).Repro (overtype.dev homepage, 2nd "WITH TOOLBAR" editor):
Use the toolbar or keyboard shortcuts:xuntil the word wraps to the next line.Backspaceonce.Root cause: This is a Safari text-shaping cache bug, not line-break recalculation. Confirmed with console probes on the live editor:
textarea.value = textarea.valuedoes not fix it.wrapattribute (line-break invalidation) does not fix it.letter-spacing(glyph-shaping invalidation) does fix it.So only something that invalidates text shaping clears the stale state.
Fix (implemented locally): a Safari-gated,
requestAnimationFrame-coalesced nudge after edits: setletter-spacing: -0.001px !importantinline, readoffsetHeightto force a synchronous reflow, then remove it. Wired intohandleInputandsetValue, cancelled indestroy().Note: the inline value needs
!importantbecause OverType's stylesheet pinsletter-spacing: normal !important; the raw snippet without!importantis a silent no-op.Reported by a contributor, who also supplied the
letter-spacingworkaround.