Стилизация собственного поля ввода для загрузки файла

Что мы делаем #

Тематическое поле ввода для загрузки файла с уникальной меткой кнопки и значком, использующим только HTML и CSS.

Intro #

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

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

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

Buildout #

Кнопка ::file-selector-button будет работать с любым допустимым свойством CSS, что означает, что мы можем передать любой стиль или переход, которые мы хотим, чтобы соответствовать системе дизайна наших сайтов. Кнопка выбора файла находится внутри теневого DOM-узла и, следовательно, не будет просачиваться за пределы теневого корня, а это означает, что существуют некоторые ограничения в отношении выбора дочерних элементов или изменения текста внутри самой кнопки. К счастью, мы можем обойти эти ограничения с помощью некоторого творческого построения псевдокласса.

Давайте начнем со стиля кнопки выбора:

Это дает нам красиво оформленную кнопку с работающими наведением и активными состояниями, но, как упоминалось ранее, мы не можем изменить текст внутри кнопки.

К счастью, есть решение этого ограничения путем передачи псевдоэлементов ::before и ::after в элемент input[type="file"] , что позволяет нам затем добавить дополнительную разметку, необходимую для достижения стилизованная кнопка, которую мы ищем.

❗ В настоящее время Firefox не поддерживает псевдоэлементы ::before или ::after в input[type="file"] . Мы включим резервное исправление для этого позже в статье.

Давайте немного разберем этот код.

Во-первых, мы будем использовать background-image для рендеринга значка загрузки файла. Один из лучших способов сделать это — оптимизировать SVG внутри URI данных

. У Тейлора Ханта есть потрясающий пост в блоге об этом методе, а также ссылка на автогенератор Codepen, который делает его таким же простым, как копирование и вставка значения.

Затем мы используем псевдокласс ::after , чтобы установить новую метку, используя реквизит content и передав любую строку , которую мы хотели бы, а затем позиционируя ее соответствующим образом. Поскольку кнопка ::file-selector-button не знает положения этих псевдоклассов или их размеров, нам нужно использовать фиксированных значений для соответствующего позиционирования значка и метки внутри него, а затем обновить

ширину из ::file-selector-button , чтобы учесть размер нашего нового значка и метки.

С нашей кнопкой, оформленной и помеченной так, как мы хотим; вы можете заметить, что наше состояние фокуса оборачивает весь ввод, а не только наш пользовательский ::file-selector-button .

Давайте это исправим:

 input[type="file"] {
  положение: родственник;
  контур: нет;
  отступ: 4px;
  поле: -4px;
}
input[type="file"]:focus-within::file-selector-button,
input[type="file"]:focus::file-selector-button {
  контур: 2px сплошной #0964b0;
  смещение контура: 2px;
} 
ДО
ПОСЛЕ

Здесь есть два основных вывода. Во-первых, наше внимание теперь сосредоточено исключительно вокруг кнопки ::file-selector-button , а не всего ввода.

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

Соображения о кросс-браузерности #

В наши дни поддержка этого типа решения в современных браузерах довольно надежна, но для Firefox еще предстоит проделать некоторую работу. Начиная с версии 110, Firefox по-прежнему не поддерживает ::before и 9.0013 ::после псевдоэлементов внутри input[type="file"] . Таким образом, этот метод в настоящее время приводит к пустой кнопке ввода, поскольку мы удалили цвет шрифта, но, к счастью, для наших друзей в Firefox есть простое исправление!

 @supports (-moz-внешний вид: нет) {
  input[type="file"]::file-selector-button {
    цвет: #0964b0;
  }
} 

Простое добавление цвета обратно к ::file-selector-button отобразит метку по умолчанию. К сожалению, это означает, что они потеряют пользовательскую метку и значок, которые мы сделали, но лучше изящно отступить, чем иметь плохой опыт для этих пользователей. Как всегда, с любым типом решения, подобного этому, настоятельно рекомендуется протестировать его в разных типах браузеров и устройств и убедиться, что результат соответствует вашим ожиданиям.

Собираем все воедино #

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

Кнопка загрузки файла в пользовательском стиле с использованием чистого CSS

В этом руководстве я покажу вам, как создать стильную и удобную кнопку загрузки файла с помощью чистого CSS и HTML.

Наценка

Чтобы загрузить файлы, вам нужно использовать входной тег с атрибутом type="file"

. Кроме того, вы можете указать, какие типы файлов вы разрешаете загружать с помощью атрибута accept .

