|
Новый сайт бюро и книги издательства состоят из модулей. Модуль — самостоятельный элемент интерфейса с собственной разметкой, внешним видом и поведением. Модули можно бесконечно вкладывать друг в друга, создавая развороты или страницы любой сложности. Примеры таких модулей: разворот, страница, изображение, сноска, карточка проекта.
Эта система подходит и для небольших проектов. Я использую её даже для одностраничных сайтов.
Модули
Каждый модуль представлен набором файлов, описывающих разметку, внешний вид и поведение элементов. Это облегчает их разработку, так как всё, что с ними связано, лежит рядом.
В файловой системе это выглядит так:
modules/
├─ image/
│ ├─ image.css
│ ├─ image.js
│ └─ image.html
├─ spread/
│ ├─ spread.css
│ └─ …
├─ caption/
│ ├─ caption.css
│ └─ …
└─ …
Все файлы, связанные с модулем, лежат в одной директории
Название модуля отражает его предназначение. Это название используется и в именах файлов, и в качестве класса для описания стилей. Благодаря этому, зная только класс, легко найти файл с его описанием.
<div class="project">
<h2 class="project-title">Типографика и вёсртка</h2>
<div class="project-description">…</div>
</div>
Если встретим класс project в разметке, то понятно, что его описание в project.css
Элементы
Элементом модуля называется то, что не имеет смысла в отрыве от модуля. Например, заголовок статьи или пункт меню.
Для отражения связи элемента с модулем мы строим классы элементов по схеме «модуль-элемент». По сути, модуль задаёт пространство имён для своих элементов.
<div class="project">
<h2 class="project-title">Типографика и вёсртка</h2>
<div class="project-description">…</div>
</div>
У проекта есть заголовок и описание
Мы не вкладываем элемент в элемент, поскольку это затрудняет их перемещение внутри модуля:
<div class="project">
<div class="project-date">
<span class="project-date-day">17</span>
<span class="project-date-month">сентября</span>
</div>
</div>
Плохо: элемент относится к другому элементу.
Если мы захотим перенести месяц в другое место модуля,
придётся переименовывать класс.
<div class="project">
<div class="project-date">
<span class="project-day">17</span>
<span class="project-month">сентября</span>
</div>
</div>
Хорошо: элемент относится напрямую к модулю…
<div class="project">
<div class="project-month">Сентябрь</div>
</div>
…поэтому структуру легко изменить без переименований
Модификаторы
Для изменения поведения модуля или элемента мы используем модификаторы. Название модификатора отражает смысл изменения. Чтобы визуально выделить модификаторы на фоне других классов, мы используем префикс с двойным подчёркиванием. Например: is__selected , has__title , in__view .
.project.is__featured {
font-size: 27px;
}
.menu-item.is__active {
background: black;
color: white;
}
Хорошо: названия сообщают об изменениях
Глобальные модификаторы запрещены:
.is__selected {
background: red;
}
Плохо: в другом модуле может использоваться модификатор с таким же именем
.menu-item.is__selected {
background: red;
}
Хорошо: модифицируем пункт меню
Запрещается стилизация модификаторами от родительских модулей.
<!-- header.html -->
<div class="header is__inverted">
<div class="searchForm has__error is__dirty">
<input type="text" class="searchForm-input">
</div>
</div>
/* header.css */
.header.is__inverted .searchForm {
background: white;
}
/* searchForm.css */
.searchForm.has__error.is__dirty {
background: red;
}
Плохо: мы описываем форму в другом файле. Непонятно, какой стиль применится в итоге.
/* searchForm.css */
.header.is__inverted .searchForm {
background: white;
}
.searchForm.has__error.is__dirty {
background: red;
}
Плохо: все стили в одном файле, но мы ссылаемся на внешний модуль. Изменение во внешнем модуле может повлиять на нашу форму.
<!-- header.html -->
<div class="header is__inverted">
<div class="searchForm has__error is__dirty is__inverted">
<input type="text" class="searchForm-input">
</div>
</div>
/* searchForm.css */
.searchForm.is__inverted {
background: white;
}
.searchForm.has__error.is__dirty {
background: red;
}
Хорошо: мы добавили модификатор самой форме и используем его для стилизции. Форма полностью независима от внешних модулей
При этом мы разрешаем изменение элемента с помощью модификатора модуля. Стили модуля хранятся в одном файле и предсказать результат возможно:
.form.is__invalid .form-input {
border-color: red;
color: red;
}
Можно: все модификации в одном месте
Составные имена классов
Если для описания модуля или элемента требуется больше одного слова, то используем кэмелКейс:
.newsItem {
width: 30%;
margin-bottom: 40px;
}
.newsItem-subTitle {
font-size: .9em;
font-weight: bold;
}
Проблемы
К сожалению, все проблемы этот набор правил не решает. Самая острая сейчас — смешение ролей: один и тот же объект одновременно быть самостоятельным модулем и элементом другого модуля:
<div class="article">
<h1 class="article-title">Интерфейс — зло</h1>
<div class="article-lead lead">
Ни одна компания, продающая дизайн интерфейсов, не признается,
что интерфейс — зло. Они никогда не скажут, что он мешает
клиенту зарабатывать.
</div>
</div>
Проблема в том, что определения lead и article-lead будут находиться в разных файлах и непонятно, какое из них применится последним.
Если у уважаемых советчиков есть опыт решения этой проблемы, буду рад услышать предложения.
|
|
О модульной системе в «Техноведре»
|
|