[Из песочницы] Стилизация поля ввода для загрузки файлов на чистом CSS
В данной статье предлагаю рассмотреть стилизацию поля ввода для загрузки файлов. Данная тема не раз рассматривалась на Хабре, но, тем не менее, адекватного решения до сих пор не было предложено.Итак, начнем. Вначале рассмотрим общую идею. Основным камнем предктовения при стилизации данного элемента является определение загружен файл или нет, чтобы менять текст и стили поля в зависимости от загрузки.На первый взгляд, здесь трудно обойтись без Javascript, однако если внимательно исследовать элемент, то можно обратить внимание на надпись, которая выставляется по умолчанию, когда файл не загружен. Возможно, это многих вводит в заблуждение при решении данной задачи, однако данная надпись на самом деле ничего не значит, то есть пользователь ее видит, но несмотря на это в понимании браузера поле все равно остается пустым. Таким образом, определить является файл выбран или нет проще простого — использовать атрибут required и прилагающийся к нему псевдокласс : invalid.
Теперь подробно разберем стилизацию для основных браузеров. Начнем с самого простого случая — Webkit. Здесь стилизация вообще превращается в сказку, так как браузера на основе webkit для поля input с атрибутом file поддерживают псевдоэлементы before и after и поэтому всю верстку можно сделать всего одним тегом. Стоит также отметить, что для вебкит-браузеров поддерживается вендорный псевдоэлемент ::-webkit-file-upload-button для стилизации кнопки 'Выберите файл', который мы благополучно убьем, так как при самой детальной кастомизации элемента толку от него не очень много, потому что в нем нельзя менять текст.
Кнопку для загрузки мы будем имитировать с помощью псевдоэлемента after, а само поле с помощью псевдоэлемента before. Ну, а дальше дело техники. В нашем примере в зависимости от того загружен файл или нет меняется цвет рамки, текст в кнопке и поле для ввода. Нативную кнопку мы скрываем (::-webkit-file-upload-button) с помощью visibility: hidden, на ее место ставим псевдоэлемент after, а псевдоэлемент before растягиваем на всю оставшуюся ширину, этот псевдоэлемент исчезает, если файл загружен.
input {position: relative; width: 100%; height: 36 px; padding-top: 14 px; border: 2 px solid #ccc; outline: 0; color: blue; background: yellow;} input: invalid {border: 2 px solid red;} input::-webkit-file-upload-button {visibility: hidden; width: 160 px;} input: before, input: after {position: absolute;} input: after {content: 'Загрузите еще'; left: 0; top: 0; background: #ccc; height: 50 px; line-height: 50 px; width: 150 px; text-align: center; color: magenta;} input: invalid: after {content: 'Загрузите файл';} input: before {display: none;} input: invalid: before {content: 'Файл не загружен'; display: inline-block; background: yellow; left: 150 px; top: 0; height: 50 px; line-height: 50 px; width: calc (100% — 160 px); padding-left: 10 px; color: blue;} Рассмотрим вариант, когда кнопка находится справа. Здесь мы просто нативной кнопке (::-webkit-file-upload-button) задаем нулевую ширину, оставляя ее спрятанной с помощью visibility: hidden, а фиктивную кнопку (псевдоэлемент after) просто прижимаем к правому краю. input {position: relative; width: 100%; height: 36 px; padding-top: 14 px; border: 2 px solid #ccc; outline: 0; color: blue; background: yellow;} input: invalid {border: 2 px solid red;} input::-webkit-file-upload-button {visibility: hidden; width: 0;} input: before, input: after {position: absolute;} input: after {content: 'Загрузите еще'; right: 0; top: 0; background: #ccc; height: 50 px; line-height: 50 px; width: 150 px; text-align: center; color: magenta;} input: invalid: after {content: 'Загрузите файл';} input: before {display: none;} input: invalid: before {content: 'Файл не загружен'; display: inline-block; background: yellow; left: 10 px; top: 0; height: 50 px; line-height: 50 px; width: calc (100% — 160 px); padding-left: 10 px; color: blue;} Теперь перейдем к Firefox. Этот браузер не поддерживает псевдоэлементы к инпутам вообще, поэтому здесь придется вместо псевдоэлементов использовать две метки, которые ссылаются на поле для загрузки файла.Рассмотрим вариант с кнопкой слева. Сделаем врапер, цвет которого будет соответствовать цвету поля. Здесь мы закроем нативную кнопку фаерфокса одной меткой. А с помощью второй метки будем имитировать поле, в которое можно засунуть любой текст. Это фиктивное поле будет исчезать после того, как файл будет выбран. По этой причине необходимый цвет поля будет виден тот, который указан во врапере.