Стилізація file input: як стилізувати поле для надсилання файлу

Дізнайтеся, як робиться стилізація file input і спробуйте налаштувати це самостійно або скористайтеся плагіном. Якщо у вас проєкт з нуля, заздалегідь подумайте про стилізацію тега input з type=file. При доопрацюванні активного сайту варіант із фреймворком може бути надмірним. Далі подробиці з самостійного налаштування.

Покрокова інструкція

Проста та ефективна стилізація елемента input [type=”file”] досягається шляхом обертання його в тег label. Сам елемент input можна приховати за допомогою CSS, а label стилізувати так, щоб він виглядав як кнопка.

<div class="input__wrapper">
  <input type="file" name="file" id="input__file" class="input input__file">
  <label for="input__file">Выберите файл</label>
</div>

За допомогою JavaScript та методу event.preventDefault() можна керувати надсиланням форми. Це корисно для попередньої перевірки даних перед їх передачею на сервер.

Ось, як зараз виглядає поле в браузері:

Додамо стилі, щоб отримати описуваний результат. Тобто приховаємо input, залишимо тільки label, помістимо в нього іконку і зробимо його схожим на звичайну кнопку.

Але спочатку, додамо дещо у верстку:

<div class="input__wrapper">
   <input name="file" type="file" id="input__file" class="input input__file" multiple>
   <label for="input__file" class="input__file-button">
      <span class="input__file-icon-wrapper"><img class="input__file-icon" src="./img/add.svg" alt="Выбрать файл" width="25"></span>
      <span class="input__file-button-text">Выберите файл</span>
   </label>
</div>

Тепер застосуємо стилі:

.input__wrapper {
  width: 100%;
  position: relative;
  margin: 15px 0;
  text-align: center;
}
 
.input__file {
  opacity: 0;
  visibility: hidden;
  position: absolute;
}
 
.input__file-icon-wrapper {
  height: 60px;
  width: 60px;
  margin-right: 15px;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  border-right: 1px solid #fff;
}
 
.input__file-button-text {
  line-height: 1;
  margin-top: 1px;
}
 
.input__file-button {
  width: 100%;
  max-width: 290px;
  height: 60px;
  background: #1bbc9b;
  color: #fff;
  font-size: 1.125rem;
  font-weight: 700;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-pack: start;
      -ms-flex-pack: start;
          justify-content: flex-start;
  border-radius: 3px;
  cursor: pointer;
  margin: 0 auto;
}

Ось що в нас вийшло:

Для покращення візуального досвіду додамо наступний скрипт ближче до тега, що закриває . Помістіть його перед тегом . Тепер при виборі файлу ви побачите його ім’я поруч із кнопкою. Цей скрипт забезпечить сповіщення та індикацію, коли файл буде вибраний:

<script>
    let inputs = document.querySelectorAll('.input__file');
    Array.prototype.forEach.call(inputs, function (input) {
      let label = input.nextElementSibling,
        labelVal = label.querySelector('.input__file-button-text').innerText;
  
      input.addEventListener('change', function (e) {
        let countFiles = '';
        if (this.files && this.files.length >= 1)
          countFiles = this.files.length;
  
        if (countFiles)
          label.querySelector('.input__file-button-text').innerText = 'Выбрано файлов: ' + countFiles;
        else
          label.querySelector('.input__file-button-text').innerText = labelVal;
      });
    });
</script>

У цьому випадку ми стежимо за змінами у полі вибору файлу (fileInput). При зміні значення поля скрипт перевіряє, чи обрано файл. Якщо файл обраний, витягується його ім’я і відображається всередині мітки (fileLabel). Якщо файл не обрано, мітка залишається незмінною.

Тепер внесемо зміни до розмітки та стилів, щоб кнопка з додаванням файлу була праворуч, а поле з виведенням повідомлення – зліва. Крім того, покращимо стилі, щоб кнопка виглядала більш привабливо.

Розмітка:

<div class="field__wrapper">
  
   <input name="file" type="file" name="file" id="field__file-2" class="field field__file" multiple>
      
   <label class="field__file-wrapper" for="field__file-2">
     <div class="field__file-fake">Файл не вбран</div>
     <div class="field__file-button">Выбрать</div>
   </label>
      
</div>

Стилі

.field__wrapper {
  width: 100%;
  position: relative;
  margin: 15px 0;
  text-align: center;
}
 
.field__file {
  opacity: 0;
  visibility: hidden;
  position: absolute;
}
 
.field__file-wrapper {
  width: 100%;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: justify;
      -ms-flex-pack: justify;
          justify-content: space-between;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -ms-flex-wrap: wrap;
      flex-wrap: wrap;
}
 
.field__file-fake {
  height: 60px;
  width: calc(100% - 130px);
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  padding: 0 15px;
  border: 1px solid #c7c7c7;
  border-radius: 3px 0 0 3px;
  border-right: none;
}
 
.field__file-button {
  width: 130px;
  height: 60px;
  background: #1bbc9b;
  color: #fff;
  font-size: 1.125rem;
  font-weight: 700;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  border-radius: 0 3px 3px 0;
  cursor: pointer;
}

Скрипт

<script>
    let fields = document.querySelectorAll('.field__file');
    Array.prototype.forEach.call(fields, function (input) {
      let label = input.nextElementSibling,
        labelVal = label.querySelector('.field__file-fake').innerText;
  
      input.addEventListener('change', function (e) {
        let countFiles = '';
        if (this.files && this.files.length >= 1)
          countFiles = this.files.length;
  
        if (countFiles)
          label.querySelector('.field__file-fake').innerText = 'Выбрано файлов: ' + countFiles;
        else
          label.querySelector('.field__file-fake').innerText = labelVal;
      });
    });
</script>

Що виходить у результаті:

У цій версії коду ми оновили скрипт, щоб він вірно знаходив мітку для файлу. Тепер він використовує попередній елемент, що робить його більш стійким до змін в розмітці.

Результат можна подивитися тут

Стилізація file input із застосуванням плагіну

Використовуйте jQuery Fileinput плагін для стилізації поля введення файлу. Приєднайте його разом з jQuery, і ви зможете легко налаштувати зовнішній вигляд та поведінку елемента вибору файлу.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="./js/fileinput.js"></script>

Створюємо input:

<input name="upl" type="file" class="input-file" multiple>

Ініціалізуємо плагін:

<script>
   $(function() {
     $(".input-file").fileinput();
   });
</script>

Після активації сам елемент input буде прихований, а замість нього з’явиться стилізована кнопка.

Для завдання власного класу та тексту на кнопці достатньо передати відповідний HTML-код у fileinput. Наприклад:

<script>
   $(function() {
     $(".input-file").fileinput('<button class="input-file__button">Выбрать файл</button>');
   });
</script>

Для наочності ви можете ознайомитися з прикладом на jsfiddle. На сьогодні все, і ми сподіваємося, що тепер у вас не залишилося питань щодо стилізації input з типом “file”.