Клавиша / esc

blur

Событие потери фокуса элементом

Время чтения: меньше 5 мин

Кратко

Скопировано

Событие blur вызывается, когда элемент теряет фокус. У этого события нет фазы всплытия.

Пример

Скопировано

blur удобно использовать, например, для валидации введённых данных:

Открыть демо в новой вкладке

Как пишется

Скопировано
        
          
          element.addEventListener('blur', (event) => {  console.log('Элемент потерял фокус')})
          element.addEventListener('blur', (event) => {
  console.log('Элемент потерял фокус')
})

        
        
          
        
      

Как понять

Скопировано

Событие blur инициируется в момент, когда интерактивный элемент теряет фокус и он перемещается на другой элемент (например, по клику или нажатию Tab).

Событие срабатывает на тех html-элементах, которые имеют атрибут tabindex, либо атрибут contenteditable.

Некоторые html-элементы по умолчанию имеют tabindex="0":

  • <button>;
  • <input>;
  • <textarea>;
  • <select>;
  • <frame>;
  • <iframe>;
  • <object>;
  • <a> или <area> с атрибутом href;
  • <summary> в связке с <details>.

Как добавить событие на любой элемент

Скопировано

Чтобы blur работал на произвольном элементе (например, на <div>), добавьте ему атрибут tabindex="0" или атрибут contenteditable="true".

tabindex="0" указывает браузеру, что на элементе можно сфокусироваться (а, значит, и потерять фокус).

contenteditable="true" указывает браузеру, что элемент может редактироваться пользователем.

        
          
          <div tabindex="0">  Здесь можно сфокусироваться и потерять фокус</div><div contenteditable="true">  Здесь так же можно сфокусироваться и потерять фокус</div>
          <div tabindex="0">
  Здесь можно сфокусироваться и потерять фокус
</div>

<div contenteditable="true">
  Здесь так же можно сфокусироваться и потерять фокус
</div>

        
        
          
        
      

Пример

Скопировано

В примере ниже одинаковый обработчик события окрашивает границы блока при потере фокуса. Кликните на блок, а затем на любое другое место:

        
          
          <div class="wrapper">  <div>Блок не может получить и потерять фокус:</div>  <div class="block" id="block1"></div></div><div class="wrapper">  <div>Блок может получить и потерять фокус (с tabindex):</div>  <div class="block" id="block2" tabindex="0"></div></div><div class="wrapper">  <div>Блок может получить и потерять фокус (с contenteditable):</div>  <div class="block" id="block3" contenteditable="true"></div></div>
          <div class="wrapper">
  <div>Блок не может получить и потерять фокус:</div>
  <div class="block" id="block1"></div>
</div>
<div class="wrapper">
  <div>Блок может получить и потерять фокус (с tabindex):</div>
  <div class="block" id="block2" tabindex="0"></div>
</div>
<div class="wrapper">
  <div>Блок может получить и потерять фокус (с contenteditable):</div>
  <div class="block" id="block3" contenteditable="true"></div>
</div>

        
        
          
        
      
        
          
          const block1 = document.getElementById("block1");const block2 = document.getElementById("block2");const block3 = document.getElementById("block3");function blurHandler(event) {  event.target.classList.add('green')  event.target.innerHTML = '👋 Я потерял фокус'}block1.addEventListener('blur', blurHandler);block2.addEventListener('blur', blurHandler);block3.addEventListener('blur', blurHandler);
          const block1 = document.getElementById("block1");
const block2 = document.getElementById("block2");
const block3 = document.getElementById("block3");

function blurHandler(event) {
  event.target.classList.add('green')
  event.target.innerHTML = '👋 Я потерял фокус'
}

block1.addEventListener('blur', blurHandler);
block2.addEventListener('blur', blurHandler);
block3.addEventListener('blur', blurHandler);

        
        
          
        
      
Открыть демо в новой вкладке

Делегирование события

Скопировано

Из-за того, что у события blur нет фазы всплытия, его нельзя просто так делегировать родительскому элементу. Вариант решения этой проблемы — передать в метод addEventListener параметр { capture: true }.

Обычно слушатель обрабатывает события на фазе всплытия, но, если установлен параметр { capture: true }, будет обрабатывать событие раньше, на фазе захвата. Нужно иметь в виду, что в этом случае событие будет обработано родительским элементом раньше, чем целевым (дочерним), т.к. фаза захвата происходит до того, как событие достигает целевого элемента.

        
          
          parentElement.addEventListener(  'blur',  (event) => {    console.log('Элемент потерял фокус')  },  { capture: true })//либо эквивалентная запись:parentElement.addEventListener(  'blur',  (event) => {    console.log('Элемент потерял фокус')  },  true //тоже самое, что прописать { capture: true })
          parentElement.addEventListener(
  'blur',
  (event) => {
    console.log('Элемент потерял фокус')
  },
  { capture: true }
)

//либо эквивалентная запись:

parentElement.addEventListener(
  'blur',
  (event) => {
    console.log('Элемент потерял фокус')
  },
  true //тоже самое, что прописать { capture: true }
)

        
        
          
        
      

Пример

Скопировано

В примере ниже одинаковый обработчик события, выводящий ошибку о незаполненном поле, вешается на две формы. В первой форме параметр { capture: true } не установлен, во второй установлен.

        
          
          <form class="form" id="form1">  <div class="form-row">    <label for="name1">Введите имя:</label>    <input id="name1" type="text">  </div>  <div class="form-row">    <label for="city1">Введите город:</label>    <input id="city1" type="text">  </div></form>
          <form class="form" id="form1">
  <div class="form-row">
    <label for="name1">Введите имя:</label>
    <input id="name1" type="text">
  </div>
  <div class="form-row">
    <label for="city1">Введите город:</label>
    <input id="city1" type="text">
  </div>
</form>

        
        
          
        
      
        
          
          const form1 = document.getElementById("form1");const form2 = document.getElementById("form2");function blurHandler(event) {  const input = event.target;  if (!event.target.value) {    input.classList.add('invalid');    const error = document.createElement('div');    error.textContent = 'Поле обязательно для заполнения!';    error.classList.add('error-message');    input.insertAdjacentElement('afterend', error);  }}form1.addEventListener('blur', blurHandler);form2.addEventListener('blur', blurHandler, { capture: true });
          const form1 = document.getElementById("form1");
const form2 = document.getElementById("form2");

function blurHandler(event) {
  const input = event.target;

  if (!event.target.value) {
    input.classList.add('invalid');
    const error = document.createElement('div');
    error.textContent = 'Поле обязательно для заполнения!';
    error.classList.add('error-message');
    input.insertAdjacentElement('afterend', error);
  }
}

form1.addEventListener('blur', blurHandler);
form2.addEventListener('blur', blurHandler, { capture: true });

        
        
          
        
      
Открыть демо в новой вкладке