Оформление элемента input type=file средствами CSS и JavaScript

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

На самом деле проблема куда как масштабней чем может показаться на первый взгляд, но и её решение нельзя назвать особо сложным. Вот такой вот парадокс. С одной стороны, оформить input type="file" только средствами CSS не представляется возможным, а с другой – JavaScript не может вызвать диалоговое окно для открытия файла. Будет не лишним учесть и возможность отключения JavaScript в браузере.

Для решения такого рода задачи используется JavaScript интеграция специальной HTML надстройки над имеющимся тегом INPUT, конечный результат которой может выглядеть следующим образом:

<label class="upload_field">
  <input type="file" name="file">
  <div class="upload_value"><span>no file selected</span></div>
  <div class="upload_button"></div>
</label>

Разберём эту надстройку подробнее. Тег INPUT оборачивается в метку LABEL, что делает входящие в неё элементы активными для дальнейшего вызова диалогового окна открытия файла. Примечательно, что сам тег INPUT скрывается через CSS-свойства, задаваемые (в данном случае) через: .upload_field input – но без использования display: none. Осталось лишь оформить блочные элементы upload_value и upload_button и создать JavaScript обработчик события change (с англ. изменение) для тега INPUT.

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

(function( $ ) {
$.fn.extended_itf = function() {
  if ( /msie/.test(navigator.userAgent.toLowerCase()) ) return; // не работает для IE
  this.each(function() {
    var obj = $(this);
    var placeholder = obj.is('[placeholder]') ? obj.attr('placeholder') : 'no file selected';
    var value = $('<div class="upload_value"/>').html('<div>'+ placeholder +'</div>');
    var button = $('<div class="upload_button"/>');
    obj.wrap('<label class="upload_file"/>');
    obj.parent().append(value);
    obj.parent().append(button);
    obj.change(function() { value.find('div').text($(this).val()); });
  });
};
})(jQuery);

Обращаю ваше внимание на то, что для браузера Internet Explorer такое решение не работает. Конечно, можно было бы нагородить огород со слоями, но я решил просто исключить его из поля своего интереса. Само же использование плагина может иметь следующий вид:

$(function() {
  $('input[type="file"]').extended_itf();
});

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

.upload_file {
  background: #eee;
  border: 1px solid #bbb;
  display: block;
  min-width: 200px;
  overflow: hidden;
  padding-right: 81px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.upload_file input {
  position: absolute;
  left: -9999px;
}
.upload_value {
  float: left;
  width:100%;
}
.upload_value div {
  color: #333;
  font: 14px/32px Arial, Helvetica, sans-serif;
  padding: 0 6px;
}
.upload_button {
  background: url(button.png) 50% 50% no-repeat;
  cursor: hand;
  cursor: pointer;
  float: left;
  margin-right: -81px;
  width: 81px;
  height: 32px;
}

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

var button = $('<div class="upload_button"/>');

на что-то вроде следующего:

var button = $('<div class="upload_button"/>').html('<span>Отправить…</span>');

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

Просмотреть демо-версию работы решения вы можете проследовав по этой ссылке »

На этом у меня всё. Спасибо за внимание. Удачи!

Никто ещё не оставил комментариев, станьте первым.