Первое, что нужно научиться делать — находить повторяющиеся сущности (которые в последствии станут Блоками и Элементами). Вы уже пытаетесь сделать это, но пока получается слишком многословно, судя по количеству классов и это, очевидно, сбивает с толку.
Я уже рассказывал на последнем БЭМапе (
https://youtu.be/d4dcGj8abv0) о том, как я ищу эти повторяющиеся закономерности, поэтому постараюсь кратко:
1) Собираем и группируем «данные»
Разберём «шапку» и «подвал». И там, и там есть логотип, какая-то навигация, контактная информация, ссылки на соц. сети, в шапке есть кнопка:
1.1) «Шапка»
{
logo: {
img: 'путь до картинки',
text: '…',
},
contacts: [
'телефон',
'email',
'график работы',
'адрес',
'соц. сети',
'кнопка обратной связи',
],
navigation: [
'пункт меню…',
'пункт меню…',
'пункт меню…',
]
}
1.2) В «подвале» почти то же самое, что-то в другом порядке, но это неважно, и нет «кнопки обратной связи» из секции «Контактов».
1.3) Есть ещё самостоятельные секции «Свяжитесь с нами» на главной странице и на странице контактов, которые тоже используют пункты из секции «Контактов» (теперь уже понятно, что такое частое повторение позволяет выделить это в блок).
1.4) Логотип и навигацию тоже выделим в блоки (я разделил логотип на два элемента — изображение и текст, потому что на малых экранах текст превращается в замыленое нечитаемое говно, поэтому его лучше убрать).
1.5) Получается какая-то такая структура:
// Блок логотипа
{
logo: [
{ img: '…' },
{ text: '…' },
]
}
// Блок контактов
{
contacts: [
{ tel: '…' },
{ email: '…' },
{ schedule: '…' },
{ address: '…' },
{ socials: [
{ vk: '…' },
{ telegram: '…' },
{ instagram: '…' },
] },
{ map: '…' },
{ feedback: '…' },
]
}
// Блок навигации
{
navigation: [
{ item: '', link: '…' },
{ item: '', link: '…' },
{ item: '', link: '…' },
]
}
// Блок «Шапки»
{
header: [
{
logo: [] // Тут всё без изменений
},
{
contacts: [
'tel',
'email',
'schedule',
'address',
'socials',
'feedback',
]
},
{
navigation: [] // Тут тоже без изменений
}
]
}
// Блок «Подвала»
{
footer: [
{
logo: [] // Тут всё без изменений
},
{
navigation: [ // Тут почти без изменений
// …
'Марки автомобилей' // Без выпадающего списка
// …
]
},
{
contacts: [
'tel',
'email',
'address',
'socials',
'schedule', // Без иконки
]
},
]
}
2) Вроде, пока хватит. «БЭМизируем» эти данные.
Структура в формате JSON
// Блок логотипа
{
block: 'logo'
content: [
{ elem: 'img', src: '…' },
{ text: '…' },
]
}
// Блок контактов
{
block: 'contacts'
content: [
{ elem: 'tel', content: '…' },
{ elem: 'email', content: '…' },
{ elem: 'schedule', content: '…' },
{ elem: 'address', content: '…' },
{ elem: 'socials', content: [
{ elem: 'vk', content: '…' },
{ elem: 'telegram', content: '…' },
{ elem: 'instagram', content: '…' },
] },
{ elem: 'map', content: '…' },
{ elem: 'feedback', content: '…' },
]
}
// Блок навигации
{
navigation: [
{ item: '', link: '…' },
{ item: '', link: '…' },
{ item: '', link: '…' },
]
}
// Блок «Шапки»
{
header: [
{
block: 'logo'
},
{
block: 'contacts',
// У этого блока определённо свой контент,
// будем отличать его от других вариантов
// этого блока с помощью модификатора
mods: { view: 'header' },
content: [
{ elem: 'tel' },
{ elem: 'email' },
{ elem: 'schedule' },
{ elem: 'address' },
{ elem: 'socials' },
{ elem: 'feedback' },
]
},
{
block: 'navigation',
// Этот блок по внешнему виду отличается от блока в «Подвале»,
// поэтому обозначим его модификатором
mods: { view: 'header' },
content: [
// …
// У одного пункта выпадающий список
{
elem: 'item',
item: 'Марки автомобилей',
elemMods: { dropdown: true },
content: [
// …
{ elem: 'subitem', item: 'Infinity', href: '…' }
]
},
// …
]
}
]
}
// Блок «Подвала»
{
footer: [
{
block: 'logo'
},
{
block: 'navigation',
mods: { view: 'footer' },
content: [ // Тут почти без изменений
// …
{ elem: 'Марки автомобилей', link: '…' }, // Без выпадающего списка
// …
]
},
{
contacts: [
'tel',
'email',
'address',
'socials',
{ elem: 'schedule', elemMods: { noIcon: true } }, // Без иконки
]
},
]
}
2.1) Базовый лэйаут:
https://codepen.io/Realetive/pen/PoGRjZo
2.2) Добавляем обёртки для группировки некоторых элементов:
https://codepen.io/Realetive/pen/KKgoBdN
Про обёртки и зачем они нужны уже обсуждалось в
https://ru.bem.info/forum/656/, очень советую.
2.3) Добавим отступы:
https://codepen.io/Realetive/pen/bGwvjow
Как видите, миксы по-прежнему не нужны.
3) У контента есть фиксированная ширина, обозначим её через класс-элемент блока page: например, .page__layout:
https://codepen.io/Realetive/pen/WNGzgjJ
Но вёрстка закономерно сбилась, потому что классы, которые мы назначали для родительского уровня, «поднялись» ещё н один уровень. Добавим ещё обёртки, чтобы «выровнять» лэйаут: стили header перенесутся в header__body, из footer в footer__body:
https://codepen.io/Realetive/pen/wvzmEpy
4) Получилось достаточно много «лишних» обёрток только лишь для позиционирования. Можно было бы этого избежать, если бы стили были описаны в одном классе. Но тогда мы лишимся пользы разделения логики благодаря БЭМ-неймингу. Вместо этого объединим эти слои с помощью миксов: page__header + header, header__body + page__layout, page__footer + footer, footer__body + page__layout:
https://codepen.io/Realetive/pen/RwGMYyV
Вот наконец и пригодились миксы. Они лишь позволяют объединить две сущности по схожему признаку (например, лэйаут и позиционирование) на одном теге. А модификаторы обозначают различие между двумя одинаковыми сущностями (например, в одном месте у элемента есть иконка, в другом — нет, хотя это всё тот же элемент).
Блок с контактами делается аналогичным способом:
.page__section.page__section_view_feedback
.page__layout
.form.form_view_feedback.page__column_width_half (миксуем блок формы обратной связи и лэйаут 1/2 колонки)
…
.contacts_view_feedback.page__column_width_half
.contacts__info
.contacts__address
.contacts__email
.contacts__tel
.contacts__schedule
.contacts__map