CSS
Данное раздел написан на основе следующих руководств:
- Google HTML/CSS Style Guide
- Airbnb CSS/Sass Styleguide
- Hacks for dealing
with specificity
- Руководство по написанию кода
Общие правила
- Кодировка файлов - UTF8
- Названия селекторов - только на английском языке
- Комментарии только на английском языке, любой другой - только в сопроводительной документации
-
Валидный CSS - используем сервис W3C CSS
validator (правильная IDE + CI конечно же лучше)
-
Старайтесь не использовать
@import
без необходимости, он медленный, куда как
предпочтительней использование CSS препроцессоров, или даже несколько <link>
- это всё же будет лучше чем @import
сам по себе
-
Никогда не используйте
#ID
в CSS, у них нет никаких преимуществ перед классами,
но при этом - высокая специфичность и отсутствие возможности повторного использования
-
Используйте минимально необходимую вложенность селектора, если работает
.nav-head
,
то не нужно прописывать .nav .nav-head
, результат тот же
-
Не квалифицируйте селектор без необходимости, не стоит писать
ul.nav
, если можно
обойтись лишь .nav
-
Всегда используйте селекторы классов - низкая (одинаковая) специфичность, высокая портативность
и возможность повторного использования
-
Имя класса (или ID) должен быть как можно меньше, но при этом оно должно быть всё так же
информативным
-
При выборе имени класса (или ID) следует помнить, что имя должно однозначно указывать на
назначение либо содержание элементов, но никак не визуальные атрибуты
/* nice */
.warning-text {
color: #f00;
}
/* too sad */
.red {
color: #f00;
}
Исходя из данных правил, может сложиться впечатление, что нельзя использовать ID в проекте,
но это не так, правило касается только CSS, т.е. если вы хотите применить стиль к элементу с ID,
то вам следует присвоить ему класс и применять стили уже непосредственно к нему
Для проверки форматирования используйте stylelint
со стандартным конфигом
Подробная инструкция по подключению данной утилиты к продуктам компании JetBrains можно найти в
официальном руководстве
Но чтобы долго не томить, вот вам краткое содержание последних двадцати серий:
- Отступы - два пробела
- Теги, классы, свойства - всё в нижнем регистре (lowercase)
- В качестве разделителя в имени классов следует использовать
-
(kebab-case)
- При перечислении селекторов каждый из них должен быть записан с новой строки
- Между селектором и открывающей фигурной скобочкой должен быть пробел
- При описании свойств добавляйте пробел только после двоеточия
- Каждое новое свойство следует записывать с новой строки
- В конце строчки со свойствами следует писать точку с запятой
-
При указании цвета, не используйте именованные цвета: пишите
color: #ff0;
вместо color:red;
-
Для отключения границ, следует использовать
border: 0;
вместо border: none;
-
Избегайте сокращенных объявлений, используйте
margin-bottom: 10px;
вместо margin: 0 0 10px;
- Закрывающаяся фигурная скобочка должна быть на новой строке
- Удаляем пробелы в конце строк
- Между блоками правил должна быть пустая строка
- Соблюдаем единый порядок следования свойств внутри правил:
- позиционирование
- блочная модель и размеры
- свойства текста
- отображение
- остальные свойства
- анимация
Если у вас проект будет посложнее чем сайт-визитка вашего питомца, то рекомендуется
придерживаться БЭМ методологии, но помните - это отнюдь не панацея, и тянет за собой
избыточность в HTML, ломает мантичность классов и обрастает тулзами, которые не всем одинаково
полезны. Если вы засомневались, и не можете решиться, то переложите вопрос «БЭМ или неБЭМ»
на вашего техлида, пусть у него голова болит.
Примеры
Пример форматирования CSS
/* looks good */
.avatar {
border-radius: 50%;
border-collapse: separate;
border: 2px solid white;
}
.one,
.selector,
.per-line {
border: 0;
}
/* so sad */
.avatar{
border-radius:50%;border-collapse:separate;
border:2px solid white; }
.no, .nope, .not_good {
border:none
}
#lol-no {
/* ... */
}
Комплексный пример порядка свойств
.selector {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
display: block;
float: right;
width: 100px;
height: 100px;
font: 13px/1.5 "Helvetica Neue", sans-serif;
color: #333;
text-align: center;
background-color: #f5f5f5;
border: 1px solid #e5e5e5;
border-radius: 3px;
opacity: 1;
transition: all 0.3s;
}
jQuery
Модульность
Весь код должен быть инкапсулирован внутри модуля (все функции и переменные).
Один модуль === один файл, откройте для примера файл style.guide.js
/**
* @param jQuery $ - be sure `$` is `jQuery`
* @param window w - be sure `w` is `window`
*/
(function($, w){
// your code here
let foo = "bar";
// ...
})(jQuery, window);
Именование переменных
Переменные содержащие jQuery объект должны начинаться со знака $
var $header = $("#header");
var $articles = $("article");
Используйте правильно единственное (singular) и множественное (plural) числа
var $sidebar = $("#sidebar");
var $articles = $(".article");
Правильно указывайте множественное число (plural) для слов исключений:
var $child = $("#child");
var $children = $(".child");
В данных примерах используется var
, если вам нет нужды поддерживать старые
браузеры, то смело используйте let
и const
в соответствии
со стандартами от Airbnb и вашими задачами.
Так же следует быть осторожным, когда используете функции-стрелки, не забывайте про контекст.
Именование функций
Имена функций-оберток над селекторами должны начинаться со знака $
function $articles() {
return $("body").find(".content > article");
};
Имена функций должны быть короткими и содержательными, не нужно без нужды баламутить воду.
function changeColorToGreen() {}
function loadJSON() {}
function showErrorDialog() {}
function makeGreen() {} // color? background? WAT?
function loadData() {} // data? rly?
function error() {} // error in your DNA
Callback функции
Для упрощения чтения кода следует быть осторожным при использовании анонимных функций,
т.к. это сводит на нет повторное их использование, и может затруднять чтение.
// on click handler
$("body")
.on(
"click.module",
"p",
changeColorToGreen
);
// callback function
function changeColorToGreen() {
$(this).css("color", "green");
}
// on click handler + callback function
$("body")
.on(
"click.module",
"p",
function() {
$(this).css("color", "green");
}
);
Конечно данный пример ещё можно отнести к читабельным вариантам, но вот повторное использование
функции уже стало невозможным.
Более комплексный пример:
// on click handler
$("header").on("click.module", loadJSON);
// callback with AJAX call
function loadJSON(event) {
$.ajax("ajax/example.json", {context: event.currentTarget})
.done(changeColorToGreen)
.fail(changeColorToRed)
;
}
// callback for success
function changeColorToGreen() {
$(this).css("color", "green");
}
// callback for error
function changeColorToRed() {
$(this).css("color", "red");
}
Пространство имён
Все обработчики событий внутри модуля следует «вешать» внутри единого пространства имён,
таким образом можно избежать конфликтов при одновременной работе сразу нескольких модулей
// file `module.js`
(function($, w){
$("header").on("click.module", function() {
// ...
});
$("header").trigger("click.module");
})(jQuery, window);
Кэширование
Если вы пропустили этот момент в моей книге, то повторю ещё разок ПОИСК ЭЛЕМЕНТОВ НЕ КЭШИРУЕТСЯ,
следовательно, вам надо самостоятельно позаботиться о кэшировании ваших выборок:
let $sidebar = $("#sidebar");
// ...
$sidebar.css("color", "#ff0");
// ...
$sidebar.hide();
$("#sidebar");
// ...
$("#sidebar").css("color", "#ff0");
// ...
$("#sidebar").hide();
Как вариант можете использовать следующую функцию, возможно она вам пригодится:
const $function = function(selector) {
let elements;
return function() {
if (!elements) {
elements = $(selector);
}
return elements;
}
};
С её помощью получается красивый КЭШИРУЕМЫЙ вариант для выборок элементов, которые не изменяются
let $headers = $function("h2");
let $articles = $function("article");
$articles().on("click.module", e => false)
Оптимизация
Стоит так же напомнить простое правило по оптимизации поиска элементов - указывайте контекст поиска
// fastest
$(DOMElement).find("p")
// fast
$("p", DOMElement)
// fast too
$("p", $article[0])
// slowest
$("article").find("p")
// slow too
$("p", "article")
Если данное правило вам не подходит, то посмотрите в сторону использования каскадных селекторов или
селекторов
вида parent > child
// not fast, not bad
$("article > p")
// slower, not bad
$("article p")
// slower
$article.find("p")