Разделы сайта

Популярные статьи
Конечный результат стилизации инпута

Сегодня я хочу вам рассказать о том, как можно изменить внешний вид файлового инпута, как стилизовать файл-инпут под свой дизайн, как стилизовать <input type="file">.

Хватит ключевых слов =). Суть я думаю вы поняли.

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

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


Для начала давайте посмотрим на то, как отображаются файл-инпуты без применения каких-либо стилей в разных браузерах.

Пустые файл-инпуты

Как видим, во всех браузерах кроме сафари имеется текстовое поле, а справа от него кнопка. Расскажу о различиях. В Опере и IE мы можем написать адрес файла вручную (сомневаюсь, что кто-либо когда-либо пользовался этой возможностью). Файерфокс, несмотря на то, что у него есть текстовое поле, не дает нам вписать туда адрес файла. Вместо этого появляется окно выбора файла как при нажатии на кнопку «Обзор».
Давайте теперь выберем в этих полях какой-либо файл.

заполненные файл-инпуты

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

Но cначала ознакомимся с проблематикой.
1. Средствами JS мы не можем сымитировать клик на такой инпут. Вот что говорится об этом в святом писании спецификации DOM:

click
Simulate a mouse-click. For INPUT elements whose type attribute has one of the following values: “button”, “checkbox”, “radio”, “reset”, or “submit”.
No Parameters
No Return Value
No Exceptions

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

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

Основная трудность в следующей проблеме.

2. Мы не можем свободно влиять на размеры кнопок «обзор», чтобы подогнать инпут под размер перекрываемой картинки. В файерфоксе мы вообще не можем изменить внешний вид файл-инпута средствами css (кроме высоты). То есть задача заключается определении оптимального размера перекрываемой картинки, чтобы минимальное количество пикселей было некликабельно, а пустые области не реагировали на клик.

Посмотрим на кликабельные области и их размеры в разных браузерах.

Рабочие области в разных браузерах

Все что внутри голубой обводки - кликабельная область. Замечу, что высоту кнопок мы можем увеличить, а вот ширину — нет.


Проблемы ясны. Переходим к делу.

Для начала нарисуем кнопку для выбора файла. Вот какая получилась у меня.

В обычном состоянии:

alt

при наведении:

alt

Теперь для разных типов файлов подготовим иконки и объединим их в один файл.

alt

Итак, сверстаем шаблон инпута:

HTML:
<div class="blocker" <!--блок, перекрывающий поле ввода слева от кнопки--> <input type="file" id="File1" class="customFile" /> <div id="BrowseButton" title="Выбрать файл" class="fakeButton" <div id="FileName" <!--сюда мы будем вставлять имя файла и иконку-->
CSS:
<style type="text/css" #File1 { position: absolute; } .customFile { width: 219px; margin-left: -140px; cursor: default; height: 21px; z-index: 2; filter: alpha(opacity: 0); opacity: 0; } .fakeButton { position: absolute; z-index: 1; width: 85px; height: 21px; background: url(images/button.jpg) no-repeat left top; float: left; } .blocker { position: absolute; z-index: 3; width: 150px; height: 21px; background: url(images/transparent.gif); margin-left: -155px; } #FileName { position: absolute; height: 15px; margin-left: 90px; font-family: Verdana; font-size: 8pt; color: Gray; margin-top: 2px; padding-top: 1px; padding-left: 19px; } #activeBrowseButton { background: url(images/button_active.jpg) no-repeat left top; display: none; } </style

Результат выглядит приблизительно так:

alt

Обведенное красным — blocker, файл-инпут показан с половинной прозрачностью.


Теперь при выборе файла (событие onchange) мы должны вырезать название файла из value нашего файл-инпута, определить тип файла по расширению и сместить фон, чтобы показывалась нужная иконка. Обратите внимание, что в разных операционных системах путь к файлу может быть через прямой слэш (в Mac OS, например), или через обратный (Виндуз), поэтому чтобы вырезание названия файла работало везде необходимо два регулярных выражения.

function HandleChanges() { file = fileInput.value; reWin = /.*(.*)/; var fileTitle = file.replace(reWin, "$1"); //выдираем название файла для windows reUnix = /.*/(.*)/; fileTitle = fileTitle.replace(reUnix, "$1"); //выдираем название файла для unix-систем fileName.innerHTML = fileTitle; var RegExExt =/.*.(.*)/; var ext = fileTitle.replace(RegExExt, "$1");//и его расширение var pos; if (ext) { switch (ext.toLowerCase()) { case 'doc': pos = '0'; break; case 'bmp': pos = '16'; break; case 'jpg': pos = '32'; break; case 'jpeg': pos = '32'; break; case 'png': pos = '48'; break; case 'gif': pos = '64'; break; case 'psd': pos = '80'; break; case 'mp3': pos = '96'; break; case 'wav': pos = '96'; break; case 'ogg': pos = '96'; break; case 'avi': pos = '112'; break; case 'wmv': pos = '112'; break; case 'flv': pos = '112'; break; case 'pdf': pos = '128'; break; case 'exe': pos = '144'; break; case 'txt': pos = '160'; break; default: pos = '176'; break; }; fileName.style.display = 'block'; fileName.style.background = 'url(images/icons.png) no-repeat 0 -'+pos+'px'; }; }; function MakeActive() { activeButton.style.display = 'block'; }; function UnMakeActive() { activeButton.style.display = 'none'; };

Последние две функции MakeActive и UnMakeActive добавляют hover эффект к нашей кнопочке.

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

На странице у нас останется только два элемента:

<div id="wrapper" <input id="File1" type="file"/> </div

Если у пользователя будет отключен JavaScript, он увидит обычный файл-инпут. В противном случае произойдет следующее:

window.onload = WindowOnLoad; var fileInput = document.getElementById('File1'); var fileName = document.createElement('div'); fileName.style.display = 'none'; fileName.style.background = 'url(images/icons.png)'; var activeButton = document.createElement('div'); var bb = document.createElement('div'); var bl = document.createElement('div'); function WindowOnLoad() { var wrap = document.getElementById('wrapper'); fileName.setAttribute('id','FileName'); activeButton.setAttribute('id','activeBrowseButton'); fileInput.value = ''; fileInput.onchange = HandleChanges; fileInput.onmouseover = MakeActive; fileInput.onmouseout = UnMakeActive; fileInput.className = 'customFile'; bl.className = 'blocker'; bb.className = 'fakeButton'; activeButton.className = 'fakeButton'; wrap.appendChild(bb); wrap.appendChild(bl); wrap.appendChild(activeButton); wrap.appendChild(fileName); };

Теперь посмотрим как это выглядит.

 
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
Copyright www.tultip.net © Использование материалов с сайта tultip.net возможно только при наличии активной ссылки на нас