Проблема стилизации элементов форм. Отправка (submit) формы после выбора файла с оформлением input

Уже немало копий front-end разработчиков было сломано об проблему стилизации поля ввода input . Суть проблемы заключается в том, что в спецификации HTML нет строгих правил, устанавливающих, как же должен отображаться браузером этот элемент. Более того, для input не предусмотрено атрибутов, которые позволили бы изменить его внешний вид, с помощью стилей CSS можно изменить лишь вид его границы и шрифт, а средствами JavaScript, из соображений безопасности, нельзя сымитировать клик по этому элементу, который вызвал бы системное окно для выбора файла * . Но что же делать, когда заказчик хочет адаптивный сайт с красивыми стилизованными формами, в которых нельзя обойтись без этого поля ввода?

* - на момент написания этой статьи, мне было еще неизвестно, что уже во всех современных браузерах имитация клика по input вызывает системное окно выбора файла. Большое спасибо за с ссылкой на рабочий пример от !

Способы решения проблемы стилизации поля За то время, сколько существует эта проблема (а существует она очень долго), было найдено несколько способов ее решения. Всего их существует пять:Способ №1 (самый распространенный)Убедить заказчика, что можно жить и со стандартным input .Способ №2Написать/использовать готовый загрузчик файлов на Flash/Java-апплете. Используется, например, на habrastorage.org Способ №3 (будет рассмотрен в статье)Средствами CSS «замаскировать» стандартный input , сделать его полностью прозрачным и поместить на месте стилизованного фейкового поля, чтобы клик по последнему вызывал клик по стандартному, и, как следствие, открывал системное окно выбора файла.Способ №4 new! (будет рассмотрен в статье) Поместить прозрачный input внутрь элемента label, вместе с произвольными стилизованными инлайновыми элементами (кроме input, button, select и textarea, разумеется). Клик по label автоматически приведет к клику и по скрытому полю для выбора файла. Спасибо за !Способ №5 new! (будет рассмотрен в статье)Использовать имитацию клика по скрытому input средствами JavaScript. Да, это уже работает во всех современных браузерах. Еще раз спасибо за !
UPD: Внимание , данный способ неприменим для браузера Internet Explorer! Несмотря на то, что файл выбирается в скрытом input , при отправке формы значение последнего будет «сброшено». Спасибо за !

У всех четырех последних способов, разумеется, есть свои минусы. Существенный недостаток Flash/Java-решения в том, что для его работы нужны соответствующие плагины, которых в браузере пользователя может не оказаться. Большой недостаток «маскировочного» решения же заключается в том, что для его реализации необходимо использовать хаки (про это речь пойдет ниже), а также потому, что оно бессмысленно без использования JavaScript (ведь нужно же как-то различать состояния «файл не выбран» и «файл выбран» для стилизованного фейкового поля, что на одном CSS сделать невозможно). Решение на JavaScript, в целом, было бы очень хорошим, но, как оказалось на практике, оно не поддерживается браузером Internet Explorer, о чем было сказано выше. Минус решения с использованием label - все то же использование JavaScript, однако, оно гораздо лучше «маскировочного» способа и должно, на мой взгляд, использоваться сейчас для решения этой острой проблемы.

Схема велосипеда Ключевой задачей было поставлено создание «резинового» input , который на экранах мобильных устройств представлял бы из себя простую кнопку для выбора файла (имя выбранного файла выводится на ней же), а на широких экранах выглядел бы как привычное для всех текстовое поле + кнопка, которое может тянуться на всю ширину окна:

Схематический вид элемента на мобильных устройствах

Схематический вид элемента на десктопных устройствах

В статье будут рассмотрены три последних способа стилизации поля выбора файла. Таким образом, с учетом оговоренной выше схемы, исходная верстка для «маскировочного» способа №3 будет иметь следующий вид (порядок дочерних элементов важен!):

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

Возможная верстка для способа с применением элемента label:
Выбрать Файл не выбран

Возможная верстка для решения на JavaScript (совпадает с версткой для «маскировочного» способа):
Выбрать Файл не выбран

«Тяни, Пятачок!» или стили для «маскировочного» способа Чтобы у читателя не сложилось неверное впечатление, что каждое используемое в статье значение свойств CSS имеет огромную важность (так называемые «магические числа»), договоримся помечать те из них, которые можно смело изменять под свои нужды, комментарием

