Cтилизация file input: как стилизовать поле для отправки файла

Опубликовал(а): Артём Масальский
Обновлено: 11.03.2024

Узнайте, как делается стилизация file input и попробуйте настроить это самостоятельно или воспользуйтесь плагином. Если у вас проект «с нуля», заранее подумайте о стилизации тега input с type=file. При доработке существующего сайта вариант с фреймворком может быть избыточным. Далее подробности по самостоятельной настройке.

Cтилизация file input

Пошаговая инструкция

Простая и эффективная стилизация элемента 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;
}

Вот что у нас получилось:

Для улучшения визуального опыта добавим следующий скрипт ближе к закрывающему тегу </body>. Поместите его перед закрывающим тегом </body>. Теперь при выборе файла вы увидите его имя рядом с кнопкой. Этот скрипт обеспечит уведомление и индикацию, когда файл будет выбран:

<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>

Что получается в итоге:

В этой версии кода мы обновили скрипт, чтобы он правильно находил метку (label) для файла. Теперь он использует previousElementSibling, что делает его более устойчивым к изменениям в разметке.

Результат можно посмотреть здесь

Cтилизация 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».