📜 ⬆️ ⬇️

HTML / CSS / JavaScript Guide

Frontend guidelines

Rules and guidelines for formatting HTML, CSS and JavaScript code. Its goal is to improve the quality of the code and facilitate collaboration and infrastructure support.

From translator

Greetings to all again, my name is Maxim Ivanov, and today I have prepared a translation that may be useful to you. Benjamin De Cook (Belgian developer), a developer from Belgium, has gathered some code design guidelines that position themselves as best practices for writing HTML, CSS, JS. Of course, there are many recommendations, for example, there is a good guideline from Google , perhaps there is something else, however, if you follow at least some of them, then we can hope that your code will get better. In some cases, following these guidelines is not useful, but quite the opposite. In general, everything depends on your experience and vision, if you are a beginner, then you will most likely be useful to evaluate what others are writing and is considered correct in society, if you are a guru, then you probably don’t need guidelines that are not clearly written who do you think So let's get started.


HTML


  1. Semantics
  2. Conciseness
  3. Readability
  4. Document language
  5. Efficiency

')

CSS


  1. Semicolon
  2. Block model
  3. Streams
  4. Positioning
  5. Selectors
  6. Specificity
  7. Overrides
  8. Inheritance
  9. Conciseness
  10. English notation
  11. Vendor Prefixes
  12. Animation
  13. Units
  14. Color model
  15. Drawing
  16. Khaki


Javascript


  1. Performance
  2. Independence from the external state
  3. Nativity
  4. Forced comparison
  5. Cycles
  6. Arguments
  7. Using the apply method
  8. Using the bind method
  9. Higher order methods
  10. Compositions
  11. Caching
  12. Variables
  13. Conditions
  14. Iterator
  15. Object as an associative array
  16. Currying
  17. Readability
  18. Code reuse
  19. Dependencies


HTML


Semantics


HTML5 provides us with a sufficient number of elements aimed at an exact semantic description of a document or content. Therefore, make sure that you are doing well with the vocabulary.

<!--  --> <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> 


Make sure you understand the semantics of the elements you use in your code. It is very bad to use semantic elements for purposes other than intended or in the wrong place if you just remained neutral to these semantic elements.

 <!--  --> <h1> <figure> <img alt=Company src=logo.png> </figure> </h1> <!--  --> <h1> <img alt=Company src=logo.png> </h1> 


Conciseness


Try to write a short code. Forget about your old habits flowing from XHTML.

 <!--  --> <!doctype html> <html lang=en> <head> <meta http-equiv=Content-Type content="text/html; charset=utf-8" /> <title>Contact</title> <link rel=stylesheet href=style.css type=text/css /> </head> <body> <h1>Contact me</h1> <label> Email address: <input type=email placeholder=you@email.com required=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=stylesheet href=style.css> <h1>Contact me</h1> <label> Email address: <input type=email placeholder=you@email.com required> </label> <script src=main.js></script> </html> 


Readability


The readability of your code should not be of secondary importance. Of course, you don’t have to be an optimization expert (WCAG) in order to improve your website for sure, but right now you can start immediately correcting the little things that will ultimately help make your code better, for example:

- use alt attribute correctly
- link the names (links) and elements (buttons) and name them by meaning ( <div class = button> is atrocity)
- do not rely on the name of flowers as information
- explicitly link a form element with a specific label

 <!--  --> <h1><img alt="Logo" src="logo.png"></h1> <!--  --> <h1><img alt="My Company, Inc." src="logo.png"></h1> 


Document language


Language definitions and character encodings are optional, but it is recommended to always declare them at the document level, even if they are specified in HTTP headers. The priority character encoding is UTF-8.

 <!--  --> <!doctype html> <title>, .</title> <!--  --> <!doctype html> <html lang=ru> <meta charset=utf-8> <title>, .</title> </html> 


Efficiency


If there are no valid reasons to add download scripts to the content, try to write the scripts at the end of the document, thus your scripts will not block the rendering of the page. If you have very heavy style sheets, try to break them up into several and load them separately, so that the primary content is immediately drawn. Obviously, the more files, the more HTTP requests, two requests are, of course, slower than one, but in our case, the speed of displaying the desired content will be an important factor.

 <!--  --> <!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


Semicolon


While the semicolon is a purely technical rule delimiter, CSS always refers to the comma as the completion operator.

 /*  */ div { color: red } /*  */ div { color: red; } 


Box model


