You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Состояние индикатора может быть "в процессе" (loading) или "загрузка завершена" (complete). С точки зрения оформления оно может влиять только на показ внутреннего `span`, но ставить его нужно всё равно на внешний элемент, ведь это -- состояние всего компонента:
Состояние индикатора может быть "в процессе" (loading) или "загрузка завершена" (complete). С точки зрения оформления оно может влиять только на показ внутреннего `span`, но ставить его нужно всё равно на внешний элемент, ведь это -- состояние всего компонента.
87
81
88
82
Из примеров выше можно подумать, что классы, описывающие состояние, всегда ставятся на корневой элемент. Но это не так.
89
83
@@ -103,80 +97,104 @@ HTML-разметка и названия CSS-классов должны отр
103
97
</ul>
104
98
```
105
99
106
-
На практике, даже если в начале разработки поставить класс не там -- то, при правильном понимании CSS, рано или поздно он всё равно переместится куда надо, поскольку стилизация открытого/закрытого меню касается также и заголовка.
107
-
108
-
Но оптимальнее -- сразу ставить его на правильное место.
109
-
110
-
## Префиксы у классов
100
+
## Префиксы компонента у классов
111
101
112
-
Посмотрите, пожалуйста, вёрстку для виджета диалогового окна.
102
+
Рассмотрим пример вёрстки "диалогового окна":
113
103
114
104
```html
105
+
<!--+ autorun height=100 -->
115
106
<divclass="dialog">
116
107
<h2class="title">Заголовок</h2>
117
108
<divclass="content">
118
-
Содержимое. Имена классов в этой вёрстке опасны.
109
+
HTML-содержимое.
119
110
</div>
111
+
<divclass="close">Закрыть</div>
120
112
</div>
121
113
122
114
<style>
123
-
.dialog.title { стиль заголовка }
124
-
.dialog.content { стиль содержимого окна }
125
-
</style>
126
-
```
127
-
128
-
В этой вёрстке есть серьёзная проблема, которая появится, если в содержимом окна будет элемент с классом `.title`:
129
-
130
-
```html
131
-
<divclass="dialog">
132
-
<h1class="*!*title*/!*">Заголовок</h1>
133
-
<divclass="content">
115
+
.dialog {
116
+
background: lightgreen;
117
+
border: lime2pxsolid;
118
+
border-radius: 10px;
119
+
padding: 4px;
120
+
position: relative;
121
+
}
134
122
135
123
*!*
136
-
<h2class="*!*title*/!*">Привет!</h2>
137
-
... текст диалога ...
124
+
.dialog.title {
125
+
margin: 0;
126
+
font-size: 24px;
127
+
color: darkgreen;
128
+
}
138
129
*/!*
139
130
140
-
</div>
141
-
</div>
131
+
.dialog.content {
132
+
padding: 10px000;
133
+
}
134
+
135
+
.dialog.close {
136
+
position: absolute;
137
+
right: 4px;
138
+
top: 4px;
139
+
font-size: 10px;
140
+
}
141
+
</style>
142
142
```
143
143
144
-
Такое вполне возможно, ведь диалоговое окно может иметь любое содержимое.
144
+
Диалоговое окно может иметь любое HTML-содержимое.
145
145
146
-
**В этом случае CSS-правило `.dialog .title` будет применено и к `<h2 class="title">`в содержимом с непредсказуемыми последствиями.**
146
+
А что будет, если в этом содержимом окажется меню -- да-да, то самое, которое рассмотрели выше, со `<span class="title">`?
147
147
148
-
Конечно, можно попытаться бороться с этим. Например, нейтрализовать его действие, добавив дополнительное правило `.dialog .content .title`, но это скорее "заплатка", нежели полноценное решение проблемы.
148
+
Правило `.dialog .title` применяется ко всем `.title` внутри `.dialog`, а значит -- и к нашему меню тоже. Будет конфликт стилей с непредсказуемыми последствиями.
149
149
150
-
Ещё один вариант -- жёстко задать вложенность. А именно, использовать класс `.dialog > .title`. Это сработает в данном конкретном примере, но как быть в тех местах, где нужен более глубокий потомок?
150
+
Конечно, можно попытаться бороться с этим. Например, жёстко задать вложенность -- использовать класс `.dialog > .title`. Это сработает в данном конкретном примере, но как быть в тех местах, где между `.dialog` и `.title` есть другие элементы? Длинные цепочки вида `.dialog > ... > .title` страшновато выглядят и делают вёрстку ужасно негибкой. К счастью, есть альтернативный путь.
151
151
152
152
**Чтобы избежать возможных проблем, все классы внутри виджета начинают с его имени.**
153
153
154
-
Подходящий вариант:
154
+
Здесь имя `dialog`, так что все, относящиеся к диалогу, будем начинать с `dialog__`
В этом случае внутрь `.dialog-content` можно смело помещать другие компоненты со своими классами `..-title`, `..-content` и т.п.
175
+
Здесь двойное подчёркивание `__` служит "стандартным" разделителем. Можно выбрать и другой разделитель, но при этом стоит иметь в виду, что иногда имя класса может состоять из нескольких слов. Например `title-picture`. С двойным подчёркиванием: `dialog__title-picture`, очень наглядно видно где что.
169
176
170
-
Кроме всего прочего, обработка такого CSS будет чуть-чуть быстрее ;) Так как один класс вместо каскада.
177
+
Есть ещё одно полезное правило, которое заключается в том, что стили должны вешаться на класс, а не на тег. То есть, не `h2 { ... }`, а `.dialog__title { ... }`, где `.dialog__title` -- класс на соответствующем заголовке.
171
178
172
-
[smart header="Когда префиксы не нужны?"]
173
-
Префиксы делают названия классов длиннее, поэтому иногда не хочется их ставить.
179
+
Это позволяет и избежать конфликтов на вложенных `h2`, и использовать всегда те теги, которые имеют правильный смысл, не оглядываясь на встроенные стили (которые можно обнулить своими).
174
180
175
-
Без них можно обойтись в тех случаях, когда внутри элемента заведомо не будет произвольного HTML и других компонент. То есть когда конфликты заведомо исключены.
176
181
177
-
С другой стороны, требования имеют свойство расти. Компоненты зачастую вставляются туда, где их не предполагалось. Ваш виджет, написанный для одной задачи или проекта, может быть потом использован совсем в другом месте, где потребуются вложенные компоненты. И тогда заранее предусмотренные префиксы сослужат хорошую службу.
182
+
[smart header="Без фанатизма"]
183
+
На практике из этих правил зачастую делают исключения. Можно "вешать" стили на теги и использовать CSS-каскады без префиксов, если мы при этом твёрдо понимаем, что конфликты заведомо исключены.
184
+
185
+
Например, когда мы точно знаем, что никакого произвольного HTML внутри элемента (или внутри данного поддерева DOM) не будет.
178
186
[/smart]
179
187
188
+
## БЭМ
189
+
190
+
Описанное выше правило именования элементов является частью более общей концепции "БЭМ", которая разработана в Яндексе.
191
+
192
+
БЭМ предлагает способ организации HTML/CSS/JS в виде независимых "блоков" -- компонент, которые можно легко перемещать по файловой системе и между проектами.
193
+
194
+
Можно как взять часть идеологии, например систему именования классов, так и полностью перейти на инструментарий БЭМ, который даёт инструменты сборки для HTML/JS/CSS, описанных по БЭМ-методу.
195
+
196
+
Более подробное описание основ БЭМ можно почитать в статье [](https://ru.bem.info/articles/bem-for-small-projects/), а о системе вообще -- на сайте [](http://ru.bem.info).
197
+
180
198
## Итого
181
199
182
200
<ul>
@@ -186,8 +204,9 @@ HTML-разметка и названия CSS-классов должны отр
186
204
187
205
Это не всегда строго необходимо, но позволяет избежать проблем в случаях, когда компонент может содержать произвольный DOM, как например диалоговое окно с произвольным HTML-текстом.
188
206
189
-
Использование `.dialog-title` вместо `.dialog .title` гарантирует, что CSS не применится по ошибке к какому-нибудь другому `.title` внутри диалога.
207
+
Использование `.dialog__title` вместо `.dialog.title` гарантирует, что CSS не применится по ошибке к какому-нибудь другому `.title` внутри диалога.
0 commit comments