Frontend Sprint: 100 Quick Tips on HTML, CSS and JavaScript

100 useful tricks, best practices and free tips on HTML, CSS and JavaScript for new and continuing frontend developers.

Semantics and accessibility

1. The most popular HTML tags are div and span. These are ordinary containers with no hidden meaning.

2. Previously, they were used to design everything and everywhere, but the HTML5 standard brought many more suitable tags.

3. You now have about 110 tags to choose from. The probability that you will not be able to find one that is suitable is very small.

Text

4. When choosing a text selection method, think carefully about the meaning you put into it.

5. For example, the b and strong tags look the same (bold text), but the first one does not carry any semantic meaning, and the second one emphasizes the importance of the highlighted fragment.

6. The same situation with i and em. These are italic fonts, but em (emphasis) places a logical emphasis on the text, but i does not.

7. For headings, use h1 — h6.

8. If the selected text is not of semantic importance, it is better to use for it a regular span. For example, you can select icons in this way.

Markup

9. When creating a new structural component, focus on its semantics and select the appropriate elements.

10. For headers and footers, header and footer tags are intended. On one page there can be a lot of them, for example, the footer of the site with contact details and the footer of articles with information about the author.

11. But the main in document should be only one – it contains unique information that is different from page to page. Usually the markup looks like this:

<body>
  <header><header>
  <main></main>
  <footer></footer>
</body>

12. For the semantic content design, use the article and section tags.

13. In a nutshell, an article is self-contained content like an article, note, or comment that can be easily moved somewhere else, for example, to share on social networks.

14. And section is a separate thematic section of the document, as a rule, with its own title.

15. Inside the article you can place the address block with contact information.

16. The main navigation page is made in the form of a tag nav.

17. Another useful tag is noscript. Its role is to provide feedback for users with disabled JavaScript.

18. Be sure to review all existing HTML elements in the documentation.

19. Many semantic elements have their own default styles, which may differ from your design. Do not be afraid to change them in your CSS.

20. Consider the hierarchy and relationship of the elements. Each tag has allowed content and valid parent containers. You can find out which ones in the MDN documentation.

21. For example, earlier inside a tag it was impossible to place block elements and headers. In order to preserve the validity of the document, it was necessary to make a link to the child element and absolutely position it over the parent.

22. In the current standard, the a tag can itself serve as a container for other elements besides links, and this is very convenient.

ARIA-attributes

23. To improve the semantics and even greater accessibility of the project, you can use a set of ARIA attributes.

24. For example, for modal windows, the role attribute with the value dialog is used.

<div role="dialog">

25. Mark the main header and footer as follows:

<header role="banner">
<footer role="contentinfo">

26. If an element does not have a visible label, it can be denoted using the aria-label attribute.

<svg aria-label="Facebook">

27. It is also very simple to hide decorative elements, for example, icons, from the screen reader:

<svg aria-hidden="true">

28. ARIA attributes can be combined with CSS pseudo-elements to create wonderful accessible components like this slider.

29. Using ready-made libraries of components, resist the temptation to remove all semantic attributes. Accessibility of the application should be for the developer in the first place.

30. WAI-ARIA takes on even greater significance if the HTML markup does not use semantic elements. In this case, only attributes can make the page accessible.

31. Accessibility is gradually becoming the recognized standard of frontend development. In many countries, it is fixed at the level of legislation. Therefore, do not stay away from progress, learn the best practices of creating accessible sites.

CSS

32. Many HTML elements have default styles. For example, display: block at div or display: inline at span. There is no need to explicitly specify such properties in your CSS code.

33. Use CSS variables to store base values. This avoids the use of “magic numbers” and makes your code clearer and easier to maintain.

$space-xxs : .4rem;
$space-xs : .8rem;
$space-sm : 1.6 rem;
$space : 2.4 rem;
$space-md : 3.2 rem;
$space-lg : 4.8 rem;

34. It is especially useful to put into variable values of z-index, with which you can otherwise get confused very well:

$zindex-default : 1;
$zindex-footer : 10;
$zindex-header : 30;
$zindex-overlay : 40;

Attributes

35. CSS combines remarkably well with various HTML meaning attributes, which makes it possible to distinguish semantically meaningful elements.

36. For example, you can stylize elements with different default text language (the lang attribute can be used with any tag, not just with html).

