Стандарты написания гибкого, надежного и жизнеспособного HTML c CSS
Вообще, эта статья является неким руководством по написанию грамотного HTML и CSS. Но явно не полноценным руководством сводом правил или БЭМ, который, кстати, является очень спорным моментом в мире фронт-энда. Но об этом потом.
То, что вы прочитаете, скорее является сводом правил хорошего тона при вёрстке, которые сведут на минимум проблемы с пониманием и рендерингом вашей работы.
HTML
Синтаксис
Используйте двойные пробелы — это единственный способ, который будет гарантировать то, что ваш код покажется и отрендерится одинаковым образом в любой среде разработки.
Вложенные элементы должны иметь только одинарный отступ, то есть двойным пробелом.
На атрибутах всегда используйте двойные кавычки, а не одинарные.
Не включайте закрывающий слеш в самозкрывающиеся элементы — HTML5 спецификация указывает на то, что они вообще опциональны, но мы то знаем.
Ни в коем случае не пропускайте закрывающие теги (такие как </li>
или </body>
).
<!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="ru">
<!-- ... -->
</html>
Режим совместимости IE
Internet Explorer поддерживает тег использования совместимости <meta>
, чтобы указывать то, под какую версию IE должна быть отрендерена страница. Да, пока что обстоятельства этого требуют и самый подходящий способ — это указать IE использовать последний поддерживаемый мод с edge mode.
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
Кодировки
Легко и быстро делайте правильный рендеринг вашего контента, указывая точную кодировку вашим страницам. Так вы можете избежать использования мнемоников в HTML ( Это и т.п. В общем, дальше вы поняли), указывая их точную кодировку документу. В основном, самая ходовая кодировка это UTF-8
.
<head>
<meta charset="UTF-8">
</head>
Указание пути к CSS и JavaScript
По спецификации HTML5, нет нужды в конкретном указании type при вставке CSS и JavaScript файлов, добавля как text/css
так и text/javascript
как страндартные указатели на типы подключаемых файлов. Теперь это лишнее.
Просто сделайте так:
<!-- Внешний CSS -->
<link rel="stylesheet" href="code-guide.css">
<!-- Внутренний CSS -->
<style>
/* ... */
</style>
<!-- JavaScript -->
<script src="code-guide.js"></script>
Практичность прежде всего
Старайтесь поддерживать HTML стандарты и семантику, но не ценой практичности. Используйте как можно меньше разметки с наименее возможным количеством запутанных моментов и спорных вложений.
Порядок атрибутов
HTML атрибуты должны располагаться именно в таком порядке для облегчения чтения кода:
class
id, name
data-*
src, for, type, href, value
title, alt
role, aria-*
Классы сделаны для удобного переиспользования компонентов, так что они идут первыми. ID
это уже более специфичные вещи и относится к ним нужно довольно бережно, так что они идут вторыми.
<a class="..." id="..." data-toggle="modal" href="#">
Example link
</a>
<input class="form-control" type="text">
<img src="..." alt="...">
Булиные атрибуты (Логические атрибуты)
p.s. тут используется слово булиные для простоты упоминания в тексте, который и так не очень простой. В общем, как в простом сленге разработки.
Это атрибуты, которые нуждаются в необъявленном значении. Да, XHTML
требует, чтобы вы объявляли их значение, но в HTML5 нет такого требования.
Для дальнейшего чтения, примите во внимание следующую WhatWG секцию по булиным атрибутам.
Присутствие булиных атрибутов на элементе указывает на значение
true
, а отсутствие атрибута указывает на значениеfalse
.
Если вам необходимо присутствие атрибута, НО наличие его значения вам ненужно, то следуйте этому наставлению WhatWG:
Если атрибут есть, его значение должно быть либо пустой строкой, либо каноничным именем атрибута, без заглавного или замыкающего пробела.
<input type="text" disabled>
<input type="checkbox" value="1" checked>
<select>
<option value="1" selected>1</option>
</select>
Сокращение разметки
Где только возможно, избегайте излишних родительских элементов при написании HTML. Во многих случаях это приводит к повторениям и рефакторингу, но в итоге вы получаете меньше HTML. Вот хороший пример:
<!-- Отстой -->
<span class="avatar">
<img src="...">
</span>
<!-- Уже получше -->
<img class="avatar" src="...">
Разметка созданная в JavaScript
Создание разметки в JavaScript файле усложняет поиск контента, усложняет его редактирование и уменьшает скорость его рендеринга. Избегайте такого подхода всегда, когда это только возможно.
CSS
Синтаксис
Используйте двойные пробелы, это единственный способ гарантировать то, что ваш код везде одинаково отрендерится и будет легко прочитан.
Группируя селекторы, дайте каждому по строке.
Включайте один пробел перед открывающей скобкой блока, чтобы было понятнее.
Ставьте закрывающие скобки на новой строке.
Делайте один пробел после каждого :
Каждое объявление должно появляться на своей собственной строке для получения точного отчета об ошибках. В общем, чтобы видеть на какой строке был сбой.
Заканчивайте каждое объявление точкой с запятой. В последнем объявлении это опционально, но в таком случае ваш код будет более склонен выдать ошибку в самых странных моментах при рендеринге.
Свойства, разделенные запятой, должны включать в себя пробел после каждой запятой. Например как в случае с box-shadow
.
Не ставьте пробелы после запятых в значениях rgb()
, rgba()
, hsl()
, hsla()
, or rect()
. Это поможет различать разные значения цвета(запятая, без пробела) от разных значений свойств (запятая с пробелом).
Не добавляйте ноль к свойствам значений или цветовым параметрам, то есть .5
вместо 0.5
и -.5px
вместо -0.5px
.
Все хекс значения пишите в нижнем регистре, то есть #fff
. Буквы в нижнем регистре легче отличить, когда читаешь документ, так как у них больше уникальных очертаний.
Используйте сокращенные хекс значения, где это только возможно. Например, #fff
вместо #ffffff
.
Заключайте в скобки значения атрибутов в селекторах. Например, input[type=”text”]
. Хоть это и опционально, но это хорошая практика в плане логичности.
Избегайте указывания единиц измерения для нулевых значений. Например, margin: 0
, вместо margin: 0px
.
/* Плохой CSS */
.selector, .selector-secondary, .selector[type=text] {
padding:15px;
margin:0px 0px 15px;
background-color:rgba(0, 0, 0, 0.5);
box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF
}
/* Хороший CSS */
.selector,
.selector-secondary,
.selector[type="text"] {
padding: 15px;
margin-bottom: 15px;
background-color: rgba(0,0,0,.5);
box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
}
Порядок объявления
Следующие объявления, должны группироваться в таком порядке:
Позиционирование
Box model
Типография
Визуализация
Главное — позиционирование идет первым, так как оно может удалить элемент с потока документа и переопределить относительные стили для box-модели, которая идет следующей, так как указывает размещение и размеры элемента.
Всё остальное, что внутри компонента или не влияет на предыдущие две секции, идет последним:
.declaration-order {
/* Позиционирование */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
/* Box-model */
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>
элементов
Компилируйте свой CSS с препроцессором, таким как Sass, в один файл.
Сливайте вместе ваши CSS файлы с функционалом, предоставленным в Rails, Jekyll и других.
<!-- Используйте link -->
<link rel="stylesheet" href="core.css">
<!-- Избегайте @imports -->
<style>
@import url("more.css");
</style>
Размещение медиа запросов
Размещайте медиа запросы как можно ближе к своим релевантным наборам правил. Не связывайте их через разные таблицы стилей или под конец документа. Делая так, вы только усложните работу с ними в будущем, не говоря уже о том треше, с которым придется столкнуться тому, кто потом будет работать с вашим кодом. Вот обычная хорошая разметка с медиа-запросами:
.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; }
Условные сокращения
Ограничивайте себя в использовании условных сокращений, в тех примерах, где вам надо выставлять все доступные значения. По обыкновению, злоупотребляют сокращениями следующих свойств:
padding
margin
font
background
border
border-radius
Зачастую, нам просто не нужно выставлять все значения в условных сокращениях. Для примера, HTML заголовки выставляют только верхний и нижний margin, так что когда необходимо, переписывайте только два этих значения. Чрезмерное использование сокращений зачастую ведет к медленному рендеренгу кода, с ненужными перезаписями и непреднамеренными побочными эффектами.
/* Плохой пример */
.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 { … }
}
Операторы в Less и Sass
Для улучшения читабельности, заключайте математические операции в скобки с пробелом между значениями, переменными и операторами.
// Плохой пример
.element {
margin: 10px 0 @variable*2 10px;
}
// Хороший пример
.element {
margin: 10px 0 (@variable * 2) 10px;
}
Комментарии
Помните, что код пишется и поддерживается людьми. Убедитесь, что ваш код достаточно описателен, хорошо прокомментирован и доступен для понимания другими. Создавайте комменты в коде, передающие контекст и своё конкретное предназначение. А не просто повторяющие компонент или имя класса.
Убеждайтесь в том, что вы пишите полные предложения для больших комментариев и сжатые фразы для заглавных записей.
/* Плохой пример */
/* Modal header */
.modal-header {
...
}
/* Good example */
/* Wrapping element for .modal-title and .modal-close */
.modal-header {
...
}
Именование классов
Пишите классы в нижнем регистре и используйте тире, а не нижние подчеркивания или горбатый регистр. Тире служит как естественный пробел в связанных классах. (.btn
и .btn-danger
).
Избегайте чрезмерных или слишком коротких, спорных определений названий. .btn
очень полезно для кнопок, но .s
не означает ровным счетом ничего.
Классы должны быть как можно короче и более сжатыми, на сколько это возможно.
Используйте имена со смыслом, предпочитайте структурные или целесообразные имена, взамен презентативных.
Добавляйте классам префикс, основываясь на их ближайшем родителе или основном классе.
Используйте .js-*
классы для обозначения поведения, но держите эти классы подальше от вашего CSS.
Также, очень полезно применять эти правила при раздаче имен переменным в Sass и Less.
/* Плохой пример */
.t { ... }
.red { ... }
.header { ... }
/* Хороший пример */
.tweet { ... }
.important { ... }
.tweet-header { ... }
Селекторы
Обязательно обратите внимание на эту статью — Прокачиваем навыки работы с CSS селекторами
Используйте классы вместо обычных тегов элементов для оптимального рендеринга.
Избегайте исползования нескольких селекторов атрибутов, например [class^="…"]
, на часто встречающихся компонентах. Известно, что производительность браузера страдает из-за этого.
Сохраняйте селекторы краткими и ограничивайте количество элементов в каждом селекторе до трех.
Масштабируйте классы до ближайшего родителя, только тогда, когда нужно. Когда не используются префиксные классы.
/* Плохой пример */
span { ... }
.page-container #stream .stream-item .tweet .tweet-header .username { ... }
.avatar { ... }
/* Хороший пример */
.avatar { ... }
.tweet-header .username { ... }
.tweet .avatar { ... }
Организация кода
Организуйте секции кода по компонентам.
Создавайте последовательную иерархию комментирования.
Используйте последовательные пробелы при разделении секций кода, чтобы потом вам было легче читать большие документы.
Используя несколько CSS файлов, разделяйте их по компонентам, а не по страницам. Страницы могут быть перераспределены, а компоненты смещены.
/*
* Начало секции компонента
*/
.element { ... }
/*
* Начало секции компонента
*
* Иногда вам надо добавлять дополнительный контекст для целого компонента. Делайте это как описано ниже, при необходимости.
*/
.element { ... }
/* Связанный саб-компонент или модификатор стиля */
.element-heading { ... }
Предпочтения при редактировании
Выставите вашему редактору следующие настройки, чтобы избежать распространенные несоответствия в коде и странные различия:
Используйте двойной пробел.
Обрезайте болтающиеся(лишние) пробелы при сохранении.
Выставляйте кодировку на UTF-8
.
Добавляйте новые строки с конца.
Рассмотрите документирование и применение этих свойств в вашем проекте в .editorconfig
файле. Для примера, вот один для Bootstrap. Вот больше про EditorConfig.