HTML
Семантика
В HTML5 было внедрено большое количество семантических элементов для точного описания содержимого веб-страницы. Постарайтесь извлечь максимум пользы из богатого синтаксиса HTML5.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<!-- плохой стиль -->
<div id="main">
<div class="article">
<div class="header">
<h1>Blog post</h1>
<p>Published: <span>21st Feb, 2015</span></p>
</div>
<p>…</p>
</div>
</div>
<!-- хороший стиль -->
<main>
<article>
<header>
<h1>Blog post</h1>
<p>Published: <time datetime="2015-02-21">21st Feb, 2015</time></p>
</header>
<p>…</p>
</article>
</main>
|
Постарайтесь понять назначение используемых вами элементов. Лучше не использовать элемент вообще, чем использовать его неправильно.
|
1
2
3
4
5
6
7
8
9
10
11
|
<!-- плохой стиль -->
<h1>
<figure>
<img alt=Companysrc=logo.png>
</figure>
</h1>
<!-- хороший стиль -->
<h1>
<img alt=Companysrc=logo.png>
</h1>
|
Краткость
Старайтесь писать меньше кода — используйте новые семантические элементы. Забудьте ваши старые XHTML привычки.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
<!-- плохой стиль -->
<!doctype html>
<html lang=en>
<head>
<meta http-equiv=Content-Typecontent="text/html; charset=utf-8" />
<title>Contact</title>
<link rel=stylesheethref=style.csstype=text/css />
</head>
<body>
<h1>Contact me</h1>
<label>
Email address:
<input type=emailplaceholder=you@email.comrequired=required />
</label>
<script src=main.js type=text/javascript></script>
</body>
</html>
<!-- хороший стиль-->
<!doctype html>
<html lang=en>
<meta charset=utf-8>
<title>Contact</title>
<link rel=stylesheethref=style.css>
<h1>Contact me</h1>
<label>
Email address:
<input type=emailplaceholder=you@email.comrequired>
</label>
<script src=main.js></script>
</html>
|
Общедоступность
Не стоит заниматься этим пунктом в последнюю очередь. Совсем не обязательно быть экспертом по WCAG (Web Content Accessibility Guidelines — Руководство по созданию доступного контента), чтобы улучшить свой сайт, можно начать с малого:
- Научиться правильно и по назначению использовать свойство alt.
- Для ссылок и кнопок использовать соответствующие семантические элементы HTML5 (а не зверства вроде
<div class=button>). - Для передачи информации использовать не только цвет.
- Не стоит явно подписывать элементы веб-форм.
|
1
2
3
4
5
|
<!-- плохой стиль-->
<h1><img alt="Logo"src="logo.png"></h1>
<!-- хороший стиль -->
<h1><img alt="My Company, Inc."src="logo.png"></h1>
|
Язык
Хоть определение языка и кодировки не является обязательным, рекомендуется определять их и на уровне HTML-документа, даже если они передаются в HTTP-заголовках. Предпочитайте UTF-8 любым другим кодировкам.
|
1
2
3
4
5
6
7
8
9
10
|
<!-- плохой стиль -->
<!doctype html>
<title>Hello, world.</title>
<!-- хороший стиль-->
<!doctype html>
<html lang=en>
<meta charset=utf-8>
<title>Hello, world.</title>
</html>
|
Производительность
Не стоит прерывать загрузку страницы для выполнения скриптов без веской на то причины. Если ваша таблица стилей имеет большой размер, стоит выделить те стили, которые нужно загружать вначале, а остальные — поместить в отдельный файл таблицы стилей. Два HTTP запроса выполняются существенно дольше, чем один, но при этом страница будет частично загружена, а это хорошо с точки зрения восприятия пользователя.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- плохой стиль -->
<!doctype html>
<meta charset=utf-8>
<script src=analytics.js></script>
<title>Hello, world.</title>
<p>...</p>
<!-- хороший стиль -->
<!doctype html>
<meta charset=utf-8>
<title>Hello, world.</title>
<p>...</p>
<script src=analytics.js></script>
|
CSS
Точки с запятыми
Несмотря на то, что в CSS точка с запятой является разделительным символом, лучше используйте его как завершающий символ.
|
1
2
3
4
5
6
7
8
9
|
/* плохой стиль */
div {
color:red
}
/* хороший стиль */
div {
color:red;
}
|
Боксовая модель
Такая модель, в идеале, должна быть одинаковой для всего документа. Глобальное объявление { box-sizing: border-box; } приемлемо, но для конкретных элементов страницы не стоит изменять их боксовую систему.
|
1
2
3
4
5
6
7
8
9
10
11
|
/* плохой стиль */
div {
width:100%;
padding:10px;
box-sizing:border-box;
}
/* хороший стиль */
div {
padding:10px;
}
|
Поведение элементов
Изменяйте стандартное поведение элемента только при необходимости. Например, не стоит изменять способ отображения изображения чтобы убрать отступы под ним.
|
1
2
3
4
5
6
7
8
9
|
/* плохой стиль */
img {
display:block;
}
/* хороший стиль */
img {
vertical-align:middle;
}
|
Кроме того, не выводите элемент за пределы страницы.
|
1
2
3
4
5
6
7
8
9
10
11
12
|
/* плохой стиль */
div {
width:100px;
position:absolute;
right:0;
}
/* хороший стиль */
div {
width:100px;
margin-left:auto;
}
|
Позиционирование
В CSS существует множество способов позиционирования элементов, но постарайтесь ограничиться использованием списка свойств с такими значениями (в порядке приоритета):
|
1
2
3
4
5
6
|
display:block;
display:flex;
position:relative;
position:sticky;
position:absolute;
position:fixed;
|
Селекторы
Старайтесь уменьшить до минимума количество селекторов, жестко привязанных к DOM. В случае, если ваш селектор применяется к более чем трем псевдоклассам, дочерним или соседним элементам, лучше добавить для этого элемента отдельный CSS класс.
|
1
2
3
4
5
|
/* плохой стиль */
div:first-of-type:last-child >p~*
/* хороший стиль */
div:first-of-type.info
|
Без необходимости не переопределяйте селекторы.
|
1
2
3
4
5
6
7
8
9
|
/* плохой стиль */
img[src$=svg], ul > li:first-child {
opacity:0;
}
/* хороший стиль */
[src$=svg], ul > :first-child {
opacity:0;
}
|
Спецификация элементов
Не нужно делать селекторы сложными для переопределения. Для этого уменьшите частоту использования спецификатора id и избегайте использования правила!important.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/* плохой стиль */
.bar{
color:green!important;
}
.foo{
color:red;
}
/* хороший стиль */
.foo.bar{
color:green;
}
.foo{
color:red;
}
|
Переопределение
Переопределение стилей усложняет селекторы и отладку верстки. Избегайте его по возможности.
|
1
2
3
4
5
6
7
8
9
10
11
12
|
/* плохой стиль */
li {
visibility:hidden;
}
li:first-child {
visibility:visible;
}
/* хороший стиль */
li + li {
visibility:hidden;
}
|
Наследование
Не дублируйте объявления стилей, которые могут быть пронаследованы.
|
1
2
3
4
5
6
7
8
9
|
/* плохой стиль */
div h1, div p {
text-shadow:01px0#fff;
}
/* хороший стиль */
div {
text-shadow:01px0#fff;
}
|
Компактность
Старайтесь писать компактный код — используйте сокращенную форму записи.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/* плохой стиль */
div {
transition:all1s;
top:50%;
margin-top:-10px;
padding-top:5px;
padding-right:10px;
padding-bottom:20px;
padding-left:10px;
}
/* хороший стиль */
div {
transition:1s;
top:calc(50%-10px);
padding:5px10px20px;
}
|
Язык
Для ясности предпочитайте осмысленные английские названия.
|
1
2
3
4
5
6
7
8
9
|
/* плохой стиль */
:nth-child(2n + 1) {
transform:rotate(360deg);
}
/* хороший стиль */
:nth-child(odd) {
transform:rotate(1turn);
}
|
Префиксы
Удаляйте устаревшие префиксы без зазрения совести. Если же вам необходимо их использовать, то вставляйте их перед именем стандартного свойства.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/* плохой стиль */
div {
transform:scale(2);
-webkit-transform:scale(2);
-moz-transform:scale(2);
-ms-transform:scale(2);
transition:1s;
-webkit-transition:1s;
-moz-transition:1s;
-ms-transition:1s;
}
/* хороший стиль */
div {
-webkit-transform:scale(2);
transform:scale(2);
transition:1s;
}
|
Анимация
Предпочитайте переходы анимациям. Анимацию стоит применять только для свойств элемента opacity и transform.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/* плохой стиль */
div:hover {
animation:move1sforwards;
}
@keyframes move {
100% {
margin-left:100px;
}
}
/* хороший стиль */
div:hover {
transition:1s;
transform:translateX(100px);
}
|
Единицы измерения
Где возможно, используйте безразмерные величины. Если используете относительные единицы измерения, то используйте rem. Для значений, связанных со временем, используйте секунды.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/* плохой стиль */
div {
margin:0px;
font-size:.9em;
line-height:22px;
transition:500ms;
}
/* хороший стиль */
div {
margin:0;
font-size:.9rem;
line-height:1.5;
transition:.5s;
}
|
Цвета
Если вам необходима прозрачность, используйте rgba. В любом другом случае — используйте hex формат.
|
1
2
3
4
5
6
7
8
9
|
/* плохой стиль */
div {
color:hsl(103,54%,43%);
}
/* плохой стиль */
div {
color:#5a3;
}
|
Отрисовка
Не загружайте ресурс, создать который можно средствами CSS.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/* плохой стиль */
div::before {
content:url(white-circle.svg);
}
/* хороший стиль */
div::before {
content:"";
display:block;
width:20px;
height:20px;
border-radius:50%;
background:#fff;
}
|
Обходные приемы
Не используйте их.
|
1
2
3
4
5
6
7
8
9
10
11
|
/* плохой стиль */
div {
//position:relative;
transform:translateZ(0);
}
/* хороший стиль */
div {
/* position: relative; */
will-change:transform;
}
|
JavaScript
Производительность
Предпочитайте правильный, выразительный, читабельный код производительному. В основном не JavaScript будет узким местом производительности вашей системы. Оптимизировать стоит такие моменты как сжатие изображений, перепостроение дерева DOM и доступ из сети. Если и выбирать совет из этого документа, то выбирайте этот.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// плохой стиль (хотя намного быстрее по скорости)
constarr=[1,2,3,4];
constlen=arr.length;
vari=-1;
varresult=[];
while(++i<len){
varn=arr[i];
if(n%2>0)continue;
result.push(n*n);
}
// хороший стиль
constarr=[1,2,3,4];
constisEven=n=>n%2==0;
constsquare=n=>n*n;
constresult=arr.filter(isEven).map(square);
|
Не храните состояние
Старайтесь поддерживать чистоту ваших функций. В идеале, у них не должно быть побочных эффектов, кроме того, они не должны использовать переданные извне данные и возвращать новые объекты вместо изменения существующих.
|
1
2
3
4
5
6
7
|
// плохой стиль
constmerge=(target,...sources)=>Object.assign(target,...sources);
merge({foo:"foo"},{bar:"bar"});// => { foo: "foo", bar: "bar" }
// хороший стиль
constmerge=(...sources)=>Object.assign({},...sources);
merge({foo:"foo"},{bar:"bar"});// => { foo: "foo", bar: "bar" }
|
Встроенные конструкции языка
Старайтесь как можно больше использовать встроенные методы.
|
1
2
3
4
5
6
7
|
// плохой стиль
consttoArray=obj=>[].slice.call(obj);
// хороший стиль
consttoArray=(()=>
Array.from?Array.from:obj=>[].slice.call(obj)
)();
|
Приведение типов
Если это обоснованно, используйте неявное преобразование типов. В любых других случаях избегайте этого.
|
1
2
3
4
5
|
// плохой стиль
if(x===undefined||x===null){...}
// хороший стиль
if(x==undefined){...}
|
Циклы
Не используйте циклы, поскольку они вынуждают вас использовать изменяемые объекты. Используйте методы объявленные в array.prototype.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// плохой стиль
constsum=arr=>{
varsum=0;
vari=-1;
for(;arr[++i];){
sum+=arr[i];
}
returnsum;
};
sum([1,2,3]);// => 6
// хороший стиль
constsum=arr=>
arr.reduce((x,y)=>x+y);
sum([1,2,3]);// => 6
|
Если же вы не можете использовать эти методы, либо их использование неприемлемо, используйте рекурсию.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// плохой стиль
constcreateDivs=howMany=>{
while(howMany--){
document.body.insertAdjacentHTML("beforeend","<div></div>");
}
};
createDivs(5);
// плохой стиль
constcreateDivs=howMany=>
[...Array(howMany)].forEach(()=>
document.body.insertAdjacentHTML("beforeend","<div></div>")
);
createDivs(5);
// хороший стиль
constcreateDivs=howMany=>{
if(!howMany)return;
document.body.insertAdjacentHTML("beforeend","<div></div>");
returncreateDivs(howMany-1);
};
createDivs(5);
|
Параметры функций
Не используйте объект arguments. Лучше использовать синтаксис функции с переменным количеством параметров, поскольку:
- У параметров есть имя, поэтому можно понять что именно ожидает функция на входе.
- Это настоящий массив, поэтому его удобно использовать.
|
1
2
3
4
5
6
|
// плохой стиль
constsortNumbers=()=>
Array.prototype.slice.call(arguments).sort();
// хороший стиль
constsortNumbers=(...numbers)=>numbers.sort();
|
Функция Apply
Забудьте о функции аpply(). Используйте оператор развертки вместо нее.
|
1
2
3
4
5
6
7
8
|
constgreet=(first,last)=>`Hi${first}${last}`;
constperson=["John","Doe"];
// плохой стиль
greet.apply(null,person);
// хороший стиль
greet(...person);
|
Функция Bind
Не используйте функцию bind(), существует более идиоматичный подход:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// плохой стиль
["foo","bar"].forEach(func.bind(this));
// хороший стиль
["foo","bar"].forEach(func,this);
// плохой стиль
constperson={
first:"John",
last:"Doe",
greet(){
constfull=function(){
return`${this.first}${this.last}`;
}.bind(this);
return`Hello${full()}`;
}
}
// хороший стиль
constperson={
first:"John",
last:"Doe",
greet(){
constfull=()=>`${this.first}${this.last}`;
return`Hello${full()}`;
}
}
|
Функции высшего порядка
Используйте вложенные функции только в случае необходимости.
|
1
2
3
4
5
|
// плохой стиль
[1,2,3].map(num=>String(num));
// хороший стиль
[1,2,3].map(String);
|
Композиция
Избегайте вложенности при вызове функций. Используйте композицию функций.
|
1
2
3
4
5
6
7
8
9
10
|
constplus1=a=>a+1;
constmult2=a=>a*2;
// плохой стиль
mult2(plus1(5));// => 12
// хороший стиль
constpipeline=(...funcs)=>val=>funcs.reduce((a,b)=>b(a),val);
constaddThenMult=pipeline(plus1,mult2);
addThenMult(5);// => 12
|
Кэширование
Кэшируйте тесты, большие структуры данных, а также результаты выполнения дорогостоящих операций.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// плохой стиль
constcontains=(arr,value)=>
Array.prototype.includes
?arr.includes(value)
:arr.some(el=>el===value);
contains(["foo","bar"],"baz");// => false
// хороший стиль
constcontains=(()=>
Array.prototype.includes
?(arr,value)=>arr.includes(value)
:(arr,value)=>arr.some(el=>el===value)
)();
contains(["foo","bar"],"baz");// => false
|
Переменные
Используйте const вместо var, там где это возможно:
|
1
2
3
4
5
6
7
8
|
// плохой стиль
varobj={};
obj["foo"+"bar"]="baz";
// хороший стиль
constobj={
["foo"+"bar"]:"baz"
};
|
Условные операторы
Предпочитайте IIFE (вызываемое «по месту» функциональное выражение) конструкциям типа if,else if,if, else и switch выражениям.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// плохой стиль
vargrade;
if(result<50)
grade="bad";
elseif(result<90)
grade="good";
else
grade="excellent";
// хороший стиль
constgrade=(()=>{
if(result<50)
return"bad";
if(result<90)
return"good";
return"excellent";
})();
|
Итерирование объектов
Где это возможно, не используйте for..in.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
constshared={foo:"foo"};
constobj=Object.create(shared,{
bar:{
value:"bar",
enumerable:true
}
});
// плохой стиль
for(varprop inobj){
if(obj.hasOwnProperty(prop))
console.log(prop);
}
// хороший стиль
Object.keys(obj).forEach(prop=>console.log(prop));
|
Объекты как пары «ключ/значение»
Обычно лучше использовать объект как пару «ключ/значение», это решение более мощное, но существуют случаи, когда объекты правильнее использовать как экземпляры класса Object.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// плохой стиль
constme={
name:"Ben",
age:30
};
varmeSize=Object.keys(me).length;
meSize;// => 2
me.country="Belgium";
meSize++;
meSize;// => 3
// хороший стиль
constme=Map();
me.set("name","Ben");
me.set("age",30);
me.size;// => 2
me.set("country","Belgium");
me.size;// => 3
|
Каррирование
Возможно, в других языках программирование каррирование реализовано хорошо, но в JavaScript этого следует избегать. Оно ухудшает читабельность кода, поскольку выглядит инородной конструкцией, а случаи, когда использование каррирования обоснованно, крайне редки и необычны.
|
1
2
3
4
5
6
7
|
// плохой стиль
constsum=a=>b=>a+b;
sum(5)(3);// => 8
// хороший стиль
constsum=(a,b)=>a+b;
sum(5,3);// => 8
|
Читабельность
Не запутывайте ваш код, используя, с виду, «умные» конструкции.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// плохой стиль
foo||doSomething();
// хороший стиль
if(!foo)doSomething();
// bad
voidfunction(){/* IIFE */}();
// хороший стиль
(function(){/* IIFE */}());
// плохой стиль
constn=~~3.14;
// хороший стиль
constn=Math.floor(3.14);
|
Переиспользование кода
Не бойтесь создавать большое количество небольших, компонуемых функций, которые можно использовать много раз.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// плохой стиль
arr[arr.length-1];
// хороший стиль
constfirst=arr=>arr[0];
constlast=arr=>first(arr.slice(-1));
last(arr);
// плохой стиль
constproduct=(a,b)=>a*b;
consttriple=n=>n*3;
// хороший стиль
constproduct=(a,b)=>a*b;
consttriple=product.bind(null,3);
|
Зависимости
Сводите к минимуму зависимость от чужого кода. Не нужно добавлять в проект целую библиотеку ради пары строчек, которые можно написать самому.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// плохой стиль
var_=require("underscore");
_.compact(["foo",0]));
_.unique(["foo","foo"]);
_.union(["foo"],["bar"],["foo"]);
// хороший стиль
constcompact=arr=>arr.filter(el=>el);
constunique=arr=>[...Set(arr)];
constunion=(...arr)=>unique([].concat(...arr));
compact(["foo",0]);
unique(["foo","foo"]);
union(["foo"],["bar"],["foo"]);
|
Перевод статьи «Frontend Guidelines.»
Источник: https://tproger.ru/translations/web-frontend-guidelines/
