케이스 ce-0280-ios-keyboard-hides-text-ko · 시나리오 scenario-ios-keyboard-hides-text

iOS에서 소프트웨어 키보드가 텍스트를 숨김

OS: iOS 16+ 기기: Mobile (iPhone/iPad) Any 브라우저: Safari 16+ 키보드: English (QWERTY) or iOS Virtual Keyboard 초안
iossafarikeyboardmobileauto-scroll

현상

iPhone/iPad Safari에서 contenteditable 요소 안에 텍스트를 입력하거나 Enter 키를 여러 번 누를 때, 소프트웨어 키보드가 나타나지만 입력되는 텍스트가 숨겨집니다.

재현 예시

  1. iPhone 또는 iPad에서 Safari 브라우저를 엽니다.
  2. contenteditable 요소에 포커스합니다.
  3. 텍스트를 입력합니다 (예: “안녕하세요”).
  4. Enter 키를 여러 번 눌러 여러 줄을 만듭니다.

관찰된 동작

  • 텍스트 숨김: 키보드가 입력되는 텍스트를 덮어서 사용자가 볼 수 없음
  • 자동 스크롤 없음: 페이지가 자동으로 스크롤되지 않아 입력점이 키보드 아래에 남음
  • 맹목 타이핑: 사용자가 타이핑하는 내용을 볼 수 없어 맹목 타이핑하게 됨
  • iOS 특유: iPhone/iPad Safari에서만 발생
  • Android 정상: Android 브라우저에서는 정상 작동

예상 동작

  • 소프트웨어 키보드가 나타나야 함
  • 입력점이 항상 보여야 함
  • 페이지가 자동으로 스크롤되어 입력점이 키보드 위에 유지되어야 함

참고사항 및 가능한 해결 방향

  • input 이벤트로 스크롤: 입력 발생할 때마다 캐럿 위치로 스크롤
  • focus 이벤트로 스크롤: 포커스 시 캐럿 위치로 스크롤
  • resize observer 사용: 키보드 높이 변화를 감지하여 스크롤
  • CSS viewport 설정: height: 100vh 등으로 viewport 높이 설정 시도
  • 시각적 피드백 제공: 텍스트가 숨겨도 캐럿 위치를 볼 수 있는 인디케이터 제공

코드 예시

const editor = document.querySelector('div[contenteditable]');
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

// input 이벤트로 스크롤
editor.addEventListener('input', (e) => {
  if (!isIOS) return;
  
  setTimeout(() => {
    const selection = window.getSelection();
    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      const rect = range.getBoundingClientRect();
      
      // 캐럿 위치로 스크롤 (200px 버퍼)
      window.scrollTo({
        top: rect.top + window.scrollY - 200,
        behavior: 'smooth'
      });
      
      console.log('Scrolled to caret position:', rect.top);
    }
  }, 100);
});

// focus 이벤트로 스크롤
editor.addEventListener('focus', () => {
  if (!isIOS) return;
  
  setTimeout(() => {
    const selection = window.getSelection();
    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      const rect = range.getBoundingClientRect();
      
      window.scrollTo({
        top: rect.top + window.scrollY - 200,
        behavior: 'smooth'
      });
    }
  }, 300);
});

// 시각적 캐럿 인디케이터 (iOS에서만 활성화)
if (isIOS) {
  const caret = document.createElement('span');
  caret.className = 'ios-caret-indicator';
  caret.style.cssText = `
    position: absolute;
    width: 2px;
    height: 20px;
    background: rgba(0, 120, 255, 0.5);
    pointer-events: none;
    transition: top 0.1s, left 0.1s;
  `;
  
  // 캐럿 위치 업데이트
  const updateCaretPosition = () => {
    const selection = window.getSelection();
    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      const rect = range.getBoundingClientRect();
      caret.style.top = rect.top + 'px';
      caret.style.left = rect.left + 'px';
    }
  };
  
  editor.addEventListener('input', updateCaretPosition);
  editor.addEventListener('selectionchange', updateCaretPosition);
  document.body.appendChild(caret);
}
/* CSS 해결책 시도 */
html, body {
  height: 100vh;
  overflow: auto;
}

[contenteditable] {
  min-height: 200px;
}

.ios-caret-indicator {
  /* iOS에서만 보이는 캐럿 인디케이터 */
  z-index: 9999;
}

이 시나리오의 변형

케이스 OS 브라우저 상태
ce-0280-ios-keyboard-hides-text-ko iOS 16+ Safari 16+ 초안
ce-0281-ios-keyboard-hides-text-android-en-ko Android 10-14 Chrome for Android 120+ 확인됨

Playground for this case

Use the reported environment as a reference and record what happens in your environment while interacting with the editable area.

Reported environment
OS: iOS 16+
Device: Mobile (iPhone/iPad) Any
Browser: Safari 16+
Keyboard: English (QWERTY) or iOS Virtual Keyboard
Your environment
Sample HTML:
Event log
Use this log together with the case description when filing or updating an issue.
0 events
Interact with the editable area to see events here.