It's easy to write CSS code, but it is hard to scale and support it"
(Ben Frain)
1. Количество CSS на проекте всегда увеличивается — становится сложнее поддерживать.
2. «Плохие техники» CSS: повторения, плохая группировка, малопонятные связи между элементами.
3. Обычный CSS сложно понять без контекста (того HTML, к которому он применяется).
4. CSS поощряет переопределения свойств, что сильно осложняет поддержку кода.
5. Часть CSS-свойств наследуются.
6. Свойства одного элемента могут быть описаны в удаленных друг от друга местах кода.
Scalable and Modular Architecture for CSS. Джонатан Снук. 2011.
ФЕВРАЛЬ 2009
#button {
width: 200px;
padding: 10px;
border: solid 1px #ccc;
background: linear-gradient(#ccc,#222);
box-shadow: rgba(0,0,0,.5) 2px 2px 5px;
}
#box {
width: 400px;
overflow: hidden;
border: solid 1px #ccc;
background: linear-gradient(#ccc,#222);
box-shadow: rgba(0,0,0,.5) 2px 2px 5px;
}
#button {
width: 200px;
padding: 10px;
}
#box {
width: 400px;
overflow: hidden;
}
/* А вот это уже объект: */
.style-skin {
border: solid 1px #ccc;
background: linear-gradient(#ccc,#222);
box-shadow: rgba(0,0,0,.5) 2px 2px 5px;
}
/* Такого не должно быть по OOCSS: */
.header .social-widget {
width: 250px;
}
Если использовать .social-widget вне указанного родителя, он станет другой ширины (придётся дописывать стили).
1. Избегайте использования id для стилизации.
2. Избегайте использования селекторов потомков.
3. Избегайте !important
4. Не следует добавлять к селекторам по типу ( h2 {...} ) селекторы классов
1. Получаем объект — класс для повторного использования — уменьшается дублирование кода (малый размер CSS- файла).
2. Отредактировав объект, получится изменить стили всех элементов, к которым он применён.
1. Отредактировав объект, получится изменить стили всех элементов, к которым он применён. С более прицельным изменением будут проблемы.
2. Необходимость сопроводительной документации (иначе код становится малопонятным для других разработчиков).
3. Большое количество объектов требует держать их в уме (или просматривать почаще), чтобы не создавать новые объекты в тех случаях, когда нужные уже существуют.
4. HTML раздувается из-за большого количества классов у каждого элемента (6-10 штук — легко).
5. Имена классов отдельных элементов страницы не уникальны (возможны наложения стилей).
ОКТЯБРЬ 2011
Scalable and Modular Architecture for CSS.
Документация:
Основная цель подхода — уменьшение количества кода и на упрощение поддержки кода.
Предлагает разделять все CSS-классы на несколько типов: основа (базис), структура (каркас), модуль (группа элементов), состояние, тема.
Основа
Структура
Модуль
Состояние
Тема
Основа (Base) — это CSS-сброс и стилизация тегов
/* Тут подключим CSS-reset */
body, form {
font: 16px/18px Arial, sans-serif;
}
a {
color: #039;
}
a:hover {
color: #03F;
}
Структура (Layout) — классы для указания размеров, позиционирования, обтеканий, блочности (и модульные сетки).
#header, #article, #footer {
width: 960px;
margin: auto;
}
#sidebar {
float: right;
}
.l-right-block {
float: right;
}
К названию классов добавляется префикс l- .
Модуль — это более дискретная часть страницы (карусель, диалог, виджет)
.module > h2 {
padding: 5px;
}
.module span {
padding: 5px;
}
Префиксы к названию классов не добавляются. Нужна независимость модуля от контекста.
Подробнее — в первоисточнике.
Состояние (State) — описание любого состояния, отличающегося от умолчания.
.tab { /* Это МОДУЛЬ */
background-color: purple;
color: white;
}
.is-tab-active { /* Это СОСТОЯНИЕ */
background-color: white;
color: black;
}
К названию классов добавляется префикс is-
Допустимо оправданное использование !important.
Тема — набор правил, определяющих внешнее оформление любых элементов (цвета текста и фона, оформительские изображения).
/* module-name.css */
.module {
border: 1px solid;
}
Используются редко — только когда проект имеет несколько тем оформления.
/* module-theme.css */
.module {
border-color: blue;
}
1. Контроль распределён по 4-5-и плоскостям (основа, структура, модуль, состояние,тема). Модифицируя один уровень, не влияем на другой.
1. Нет, хорошая техника.
АВГУСТ 2007
Документация:
Блоки должны быть абсолютно независимы.
Простота освоения: 2 главных правила:
1. «Нет селектора вне класса» и «избегаем вложенных селекторов»; 2 правила в написании (об этом ниже).
2. Самодокументируемость (по имени CSS-класса ясно что это такое).
3. Независимость блоков. А значит:
• Предсказуемость работы кода, нет пересечений имён.
• Реиспользуемость блоков (произвольное количество раз в разных местах, произвольная вложенность блоков друг в друга). Быстро создаём новые компоненты из существующих.
• Поддержка (модификация, расширение) — это просто и безопасно.
• Возможность собирать собственные библиотеки компонентов.
Проблема 1. Зависимость компонента от его родителя
Непрозрачная зависимость одного блока от другого — непредсказуемость поведения.
Везде:
.selector {color: red}
Но в каком-то месте:
.parent .selector {color: green}
И если потом потребуется поменять:
.selector {color: blue}
Придётся потрать некоторое время на понимание того, почему цвет изменился не везде.
А теперь представьте, что селектор состоит из 4-х частей...
В БЭМ такого каскада нет вовсе. Или есть, но, максимум, двусоставной.
Проблема 2. Сложные и специфические селекторы.
Чем сложнее и/или специфичнее селектор,тем больше он привязан к HTML.
Есть выпадающее меню:
#nav ul li ul li {...}
А если потребуется выпадающее меню там, где нет родителя #nav ?
.parent .selector {color: green}
В БЭМ каскад избегается (хотя и допустим).
Используемые в БЭМ селекторы — только классы.
Проблема 3. Слишком общие имена классов.
Общие имена классов создают вероятность повторов и неочевидных наследований стилей.
<div class="block">
<h3 class="title">Заголовок</h3>
<div class="contents">
Контент
</div>
</div>
<style>
.block {...}
.block .title {...}
.block .contents {...}
</style>
Разве можно быть уверенным, что где-то в другом месте не появятся:
.title {...}
.contents {...}
Наложение стилей → БОЛЬ
В БЭМ каждое имя селектора уникально.
Проблема 4. Непонятность CSS без контекста (HTML).
Даже если сейчас Вы работаете над проектов в одиночку, это не значит, что потом не появятся другие разработчики. И, что куда важнее, Вы можете вернуться к проекту через n*месяцев и уже ничего о нем не помнить.
SbcPstW { /* что это??? */
...
}
/* Это обёртка подвала поста в блоге */
/* По БЭМ: */
.post {...}
...
.post__footer-wrap {...}
.post__footer-date {...}
.post__footer-tags {...}
В БЭМ каждое имя селектора указывает на его применение в HTML.
Блок — независимый элемент страницы с собственным смыслом.
Элемент — составная часть блока, имеющая смысл только внутри блока.
Модификатор — модификация внешнего вида или поведения блока (или элемента).
.page-header /* блок */
.page-header--tali /* модификатор блока */
.page-header__slogan /* элемент */
.page-header__slogan--big /* модификатор элемента */
1. Селектор — только класс.
2. Избегаем каскада (но, иногда, можно).
3. Элементы отделяем __ в имени класса.
4. Модификаторы отделяем -- в имени класса.
1. Минимум глобальных стилей (сброс/нормализатор + типографика).
2. Минимум тегов, не покрытых классами.
3. Осторожно используем дочерний селектор ( > ), последовательность ( + ), псевдоклассы ( :nth-child ).
4. Никогда не стилизуем по id
5. Избегаем тегов в селекторах.
6. Избегаем классов-не-блоков ( .red , .float-left ...)
Логически и функционально независимый компонент страницы. Независимость блоков обеспечивает возможность их повторного использования, а также удобство в разработке и поддержке проекта.
Блоки могут быть вложены в любые другие блоки.
Например, блок head может включать логотип (logo), форму поиска (search) и блок авторизации (auth).
Блоки могут быть вложены в любые другие блоки.
Например, блок head может включать логотип (logo), форму поиска (search) и блок авторизации (auth).
В интерфейсе может одновременно присутствовать несколько экземпляров одного и того же блока.
Составная часть блока, которая не может использоваться в отрыве от него.
Например, пункт меню вне контекста блока меню не используется, значит является элементом.
— ЭТО может потребоваться вне родителя?
— Да, может — это блок.
— Нет,тольно внутри родителя — это элемент.
В имени элемента пишут два сегмента __ . Не надо так.
В БЭМ плоская структура Блок → Элемент, максимально независимая от разметки.
По своей сути модификаторы похожи на атрибуты в HTML. Один и тот же блок выглядит по-разному благодаря применению модификатора.
Например, внешний вид блока меню (menu) может меняться в зависимости от примененного модификатора.
Дополнительный класс, изменяющий внешний вид блока (или элемента, если добавлен к элементу).
CSS-класс модификатора формируется так: класс-блока--название-модификатора Даёт возможность блокам выглядеть по-разному на разных страницах или в разных частях страницы.
Классы-модификаторы не используются без тех классов, которые они модифицируют.
У одного блока (элемента) может быть несколько модификаторов. Можно модифицировать элементы от модификатора блока (это делает код неочевидным!).
Избегайте модифицировать вложенные блоки от модификатора блока-родителя.
<div class="header--big"> — неправильно.
<div class="header header--big"> — правильно.
Не используйте имена классов наподобие header__search__button , вне зависимости от реальной иерархии элементов, в имени класса должен быть только один сегмент __ .
Не используйте префикс .b- для классов блоков.
Не используйте элементы блока без самого блока: Класс .gallery__item должен встречаться только внутри блока .gallery
Не используйте классы-модификаторы без тех классов, которые они модифицируют: Класс .gallery--large не должен встречаться без класса .gallery
Избегайте избыточного сокращения — имя CSS-класса должно говорить о том, какому элементу дан этот класс. .g__it — плохо, .gallery__item — хорошо. Используйте лаконичные, но понятные названия классов, подумайте о простом и коротком словаре сокращений.
1. Отсутствие классов, обобщающих разные блоки (одинаковые правила дублируются). Как следствие независимости блоков. Нужны ли такие объединения?
2. Нужно писать классы у всех тегов. У всех? Недостаток ли это? Большие и маленькие проекты.
3. Длинные названия классов. Которые сами по себе документируют вёрстку. С препроцессорами — идеально.
4. Использование в названии классов сегментов __ и -- , длинные имена классов. Некоторым это кажется уродливым.
Шрифт состоит из глифов - векторных форм каждой буквы или символа. Поэтому размер файла шрифта зависит от двух переменных: количества глифов в шрифте и сложности их векторных контуров.
Например, Open Sans, один из самых популярных веб-шрифтов, содержит 897 глифов, включая латинские, греческие и кириллические символы.
К сожалению, несмотря на возможность выбора, не существует единого формата, который работает во всех браузерах.
Поэтому мы должны использовать несколько форматов, чтобы страница выглядела одинаково у всех пользователей:
В каждом объявлении @font-face указано название семейства шрифтов, которые действует как логическая группа из нескольких объявлений, характеристик шрифта, например стиля, толщины и интервала, и дескриптора src, который определяет список расположений шрифта в порядке важности.
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
src: local('Awesome Font'),
url('/fonts/awesome.woff2') format('woff2'),
url('/fonts/awesome.woff') format('woff'),
url('/fonts/awesome.ttf') format('ttf'),
url('/fonts/awesome.eot') format('eot');
}
@font-face {
font-family: 'Awesome Font';
font-style: italic;
font-weight: 400;
src: local('Awesome Font Italic'),
url('/fonts/awesome-i.woff2') format('woff2'),
url('/fonts/awesome-i.woff') format('woff'),
url('/fonts/awesome-i.ttf') format('ttf'),
url('/fonts/awesome-i.eot') format('eot');
}
/*Использование:*/
.class-name {
font-family: 'Awesome Font';
font-size: 14px;
}
— превосходный сервис, который и шрифты даст скачать, и покажет код как их оптимальнее всего подключать.
Когда браузер определяет, что для отображении сайта нужен какой-либо шрифт, он читает предоставленных список ресурсов в указанном порядке и старается скачать нужный шрифт. Например, используя следующий пример:
Браузер читает разметку страницы и определяет, какие варианты шрифтов нужны для отрисовки текста.
Браузер проверяет, не установлены ли нужные шрифты на устройстве.
Если файла нет на устройстве, браузер читает список внешних расположений:
Если формат указан, перед скачивание браузер проверяется, поддерживается ли он. В случае отрицательного ответа программа переходит к следующему варианту.
Если указание на формат отсутствует, браузер скачивает ресурс.
С помощью сочетания локальных и внешних директив и подсказки мы можем указать все доступные форматы шрифта. После этого браузер сделает все остальное: определит нужные ресурсы и выберет подходящий формат.
Note: Порядок, в котором указаны варианты шрифтов, имеет значение, потому что браузер выбирает первый поддерживаемый шрифт. Таким образом, если вы хотите, чтобы современные браузеры использовали WOFF2, укажите его до WOFF, и т. д.
http://nicothin.pro/page/webfonts-min — оптимизация шрифтов