Как известно традиционными методами стилизации полей ввода стилизовать поле выбора файла стилизовать не представляется возможным. Таким образом, по умолчанию стиль поля ввода устанавливается самим браузером, а еще самое худшее, что в каждом браузере поле выбора отображается по-разному. Т.к. всегда хочется как лучше, довольно часто возникает необходимость стилизации поля выбора файла. Здесь на помощь помогает небольшая хитрость, о которой мы поговорим в данном посту.
Пример опубликованный здесь демонстрирует как вариант один из решений, который позволяет стилизовать поле выбора файла. Делается это таким образом, в форме мы размещаем 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{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_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");
});
Из плюсов всех рассмотренных в статье подходов можно выделить следующие основные:
Из основных минусов:
Какой из трех двух элегантных способов создания стилизованного input выбрать для повседневного использования - решать вам. Мой выбор - способ с использованием label (хоть он и имеет несемантичную верстку).
Рабочие примеры всех трех способов можно посмотреть на CodePen.