현상
In Chrome on macOS, when editing content inside an element with position:relative, the text caret is completely invisible.
재현 예시
- Create a container element with
position:relative. - Place contenteditable element inside it.
- Focus on the contenteditable element.
- ❌ Caret is not visible!
관찰된 동작
- No visible caret: Cannot see where text will be inserted
- Text still appears: Typed text shows up in editor
- Difficult editing: User has to guess insertion point
- WebKit issue: Affects WebKit-based browsers on macOS
- position:relative trigger: This CSS property causes the issue
예상 동작
- Caret should be visible (blinking line or other indicator)
- User should clearly see insertion point
- position:relative should not affect caret rendering
참고사항 및 가능한 해결 방향
- Remove position:relative: Remove the problematic CSS property from parent
- Use position:static: Change to static positioning
- Move to wrapper element: Apply position:relative to wrapper, keep editor static
- Custom caret implementation: Create blinking cursor with CSS animation
코드 예시
Solution 1: Remove position:relative
.editable-container {
position: static; /* Remove or omit position property */
}
[contenteditable] {
min-height: 100px;
outline: 2px solid #ddd;
}
Solution 2: Wrapper element
.wrapper {
position: relative;
padding: 20px;
border: 1px solid #ccc;
}
[contenteditable] {
position: static; /* Keep contenteditable static */
min-height: 100px;
}
Solution 3: Custom caret
@keyframes caret-blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.custom-caret {
position: absolute;
width: 2px;
height: 20px;
background: black;
animation: caret-blink 1s infinite;
pointer-events: none;
}
const editor = document.querySelector('[contenteditable]');
const caret = document.createElement('span');
caret.className = 'custom-caret';
document.body.appendChild(caret);
editor.addEventListener('input', (e) => {
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
// Update caret position
caret.style.top = rect.top + 'px';
caret.style.left = rect.left + 'px';
}
});