/* example */

Договорились? Отлично! Начнем стилизовать наше фейковое поле выбора файла с его «обертки» - div.file_upload :

File_upload{ position: relative; overflow: hidden; font-size: 1em; /* example */ height: 2em; /* example */ line-height: 2em /* the same as height */ }
- свойство position задается для того, чтобы относительно div.file_upload можно было абсолютно позиционировать его дочерние элементы, а свойство overflow - для того, чтобы скрывать все то, что по каким-то причинам не влезет в нашу обертку (а такое найдется, но об этом позже). На широких экранах наши красивые поле и кнопка должны отображаться в одну строку - зададим для последней фиксированную ширину и float: right, а для первого - небольшой внутренний отступ:

File_upload > button{ float: right; width: 8em; /* example */ height: 100% } .file_upload > div{ padding-left: 1em /* example */ }
Поскольку мы хотим, чтобы на мобильных устройствах текстовое поле скрывалось, и оставалась одна кнопка выбора файла, необходимо задать media query :
@media only screen and (max-width: 500px){ /* example */ .file_upload > div{ display: none } .file_upload > button{ width: 100% } }
Ну а теперь - самое веселое в данном методе! Необходимо сделать стандартный input полностью прозрачным, и растаращить растянуть его до размеров «обертки» div.file_upload . Для реализации последнего применим хак в виде абсолютного позиционирования и свойства CSS 3 transform , с помощью которого увеличим элемент, например, в 20 раз (да, это самое обычное «магическое число»):
.file_upload input{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; transform: scale(20); letter-spacing: 10em; /* IE 9 fix */ -ms-transform: scale(20); /* IE 9 fix */ opacity: 0; cursor: pointer }
Как видно из приведенного выше фрагмента CSS, для IE 9 потребовались дополнительные костыли. Это связано с тем, что данный браузер при клике на текстовое поле не вызывает системное окно выбора файла, а любезно предлагает «стереть» имя уже выбранного, что символизируется мигающим текстовым курсором. Поэтому для него дополнительно задается огромный интервал между буквами, что увеличивает кнопку элемента до размеров div.file_upload . Отмечу также, что z-index в данном случае не указывается, т.к. элемент идет последним «потомком» в выбранной с самого начала разметке.

На примере десктопного браузера FireFox, сейчас наше кастомизированное поле выбора файла для разных размеров окна выглядит так:

«Все гениальное - просто!» или стили для способа с применением label Основные стили, применяемые к текстовому полю и кнопке, для этого способа похожи на уже рассмотренные выше:

File_upload{ display: block; position: relative; overflow: hidden; font-size: 1em; /* example */ height: 2em; /* example */ line-height: 2em /* the same as height */ } .file_upload .button, .file_upload > mark{ display: block; cursor: pointer /* example */ } .file_upload .button{ float: right; box-sizing: border-box; -moz-box-sizing: border-box; width: 8em; /* example */ height: 100%; text-align: center /* example */ } .file_upload > mark{ background: transparent; /* example */ padding-left: 1em /* example */ }
Однако, теперь уже нет необходимости использовать хак с «растягиванием» прозрачного input :

File_upload input{ position: absolute; top: 0; opacity: 0 }

«Как это работает?» или стили для решения на JavaScript Поскольку исходная верстка для данного способа была выбрана такой же, как и в «маскировочном», стили для кнопки и текстового поля для обоих способов также совпадают (за исключением, разве что, свойства cursor: pointer , которое, в данном случае, будет применяться к кнопке и текстовому полю). Стиль же input можно взять тот же, что использовался в методе c применением элемента label, но в нем лучше вместо свойства opacity использовать visibility:

File_upload input{ position: absolute; top: 0; visibility: hidden }

Нужно больше стилей! Разумеется, в таком примитивном виде поле выбора файла вряд ли кого-то устроит, поэтому добавим дополнительные стили, которые сделают кнопку выбора файла, скажем, фиолетовой, добавят тени и т.д. Не забудем также добавить свой стиль для кнопки, когда на нее наведен курсор, стиль для нажатой кнопки, а еще добавим стиль для всего элемента, когда на нем находится фокус (будет применяться при помощи JavaScript):