The block model, ideally, should be the same for the entire document. Global rule * {box-sizing: border-box; } this is normal, however, you need to remember that you cannot change the block model for specific elements.

 /*  */ div { width: 100%; padding: 10px; box-sizing: border-box; } /*  */ div { padding: 10px; } 


Streams


Do not change the standard behavior of the element if you can do without it. Keep the elements in their classic display in the document stream. For example, removing spaces under the image should not affect its display.

 /*  */ img { display: block; } /*  */ img { vertical-align: middle; } 


Similarly, do not pull items out of the main stream if you can do without it.

 /*  */ div { width: 100px; position: absolute; right: 0; } /*  */ div { width: 100px; margin-left: auto; } 


Positioning


There are many ways to position elements in CSS, but try to limit yourself to the properties presented below. In order of preference:

 display: block; display: flex; position: relative; position: sticky; position: absolute; position: fixed; 


Selectors


Minimize combinations of DOM-related selectors. Sometimes it is better to add an extra class to the element that you want to find, than to look for it through three structural selectors: pseudo-class, descendant, combinator.

 /*  */ div:first-of-type :last-child > p ~ * /*  */ div:first-of-type .info 


Avoid overloading selectors.

 /*  */ img[src$=svg], ul > li:first-child { opacity: 0; } /*  */ [src$=svg], ul > :first-child { opacity: 0; } 


Specificity


Do not use values ​​and selectors that cannot be overridden. Minimize the use of id (id) and avoid the rule ! Important

 /*  */ .bar { color: green !important; } .foo { color: red; } /*  */ .foo { color: red; } .foo.bar { color: green; } 


Overrides


Redefining selector styles makes debugging difficult. Avoid this if you can.

 /*  */ li { visibility: hidden; } li:first-child { visibility: visible; } /*  */ li + li { visibility: hidden; } 


Inheritance


Do not duplicate the definitions of selectors whose styles can be inherited.

 /*  */ div h1, div p { text-shadow: 0 1px 0 #fff; } /*  */ div { text-shadow: 0 1px 0 #fff; } 


Conciseness


Let your code be concise. Try to avoid using several properties in the place where it is not needed at all.

 /*  */ div { transition: all 1s; 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: 5px 10px 20px; } 


English notation


It is preferable to use English mathematics.

 /*  */ :nth-child(2n + 1) { transform: rotate(360deg); } /*  */ :nth-child(odd) { transform: rotate(1turn); } 


Vendor Prefixes


Do not use outdated prefixes. If you really need to use them, in this case, add them before the standard ones.

 /*  */ 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; } 


Animation


Sometimes it is preferable to use transitions (transitions), rather than animation (animations). Avoid animating properties in favor of opacity and transform .

 /*  */ div:hover { animation: move 1s forwards; } @keyframes move { 100% { margin-left: 100px; } } /*  */ div:hover { transition: 1s; transform: translateX(100px); } 


Units


Use dimensionless values. Try to use rem if you count everything in relative units. It is preferable to use seconds rather than milliseconds.

 /*  */ div { margin: 0px; font-size: .9em; line-height: 22px; transition: 500ms; } /*  */ div { margin: 0; font-size: .9rem; line-height: 1.5; transition: .5s; } 


Color model


