Skip to content

Commit e706693

Browse files
committed
renovations
1 parent 718ab32 commit e706693

12 files changed

Lines changed: 245 additions & 256 deletions

File tree

2-ui/5-widgets/3-widgets-markup/1-semantic-menu/solution.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222

2323
```html
2424
<ul class="menu">
25-
<li class="item"><a href="#">Главная</a></li>
26-
<li class="vertical-splitter"></li>
27-
<li class="item"><a href="#">Товары</a></li>
28-
<li class="item"><a href="#">Фотографии</a></li>
29-
<li class="item"><a href="#">Контакты</a></li>
25+
<li class="menu__item"><a href="#">Главная</a></li>
26+
<li class="menu__vertical-splitter"></li>
27+
<li class="menu__item"><a href="#">Товары</a></li>
28+
<li class="menu__item"><a href="#">Фотографии</a></li>
29+
<li class="menu__item"><a href="#">Контакты</a></li>
3030
</ul>
3131
```
3232

33-
[edit src="solution"]Полное меню со стилями[/edit]
33+
Дополнительно, классы помечены префиксом компонента, на тот случай, если в заголовках появится произвольный HTML.
34+
35+

2-ui/5-widgets/3-widgets-markup/1-semantic-menu/solution.view/index.html

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,13 @@
88
padding: 0;
99
}
1010

