Руководство по написанию кода от @mdo

Стандарты для разработки гибкого, надежного и поддерживаемого кода на HTML и CSS.

Оглавление

HTML

CSS

Золотое правило

Строго соблюдайте предложенные здесь или свои собственные соглашения. Если вы нашли ошибку, будь она большая или маленькая, сразу сообщите об этом. Если у вас есть что дополнить или вы хотите принять участие в разработке этих соглашений, пожалуйста, создайте issue на GitHub.

Каждая строка кода должна казаться написанной только одним человеком, вне зависимости от количества разработчиков.

HTML

Синтаксис

<!DOCTYPE html>
<html>
  <head>
    <title>Заголовок страницы</title>
  </head>
  <body>
    <img src="images/company-logo.png" alt="Company">
    <h1 class="hello-world">Привет, мир!</h1>
  </body>
</html>

HTML5 doctype

Укажите в начале каждой вашей HTML-страницы этот тип документа. Это заставит браузер работать в режиме соответствия стандартам, что обеспечит единообразное отображение ваших страниц в разных браузерах.

<!DOCTYPE html>
<html>
  <head>
  </head>
</html>

Атрибут языка

Из спецификации HTML5:

Для указания языка документа авторам рекомендуется прописывать атрибут языка в корневом элементе html. Это поможет инструментам синтеза речи определить какое произношение использовать, а инструментам перевода - какие правила, и так далее.

Подробнее познакомиться с атрибутом lang можно в спецификации.

Список кодов различных языков на Sitepoint.

<html lang="en-us">
  <!-- ... -->
</html>

Режим совместимости Internet Explorer

IE поддерживает использование специального <meta>-тега, который указывает в режиме совместимости с какой версией IE следует отрендерить страницу. Если обстоятельства не требуют какой-то специальной версии IE, то самым правильным будет заставить браузер использовать режим самой последней версии (edge mode).

Для получения дополнительной информации следует познакомиться со статьей на Stack Overflow.

<meta http-equiv="X-UA-Compatible" content="IE=Edge">

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

Явно объявив кодировку символов, вы быстро и легко обеспечите правильное отображение вашего контента. При этом, вы сможете избежать использования символьных сущностей в вашем HTML-коде, при условии, что их кодировка совпадает с кодировкой документа (как правило, UTF-8).

<head>
  <meta charset="UTF-8">
</head>

Подключение CSS и JavaScript

Согласно спецификации HTML5, при подключении CSS и JavaScript файлов не требуется указание атрибута type, так как text/css и text/javascript являются значениями по умолчанию.

Ссылки на спецификацию HTML5:

<!-- Внешний CSS -->
<link rel="stylesheet" href="code-guide.css">

<!-- CSS внутри документа -->
<style>
  /* ... */
</style>

<!-- JavaScript -->
<script src="code-guide.js"></script>

Практичность важнее чистоты

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

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

Для удобства чтения HTML-атрибуты должны быть указаны именно в этом порядке:

Классы создают для многократно используемых компонентов верстки, поэтому они идут первыми. Идентификаторы более специфичны и должны использоваться умеренно (например, для закладок на странице), поэтому они следуют вторыми.

<a class="..." id="..." data-modal="toggle" href="#">
  Какая-то ссылка
</a>

<input class="form-control" type="text">

<img src="..." alt="...">

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

Логические атрибуты одни из тех, которые не требуют объявленного значения. XHTML требует от вас задать значение, но в HTML5 нет такого требования.

За подробной информацией обратимся к разделу о логических атрибутах на WhatWG:

Наличие логического атрибута у элемента говорит об истинном его значении, а отсутствие атрибута — о ложном.

Если вы должны указать значение атрибута, но вам это не нужно, следуйте этой рекомендации от WhatWG:

Если атрибут присутствует, его значение должно быть либо пустой строкой или [...] каноническим именем атрибута без начальных или конечных пробелов.

