Статьи

Вы можете сделать это с помощью CSS?

Некоторое время назад я опубликовал статью о том, как имитировать демонстрацию кнопки меню Morphing в CoDrops . Затем я написал краткое продолжение, показывающее, как расширить исходную демонстрацию, чтобы обеспечить некоторые дополнительные функции наложения в виде JavaScript.

Это было своего рода начало всего этого …

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

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

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

Простой пример формы

Недавно я написал статью, демонстрирующую два примера без JavaScript для предоставления обратной связи с пользователем при заполнении форм.

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

Здесь у нас есть три текстовых ввода, которые используют заполнители в качестве меток. Это действительно UX-нет-нет, но я сталкивался со многими ситуациями, когда «ответственный дизайнер» боролся изо всех сил, чтобы заблокировать добавление видимых ярлыков.

Валовой.

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

<div class="form-row"> <input type="email" class="input-text" id="name2" placeholder="Your Email" /> <label class="label-helper" for="name2">Your Email</label> </div> 

Как видите, с HTML здесь ничего особенного не происходит. Единственное, что немного необычно, это то, что <label> идет после ввода.

Теперь вот CSS, необходимый для того, чтобы это заработало:

 .form-row { position: relative; } .input-text { background-color: #fff; border: 1px solid #ccc; margin-bottom: 8px; padding: 8px 4px; position: relative; width: 100%; z-index: 3; } .label-helper { bottom: 0; left: 0; opacity: 0; position: absolute; transition: .2s bottom, .2s opacity; z-index: 1; } 

Этот первый фрагмент CSS является стилем по умолчанию для элементов формы. .form-row абсолютно позиционированный .label-helper рядом с соответствующим вводом.

Элемент .input-text имеет относительную позицию и применен к нему z-index, потому что мы не хотим, чтобы метка .input-text перед входом, когда он находится в фокусе.

Теперь вот CSS, который обрабатывает метки, отображаемые в фокусе:

 .input-text:focus + .label-helper, .input-text:invalid + .label-helper { bottom: 95%; /* magic number, boo */ font-family: arial; font-size: 14px; line-height: 1; opacity: 1; padding: 4px; } .input-text:invalid { border-left: 10px solid #f00; } .input-text:invalid + .label-helper:after { color: #f00; content: "X"; font-family: arial; font-size: 14px; line-height: 1; padding-left: 12px; } 

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

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

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

В качестве дополнительной информации я также добавил недопустимое состояние для ввода электронной почты. Поскольку входные данные не поддерживают псевдоэлементы, к метке применяется ошибка «x».

Теперь переключение передач…

Некоторые более сложные случаи использования

Приведенный выше пример на самом деле становится довольно распространенным в последнее время. Как я знаю, я не первый и не последний, кто сделал ввод с меткой или всплывающей подсказкой.

Итак, давайте перейдем к еще нескольким «примерным» примерам того, что вы можете сделать с помощью специально созданной разметки и CSS.

Переходы к макету одной страницы

Codrops опубликовал полноэкранный макет с демонстрацией переходов страниц в апреле 2013 года. Я всегда думал, что это действительно круто, и хотел посмотреть, смогу ли я воссоздать его или что-то подобное без JavaScript.

Оказывается, я мог:

Вот HTML-код:

 <input type="radio" class="radio" name="pages" id="exit" checked /> <div class="page demo2"> <input type="radio" class="radio" name="pages" id="page_1" /> <section class="section-container section-one"> <label for="exit" class="check-label exit-label"> X </label> <label for="page_1" class="page-label check-label"> <span>Page X</span> </label> <header class="section-header"> <div class="section-content"> <h1> Title of Section X </h1> </div> </header> <div class="section-info"> <div class="section-content"> <p> ... </p> </div> </div> </section> <!-- repeat this 3 more times, with IDs of "page_2, page_3, and page_4" --> </div> 

Вы заметите использование элементов <input type="radio"> перед каждым разделом. Мы будем активно использовать их в CSS, так как нам нужно снова полагаться на соседний селектор (+), чтобы эти переходы работали.

По сути, мы будем использовать переключатели :checked состояния, активируемые нажатием на соответствующую метку, и селектор брата, чтобы изменить макет только с помощью CSS.

Теперь вот CSS:

 .radio, .exit-label { display: none; height: 0; visibility: hidden; } .exit-label { border: 1px solid #333; color: #444; display: inline-block; padding: 4px 12px; text-decoration: none; } .page-label { height: 100%; left: 0; position: absolute; text-align: center; top: 0; width: 100%; } .page-label span { position: relative; top: 50%; } 

Приведенный выше CSS заботится о стиле наших «кнопок» и скрывает переключатели от просмотра / непосредственного взаимодействия с ними.

.page-label и .page-label span предназначены для «кнопок» большой панели, в то время как класс .exit-label стилизует «кнопку закрытия» при открытии каждой из панелей (опять же, метки в стиле кнопок) ,

 .section-container { border: 0px solid; height: 50%; overflow: hidden; position: fixed; transform-origin: center center; transition: 0.4s all; width: 50%; z-index: 1; } .section-content { margin: auto; max-width: 800px; opacity: 0; padding: 20px; transition: 0.66s all; visibility: hidden; } .section-one { transform: translate(0%, 0%); } .section-two { transform: translate(0%, 100%); } .section-three { transform: translate(100%, 0%); } .section-four { transform: translate(100%, 100%); } 

Выше у нас есть начальная настройка для контейнеров панелей (разделов) и их содержимого. Контейнеры установлены на 50% высоты и ширины, чтобы имитировать сетчатый макет примера Codrops.

Разделы позиционируются с использованием transform: translate вместо использования позиционирования top, left, bottom или right. Это связано с тем, что преобразование лучше для производительности, так как не требует такой интенсивной перекраски, как изменение положения элемента .

 :checked + .section-container { height: 100%; overflow: auto; transform: translate(0%, 0%); width: 100%; z-index: 5; } :checked + .section-container .exit-label { display: inline-block; visibility: visible; } :checked + .section-container .page-label { display: none; } :checked + .section-container .section-content { opacity: 1; visibility: visible; } #exit:checked + .page .section-container { border: none; opacity: 1; } .page :not(:checked) + .section-container { border: 40px solid; } 

И вот забавная часть, где мы проверяем, была ли выбрана радиокнопка, и если да, то:

  • .section-container преобразуется в полную высоту, ширину и преобразуется в верхнее левое положение окна браузера.
  • Кнопка «Выход» и контент для выбранного раздела становятся видимыми
  • Ярлык, по которому щелкнули, чтобы открыть выбранный раздел, скрыт, так что он больше не может быть кликабелен / расположен поверх содержимого, которое только что стало видимым
  • Разделы, которые не были выделены, имеют границу, которая увеличивается до 40px, имитируя их «сокращение» за разделом, который анимируется на весь экран.

Альтернативные переходы макета

Используя очень похожий модифицированный CSS разметки, вот еще два примера, которые следуют тем же концепциям, изложенным выше.

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

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

Честно говоря, я попробовал сделать это с первым примером здесь, и мне пришлось написать больше JavaScript, чтобы он соответствовал стандартам доступности, чем мне пришлось бы писать, если бы я использовал семантически подходящие элементы и JavaScript в первое место.

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

Изменения макета с: цель

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

Давайте посмотрим, как выглядит обновленная разметка:

 <section class="section-container section-one" id="page_1"> <a href="#exit" class="btn btn-exit"> X </a> <a href="#page_1" class="btn btn-page"> <span>Page 1</span> </a> <header class="section-header"> <div class="section-content"> <h1> Title of Section X </h1> </div> </header> <div class="section-info"> <div class="section-content"> <p> ... </p> </div> </div> </section> <!-- this is again repeated for id="page_2", etc --> 

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

CSS — это место, где происходят большие изменения:

 .btn-exit { display: none; visibility: hidden; } #page_1:target .btn-exit, #page_2:target .btn-exit, #page_3:target .btn-exit, #page_4:target .btn-exit { border: 1px solid #333; display: inline-block; padding: 4px 12px; text-decoration: none; visibility: visible; } .btn-page { height: 100%; left: 0; position: absolute; text-align: center; top: 0; width: 100%; } .btn-page span { position: relative; top: 50%; } #page_1:target, #page_2:target, #page_3:target, #page_4:target { transform: translate(0%, 0%); width: 100%; height: 100%; z-index: 5; overflow: auto; } #page_1:target .btn-exit, #page_2:target .btn-exit, #page_3:target .btn-exit, #page_4:target .btn-exit { display: inline-block; visibility: visible; } #page_1:target .btn-page, #page_2:target .btn-page, #page_3:target .btn-page, #page_4:target .btn-page { display: none; } #page_1:target .section-content, #page_2:target .section-content, #page_3:target .section-content, #page_4:target .section-content { border: 0; opacity: 1; visibility: visible; } #exit:target .page .section-container { border: none; opacity: 1; } 

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

Селекторы для меток были обновлены для использования атрибута href в отличие от атрибута for , и снова мы смогли удалить любую ссылку на переключатели.

Поскольку теперь мы используем :target to… well… target для наших различных разделов, все селекторы :checked + были заменены соответствующими селекторами :target . В то время как раньше у нас мог быть один :checked + селектор для этих правил, путь :target работает, мы должны продублировать наш селектор для каждого другого :target URI.

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

С учетом вышесказанного, если мы действительно хотим сделать эту демонстрацию доступной для всех, есть некоторые дополнительные функции ARIA, которые должны применяться к различным областям щелчков, которые визуально оформлены в виде кнопок, но на самом деле являются ссылками (что на самом деле дело по причинам доступности, всем). И простого добавления функций ARIA будет недостаточно, так как при изменении состояния атрибуты, такие как aria-hidden , должны быть обновлены, а фокусировка элемента должна сместиться между последним активным элементом и новым активным экраном, для чего требуется JavaScript. Тем не менее, JavaScript будет гораздо меньше, чем в оригинальной версии этого примера.

Дополнительным доводом «за» или «против» в этом примере является то, что если кто-то знает или добавляет в закладки URI, использованный для обновления макета, он может обойти нормальное состояние нашей страницы. Опять же, это может быть за или против в зависимости от ваших целей UX. Но это то, что нужно иметь в виду.

В заключение…

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

Но в последний раз, просто убедитесь, что вы потенциально не затрудняете кому-то использовать ваше веб-приложение или веб-сайт, потому что вы умны с CSS. А в случае веб-приложений вам, вероятно, лучше продолжать использовать JavaScript для вызова переходов экрана. Опять же, эти примеры должны вдохновлять, а не обязательно повторять.

И, как и было обещано, здесь есть архив всех исходных файлов для демонстраций в этой статье. Наслаждайтесь!