Как настроить смартфоны и ПК. Информационный портал
  • Главная
  • Windows 7, XP
  • Оформление формы css. Современное оформление форм с использованием CSS

Оформление формы css. Современное оформление форм с использованием CSS

В статье представлено несколько трюков, которые вы, возможно, не знали и которые вы найдёте полезными в своих разработках.

1. Изображение в качестве фона, которое пропадает при вводе текста.

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

Textarea { background: url(images/benice.png) center center no-repeat; border: 1px solid #888; }

Фоновое изображение может повлиять на читаемость текста. Поэтому фоновое изображение надо убирать при получении фокуса и возвращать его, если textarea осталась без текста. Например, используя jQuery это можно сделать таким образом:

$("textarea") .focus(function() { $(this).css("background", "none"); }) .blur(function() { if ($(this).value == "") { $(this).css("background", "url(images/benice.png) center center no-repeat"); } });

2. Placeholder в HTML5


В HTML5 появился новый атрибут, называемый placeholder . Значение этого атрибута показывается в текстовом элементе и исчезает при получении фокуса, а также в случае когда в элементе введён текст.

HTML5 placeholder поддерживается в следующих браузерах: Safari 5, Mobile Safari, Chrome 6, и Firefox 4 alpha.

3. Placeholder, HTML5 с поддержкой старых браузеров используя jQuery

Самый простой способ проверить поддерживается ли атрибут браузером это проверить с помощью javaScript:

Function elementSupportsAttribute(element, attribute) { var test = document.createElement(element); return (attribute in test); };

Затем можно написать код, который будет срабатывать если браузер не поддерживает атрибут placeholder .

If (!elementSupportsAttribute("textarea", "placeholder")) { // Если браузер не поддерживает атрибут, то выполняется код jQuery $("#example-three") .data("originalText", $("#example-three").text()) .css("color", "#999") .focus(function() { var $el = $(this); if (this.value == $el.data("originalText")) { this.value = ""; } }) .blur(function() { if (this.value == "") { this.value = $(this).data("originalText"); } }); } else { // Если же браузер поддерживает HTML5, то просто используем эту возможность $("#example-three") .attr("placeholder", $("#example-three").text()) .text(""); }

4. Удаляем обводку textarea


Браузеры на движках webkit, а также в FireFox 3.6, обводят textarea , когда он находится в фокусе. Удалить эту обводку можно используя css-свойство outline для webkit-браузеров. Для FireFox используется свойство -moz-appearance , либо можно просто установить элементу бордер или фон.

Textarea { outline: none; -moz-appearance: none; border: 1px solid #999; /* указание этого свойства также удалит обводку в FireFox */ }

5. Запрет изменения размера


Webkit-браузеры добавляют к textarea визуальный элемент в правом нижнем углу, который позволяет изменять размер текстовой области. Если вы хотите убрать эту возможность, то вам необходимо использовать следующее css-свойство:

Textarea { resize: none; }

6. Добавление возможности изменения размера

jQuery UI позволяет добавить возможность изменения размера для textarea. Это работает для всех браузеров, а для webkit-браузеров подменяет стандартное поведение. Для того, чтобы использовать эту возможность, необходимо подключить jquery.ui и написать следующий код:

$("textarea").resizable();

7. Изменение размера под содержимое


James Padolsey написал удобный jQuery-скрипт который позволяет автоматически изменять размер textarea под его содержимое. Похоже что этого плагина больше нет, но можно использовать например вот этот . Плагин содержит много настроек, но самый простой способ его использовать это:

$("textarea").autoResize();

8. Nowrap

Чтобы не переносить слова на новые строки, для всех элементов используется css-свойство white-space , которое не работает с textarea . Для textarea необходимо использовать атрибут wrap .

9. Удаляем скролл-бары в IE


IE показывает вертикальный скролл-бар для всех textarea . Вы можете их спрятать используя overflow: hidden , но в таком случае он не будет показываться при увеличении контента. Поэтому правильнее использовать следующий подход:

Textarea { overflow: auto; }

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

Примеры к статье вы можете посмотреть .

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

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

Способы решения проблемы стилизации поля

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

У всех четырех последних способов, разумеется, есть свои минусы. Существенный недостаток 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

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

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

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

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

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

Познакомьтесь с новыми и старыми селекторами, которые вы можете использовать для оформления input-элементов формы в зависимости от того, являются ли поля обязательными, правильно заполненными и т. д., – предлагает Джонатан Харрел. Представляем вам адаптированный перевод его статьи .

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

Посмотреть пример их использования можно .

:placeholder-shown

Первый селектор относительно новый и еще не полностью поддерживается браузерами. Но представляется, что его можно будет довольно легко использовать в качестве улучшения в будущем. Этот селектор дает нам возможность определять, является ли плейсхолдер в настоящее время видимым для пользователя. Это может пригодиться если мы хотим динамически скрывать и показывать метку, связанную с input.

Здесь я скрываю метку, пока пользователь не начнет печатать в input, скрыв плейсхолдер. Для появления метки я использую красивый эффект перехода. Запомните, чтобы это работало, label должен идти ПОСЛЕ input .

.form-group { position: relative; padding-top: 1.5rem; } label { position: absolute; top: 0; font-size: var(--font-size-small); opacity: 1; transform: translateY(0); transition: all 0.2s ease-out; } input:placeholder-shown + label { opacity: 0; transform: translateY(1rem); }

Используйте этот селектор чтобы показать, что поле имеет атрибут . Здесь я использую пустой span с классом help-text и помещаю некое содержимое динамически, с помощью псевдоэлемента ::before . Собственно, это может быть сделано с JavaScript, но я включил этот пример чтобы показать метод с использованием чистого CSS.

input:required + .help-text::before { content: "*Required"; }

Если сравнивать с required, этот селектор действует противоположным образом. Я опять использую пустой span с классом help-text для показа какого-то возможного текста, если отсутствует атрибут .

Input:optional + .help-text::before { content: "*Optional"; }

Этот должен быть знаком большинству из вас, но важно о нем помнить. Показывать, заблокировано ли поле для пользователя, очень важно.

&:disabled { border-color: var(--gray-lighter); background-color: var(--gray-lightest); color: var(--gray-light); }

:read-only

Input с атрибутом readonly должен передавать немного другое значение, чем . Хорошо, что для этой цели есть такой селектор.

input:read-only { border-color: var(--gray-lighter); color: var(--gray); cursor: not-allowed; }

:valid

Хотя большая часть проверки формы будет осуществляться с помощью JavaScript, мы можем воспользоваться преимуществом HTML5 как для проверки формы, так и для оформления поля ввода. Этот селектор дает нам возможность придать стили любому input, который в настоящее время проходит встроенные правила проверки браузера.

Здесь я пишу код для svg чтобы, используя свойство background-image , отображать галочку в поле ввода.

Input:valid { border-color: var(--color-primary); background-image: url("data:image/svg+xml,%3Csvg width="45px" height="34px" viewBox="0 0 45 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"%3E%3Cg stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"%3E%3Cg transform="translate%28-56.000000, -59.000000%29" fill="%232EEC96"%3E%3Cpolygon points="70.1468531 85.8671329 97.013986 59 100.58042 62.5664336 70.1468531 93 56 78.8531469 59.5664336 75.2867133"%3E%3C/polygon%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A"); }

Этот селектор проверяет, является ли input НЕ проходящим встроенные правила проверки браузера (например, если введенный адрес электронной почты не содержит настоящего email).

И снова я добавляю код для svg чтобы отображать «Х» в поле ввода.

Input:invalid { border-color: var(--color-error); background-image: url("data:image/svg+xml,%3Csvg width="30px" height="30px" viewBox="0 0 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"%3E%3Cg stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"%3E%3Cg transform="translate%28-128.000000, -59.000000%29" fill="%23F44336"%3E%3Cpolygon points="157.848404 61.9920213 145.980053 73.8603723 157.848404 85.7287234 154.856383 88.7207447 142.988032 76.8523936 131.119681 88.7207447 128.12766 85.7287234 139.996011 73.8603723 128.12766 61.9920213 131.119681 59 142.988032 70.8683511 154.856383 59"%3E%3C/polygon%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A"); }

Также можно настроить некоторые проверочные сообщения для каждого типа input, воспользовавшись span с классом help-text и псевдоэлементом ::before .

input:invalid + .help-text::before { content: "You must enter a valid email." }

:in-range/:out-of-range

Эти селекторы определяют, находится ли значение числового поля в пределах указанных минимальных/максимальных значений.

(value must be between 1 and 10) input:out-of-range + .help-text::before { content: "Out of range"; }

Вероятно, вам знаком этот селектор. Он дает возможность применить пользовательские стили к чекбоксам и радиокнопкам. Моя техника оформления чекбоксов включает создание встроенного элемента и помещения label после input .

Я зрительно прячу input, так что он исчезает из поля зрения, но все еще кликабелен. Затем я оформляю label::before так чтобы он выглядел как поле чекбокса, а label::after – как галочка. Я использую селектор для соответствующего оформления этих двух псевдоэлементов.

&:checked + label::before { background-color: var(--color-primary); } &:checked + label::after { display: block; position: absolute; top: 0.2rem; left: 0.375rem; width: 0.25rem; height: 0.5rem; border: solid white; border-width: 0 2px 2px 0; transform: rotate(45deg); content: ""; }

Лучшие статьи по теме