.description[lang="en"] { color: red };
.description[lang="ru-ru"] { color: blue };

37. Or elements not available for interaction:

[disabled] { cursor: not-allowed; }

38. Do not forget that a class is also an attribute, which means that you can use the following selector:

[class="active"]

39. CSS allows you to select classes (or any other attributes) whose value contains some combination of characters:

span[class*="icon-"]

40. Or even one of several combinations, separated by spaces:

span[class~="icon arrow-right"]

41. You can select elements whose attribute value starts with a specific word, for example, icons:

span[class^="icon"]

42. Or secure links:

[href^="http://"]

43. Using ARIA attributes and CSS attribute selectors, you can create great things, for example, here are the available tooltips:

Pseudo-selectors

44. Pseudo-classes and pseudo-elements of CSS offer tremendous possibilities for styling a document.

45. For example, you can hide empty elements:

div:empty { display: none; }

46. Very often there is the task of discarding some styles from the last element in the group, for example, frames or indents. Previously, this element had to add a special class:

<li class="last"></li>

<style>
  li { border: solid black 1px; }
  .last { border: 0; }
</style>

47. Pseudo-classes greatly simplify this task:

:last-child {  border: 0; }

48. And there is a better solution!

li:not(:last-child} { border: solid black 1px; }

49. Some interesting and useful examples of using the selector :not you can find in internet.

50. Pseudo-classes solve more nontrivial problems. They can, for example, gracefully select elements that are the last descendant of the parent, but not the only one:

.btn:last-child:not(:first-child)

51. The pseudo-elements :before and :after allow you to make as many as three of one HTML element: one source parent block and two of its pseudo-shots. This opens up a lot of possibilities for page styling.

52. Do not forget that these pseudo-elements do not work without the content property, even if it is empty.

:before { content: "Over?"; }
:after { content: "Not yet"; }
:after { content: ''; }

53. Please note that any contents :before and :after cannot have a semantic meaning and is not available for screen readers. Use them exclusively for decorative purposes.

54. By combining pseudo-elements and relative positioning, you can adjust the aspect ratio of the block, which is especially useful when working with images and media objects.

Selector combinations

55. In CSS, you can select elements based on their environment, for example, by selectors of the previous neighbor:

.btn.active + .btn { margin-left: 20px; }

56. Or parent:

.btn.active ~ .btn { margin-top: 20px; }

57. Feel free to combine selectors of different types:

input[type="checkbox"]:checked ~ p { color: red; }

58. You can create completely crazy combinations. For example, this one will select all headers with the class .title (except for the headers of the second level) that lie inside the .main block, which is in the markup after the .header block, which does not have the class .active. Dizzy!

.header:not(.active) + .main .title:not(h2)

59. Using the properties of radio buttons and checkboxes, you can make interactive elements that will appear and disappear when you click:

p { display: none; }
input[type="checkbox"]:checked ~ p { display: block; }

CSS organization

60. Carefully analyze your code for anything that can be reused, and make it components.

61. When developing your own extensible component system, follow the proven best practices of frontend development.

62. Avoid common mistakes in working with cascading style sheets.

63. Use common class naming conventions, such as BEM, to keep your CSS clean and tidy.

64. But remember that BEM is not a panacea, and in some cases it is better to do without it.

65. Use CSS Modules and CSS-in-JS to insulate the styles of different modules. These approaches allow you to no longer suffer with the names of classes. Instead of .header__title, you can write with a clear conscience just .title.

66. If you are not familiar with modular concepts, take a look here.

67. However, there are also drawbacks, the main one being the complication of the development process. So think carefully before introducing CSS modules into your project.

68. CSS-in-JS will be especially useful if you use component JavaScript tools like React or Vue.

69. If you work in a team, be sure to discuss with your colleagues (designers, frontend and backend developers) how to organize the CSS code and component base. This will make it easier for you to select and implement the appropriate tools for your project.

CSS optimization

70. Different selectors operate at different speeds. Consider this by optimizing your code.

