Пример простой кастомизации поля загрузки файлов (input file)

Проблема стилизации поля типа file связана с тем, что на нем невозможно инициировать клик. То есть мы не можем просто взять и сделать document.dispatchEvent(‘click’) на input file, пользователь должен сам совершить этот клик. Также поля данного типа, как и некоторые другие, практически не поддаются стилизации через CSS.

Если стилизовать input file нельзя, значит его в любом случае нужно прятать, а кликать по нему каким-то другим способом. И здесь вы удивитесь, какое количество способов, нередко безумных, было придумано. Я рассмотрю, на мой взгляд, самый адекватный и семантичный. Остальные легко найти в интернете, если интересно.

Способ похож на тот, что используется для кастомизации checkbox и radio кнопок. Мы будем скрывать поле и использовать элемент <label> с параметром for="", что позволит инициировать открытие окна выбора файла. То есть мы решаем главную проблему – клик по полю, которого нет или которое скрыто. Увы, в отличии от решения для чекбоксов, обойтись только CSS не получится. Часть решения подразумевает использование JavaScript.

html разметка:

<div class="field-file">
    <input id="file" class="field-file__input" type="file" name="uploadFile"/>
    <label class="field-file__label" for="file">
        <i class="field-file__icon"></i>
        <span class="field-file__label--text">Выберите файл для загрузки</span>
    </label>
</div>

Иконка добавлена для красоты. В действительности, для решения задачи достаточно контейнера, которым выступает div.field-file, поля формы input[type=”file”]. field-file__input и следом label.field-file__label. Тэг label обязательно должен идти после input, чтобы у нас была возможность реагировать на фокус поля без лишнего JS кода. При такой очередности тэгов можно обойтись CSS селекторами отношения + или ~.

Теперь CSS. Сначала прячем input file:

.field-file__input {
    position: absolute;
    opacity: 0;
    top: 0;
    right: 100%;
}

Не прячем через disaplay: none или visibility: hidden, так как в некоторых браузерах или отдельных их версиях эти свойства станут причиной того, что на сервер не будет передаваться значение поля.

С дополнительными стилями, которые напрямую не относятся к решению задачи, это будет выглядеть следующим образом:

На текущий момент кастомный элемент позволяет выбрать файл для загрузки. Можно даже добавить некоторую реакцию на действия пользователя, используя для этого CSS селектор вида:

.field-file__input:focus ~ .field-file__label {
    color: #6979F8;
}

.field-file__input:focus ~ .field-file__label .field-file__icon {
    border-color: #3444c3;
}

Это работает за счет порядка и связи тэгов label и input. Но вряд ли этого достаточно для того, чтобы назвать вашу форму отзывчивой. Как минимум, пользователь должен видеть, какой файл он выбрал.  Именно так ведет себя стандартный input file. Добавим JavaScript код:

document.getElementById('file').addEventListener('change', function (e) {
    // Проверяем, что только 1 файл был выбран
    if (this.files && this.files.length == 1) {
        const textContainer = this.nextElementSibling.querySelector('.field-file__label--text');
        const fileName = e.target.value.split('\\').pop();

        if (textContainer) {
            textContainer.textContent = fileName || 'Выберите файл для загрузки';

            return true;
        }
    }

    return false;
});

Это не готовое решение, а лишь демонстрация того, как можно работать с данным типом поля с помощью JavaScript. Пока мы просто показали имя выбранного файла вместо строки «Выберите файл для загрузки», отображаемой по умолчанию. Но нередко этого достаточно и в реальных задачах.

Живой пример http://wmate.ru/wp-content/demo/4/84/index.html

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Комментарии (0)

Пока нет комментариев