Пару лет назад я впервые услышал про веб-компоненты (Web Components). Сперва меня это действительно заинтересовало, но как только шумиха вокруг них приутихла, они тут же вылетели у меня из головы. Но, как оказалось, в последнее время прошло интересное движение и поддержка этой технологии значительно выросла. Отзывчивые веб-компоненты, в частности, призваны упростить наш подход к адаптивному дизайну. Как многообещающе звучит!
Вот четыре пункта, с которыми стоит ознакомиться любому разработчику перед началом использования данной технологии:
- Поддержка технологии;
- Кроссбраузерная работа;
- Возможность адаптации в среде удельного проекта;
- Модульный подход.
В этой статье мы рассмотрим каждый из этих пунктов в отдельности...
*Данная статья переведена исключительно в ознакомительных целях и не навязывает вам использование веб-компонентов, так как поддержка данной технологии всё ещё отставляет желать лучшего.
Что такое веб-компоненты?
По сути, это технология из спецификации W3, которая даёт возможность создавать свои собственные HTML-элементы. В случае, если вы буквально ничего о ней не слышали, желательно ознакомиться с данной статьёй, так как некоторые термины, которые я буду использовать, требуют хотя бы базового понимания.
Почему я хочу их использовать?
Хорошим примером того, когда вы можете захотеть использовать веб-компоненты является задача, где вам требуется создать пользовательский интерфейс, которого нативно не существует в браузере — такие элементы, как селектор цвета, карусель, аккордеон, поле с автодополнением. Можно использовать в качестве альтернативы одним и тем же компонентам, которыми вы пользуетесь из проекта в проект, предварительно лениво кастомизируя их под требования текущего. Это такие вещи, как социальные кнопки, формы подписки или уведомления. С помощью веб-компонентов вы можете связать разметку, стили и скрипты в один герметизированный модуль и использовать HTML-тег (как <color-picker></color-picker>), чтобы ссылаться на него. Это довольно таки знакомо, если вы уже использовали Angular-директивы или компоненты React, но преимущество здесь в том, что данный подход является родным для браузера и «агностиком» фреймворков.
Веб-компоненты дают вам возможность единожды создать UI-элемент и потом использовать его где угодно. Это идеально подходит для таких проектов как живой стилистический справочник (или styleguide), где вы хотите создать библиотеку с единственным источником истины для каждого из компонентов (где каждый компонент попадает только под своё уникальное правило поведения и отображения). Такой подход подразумевает более короткий, минималистичный код, а также наличие готовых UI-компонентов, ссылки на которые вы или ваша команда можете лёгко добавить в текущий интерфейс.
Другое большое преимущество использования веб-компонентов — это возможность упаковать свой модуль и поделиться ним с другими разработчиками/владельцами сайтов. По сути, пользователю всего лишь остаётся добавить оператор импорта на свой веб-сайт:
<link rel="import" href="http://url.com/subscribe-form.html">
А затем использовать кастомный тег элемента, что определён для данного веб-компонента. Так пользователь может добавить на свой веб-сайт столько кастомных веб-компонентов, сколько он захочет. К примеру, для формы подписки вы можете использовать тег — <subscribe-form></subscribe-form>, таким образом размещая её в одном, или нескольких местах на странице. Конечно, перед тем как сделать это, вы должны убедиться в том, что созданный вами веб-компонент достаточно гибок и будет адекватно работать в ряду различных устройств и размеров экранов.
Переходим от теории к практике
Я считаю, что лучший способ объяснить что-либо — это показать на примере. Так что далее мой рассказ будет заключаться в описании работы с выше упомянутой формой подписки. Она является отличным примером пользовательского интерфейса, который не сильно изменяется между различными сайтами и реализациями.
К примеру возьмём форму, которую я создал ранее:
Внутри данного шаблона я создал некую базовую разметку для формы:
<ul class="form">
<li class="form__item">
<label for="name">Name:</label>
<input id="name" name="name" type="text">
</li>
<li class="form__item">
<label for="name">Email:</label>
<input id="name" name="name" type="text">
</li>
</ul>
Моя разметка и стили спрятаны внутри веб-компонента с помощью возможностей, которые предоставляет Shadow DOM спецификация. Данный способ организовывает некую инкапсуляцию, которая даёт мне возможность использовать label и input селекторы свободно, не боясь влияния на них стилей родительского веб-сайта.
Для ясности и краткости, я не буду описывать написание стилей, кроме тех, которые я использовал для отображения разметки. Я использовал комбинацию свойств float: left и display: table для реализации данного интерфейса и избегания поломки при любой ширине.
.form__item {
display: table;
float: left;
width: 50%;
}
label {
display: table-cell;
width: auto;
}
input {
display: table-cell;
width: 100%;
}
По ходу урока я буду использовать скриншоты для демонстрации проделанной нами работы:
Теперь у нас все готово, давайте рассмотрим некоторые техники достижения адаптивности.
Медиа запросы
Классический подход, который мы все знаем и любим, так же хорошо работает и в отзывчивых веб-компонентах. Вы можете использовать медиа запросы внутри вашего шаблона в случае, если вы хотите создать какие-либо дефолтные контрольные точки. С другой стороны вы можете использовать «крючки» (к примеру, создавая классы) и применяя их к родительскому контейнеру, таким образом оставляя возможность пользователю самостоятельно принимать решение. В нашем случае, всё, что нам нужно, — это создать контрольную точку, достигая которую мы отменяем свойство float для дочерних элементов и задаём им ширину в 100%.
@media (max-width: 30em) {
.form__item {
float: none;
width: 100%;
}
}
Однако, одних медиа запросов тут будет не достаточно.
Я доволен созданной формой подписки, она замечательно работает в основном теле страницы, но что будет, если автор сайта захочет засунуть её в сайдбар? Внезапно моя форма станет сжатой, и не похоже, что ею можно пользоваться.
Это происходит потому, что веб-компонент не видит своих границ — не имеет представления о контексте.
Но стоп! Разве весь смысл веб-компонентов не в том, чтобы вы могли вставить их в любое место на сайте, где они будут просто работать? Ну так очевидно, что созданный нами ранее веб-компонент так делать не будет, но есть несколько методов, которые мы можем использовать, для достижения поставленной цели.
Flexbox-хак
Если вы задумали использовать веб-компоненты в своём проекте и готовы пожертвовать поддержкой старых браузеров (таких как IE9 и тд.), то чуточку Flexbox-магии вам совсем не навредит. Это отличное решение, которое, к тому же, совершенно не требует использование JavaScript.
Опять же, код ниже содержит только стили, которые я использовал для отображения разметки.
.form {
display: flex;
flex-wrap: wrap;
}
.form__item {
align-items: center;
display: flex;
flex: 1 0 320px;
flex-wrap: wrap;
max-width: 100%;
}
label {
flex: 1 0 90px;
}
input {
flex: 1 0 230px;
width: 100%;
}
Устанавливая родительскому контейнеру display: flex и flex-wrap: wrap, дочерние .form__item выстроются один к одном, блок-о-блок, но нам всё ещё нужно определить несколько правил, чтоб в случае, если контейнер становится слишком мал, дочерние элементы спрыгивали один под другой.
Внутри .form__item мы использовали краткое записание свойства — flex: 1 0 320px, которое можно разложить как: flex-grow: 1, flex-shrink: 0, flex-basis: 320px. Установив flex-wrap: wrap, мы определили, что ширина нашего элемента не станет меньше указанной в 320px, в то время как указав свойство flex, мы разрешили нашему элементу расти и занимать оставшееся свободное место в строке.
Такой же подход я использовал для элементов input и label. Их суммарное значение flex будет равно 320px, что подразумевает, что они будут адекватно отображены и при меньших размерах контейнера.
Давайте посмотрим, к чему привели сделанные нами изменения:
Гораздо лучше! Тем не менее, это не единственный способ решения данной проблемы, их бесчисленное множество.
Запросы соответствующие веб-элементам
Идея использования запросов соответствующих определённым элементам — это то, что позволяет вам эмулировать функциональность медиа запросов на уровне веб-элемента — что очень удобно при создании отзывчивых веб-компонентов. Проще говоря, представьте, если бы у вас была возможность писать нечто на подобии этого в вашем css:
.form__item[max-width~="30em"] {
/* Styles here */
}
Это очень близко к тому, что мы можем сделать используя данную технологию. Довольно таки перспективно, не правда ли?
Однако, во избегания бесконечных циклов, данная технология не доступна нативно в браузере. Но для этих целей существуют довольно таки интересные плагины.
В моём примере я использовал CSS Element Queries, созданный человеком по имени Marc J Schmidt. Этот плагин является действительно хорошей реализацией решения данной задачи. Есть также следующие похожие проекты:
По сути, данные плагины используют JavaScript для определения ширины веб-элемента и добавляют ему соответствующий атрибут, тем самым позволяя определять новые соответствующие стили элементу посредством CSS.
.form__item[max-width~="30em"] {
float: none;
width: 100%;
}
С помощью комбинации одного из этих плагинов с небольшим сниппета CSS-кода, мы добились того же результата, что и с помощью flexbox.
Атрибуты
Одна из потрясающих вещей, которую мы можем предложить потребителю нашего отзывчивого веб-компонента, — это API атрибутов к данному элементу. Например, вы могли бы установить атрибут, называемый layout, определяющий размеры компонента в данном контексте: «малый» или «большой». А затем его можно использовать следующим образом:
<subscribe-form layout="small"></subscribe-form>
Таким образом создаём крючок, что определяет дополнительные CSS-свойства.
В Shadow DOM спецификации контейнер, содержащий в себе элемент, определён как :host. Пример будет выглядеть так:
:host {
display: block;
}
:host([layout = "small"]) .form__item {
float: none;
width: 100%;
}
:host([layout = "large"]) .form__item {
display: table;
float: left;
width: 50%;
}
Это даст возможность потребителю, написав не сложный JavaScript, переключаться между размерами, которые вы ему предоставили. Это означает, что вместо того, чтоб включать дополнительный JavaScript-код внутрь вашего веб-компонента, вы оставляете возможность разработчику самостоятельно кастомизировать ваш компонент под требования его текущего проекта.
Вывод
Подходы указанные выше могут быть использованы для создания любого пользовательского веб-интерфейса, но особенно они хороши при создании отзывчивых веб-компонентов.
Если вы ещё не пробовали использовать веб-компоненты, я настоятельно рекомендую вам сделать это. К сожалению, все возможности данной технологии пока доступны только в Chrome и Opera, но и другие производители браузеров не сидят без дела, и повсеместная поддержка данной технологии не за горами.
Автор: web_for_mass