If transparency is needed, use rgba . Otherwise, always use the hexadecimal format.

 /*  */ div { color: hsl(103, 54%, 43%); } /*  */ div { color: #5a3; } 


Drawing


Avoid http requests if the resource is easily reproduced using CSS.

 /*  */ div::before { content: url(white-circle.svg); } /*  */ div::before { content: ""; display: block; width: 20px; height: 20px; border-radius: 50%; background: #fff; } 


Khaki


Do not use them.

 /*  */ div { // position: relative; transform: translateZ(0); } /*  */ div { /* position: relative; */ will-change: transform; } 


Javascript


Performance


Easily readable, expressive and correct code is more important than performance. In fact, JavaScript will never be your bottleneck based on performance. It is better to pay attention to such things as image compression, optimization of http requests and network access, recalculation of the DOM tree. If you remember at least one of the recommendations in this article, rely on it.

 /*  (   ) */ const arr = [1, 2, 3, 4]; const len = arr.length; var i = -1; var result = []; while (++i < len) { var n = arr[i]; if (n % 2 > 0) continue; result.push(n * n); } /*  */ const arr = [1, 2, 3, 4]; const isEven = n => n % 2 == 0; //     const square = n => n * n; // : (param1, param2, …, paramN) => expression const result = arr.filter(isEven).map(square); 


To read :
1. Babeljs (example in ES5): bad vs good
2. Arrow functions and enumerating array methods

Independence from the external state


Try to create free features. All functions and methods ideally should not bear any side character, depend on external data, and as a result, they should return new objects, and not make changes to existing ones.

 /*  */ const merge = (target, ...sources) => Object.assign(target, ...sources); merge({ foo: "foo" }, { bar: "bar" }); // => { foo: "foo", bar: "bar" } /*  */ const merge = (...sources) => Object.assign({}, ...sources); merge({ foo: "foo" }, { bar: "bar" }); // => { foo: "foo", bar: "bar" } 


To read :
1. Babeljs (example in ES5): bad vs good
2. Residual parameters

Nativity


Rely on standard methods as much as possible.

 /*  */ const toArray = obj => [].slice.call(obj); /*  */ const toArray = (() => Array.from ? Array.from : obj => [].slice.call(obj) )(); 


To read :
1. Babeljs (example in ES5): bad vs good
2. Massive objects

Forced comparison


Superfluous comparisons do not make sense, avoid them.

 /*  */ if (x === undefined || x === null) { /* ... */ } /*  */ if (x == undefined) { /* ... */ } 


To read :
1. Comparison with null and undefined

Cycles


Do not use loops, as they force you to use mutable objects. Rely on the Array.prototype methods.

 /*  */ const sum = arr => { var sum = 0; var i = -1; for (;arr[++i];) { sum += arr[i]; } return sum; }; sum([1, 2, 3]); // => 6 /*  */ const sum = arr => arr.reduce((x, y) => x + y); sum([1, 2, 3]); // => 6 


To read :
1. Babeljs (example in ES5): bad vs good
2. Summation of all values ​​in the array

If you cannot use the Array.prototype methods, use recursion.

 /*  */ const createDivs = howMany => { while (howMany--) { document.body.insertAdjacentHTML("beforeend", "<div></div>"); } }; createDivs(5); /*  */ const createDivs = howMany => [...Array(howMany)].forEach(() => document.body.insertAdjacentHTML("beforeend", "<div></div>") ); createDivs(5); /*  */ const createDivs = howMany => { if (!howMany) return; document.body.insertAdjacentHTML("beforeend", "<div></div>"); return createDivs(howMany - 1); }; createDivs(5); 


Here is a common Loop function that makes recursion easier to use.

To read :
1. Babeljs (example in ES5): bad ( or ) vs good
2. insertAdjacentHTML () is faster than manipulating innerHTML ()

Arguments


Forget about arguments as an object. Residual parameters are always the best option, because:
1. The transferred name gives a better idea of ​​what the function expects at the input
2. The residual parameter is an array and it is easy to use.

 /*  */ const sortNumbers = () => Array.prototype.slice.call(arguments).sort(); /*  */ const sortNumbers = (...numbers) => numbers.sort(); 


To read :
1. Babeljs (example in ES5): bad vs good
2. Access to arguments

Using the apply method


Forget the apply () method. Instead, use the distribution operator (function call).

 const greet = (first, last) => `Hi ${first} ${last}`; const person = ["John", "Doe"]; /*  */ greet.apply(null, person); /*  */ greet(...person); 


To read :
1. Babeljs (example in ES5): bad vs good
2. Distribution operator

Using the bind method


Do not use bind () when there are more idiomatic approaches.

 /*  */ ["foo", "bar"].forEach(func.bind(this)); /*  */ ["foo", "bar"].forEach(func, this); 


 /*  */ const person = { first: "John", last: "Doe", greet() { const full = function() { return `${this.first} ${this.last}`; }.bind(this); return `Hello ${full()}`; } } /*  */ const person = { first: "John", last: "Doe", greet() { const full = () => `${this.first} ${this.last}`; return `Hello ${full()}`; } } 


To read :
1. Babeljs (example in ES5): bad vs good
2. bind () , and also iterators in JavaScript

Higher order methods


Avoid nested functions where not needed.

 /*  */ const result = [1, 2, 3].map(num => String(num)); // => ["1", "2", "3"] /*  */ const result = [1, 2, 3].map(String); //      string 


To read :
1. Babeljs (example in ES5): bad vs good
2. Displaying an array of numbers using the function

Compositions


Avoid multiple nested function calls. Use composition instead.

 const plus1 = a => a + 1; const mult2 = a => a * 2; /*  */ mult2(plus1(5)); // => 12 /*  */ const pipeline = (...funcs) => val => funcs.reduce((a, b) => b(a), val); const addThenMult = pipeline(plus1, mult2); addThenMult(5); // => 12 


To read :
1. Babeljs (example in ES5): bad vs good

Caching


Costly operations with large data structures are unforgivable unless you cache them.

 /*  */ const contains = (arr, value) => Array.prototype.includes ? arr.includes(value) : arr.some(el => el === value); contains(["foo", "bar"], "baz"); // => false /*  */ const contains = (() => Array.prototype.includes ? (arr, value) => arr.includes(value) : (arr, value) => arr.some(el => el === value) )(); contains(["foo", "bar"], "baz"); // => false 


To read :
1. Babeljs (example in ES5): bad vs good
2. Determine whether one line is inside another , and also check the values ​​of array elements

Variables


Use const instead of let and let instead of var .

 /*  */ var me = new Map(); me.set("name", "Ben").set("country", "Belgium"); /*  */ const me = new Map(); me.set("name", "Ben").set("country", "Belgium"); 


To read :
1. Babeljs (example in ES5): bad vs good
2. Constants , the let statement , and a bit about the associative array

Conditions


Be committed to IIFE's concept (immediately executed functor), use return values ​​in conditions (if, else if, else, and switch).

 /*  */ var grade, result = 50; if (result < 50) grade = "bad"; else if (result < 90) grade = "good"; else grade = "excellent"; // grade = "good"; /*  */ let result = 50; const grade = (() => { if (result < 50) return "bad"; if (result < 90) return "good"; return "excellent"; })(); // grade = "good"; 


To read :
1. Babeljs (example in ES5): bad vs good ( or )
2. Immediately Called Functions

Iterators


Avoid looping for ... in loop

 const shared = { foo: "foo" }; const obj = Object.create(shared, { bar: { value: "bar", enumerable: true } }); /*  */ for (var prop in obj) { if (obj.hasOwnProperty(prop)) console.log(prop); // => bar } /*  */ Object.keys(obj).forEach(prop => console.log(prop)); 


The difference between a cycle and a method is that the cycle lists properties from a chain of prototypes.

To read :
1. Babeljs (example in ES5): bad vs good
2. Using hasOwnProperty to check for the existence of a property and traversing the properties of an object

Object as an associative array


While objects can legally be used, as a rule, an associative array ( Map ) is better and more powerful. If in doubt, then use Map exactly.

 /*  */ const me = { name: "Ben", age: 30 }; var meSize = Object.keys(me).length; meSize; // => 2 me.country = "Belgium"; //  meSize++; meSize; // => 3 /*  */ const me = new Map(); me.set("name", "Ben"); me.set("age", 30); me.size; // => 2 me.set("country", "Belgium"); me.size; // => 3 


To read :
1. Babeljs (example in ES5): bad vs good
2. Collection for storing records of the form key: value

Currying


Currying is a powerful, but in turn, alien paradigm for many developers. Do not abuse.

 /*  */ const sum = a => b => a + b; sum(5)(3); // => 8 /*  */ const sum = (a, b) => a + b; sum(5, 3); // => 8 


To read :
1. Babeljs (example in ES5): bad vs good
2. Currying and examples

Readability


Do not hide the intent of your code using clever tricks.

 /*  */ foo || doSomething(); /*  */ void function() { /* IIFE */ }(); /*  */ const n = ~~3.14; /*  */ if (!foo) doSomething(); /*  */ (function() { /* IIFE */ }()); /*  */ const n = Math.floor(3.14); 


To read :
1. On the ideal code and harsh reality

Code reuse


Do not be afraid to create many small and reusable functions, they are very useful.

 /*  */ let last = arr[arr.length - 1]; /*  */ const product = (a, b) => a * b; const triple = n => n * 3; /*  */ const first = arr => arr[0]; // => first(arr); const last = arr => first(arr.slice(-1)); // => last(arr); /*  */ const product = (a, b) => a * b; const triple = product.bind(null, 3); 


To read :
1. Babeljs (example in ES5): bad vs good

Dependencies


Minimize dependencies of third-party code if you are not aware of how it works. No need to load the entire library for the sake of several methods that are easily reproducible:

 /*  */ var _ = require("underscore"); _.compact(["foo", 0])); _.unique(["foo", "foo"]); _.union(["foo"], ["bar"], ["foo"]); /*  */ const compact = arr => arr.filter(el => el); const unique = arr => [...Set(arr)]; const union = (...arr) => unique([].concat(...arr)); compact(["foo", 0]); unique(["foo", "foo"]); union(["foo"], ["bar"], ["foo"]); 


To read :
1. Babeljs (example in ES5): bad vs good
2. JavaScript module path and Underscore library documentation

Source: https://habr.com/ru/post/275729/


All Articles