Если коротко, то не указывайте значение логическому атрибуту.

<input type="text" disabled>

<input type="checkbox" value="1" checked>

<select>
  <option value="1" selected>1</option>
</select>

Сокращение разметки

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

<!-- Неплохо -->
<span class="avatar">
  <img src="...">
</span>

<!-- Лучше -->
<img class="avatar" src="...">

Разметка, генерируемая с помощью JavaScript

Создание разметки с помощью JavaScript делает ее менее производительной, сложной для поиска и редактирования. По возможности избегайте этого.

CSS

Синтаксис

Есть вопросы по перечисленным соглашениям? Ознакомьтесь с разделом о синтаксисе статьи о каскадных таблицах стилей на Википедии.

/* Плохой CSS */
.selector, .selector-secondary, .selector[type=text] {
  padding:15px;
  margin:0px 0px 15px;
  background-color:rgba(0, 0, 0, 0.5);
  box-shadow:0 1px 2px #CCC,inset 0 1px 0 #FFFFFF
}

/* Хороший CSS */
.selector,
.selector-secondary,
.selector[type="text"] {
  padding: 15px;
  margin: 0 0 15px;
  background-color: rgba(0,0,0,.5);
  box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
}

Порядок объявления

Объявления логически связанных свойств должны быть сгруппированы в следующем порядке:

  1. Позиционирование
  2. Блочная модель
  3. Типографика
  4. Отображение

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

Все остальные объявления, выполняющиеся внутри компонента или не оказывающие влияния на предыдущие два раздела, следуют в последнюю очередь.

Для ознакомления с полным списком свойств и их порядком обратитесь к Recess.

.declaration-order {
  /* Позиционирование */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;

  /* Блочная модель */
  display: block;
  float: right;
  width: 100px;
  height: 100px;

  /* Типографика */
  font: normal 13px "Helvetica Neue", sans-serif;
  line-height: 1.5;
  color: #333;
  text-align: center;

  /* Отображение */
  background-color: #f5f5f5;
  border: 1px solid #e5e5e5;
  border-radius: 3px;

  /* Прочее */
  opacity: 1;
}

Не используйте @import

По сравнению с тегом <link> правило @import медленнее, создает дополнительные запросы и может вызвать иные непредвиденные проблемы. Избегайте это правило и используйте вместо него один из альтернативных подходов:

Для получения дополнительной информации следует познакомиться со статьей Стива Соудерса.

<!-- Используйте тег link -->
<link rel="stylesheet" href="core.css">

<!-- Избегайте @imports -->
<style>
  @import url("more.css");
</style>

Место для media query

Помещайте media queries настолько близко к соответствующим наборам правил, насколько это возможно. Не объединяйте их в отдельную таблицу стилей. Не помещайте их в конце файла. В противном случае это приведет к тому, что media queries будут не замечены в будущем. Вот типичная структура:

.element { ... }
.element-avatar { ... }
.element-selected { ... }

@media (min-width: 480px) {
  .element { ...}
  .element-avatar { ... }
  .element-selected { ... }
}

Свойства с префиксами

Когда вы используете свойства с префиксами вендоров, оставляйте отступы для каждого свойства так, чтобы значения объявлений выстраивались в вертикальную линию. Это упрощает многострочное редактирование.

В Textmate используйте Text → Edit Each Line in Selection (⌃⌘A). В Sublime Text 2, используйте Selection → Add Previous Line (⌃⇧↑) и Selection → Add Next Line (⌃⇧↓).

/* Свойства с префиксами */
.selector {
  -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.15);
          box-shadow: 0 1px 2px rgba(0,0,0,.15);
}

Правила с одиночными объявлениями

В случаях, когда набор правил включает в себя только одно объявление, рекомендуется удалить переносы строк для удобства чтения и редактирования. Любой набор правил с несколькими объявлениями должен быть разделен на отдельные строки.