71. The fastest – selectors by identifier (#header). Further – in descending order of effectiveness:

  • classes – .header
  • tags – header
  • neighboring elements – nav + header
  • immediate parent – main > h1
  • simple nesting – main header
  • universal selector – *
  • attributes – [type = "text"]
  • pseudo selectors – .header: before, .header: after

72. Avoid large nesting of elements:

body header ul li

73. It is better to mark the desired item using the class than to increase the number of search levels.

74. This article will help you understand the CSS optimization facts and myths.

Grid

75. With the advent of Flexbox and CSS Grid, you can stop using float to create layouts.

76. CSS Grid to some extent can replace ready-made grid systems, for example, Bootstrap.

77. No need to choose between CSS Grid and Flexbox, just use them together depending on the tasks.

78. Flexbox is ideally suited for organizing internal one-dimensional marking of containers, for example, aligning the logo on the left, and the menu on the right in the header of the site.

.header {
  align-items: center;
  display: flex;
  justify-content: space-between;
  height: 60px;
}

79. CSS Grid is a great choice for building complex multidimensional meshes.

Relative Units

80. Assess the advantage of relative units of measure and begin to actively use them in your frontend-development. For example, rem is based on the font size of the root element. If the html property is set to font-size: 10px, then 1rem will be equal to 10px, and 2rem20px.

81. By default, the size of the root element (html) is most often equal to 16px, that is, 1rem = 16px.

82. rem makes it easy to scale all sizes. To make changes, simply increase or decrease the font-size value of the root element.

media (max-width: 600px) {
  html {
    font-size: 10px;
  }
}

83. Experiment with the viewport units and the calc function to set up a perfectly responsive font size:

html {
  font-size: calc(#{$minimum-size}px + (#{$maximum-size} — #{$minimum-size}) * ((100vw — #{$minimum-viewport}px) / (#{$maximum-viewport} — #{$minimum-viewport})));
}

Media queries

84. Adapting your website for different screens and devices, use the mobile first approach popular in frontend-development: start layout with a small resolution and gradually increase it.

85. Within a single media query, you can combine all the styles associated with it.

86. A lot of useful information about various media queries can be found in the documentation.

Javascript

87. Check whether there is a value in the variable, you can use double negation:

const xis = 'x'
const hasXis = !!xis
console.log(hasXis) // true

88. To avoid mistakes, use a strict equality test with regard to the type:

console.log(1 === '1') // false

89. On the other hand, lax validation makes JavaScript programming more flexible:

console.log(1 == '1') // true

90. Variables declared with const are not so constant. You cannot change the variable itself, but its properties are easy:

const animals = ['cat', 'dog']
animals.push('mouse')
console.log(animals) // ['cat', 'dog', 'mouse']

91. To make a const variable completely immutable, use the Object.freeze method:

const d2k = Object.freeze(['javascript', 'ninja', 'react])
d2k.push('jquery') // Uncaught TypeError: Cannot add property 3, object is not extensible

92. Use patterned strings for convenient concatenation:

const f = (s = '❤️') => `I ${s} frontend`
console.log(f())
// I ❤️ frontend

93. Spread-operator makes it easy to combine arrays:

const skills1 = [ 'css', 'html' ]
const skills2 = [ 'js', 'ts' ]
const newSkills = [ …skills1, …skills2, 'ux' ]
console.log(newSkills) // [ 'css', 'html', 'js', 'ts', 'ux' ]

94. And objects:

const obj1 = { a: 1, x: 'Hello' }
const obj2 = { b: 2, y: 'world' }
const mergedObj = { ...obj1, obj2 }
console.log(mergedObj) // { a: 1, b: 2, x: 'Hello', y: 'world' }

95. And turn a string into an array:

const s = 'HTML'
const c = [ …s ]
console.log(c) // [ 'H', 'T', 'M', 'L' ]

96. With the help of destructuring assignment, you can easily write object properties into variables:

const person = { name: 'Felipe', lastName: 'Fialho', age: 28 }
const { name, age } = person
console.log(name, age) // Felipe 28

97. The remaining properties are not lost anywhere, they can be turned into a new object using the rest-operator

const person = { name: 'Felipe', lastName: 'Fialho', age: 28 }
const { name, …restOfPerson } = person
console.log(restOfPerson) // { lastName: "Fialho", age: 28 }

Resources

Use the selected resources of the frontend developer:

98. MDN Web Docs – the best web documentation.

99. CanIUse – reliable verification of support for various features by browsers.

100. W3C standards – first-hand frontend standards.