포커스와 블러 이벤트

포커스와 블러 이벤트

  • focus: 요소가 활성 상태가 되어 "데이터 입력 준비" 상태가 되었음을 알립니다. 사용자가 클릭하거나 Tab 키로 이동 시 트리거
  • blur: 요소가 포커스를 잃을 때 발생합니다. 다른 요소로 이동하거나 창 밖을 클릭할 때 작동
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>입력 상태 표시</title>
  <style>
    #nameField { padding: 10px; font-size: 16px; }
    .focused { border: 2px solid #42a5f5; }
    .invalid { border: 2px solid #ef5350; }
    #status { margin-top: 5px; color: #666; }
  </style>
</head>
<body>
  <label for="nameField">이름:</label>
  <input id="nameField" placeholder="3자 이상 입력">
  <div id="status"></div>
  <script>
    const nameField = document.getElementById('nameField');
    const status = document.getElementById('status');

    // 입력 시작 시 안내 표시
    nameField.addEventListener('focus', () => {
      nameField.classList.add('focused');
      nameField.classList.remove('invalid');
      status.textContent = '3자 이상의 이름을 입력하세요.';
    });

    // 입력 종료 시 검증
    nameField.addEventListener('blur', () => {
      nameField.classList.remove('focused');
      if (nameField.value.length < 3) {
        nameField.classList.add('invalid');
        status.textContent = '이름이 너무 짧습니다.';
      } else {
        status.textContent = '유효한 이름입니다.';
      }
    });
  </script>
</body>
</html>

포커스 제어하기

자바스크립트를 사용하면 특정 조건에 따라 요소에 포커스를 주거나 제거할 수 있습니다. 예를 들어, 유효하지 않은 값이 입력되면 해당 필드에 다시 포커스를 주어 사용자가 바로 수정할 수 있도록 할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>비밀번호 확인 포커스</title>
  <style>
    input { padding: 8px; margin: 5px 0; display: block; }
    .error { border: 2px solid #d81b60; }
    #feedback { color: #d81b60; }
  </style>
</head>
<body>
  <input id="password" type="password" placeholder="비밀번호">
  <input id="confirm" type="password" placeholder="비밀번호 확인">
  <div id="feedback"></div>
  <script>
    const password = document.getElementById('password');
    const confirm = document.getElementById('confirm');
    const feedback = document.getElementById('feedback');

    confirm.addEventListener('blur', () => {
      if (password.value && password.value !== confirm.value) {
        confirm.classList.add('error');
        feedback.textContent = '비밀번호가 일치하지 않습니다.';
        setTimeout(() => confirm.focus(), 0); // 비동기로 포커스 이동
      } else {
        confirm.classList.remove('error');
        feedback.textContent = '';
      }
    });
  </script>
</body>
</html>

포커스 이벤트와 버블링 문제 해결

기본적으로 focusblur 이벤트는 버블링되지 않습니다.

캡처링을 이용한 방법

캡처링 단계에서 이벤트를 처리하면 버블링 없이도 상위 요소에서 포커스와 블러를 감지할 수 있습니다.

<div id="inputContainer" style="padding: 10px; border: 1px solid #ccc;">
  <input type="text" placeholder="첫 번째 입력">
  <input type="text" placeholder="두 번째 입력">
</div>

<script>
  const container = document.getElementById('inputContainer');
  container.addEventListener('focus', () => {
    container.style.backgroundColor = '#e0f7fa';
  }, true);  // 캡처링 단계에서 실행

  container.addEventListener('blur', () => {
    container.style.backgroundColor = '';
  }, true);
</script>

focusin과 focusout 이벤트 사용

focusin과 focusout은 focus와 blur와 동일한 역할을 하지만 버블링이 발생합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>포커스 위임</title>
  <style>
    #formContainer { padding: 15px; border: 1px solid #ccc; width: 300px; }
    input { display: block; margin: 10px 0; padding: 5px; }
    .active { background: #e3f2fd; }
  </style>
</head>
<body>
  <div id="formContainer">
    <input placeholder="아이디">
    <input placeholder="비밀번호">
  </div>
  <script>
    const formContainer = document.getElementById('formContainer');

    formContainer.addEventListener('focusin', () => {
      formContainer.classList.add('active');
    });

    formContainer.addEventListener('focusout', () => {
      setTimeout(() => {
        if (!formContainer.contains(document.activeElement)) {
          formContainer.classList.remove('active');
        }
      }, 0);
    });
  </script>
</body>
</html>

tabindex로 포커스 확장

기본적으로 <input>, <button>, <a> 등은 포커스가 가능한 반면, <div>, <span> 등은 기본적으로 포커스할 수 없습니다. 그러나 tabindex 속성을 추가하면 종류와 상관없이 포커스 가능한 요소로 만들 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>tabindex 활용</title>
  <style>
    .custom-btn {
      padding: 10px 20px; background: #66bb6a; color: white;
      display: inline-block; margin: 5px; cursor: pointer;
    }
    .custom-btn:focus { outline: 3px solid #388e3c; background: #81c784; }
  </style>
</head>
<body>
  <div class="custom-btn" tabindex="0">버튼 1</div>
  <div class="custom-btn" tabindex="0">버튼 2</div>
  <p>Tab 키로 포커스 이동을 테스트하세요.</p>
  <script>
    const buttons = document.querySelectorAll('.custom-btn');
    buttons.forEach(btn => {
      btn.addEventListener('focus', () => {
        console.log(`${btn.textContent}에 포커스`);
      });
      btn.addEventListener('blur', () => {
        console.log(`${btn.textContent}에서 포커스 해제`);
      });
    });
  </script>
</body>
</html>

tabindex 값을 0으로 설정하면, 문서의 기본 순서에 따라 포커스가 이동하며, 사용자가 키보드로도 쉽게 접근할 수 있게 됩니다.

'브라우저' 카테고리의 다른 글

폼 전송하기: submit 이벤트  (1) 2025.02.21
폼 데이터 변경 이벤트 조작하기  (0) 2025.02.21
폼 조작 하기  (0) 2025.02.20
스크롤 이벤트 제어  (0) 2025.02.20
키보드 이벤트: keydown과 keyup의 활용  (0) 2025.02.20