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

Стандарты для разработки гибкого, надежного и поддерживаемого кода на Pug(Jade) и Stylus.

Оглавление

HTML

CSS

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

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

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

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

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

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

Pug (Jade)

Синтаксис

<!DOCTYPE html>
html(lang="en-us")
  head
    meta(charset="UTF-8")
    meta(http-equiv="X-UA-Compatible" content="IE=Edge")
    meta(name="viewport" content="width=device-width,initial-scale=1")
    title Title page
    link(rel="stylesheet", href="https://gitanon.github.io/css/main.css")
  body.page
    include blocks/header/header.pug
    ...
    include blocks/text/text.pug
    script(src="https://gitanon.github.io/js/main.js")

HTML5 doctype

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

<!DOCTYPE html>
html
  head

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

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

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

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

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

html(lang="en-us")

Режим совместимости 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")

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

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

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

<!-- Внешний CSS -->
link(rel="stylesheet", href="https://gitanon.github.io/css/main.css")

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

<!-- JavaScript -->
script(src="https://gitanon.github.io/js/main.js")

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

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

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

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

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

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

input(class="form-control" type="text")

img(src="https://gitanon.github.io/..." alt="...")

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

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

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

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

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

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

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

input(type="text" disabled)

input(type="checkbox" value="1" checked)

select
  option(value="1" selected) 1

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

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

<!-- Неплохо -->
span(class="avatar")
  img(src="https://gitanon.github.io/...")

<!-- Лучше -->
img(class="avatar" src="https://gitanon.github.io/...")

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

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

Stylus

Подход к разработке стилей

.element
  ...

.element-avatar
  ...

.element-selected
  ...

@media (min-width: tablet) 
  .element
    ...

  .element-avatar
    ...

  .element-selected
    ...

@media (min-width: screen)
  .element
    ...

  .element-avatar
    ...

  .element-selected
    ...

@media (min-width: screen_large)
  .element
    ...

  .element-avatar
    ...

  .element-selected
    ...

Синтаксис

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

/* Плохой Stylus */
.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
}

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

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

Объявления свойств должны быть по алфавиту

.declaration-order 
  background-color #f5f5f5
  border 1px solid #e5e5e5
  border-radius 3px
  bottom 0
  color #333
  display block
  font normal 13px "Helvetica Neue", sans-serif
  height 100px
  left 0
  float right
  line-height 1.5
  opacity 1
  position absolute
  right 0
  text-align center
  top 0
  width 100px
  z-index 100

Место для media query

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

.element
  ...

.element-avatar
  ...

.element-selected
  ...

@media (min-width: tablet) 
  .element
    ...

  .element-avatar
    ...

  .element-selected
    ...

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

Используется autoprefixer, необходимости в прописывании префиксов нет.

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

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

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

/* Одиночные объявления */
.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

Вложенность

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

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

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

Комментарии

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

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

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

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

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

/* Плохой пример */
.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
  ...