Оглавление

    HTML

    HTML-доктайп

    В начале страницы обязательно должен быть указан актуальный doctype, чтобы браузер отображал её в режиме соответствия стандартам. Это гарантирует, что страница будет выглядеть единообразно во всех современных браузерах.

    <!DOCTYPE html>
    <html lang="ru">
      <head>…</head>
      <body>…</body>
    </html>
    

    Кодировка символов

    Кодировка символов на странице всегда должна быть явно указана, чтобы обеспечить корректное отображение текста. Кодировка utf-8 предпочтительна.

    <head>
      <meta charset="utf-8">
      <title>Заголовок страницы</title>
    </head>
    

    Отступы

    Используйте отступы с двумя пробелами. Разместите файл .editorconfig (универсальные базовые настройки редактора) в папке проекта и установите его поддержку в редакторе.

    <nav class="main-nav">
      <ul>
        <li><a href="/index.html">Главная</a></li>
        <li><a href="/contacts.html">Контакты</a></li>
      </ul>
    </nav>
    
    <img src="logo.svg" width="50" height="50" alt="Company">
    

    Синтаксис

    • Теги и атрибуты пишите строчными буквами.
    • Значения атрибутов всегда пишите в двойных кавычках.
    • Не добавляйте слэш (/) в конец одиночного тега.
    • Не пропускайте необязательные закрывающие теги (например, </li> или </body>).
    • Разделяйте крупные фрагменты разметки пустыми строками
    <!-- 😊 Хорошо: Все тэги и атрибуты соответствуют правилам -->
    <figure>
      <img src="dog.png" alt="Собака" width="100" height="100">
    </figure>
    
    <!-- 💩 Плохо: тэги не совпадают, нарушены правила для атрибутов -->
    <FIGURE>
      <img src='DOG.png' ALT="Собака" width='100' HEIGHT="100" />
    

    Порядок атрибутов

    Атрибут класса у HTML-элементов пишется первым. Единообразное написание помогает легче считывать код и быстрее разбираться в назначении блоков по их классам.

    Остальные атрибуты могут быть расставлены в любом порядке, но тоже единообразно для одинаковых элементов.

    <a class="element element-big" id="element" href="/" data-name="element">Ссылка</a>
    
    <input class="form-control" type="text" name="test">
    
    <img class="pets-picture" src="cats.jpg" alt="Изображение котиков">
    

    Логические атрибуты

    Для логических атрибутов (например, checked, disabled, required) значение не указывается, а сами атрибуты указываются последними и в единообразной последовательности во всём документе.

    <!-- checked="checked" необязательно -->
    
    <input type="checkbox" required checked>
    
    <input type="text" disabled>
    
    <select>
      <option value="1" selected>1</option>
    </select>
    

    Подписи полей ввода

    Для улучшения взаимодействия пользователя с элементами форм, при нажатии на подпись поля, оно должно активироваться. Для этого элемент формы связывается с его описанием с помощью идентификатора и атрибута for тега <label>.

    <!-- 😊 Хорошо: элемент формы radio связан с подписью через идентификатор -->
    <input type="radio" id="choose">
    <label for="choose">Радио кнопка</label>
    
    <!-- 😊 Хорошо: элемент формы radio и подпись обёрнуты в label -->
    <label>
      <input type="radio"> Радио кнопка
    </label>
    
    <!-- 💩 Плохо: подпись не связана с элементом формы -->
    <input type="radio" id="choose"> Радио кнопка
    

    Размеры картинок

    Изображениям <img> должны быть явно заданы с помощью атрибута размеры в пикселях. В случае пикселей размерность не нужна.

    По возможности изображениям указываются действительные размеры, так как это улучшает производительность отрисовки страницы: браузер не будет перерисовывать страницу в процессе загрузки и отображения изображения.

    <!-- 😊 Хорошо: размеры картинке заданы -->
    <div class="logo-area">
      <img src="logo.png" alt="" width="300" height="150">
    </div>
    
    <!-- 💩 Плохо: размеры картинке заданы в px -->
    <div class="logo-area">
      <img src="logo.png" alt="" width="300px" height="150px">
    </div>
    
    <!-- 💩 Плохо: размеры картинке не заданы -->
    <div class="logo-area">
      <img src="logo.png" alt="">
    </div>
    

    Отсутствие логичной иерархии заголовков

    Иерархия важна как для SEO, так и для восприятия страницы в случае отсутствия стилей (не загрузились по каким-то причинам). Заголовки, так же, очень важны для доступности страницы.

    <!-- 😊 Хорошо: порядок заголовков правильный -->
    <h1>Главный заголовок</h1>
    <h2>Второстепенный заголовок</h2>
    
    <!-- 💩 Плохо: порядок заголовков нарушен -->
    <h2>Второстепенный заголовок</h2>
    <h1>Главный заголовок</h1>
    

    Игнорирование семантики тегов

    Часть тегов универсальны, часть имеют семантику (разной степени). К примеру, есть div — универсальный блок, а есть section — часть чего-либо (к примеру, большого «подвала»), которая при вырывании из контекста частично теряет смысл, и есть article — блок с наиболее выраженной семантикой (будучи вырван из контекста, сохраняет осмысленность полностью).

    Всегда нужно применять наиболее подходящие по смыслу теги: списки, таблицы, параграфы, заголовки и пр. должны использоваться по назначению. Это улучшает индексацию сайта (и вообще понимание страницы роботами) и доступность.

    <!-- 😊 Хорошо: блок размечен с соблюдением семантики -->
    <header></header>
    <section>
      <article>
        <figure>
          <img>
          <figcaption></figcaption>
        </figure>
      </article>
    </section>
    <footer></footer>
    
    <!-- 💩 Плохо: семантика отсутствует -->
    <div id="header"></div>
    <div class="section">
      <div class="article">
        <div class="figure">
          <img>
          <div class="figcaption"></div>
        </div>
      </div>
    </div>
    <div id="footer"></div>
    

    Ссылки с javascript:void(0)

    Псевдо-протокол javascript: давно устарел. Он поддерживается браузерами, но не описывается в веб-стандартах.

    Раньше такую конструкцию использовали для кнопок, но теперь доступен тэг button.

    <!-- 😊 Хорошо: кнопка сделана через тэг <button> -->
    <button type="button">Я кнопка</button>
    
    <!-- 💩 Плохо: кнопка сделана ссылкой -->
    <a href="javascript:void(0)">Я кнопка</a>
    

    Поведение кнопки по умолчанию

    По умолчанию у кнопки type="submit". Не забывайте явно указывать тип, чтобы избежать нежелательных багов.

    <!-- 😊 Хорошо: кнопкам указан тип -->
    <button type="button">Я просто кнопка</button>
    <button type="submit">Я кнопка для отправки формы</button>
    
    <!-- 💩 Плохо: типы кнопок не указаны -->
    <button>Я просто кнопка</button>
    <button>Я кнопка для отправки формы</button>
    

    Ссылки с target="_blank"

    Для ссылок с target="_blank" следует добавлять атрибут rel="noopener noreferrer". Это увеличивает производительность и безопасность приложения.

    <!-- 😊 Хорошо: ссылке указан атрибут rel -->
    <a href="https://svyaznoy.ru/" target="_blank" rel="noopener noreferrer">
      Ссылка на сторонний ресурс
    </a>
    
    <!-- 💩 Плохо: атрибут rel не указан -->
    <a href="https://svyaznoy.ru/" target="_blank">
      Ссылка на сторонний ресурс
    </a>
    

    Телефоны и почта

    Используйте <a> для всех элементов, которые могут куда-либо вести, даже если в макете этот элемент отрисован как обычный текст, так как в данном случае ссылка — логический элемент, а не визуальный.

    • tel:+1234567890 – для указания телефона. Номер должен начинаться с плюса и состоять только из чисел без спецсимволов типа пробелов, круглых скобок или дефиса;
    • mailto:mail@mail.ru – для указания e-mail;
    <!-- 😊 Хорошо: для телефона сделана ссылка -->
    <a href="tel:+79999999999">
      +7(999)999-99-99
    </a>
    
    <!-- 💩 Плохо: телефон сделан как обычный текст -->
    <span>
      +7(999)999-99-99
    </span>
    

    Типограф

    Когда текст статичен, мы имеем к нему доступ, он не приходит из CMS – следует прогонять его через типограф.

    <!-- 😊 Хорошо: в тексте расставлены неразрывные пробелы  -->
    Каждая строка кода должна казаться написанной только одним человеком, вне зависимости от&nbsp;количества разработчиков.
    
    <!-- 💩 Плохо: текст без специальных символов -->
    Каждая строка кода должна казаться написанной только одним человеком, вне зависимости от количества разработчиков.
    

    БЭМ. Зачем?

    • Самодокументируемость.
    • Имитация пространства имён (простота и безопасность модификации).
    • Отсутствие зависимости от DOM-структуры.
    • Проектное реиспользование блоков.
    • Кросспроектное реиспользование блоков.

    Само понятие БЭМ — не только метод именования селекторов, но парадигма восприятия проекта как набора сущностей (блоки, элементы, модификаторы). Полный стек БЭМ подразумевает двойную шаблонизацию и имеет относительно высокий порог входа. Используйте БЭМ хотя бы как способ именования селекторов.

    <!-- Блок `search-form` -->
    <form class="search-form">
      <!-- Элемент `input` блока `search-form` -->
      <input class="search-form__input">
      
      <!-- Элемент `button` блока `search-form` -->
      <button class="search-form__button">Найти</button>
    </form>
    

    Блок — это самостоятельная часть страницы

    • Название класса должно быть простым и коротким.
    • Название класса должно отвечать на вопрос «Что это?»
    • Не используйте сокращения кроме наиболее частых
    • Название не должно отвечать на вопрос «Как выглядит?»
    <!-- .product — БЭМ-блок -->
    <div class="product">
      ...
    </div>
    

    Блоки можно и нужно вкладывать друг в друга

    • Нет ограничений на вложения блоков, помимо здравого смысла.
    • Никакой дополнительной специфики вложенные блоки не имеют.
    <!-- .page-header — БЭМ-блок -->
    <div class="page-header">
      
      <!-- .logo — вложенный БЭМ-блок -->
      <a class="logo">...</a>
    
    </div>
    

    Элемент — часть БЭМ-блока

    • Название класса формируется из названия блока с добавлением __ и названия элемента.
    • Название класса должно быть простым и коротким.
    • Название класса должно отвечать на вопрос «Что это?»
    • Избегайте сокращений, кроме наиболее частых.
    • Название не должно отвечать на вопрос «Как выглядит?»
    <div class="product">
    
      <!-- product__image — БЭМ-элемент блока product -->
      <img class="product__image" src="..." alt="...">
      
      <!-- product__description — БЭМ-элемент блока product -->
      <p class="product__description">...</p>
      
      <!-- product__more-link — БЭМ-элемент блока product -->
      <a class="product__more-link" href="">...</a>
    </div>
    

    Элемент можно использовать вне его блока только в исключительных случаях

    Элемент — часть блока, но, поскольку, БЭМ-дерево независимо от HTML-дерева, элемент можно использовать и вне его блока в некоторых исключительных условиях (сам блок должен быть на странице).

    Пример: расположение попапа-элемента не внутри блока-родителя, а в самом конце DOM (дабы показывать попап независимо от ограничения видимости родителей).

    <body>
      <header>
        <div class="tooltip">
          <button class="tooltip__anchor"></button>
        </div>
      </header>
    
      <div class="tooltip__box">
        Контент в тултипе в конце DOM
      </div>
    </body>
    

    Элементов может не быть

    Не у всех блоков должны быть элементы: кнопка — всегда БЭМ-блок, но БЭМ-элементы у неё внутри встречаются относительно редко.

    <!-- Нет ошибки: блок без элементов -->
    <a class="btn" href="">Скачать</a>
    

    Как отличить БЭМ-блок и БЭМ-элемент

    Просто задайте себе вопрос: «Эта сущность может потребоваться мне отдельно, сама по себе? Или она нужна только внутри её родителя?» Если нужна отдельно — это БЭМ-блок, если мыслима только внутри родителя — это БЭМ-элемент.

    В действительно сомнительных случаях делайте выбор в пользу БЭМ-блока.

    Не забывайте о миксовании (возможности иметь на одном теге и класс уровня БЭМ-элемента какого-то родительского блока, и свой класс уровня БЭМ-блока).

    На всех проектах (кроме совсем уж крошечных или имеющих гарантировано нулевую возможность модификации) есть фрагменты дизайна, которые мудро всегда делать БЭМ-блоками по причине высокой вероятности повторения.

    Некоторые фрагменты дизайна — всегда БЭМ-блоки

    • Кнопка (любые кнопки)
    • Блоки внутри форм (блок для текстового поля, блок для радиокнопки и т.п.)
    • Пагинация
    • Табы
    • Лейблы (метки)
    • Социальные ссылки
    • «Лайк» со счётчиком
    <button type="button" class="btn">Кнопка</button>  
    

    Модификатор — дополнительный класс для смены оформления или поведения

    • Название класса формируется из названия блока/элемента с добавлением -- и названия модификатора.
    • Название должно быть простым и коротким.
    • Название класса может отвечать на вопросы «Что это?», «Что меняется?», «Чем отличается от прочих?»
    • Избегайте сокращений, кроме наиболее частых.
    <!-- .product--size-large — БЭМ-модификатор -->
    <div class="product  product--size-large">
      ...
    </div>
    

    Модификатор нельзя использовать самостоятельно

    Класс модификатор никогда не должен использоваться самостоятельно, но всегда только с тем классом, который он модифицирует.

    <!-- 😊 Хорошо: модификатор сопутствует модифицируемому классу -->
    <div class="product product--size-large">
      ...
    </div>
    
    <!-- 💩 Плохо: модификатор без класса, который он модифицирует -->
    <div class="product--sale">
      ...
    </div>
    

    Миксование — комбинирование на одном теге классов БЭМ-блока и БЭМ-элемента

    Комбинация возможна в любом сочетании: БЭМ-блок + БЭМ-элемент, БЭМ-блок + БЭМ-блок, БЭМ-элемент + БЭМ-элемент. Этот подход позволяет:

    • Добавить некоторые стилевые свойства, необходимые только в месте добавления (использование модификатора нерационально). Пример: для .btn внутри .page-header необходим внешний левый отступ в 37 пикс. Можно дописать для тега с .btn дополнительный класс .page-header__btn и дать отступ с помощью этого селектора. Это нормальная практика, её можно спокойно использовать.
    • Объединить стилизацию 2-х и более блоков. Пример: для .article и для .page-footer__section шрифтовые свойства одинаковы. Можно вынести определение шрифтовых свойств в новый блок .text и дописать этот класс на .article и .page-footer__section. Этот подход излишне связывет части страницы (напоминает OOCSS и класс-хелпер), не делайте так.
    • Обойтись без тега-обёртки с добавляемым селектором. Пример: страница каталога, 7+ товаров в потоке, каждый товар — .product, но каждому элементу потока нужны стилевые свойства ячеек модульной сетки (по которой выстроен потоковый вывод). Можно добавить для .product класс ячейки модульной сетки, что бы не делать обертку с этим классом. Это чревато конфликтом отступов/размеров, не смешивайте на одном теге классы обёртки и содержимого.

    Миксование несколько ухудшает восприятие кода и увеличивает вероятность ошибки смешения стилей, при которой вы пишите стилевое правило в контексте не того селектора, где оно реально нужно.

    <div class="page-header">
      <div class="page-header__nav-wrap">...</div>
      <a class="btn  page-header__btn" href="/buy">...</a>
    </div>
    
    <div class="slider">
      <div class="promo  slider__inner">
        <div class="promo__item  slider__item">
          ...
        </div>
      </div>
    </div>
    

    БЭМ-дерево плоское, в отличие от DOM

    В классах БЭМ-элементов нельзя прописывать иерархию (два и более сегмента __ недопустимы).

    <div class="promo">
      <div class="promo__description">
        <!-- 😊 Хорошо: вложенный элемент не имеет особенностей -->
        <a class="promo__link" href="">...</a>
      </div>
    </div>
    
    <div class="promo">
      <div class="promo__description">
        <!-- 💩 Плохо: попытка прописать иерархию -->
        <a class="promo__description__link" href="">...</a>
      </div>
    </div>