Ключевым фактором здесь является обнаружение ошибок — например, валидатор CSS сообщает вам, что в строке 183 есть синтаксическая ошибка. С одиночным объявлением не возникнет сложности с исправлением. В случае с несколькими объявлениями, разделенными на строки, так же проблем не возникнет. Но если несколько объявлений будут записаны в одну строку, то вам будет сложнее понять какое именно объявление вызвало синтаксическую ошибку.

/* Одиночные объявления в одну строчку */
.span1 { width: 60px; }
.span2 { width: 140px; }
.span3 { width: 220px; }

/* Несколько объявлений, по одному на каждую строчку */
.sprite {
  display: inline-block;
  width: 16px;
  height: 15px;
  background-image: url(../img/sprite.png);
}
.icon           { background-position: 0 0; }
.icon-home      { background-position: 0 -20px; }
.icon-account   { background-position: 0 -40px; }

Сокращенная запись

Старайтесь ограничить использование сокращенных объявлений в тех случаях, когда необходимо явно задать все доступные значения. Наиболее часто злоупотребляют сокращением следующих свойств:

Часто нам не нужно устанавливать все значения сокращенной записи свойства. Например, HTML заголовки устанавливают только отступы сверху и снизу, таким образом, в случае необходимости нужно переопределить только эти два значения. Чрезмерное использование сокращенной записи свойств часто приводит к грязному коду с ненужными переопределения и непреднамеренными побочными эффектами.

На сайте Mozilla Developer Network есть отличная статья о сокращенной записи свойств для тех кто не знаком с такой формой записи.

/* Плохой пример */
.element {
  margin: 0 0 10px;
  background: red;
  background: url("image.jpg");
  border-radius: 3px 3px 0 0;
}

/* Хороший пример */
.element {
  margin-bottom: 10px;
  background-color: red;
  background-image: url("image.jpg");
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
}

Вложенность в Less и Sass

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

// Без вложенности
.table > thead > tr > th {  }
.table > thead > tr > td {  }

// С вложенностью
.table > thead > tr {
  > th {  }
  > td {  }
}

Комментарии

Код написан и поддерживается людьми. Убедитесь, что ваш код является описательным, хорошо прокомментирован и доступным (понятным) для других. Хорошие комментарии к коду передают контекст и цель кода, а не просто повторяют название класса или компонента.

Обязательно пишите законченные предложения для больших комментариев и короткие фразы для общих замечаний.

/* Плохой пример */
/* Modal header */
.modal-header {
  ...
}

/* Хороший пример */
/* Обертывающий элемент для .modal-title и .modal-close */
.modal-header {
  ...
}

Имена классов

Также будет полезно использовать многие из приведенных рекомендаций для имен переменных в препроцессорах Sass и Less.

/* Плохой пример */
.t { ... }
.red { ... }
.header { ... }

/* Хороший пример */
.tweet { ... }
.important { ... }
.tweet-header { ... }

Селекторы

Дополнительно к прочтению:

/* Плохой пример */
span { ... }
.page-container #stream .stream-item .tweet .tweet-header .username { ... }
.avatar { ... }

/* Хороший пример */
.avatar { ... }
.tweet-header .username { ... }
.tweet .avatar { ... }

Организация кода

/*
 * Заголовок раздела для компонента
 */

.element { ... }


/*
 * Заголовок раздела для компонента
 *
 * Иногда возникает необходимость включения дополнительного контекста для всего компонента. Сделайте это в этом месте, если это достаточно важно.
 */

.element { ... }

/* Контекстный под-компонент или модификатор */
.element-heading { ... }

Настройки редактора кода

Установите в вашем редакторе следующие настройки, которые помогут избежать распространенных несогласованностей в коде и грязи:

Подумайте над документированием и применением этих настроек в файле .editorconfig вашего проекта. Для примера, ознакомьтесь с файлом настроек для Bootstrap. Узнайте больше об EditorConfig.