HTML:

 
 

Эта разметка создает кнопку с заголовком Choose file , за которым следует текст, указывающий имя файла при выборе. По умолчанию это Файл не выбран .

Результат:

Ввод с типом файла по умолчанию выглядит по-разному в разных браузерах:

ChromeEdgeFireFoxSafari

Стиль

Структура виджета загружаемого файла состоит из блока, который отображает кнопку и имя файла. Пользователь может щелкнуть в любом месте внутри блока или перетащить файл с рабочего стола, и откроется окно загрузки.

Стилизация блока загружаемых файлов

Если вы примените стили для селектора input[type=file] , они будут установлены для всего блока виджетов, то есть для кнопки и текста.

CSS:

 ввод[тип=файл] {
  ширина: 350 пикселей;
  максимальная ширина: 100%;
  цвет: #444;
  отступ: 5px;
  фон: #fff;
  радиус границы: 10px;
  граница: 1px сплошная #555;
}
 

Результат уже выглядит намного лучше, поскольку он указывает зону, в которой пользователь может щелкнуть или перетащить файл.

Результат:

Стиль кнопки загрузки файла

По умолчанию кнопка Выбрать файл имеет простой стиль пользовательского агента. Чтобы стилизовать кнопку с помощью CSS, вы должны использовать ::file-selector-button псевдоэлемент для его выбора. Поддерживается во всех современных браузерах.

CSS:

 input[type=file]::file-selector-button {
  поле справа: 20px;
  граница: нет;
  фон: #084cdf;
  отступ: 10px 20px;
  радиус границы: 10px;
  цвет: #fff;
  курсор: указатель;
  переход: фон .2s облегчение входа-выхода;
}
input[type=file]::file-selector-button:hover {
  фон: #0d45a5;
}
 

Результат

Стиль области щелчка/перетаскивания

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

Чтобы реализовать большую зону перетаскивания, вам нужно обернуть загрузку файла input в тег label и указать текст описания, который позволит пользователям узнать, как использовать виджет.

HTML

 <метка для = "изображения">
  Перетащите файлы сюда
  или
  

Для макета нам нужно установить display на flex со свойствами, связанными с flex, для позиционирования. свойства height и padding для пропорции. И, наконец, добавьте некоторые причудливые стили, такие как эффекты границы и наведения, чтобы выделить зону загрузки файла, и вы готовы к работе.

CSS:

 .drop-контейнер {
  положение: родственник;
  дисплей: гибкий;
  зазор: 10 пикселей;
  flex-направление: столбец;
  выравнивание содержимого: по центру;
  выравнивание элементов: по центру;
  высота: 200 пикселей;
  отступ: 20 пикселей;
  радиус границы: 10px;
  граница: 2 пикселя, пунктир #555;
  цвет: #444;
  курсор: указатель;
  переход: фон .
2s плавный вход-выход, граница .2s легкий вход-выход; } .drop-контейнер: наведите { фон: #еее; цвет границы: #111; } .drop-контейнер: наведение .drop-название { цвет: #222; } .drop-название { цвет: #444; размер шрифта: 20px; вес шрифта: полужирный; выравнивание текста: по центру; переход: цвет .2s легкий вход-выход; }

Результат:

Перетащите сюда файлы или

Обработка событий перетаскивания

Кроме того, вы можете обрабатывать случаи, когда пользователь пытается перетащить файл через область перетаскивания. Один лишь CSS не может справиться с такими случаями, поэтому мы можем добавить немного JavaScript.

Чтобы улучшить UX для поля перетаскивания, необходимо учитывать два момента:

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

Чтобы указать область перетаскивания, когда пользователь перетаскивает на нее файл, нам потребуется использовать события dragenter и dragleave . Оба на метке метки , поскольку она представляет собой область перетаскивания. Для каждого события мы добавляем или удаляем класс CSS соответственно.

Поскольку пользователь будет переходить на тег label , нам также необходимо установить значение input в файле. Для этого нам нужно сделать 2 вещи:

  1. Установите событие dragover для тега label , установите e.preventDefault() и передайте false в качестве третьего параметра для метода addEventListener
  2. При событии drop нам нужно установить свойство файлов ввода в файл через fileInput.files = e.dataTransfer.files
 const dropContainer = document.getElementById("dropcontainer")
 const fileInput = document.getElementById ("изображения")
 dropContainer.addEventListener("dragover", (e) => {
 // запретить дефолт, чтобы разрешить сброс
 e.