Оформление input type file. Проблема стилизации элементов форм

05.04.2019

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

Пример опубликованный здесь демонстрирует как вариант один из решений, который позволяет стилизовать поле выбора файла. Делается это таким образом, в форме мы размещаем input file, а вместе с ним добавляем label. Input file мы скрываем, а вместо него делаем из label стилизованную кнопку (благо есть такая возможность). После чего, немного магии на javascript, и наш label будет уметь открывать форму выбора файла при клике. Далее по порядку.

Поля для стилизации input file:

Выберите файл

Теперь, нам предстоит скрыть input file, чтобы в поле зрения оставался только label, который мы и будем стилизовать.

Скрываем input file:

Inputfile { width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1; }

После этого, как на странице остался только label, приступаем к его стилизации.

Стилизуем label

Inputfile + label { font-size: 1.25em; font-weight: 700; color: white; background-color: black; display: inline-block; } .inputfile:focus + label, .inputfile + label:hover { background-color: red; }

Есть моменты, которые следовало бы отметить, что мы и сделаем. По умолчанию элемент label не кликабельный, а это значит, что курсор у него будет в виде стандартного указателя «стрелочки». Чтобы обозначить курсор кликабельным, добавляем так же параметр cursor со значением pointer.

Inputfile + label { cursor: pointer; }

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

Inputfile:focus + label { outline: 1px dotted #000; outline: -webkit-focus-ring-color auto 5px; }

Теперь что касается описания кнопки выбора файла. Сделаем так, чтобы при выборе одного файла кнопка отображала его имя, при выборе нескольких – показывалось общее количество файлов. Реакцию на выбор пользователя мы запрограммируем на javascript, а так же воспользуемся библиотекой JQuery.

Подготовим скрытое поле, для работы с ним:

Код Javascript:

Var inputs = document.querySelectorAll(".inputfile"); Array.prototype.forEach.call(inputs, function(input) { var label = input.nextElementSibling, labelVal = label.innerHTML; input.addEventListener("change", function(e) { var fileName = ""; if(this.files && this.files.length > 1) fileName = (this.getAttribute("data-multiple-caption") || "").replace("{count}", this.files.length); else fileName = e.target.value.split("\\").pop(); if(fileName) label.querySelector("span").innerHTML = fileName; else label.innerHTML = labelVal; }); });

Что делать, если javasvript отключен в браузере?
Редко, но случается, что в браузере может быть выключен код javascript, что делать в этом случае? Ничего не остается, кроме того, чтобы вернуть видимость скрытому полю выбора файла.

(function(e,t,n){var r=e.querySelectorAll("html");r.className=r.className.replace(/(^|\s)no-js(\s|$)/,"$1js$2")})(document,window,0);

Дополнительный код в CSS:

Js .inputfile { width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1; } .no-js .inputfile + label { display: none; }

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

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

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

У нас же будет иметь следующий вид:

Выберите файл Файл не выбран

Давайте немножко разберем, что и как.

  • - заключаем все в блок контейнер. Условие обязательное. Присваиваем блоку класс fl_upld .
  • Выберите файл - наше поле прикрепления файла заключаем в label. Это наш и идентификатор поля. Самому полю присваиваем id="fl_inp". Тоже важный момент. Ну и добавляем текст - Выберите файл . Этот текст будет на будущей кнопке.
  • Файл не выбран - блок, который изначально выводит текст - Файл не выбран. После выбора файла вместо этого текста появится название файла. данному блоку присваиваем id="fl_nm". Забегу наперед, скажу, что если не будете подключать скрипт для вывода имени файла, то можете не добавлять данный блок. У вас будет просто кнопка без динамики.

Fl_upld{width:300px;} #fl_inp{display:none;} .fl_upld label{ cursor:pointer; background:#36c; border-radius:3px; padding:10px 25px; color:#fff; font-weight:bold; text-align: center; } .fl_upld label:hover{background:#fc0;} #fl_nm{ margin-top:20px; color:#f00;}

Быстро расскажу, что за что отвечает.

  • Для контейнера fl_upld устанавливаем ширину в 300px. Если это поле будет внутри вашей формы, у которой будет ширина, то в принципе можно эту строчку не писать и ширину не задавать.
  • #fl_inp{display:none;} - скрываем наше стандартное поле прикрепления файла. Это важный и единственный главный параметр.
  • Далее для .fl_upld label - пишем параметры. Идентификатор и станет нашей кнопкой. Прописываете все что хотите, чтобы сделать кнопку нужного вида.
  • .fl_upld label:hover{background:#fc0;} - стили для кнопки. кола на нее наводишь курсор. У нас она просто становится желтой.
  • Ну и напоследок для #fl_nm блока названия файла тоже добавляем параметры.

Вот и все стили, конечно же как и всегда можете менять их как угодно и подгонять под себя. Главный параметр - это скрыть стандартное поле. #fl_inp{display:none;}

Теперь приступим к последнему шагу, добавлению скрипта вывода имени файла при добавлении. Так как скрипт работает на jQuery , сначала нужно подключить библиотеку. если это уже сделано делать этого не нужно.

.files[ 0 ]) file_name = inp[ 0 ].files[ 0 ].name; else file_name = inp.val().replace("C:\\fakepath\\", ""); if(! file_name.length) return; if(lbl.is(":visible")){ lbl.text(file_name); btn.text("Выбрать"); }else btn.text(file_name); }).change();
- если браузер поддерживает File API, то имя файла определяется с помощью него, в противном случае оно вырезается из значения скрытого input . Для мобильных устройств, когда элемент представляет из себя одну кнопку, имя выбранного файла выводится на ней же.

Казалось бы, все, что требуется, уже написано. А вот фигушки! Если выбрать файл, используя «мобильное» поле, а затем увеличить размер окна и перевести элемент в «десктопный», то в текстовом поле так и останется «Файл не выбран» - нужно каждый раз обновлять элемент при изменении размеров окна:
$(window).resize(function(){ $(".file_upload input").triggerHandler("change"); });

И что же мы получили в итоге? Полученное стилизованное поле выбора файла было успешно протестировано для всех трех способов в следующих браузерах:
  • FireFox 22.0 (Linux, Windows)
  • Opera 12.16 (Linux, Windows)
  • Internet Explorer 9
  • Chromium 27.0 (Linux)
  • Apple Safari (iOS 6.3.1)
  • Android browser (Android 2.3.6)
  • Android FireFox

Из плюсов всех рассмотренных в статье подходов можно выделить следующие основные:

Из основных минусов:

  • Необходимость использования JavaScript (касается всех способов).
  • Использование хаков CSS для «маскировочного» способа.
  • Необходимость писать дополнительные костыли для поля с атрибутом multiple (касается всех способов).
  • Некроссбраузерность - у всех способов отсутствует поддержка IE 8, а также необходимо использовать «браузерные» свойства CSS для поддержки остальных «старичков».
  • Решение на JavaScript не поддерживается всеми версиями Internet Explorer, а также некоторыми старыми версиями других популярных браузеров (хотя ими уже практически никто и не пользуется).

Какой из трех двух элегантных способов создания стилизованного input выбрать для повседневного использования - решать вам. Мой выбор - способ с использованием label (хоть он и имеет несемантичную верстку).

Рабочие примеры всех трех способов можно посмотреть на CodePen.