11-
.menu li {
11+
.menu__item {
1212
list-style: none;
1313

14-
float: left;
14+
display: inline-block;
1515
padding: 6px;
1616
margin: 0 2px;
17-
}
1817

19-
.menu li.item {
2018
border: 1px solid gray;
2119
border-radius: 10px;
2220

@@ -25,16 +23,21 @@
2523
background: #FFF5EE;
2624
}
2725

28-
.menu li.vertical-splitter:before {
26+
.menu__vertical-splitter {
27+
list-style: none;
28+
display: inline-block;
29+
}
30+
31+
.menu__vertical-splitter:before {
2932
content: "|";
3033
}
3134

32-
.menu .item a {
35+
.menu__item a {
3336
color: black;
3437
text-decoration: none;
3538
}
3639

37-
.menu .item a:hover {
40+
.menu__item a:hover {
3841
text-decoration: underline;
3942
}
4043

@@ -43,11 +46,11 @@
4346
<body>
4447

4548
<ul class="menu">
46-
<li class="item"><a href="#">Главная</a></li>
47-
<li class="vertical-splitter"></li>
48-
<li class="item"><a href="#">Товары</a></li>
49-
<li class="item"><a href="#">Фотографии</a></li>
50-
<li class="item"><a href="#">Контакты</a></li>
49+
<li class="menu__item"><a href="#">Главная</a></li>
50+
<li class="menu__vertical-splitter"></li>
51+
<li class="menu__item"><a href="#">Товары</a></li>
52+
<li class="menu__item"><a href="#">Фотографии</a></li>
53+
<li class="menu__item"><a href="#">Контакты</a></li>
5154
</ul>
5255

5356
</body>

2-ui/5-widgets/3-widgets-markup/1-semantic-menu/task.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@
4444

4545
[iframe src="source" border=1 height=50 edit link]
4646

47-
Что делает эту вёрстку несемантичной? Найдите 3 ошибки.
47+
Что делает эту вёрстку несемантичной? Найдите 3 ошибки (или больше).
4848

4949
Как бы вы сверстали меню правильно?

2-ui/5-widgets/3-widgets-markup/2-markup-errors/solution.md

Lines changed: 0 additions & 29 deletions
This file was deleted.
-2.59 KB
Binary file not shown.

2-ui/5-widgets/3-widgets-markup/2-markup-errors/task.md

Lines changed: 0 additions & 44 deletions
This file was deleted.

2-ui/5-widgets/3-widgets-markup/article.md

Lines changed: 67 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ HTML-разметка и названия CSS-классов должны отр
4848
</div>
4949
```
5050

51-
**Семантическая верстка упрощает поддержку и развитие CSS, упрощает взаимодействие между членами команды.**
51+
Семантическая верстка упрощает поддержку и развитие CSS, упрощает взаимодействие между членами команды.
5252

5353
Такая верстка удобна для организации JS-кода. В коде мы просто ставим нужный класс, остальное делает CSS.
5454

@@ -69,21 +69,15 @@ HTML-разметка и названия CSS-классов должны отр
6969
</div>
7070
```
7171

72-
Ещё пример -- индикатор загрузки:
72+
Или, к примеру, разметка для индикатора загрузки может выглядеть так:
7373

7474
```html
75-
<div class="loader">
75+
<div class="indicator *!*loading*/!*">
7676
<span class="progress">Тут показывается прогресс</span>
7777
</div>
7878
```
7979

80-
Состояние индикатора может быть "в процессе" (loading) или "загрузка завершена" (complete). С точки зрения оформления оно может влиять только на показ внутреннего `span`, но ставить его нужно всё равно на внешний элемент, ведь это -- состояние всего компонента:
81-
82-
```html
83-
<div class="loader *!*loading*/!*">
84-
<span class="progress">Тут показывается прогресс</span>
85-
</div>
86-
```
80+
Состояние индикатора может быть "в процессе" (loading) или "загрузка завершена" (complete). С точки зрения оформления оно может влиять только на показ внутреннего `span`, но ставить его нужно всё равно на внешний элемент, ведь это -- состояние всего компонента.
8781

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

@@ -103,80 +97,104 @@ HTML-разметка и названия CSS-классов должны отр
10397
</ul>
10498
```
10599

106-
На практике, даже если в начале разработки поставить класс не там -- то, при правильном понимании CSS, рано или поздно он всё равно переместится куда надо, поскольку стилизация открытого/закрытого меню касается также и заголовка.
107-
108-
Но оптимальнее -- сразу ставить его на правильное место.
109-
110-
## Префиксы у классов
100+
## Префиксы компонента у классов
111101

112-
Посмотрите, пожалуйста, вёрстку для виджета диалогового окна.
102+
Рассмотрим пример вёрстки "диалогового окна":
113103

114104
```html
105+
<!--+ autorun height=100 -->
115106
<div class="dialog">
116107
<h2 class="title">Заголовок</h2>
117108
<div class="content">
118-
Содержимое. Имена классов в этой вёрстке опасны.
109+
HTML-содержимое.
119110
</div>
111+
<div class="close">Закрыть</div>
120112
</div>
121113

122114
<style>
123-
.dialog .title { стиль заголовка }
124-
.dialog .content { стиль содержимого окна }
125-
</style>
126-
```
127-
128-
В этой вёрстке есть серьёзная проблема, которая появится, если в содержимом окна будет элемент с классом `.title`:
129-
130-
```html
131-
<div class="dialog">
132-
<h1 class="*!*title*/!*">Заголовок</h1>
133-
<div class="content">
115+
.dialog {
116+
background: lightgreen;
117+
border: lime 2px solid;
118+
border-radius: 10px;
119+
padding: 4px;
120+
position: relative;
121+
}
134122
135123
*!*
136-
<h2 class="*!*title*/!*">Привет!</h2>
137-
... текст диалога ...
124+
.dialog .title {
125+
margin: 0;
126+
font-size: 24px;
127+
color: darkgreen;
128+
}
138129
*/!*
139130
140-
</div>
141-
</div>
131+
.dialog .content {
132+
padding: 10px 0 0 0;
133+
}
134+
135+
.dialog .close {
136+
position: absolute;
137+
right: 4px;
138+
top: 4px;
139+
font-size: 10px;
140+
}
141+
</style>
142142
```
143143

144-
Такое вполне возможно, ведь диалоговое окно может иметь любое содержимое.
144+
Диалоговое окно может иметь любое HTML-содержимое.
145145

146-
**В этом случае CSS-правило `.dialog .title` будет применено и к `<h2 class="title">` в содержимом с непредсказуемыми последствиями.**
146+
А что будет, если в этом содержимом окажется меню -- да-да, то самое, которое рассмотрели выше, со `<span class="title">` ?
147147

148-
Конечно, можно попытаться бороться с этим. Например, нейтрализовать его действие, добавив дополнительное правило `.dialog .content .title`, но это скорее "заплатка", нежели полноценное решение проблемы.
148+
Правило `.dialog .title` применяется ко всем `.title` внутри `.dialog`, а значит -- и к нашему меню тоже. Будет конфликт стилей с непредсказуемыми последствиями.
149149

150-
Ещё один вариант -- жёстко задать вложенность. А именно, использовать класс `.dialog > .title`. Это сработает в данном конкретном примере, но как быть в тех местах, где нужен более глубокий потомок?
150+
Конечно, можно попытаться бороться с этим. Например, жёстко задать вложенность -- использовать класс `.dialog > .title`. Это сработает в данном конкретном примере, но как быть в тех местах, где между `.dialog` и `.title` есть другие элементы? Длинные цепочки вида `.dialog > ... > .title` страшновато выглядят и делают вёрстку ужасно негибкой. К счастью, есть альтернативный путь.
151151

152152
**Чтобы избежать возможных проблем, все классы внутри виджета начинают с его имени.**
153153

154-
Подходящий вариант:
154+
Здесь имя `dialog`, так что все, относящиеся к диалогу, будем начинать с `dialog__`
155+
156+
Получится так:
155157

156158
```html
157159
<div class="*!*dialog*/!*">
158-
<h1 class="*!*dialog-title*/!*">Заголовок</h1>
159-
<div class="*!*dialog-content*/!*">Содержимое</div>
160+
<h2 class="dialog__title">Заголовок</h2>
161+
<div class="dialog__content">
162+
HTML-содержимое.
163+
</div>
164+
<div class="dialog__close">Закрыть</div>
160165
</div>
161166

162167
<style>
163-
.dialog-title { стиль загловка }
164-
.dialog-content { стиль содержимого окна }
168+
.dialog { ... }
169+
.dialog__title { стиль заголовка }
170+
.dialog__content { стиль содержимого }
171+
...
165172
</style>
166173
```
167174
168-
В этом случае внутрь `.dialog-content` можно смело помещать другие компоненты со своими классами `..-title`, `..-content` и т.п.
175+
Здесь двойное подчёркивание `__` служит "стандартным" разделителем. Можно выбрать и другой разделитель, но при этом стоит иметь в виду, что иногда имя класса может состоять из нескольких слов. Например `title-picture`. С двойным подчёркиванием: `dialog__title-picture`, очень наглядно видно где что.
169176
170-
Кроме всего прочего, обработка такого CSS будет чуть-чуть быстрее ;) Так как один класс вместо каскада.
177+
Есть ещё одно полезное правило, которое заключается в том, что стили должны вешаться на класс, а не на тег. То есть, не `h2 { ... }`, а `.dialog__title { ... }`, где `.dialog__title` -- класс на соответствующем заголовке.
171178
172-
[smart header="Когда префиксы не нужны?"]
173-
Префиксы делают названия классов длиннее, поэтому иногда не хочется их ставить.
179+
Это позволяет и избежать конфликтов на вложенных `h2`, и использовать всегда те теги, которые имеют правильный смысл, не оглядываясь на встроенные стили (которые можно обнулить своими).
174180
175-
Без них можно обойтись в тех случаях, когда внутри элемента заведомо не будет произвольного HTML и других компонент. То есть когда конфликты заведомо исключены.
176181
177-
С другой стороны, требования имеют свойство расти. Компоненты зачастую вставляются туда, где их не предполагалось. Ваш виджет, написанный для одной задачи или проекта, может быть потом использован совсем в другом месте, где потребуются вложенные компоненты. И тогда заранее предусмотренные префиксы сослужат хорошую службу.
182+
[smart header="Без фанатизма"]
183+
На практике из этих правил зачастую делают исключения. Можно "вешать" стили на теги и использовать CSS-каскады без префиксов, если мы при этом твёрдо понимаем, что конфликты заведомо исключены.
184+
185+
Например, когда мы точно знаем, что никакого произвольного HTML внутри элемента (или внутри данного поддерева DOM) не будет.
178186
[/smart]
179187
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+
180198
## Итого
181199
182200
<ul>
@@ -186,8 +204,9 @@ HTML-разметка и названия CSS-классов должны отр
186204
187205
Это не всегда строго необходимо, но позволяет избежать проблем в случаях, когда компонент может содержать произвольный DOM, как например диалоговое окно с произвольным HTML-текстом.
188206
189-
Использование `.dialog-title` вместо `.dialog .title` гарантирует, что CSS не применится по ошибке к какому-нибудь другому `.title` внутри диалога.
207+
Использование `.dialog__title` вместо `.dialog .title` гарантирует, что CSS не применится по ошибке к какому-нибудь другому `.title` внутри диалога.
190208
</li>
191209
</ul>
192210
193211
212+

0 commit comments

Comments
 (0)