/* Making it beautiful */ .file_upload{ border: 1px solid #ccc; border-radius: 3px; box-shadow: 0 0 5px rgba(0,0,0,0.1); transition: box-shadow 0.1s linear } .file_upload.focus{ box-shadow: 0 0 5px rgba(0,30,255,0.4) } .file_upload > button{ background: #7300df; transition: background 0.2s; border: 1px solid rgba(0,0,0,0.1); border-color: rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05); color: #fff; text-shadow: #6200bd 0 -1px 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis } .file_upload:hover > button{ background: #6200bd; text-shadow: #5d00b3 0 -1px 0 } .file_upload:active > button{ background: #5d00b3; box-shadow: 0 0 3px rgba(0,0,0,0.3) inset }

Теперь наше поле выбора файла выглядит так:

Нужно больше костылей! Поскольку мы делаем полноценное поле для выбора файла, то нужно позаботиться о том, чтобы его можно было комфортно заполнять и с клавиатуры (для «маскировочного» способа фокус сейчас вначале устанавливается на стилизованную кнопку, а затем - на скрытый input , что никак визуально не проявляется). Для этого, разумеется, используем JavaScript. Чтобы не писать много кода, я позволю себе использовать популярную библиотеку jQuery. Тогда, для «маскировочного» способа:

Var wrapper = $(".file_upload"), inp = wrapper.find("input"), btn = wrapper.find("button"), lbl = wrapper.find("div"); btn.focus(function(){ inp.focus() }); // Crutches for the:focus style: inp.focus(function(){ wrapper.addClass("focus"); }).blur(function(){ wrapper.removeClass("focus"); });
Для метода с использованием label можно убрать участок кода, отвечающий за принудительный перенос фокуса с кнопки на input (т.к. там у нас и не кнопка вовсе, а span).

Для метода, суть которого заключается в имитации клика по input , нужно, собственно, добавить эту самую имитацию:

// Yep, it works! btn.add(lbl).click(function(){ inp.click(); }); а также скорректировать код для установки класса .focus , предварительно убрав фрагмент, отвечающий за принудительный перенос фокуса:
// Crutches for the:focus style: btn.focus(function(){ wrapper.addClass("focus"); }).blur(function(){ wrapper.removeClass("focus"); });

Поле ввода до сих пор оставалось «мертвым» - при выборе файла имя последнего нигде не отображалось. Пришло время исправить и это:

Var file_api = (window.File && window.FileReader && window.FileList && window.Blob) ? true: false; inp.change(function(){ var file_name; if(file_api && inp[ 0 ].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

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

  • Не используется Flash.
  • Элемент можно легко стилизовать средствами CSS, используя современные технологии адаптивного дизайна.
  • Поле можно заполнять и с клавиатуры.

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

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

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

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

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

Поле input type="file" в разных браузерах


Дополнительную сложность создает то, что это поле попадает под различные правила безопасности браузеров, поэтому его нельзя, например, заменить каким-нибудь стилизованным div , нельзя обернуть тегом label , нельзя напрямую присвоить значение с помощью скриптов или вызвать окно выбора файла, сэмулировав нажатие через element.click(). А в некоторых браузерах даже нельзя сделать поле выбора файлов скрытым, так как после отправки формы его значение не будет передано на сервер. В разных интернетах я встречал попытки сделать кроссбраузерное решение, но все они, на самом деле, не универсальные и ограничиваются конкретными браузерами.

Когда мне понадобилось решить эту проблему, я решил воспользоваться уже проверенным трюком , при котором нужный элемент помещается внутрь блока div с фиксированными размерами и фоновым изображением, а самому же элементу присваивается атрибут "прозрачный". Не скрытый, а именно полностью прозрачный. Еще немного пришлось пошаманить, чтобы в границах родительского div"а оказалась область input, отвечающая на клик мышкой и открывающая окно выбора файла. Для этого был максимально увеличен шрифт и высота самого input"а. HTML-код получается простейший:CSS-код получается не совсем валидный за счет использования фильтров браузера Internet Explorer, но это плата за кроссбраузерность. В крайнем случае, если требуется стопроцентное прохождение валидатора, можно выставлять этот атрибут динамически средствами JavaScript или загружать отдельную таблицу стилей для IE.Теперь на экране мы видим только стилизованную кнопку, при клике на которую открывается окно выбора файлов. Поле input для выбора файлов не отображается, но при этом прекрасно работает. Небольшая проблема остается еще в том, что некоторые браузеры игнорируют стиль курсора, и над полем input все равно отображают его как текстовый. Но, как мне кажется, на это можно не обращать внимания, хотя знать об этом нелишне.

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

  • < script type = "text/javascript" >
  • function file_selected () {
  • try {
  • var file = document . getElementById ("uploaded_file" ). files [ 0 ];
  • if (file ) {
  • var file_size = 0 ;
  • if (file . size > 1024 * 1024 ) {
  • file_size = (Math . round (file . size * 100 /(1024 * 1024 ))/ 100 ). toString () + "MB" ;
  • else {
  • file_size = (Math . round (file . size * 100 / 1024 )/ 100 ). toString () + "KB" ;
  • document . getElementById ("file_name" ). innerHTML = "Name: " + file . name ;
  • document . getElementById ("file_size" ). innerHTML = "Size: " + file_size ;
  • catch(e ) {
  • var file = document . getElementById ("uploaded_file" ). value ;
  • file = file . replace (/\\/ g , "/" ). split ("/" ). pop ();
  • document . getElementById ("file_name" ). innerHTML = "Name: " + file ;
  • Некоторые браузеры предоставляют расширенный доступ к свойствам файла в поле input, для таких браузеров можно получить не только имя файла, но и его размер. Соответственно, такая расширенная информация и будет отображаться. Для остальных браузеров мы просто будем показывать имя выбранного файла, это значение всегда доступно через свойство value поля input.

    Готовый пример формы со стилизованным полем выбора файла и его обработкой, вы можете посмотреть на

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

    Год за годом не достаточно детализированная спецификация заставляла веб- разработчиков экспериментировать в попытках привести представление таких элементов, как input , select , fieldset , legend и textarea в разных браузерах к «общему знаменателю». В этой статье мы рассмотрим некоторые приемы CSS, используемые веб-разработчиками для стандартизации визуального представления элементов форм.

    Тесты Роджера Йоханссона

    Сначала в 2004, а затем и в 2007 году, Роджер Йоханссон (Roger Johansson) создал исчерпывающий набор тестов для проверки применения CSS-стилей к элементам форм. Результатом выполнения этих тестов, которые вы можете найти в его статье «К вопросу о стилизации элементов форм с помощью CSS », стал неутешительный вывод, который Йоханссон выразил следующими словами:

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

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

    Модель по умолчанию

    Спецификация CSS 2.1 указывает в предлагаемой таблице стилей по умолчанию для HTML4 , что элементы форм, такие как textarea , input и select , являются строчно-блочными:

    textarea , input , select { display : inline-block; }

    В свою очередь, элементы form и fieldset являются блочными:

    fieldset , form { display : block; }

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

      Строчно-блочные элементы могут быть стилизованы с использованием строчной модели. Он позволяет использовать такие CSS-свойства, как line-height и vertical-align , для управления высотой блока и его вертикальным выравниванием. Кроме этого, для указания внешних и внутренних отступов блока могут быть применены свойства margin и padding . Строчно-блочные элементы поддерживают width и height , так как используют блочную модель форматирования.

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

    Как веб-разработчики решают эти проблемы?

    Размеры

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

    input , select { width : 120px ; height : 32px ; }

    Разработчики пытались решить эту проблему, превратив эти элементы в блочные:

    input , select { width : 120px ; height : 32px ; display : block; }

    Сработало только с textarea . Стандартное решения этой проблемы заключается в использовании вместо height свойств font-size и padding .

    Элементы форм не наследуют гарнитуру и кегль шрифта, поэтому первым делом необходимо указать их:

    input , select { width : 120px ; font : 1em Arial, sans-serif; }

    После определения гарнитуры можно задать padding для добавления внутренних отступов блоку элемента:

    input , select { width : 120px ; font : 1em Arial, sans-serif; padding : 3px 6px ; }

    Для элементов input и textarea в таблицах стилей браузеров определен border . Нормализуем его:

    input , input , textarea { border : 1px solid #ccc ; }

    Элементам input с типом button и submit браузеры добавляют дополнительный отступ. Распространенная практика их нормализации:

    input , input { padding : 2px ; }

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

    input , input , input , input ::-webkit-file-upload-button , button { -webkit-box-align : center; text-align : center; cursor : default; color : buttontext; padding : 2px 6px 3px ; border : 2px outset buttonface; border-image : initial; background-color : buttonface; box-sizing : border-box; } input , input , input { -webkit-appearance : push-button; white-space : pre; }

    padding используется также и для элементов fieldset и legend , но приводит к другим результатам:

    • Установка значения свойства padding для элемента fieldset в 0 по умолчанию сбросит отступ элемента legend в некоторых браузерах (но не в IE).
    • Установка значения свойства padding для элемента legend в 0 приведет к его схлопыванию.

    Для select , и для input c типами checkbox и radio стоит использовать только:

    • font-family ,
    • font-size ,
    • width (для select),
    • padding .

    Применение других свойств к этим элементам часто приводит к противоречивым результатам в различных браузерах.

    Выравнивание

    Элементы форм можно выровнять по горизонтали и по вертикали. Они могут быть расположены на одной линии или как группа блоков друг под другом. Для выравнивания их на одной линии вы можете использовать один из двух подходов:

  • Использовать float ,
  • Использовать для некоторых элементов строчно-блочную модель.
  • При использовании float элементы автоматически становятся блочными. Это означает, что эти элементы форм теперь подчиняются девяти правилам float-элементов .

    Элементы форм можно выравнивать по вертикали и по горизонтали.

    При использовании float основной проблемой является правильное выравнивания по вертикали относительно текущей строки. Обычно это делают используя margin или padding:

    input , select { width : 120px ; float : left; margin-top : 0.4em ; }

    Этот подход работает, когда вам не нужно задавать выравнивание блоков относительно текста, например, содержимого label . В случае, если это необходимо, вы можете использовать относительное позиционирование, padding и margin для элементов, содержащих только текст:

    label { float : left; padding-top : 0.4em ; width : 5em ; margin-right : 1em ; }

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

    input { float : left; width : 90px ; position : relative; top : 0.4em ; }

    Еще прием с относительным позиционированием можно использовать для input с типами checkbox и radio . Относительное позиционирование можно использовать даже для нормализации отступа слева у элемента legend внутри элемента fieldset . Единственное отличие состоит в необходимости использования свойства left вместо top .

    При использовании строчной и строчно-блочной модели для вертикального выравнивания элементов вы можете использовать свойство vertical-align:

    label , input { vertical-align : middle; margin-right : 1em ; }

    Бывает удобно использовать это свойство вместе с line-height . Важно отметить, что применять это свойство необходимо к родительскому элементу. Если вы примените это свойство непосредственно к элементам формы, это скажется при расчете их высоты:

    .form-row { line-height : 1.4 ; }

    Явное указание высоты родительского элемента эффективно также при использовании вместе с равным ему значением высоты строки:

    .form-row { line-height : 1.8 ; height : 1.8em ; }

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

    Странные особенности элементов выбора файлов

    - это особый случай. Исходя из соображений безопасности, этот тип элементов всегда должен быть видимым и узнаваемым в браузере. Это означает, что браузеры преднамеренно игнорируют некоторые стили (например, стили, относящиеся к видимости элемента) и стремятся применять представление, описанное их собственными таблицами стилей.

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

    Веб-разработчики, тем не менее, быстро нашли способ преодолеть эти ограничения. Сначала они поместили поле ввода в контейнер:

    Затем они скрыли элемент input с помощью свойства opacity и применили стили к контейнеру:

    .upload { width : 157px ; height : 57px ; background : url (upload.png) no-repeat; overflow : hidden; } .upload input { display : block !important ; width : 157px !important ; height : 57px !important ; opacity : 0 !important ; overflow : hidden!important ; }

    Обратите внимание на!important . Это предпочтительный способ для переопределения стилей браузера по умолчанию.

    Заключение

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

    Оригинальная статья: The Problem Of CSS Form Elements Статью вычитывали: , visitorFM , Anton Khlynovskiy , Igor Adamenko

    3.9 из 5

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

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

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

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

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

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

    Но 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 (кроме высоты). То есть задача заключается определении оптимального размера перекрываемой картинки, чтобы минимальное количество пикселей было некликабельно, а пустые области не реагировали на клик.

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