100 Front-end Development Tips
đ A joke that turned into a really cool thread: đŻ quick tips about Front-end Development
In the last few days Twitter got a bunch of super useful threads based on the premise: âGive me a RT or a like and Iâll tweet about the topicâ.
I thought the game was cool and adapted it to the developer scene with this thread:
Vou entrar na brincadeira! đ
1 RT = 1 dica rĂĄpida de front-end
Truth is, I figured my thread would get few RTs, I never imagined the game would catch on so much among devs, but it took off!
Besides the high number of retweets, other people decided to jump in and play with the dev theme too, and anyone on Twitter had a week full of amazing tips.
It was a fun challenge to come up with all these tips, and I even had plenty more in mind, but writing this sequence wore me out more than I thought it would, so I decided to stop at 100, which is a nice number (who knows, maybe more will come in a while? đ).
I also created a Moment to make it easier to view inside Twitter.
But on the internet nothing scales better than written text, so here it is.
100 quick tips about Front-end
1. Visually, <b> and <strong> make the element bold. The difference is that <b> carries no semantics at all, while <strong> represents important text.
2. <i> and <em> make the element italic and both carry semantic meaning, with <i> usually used for things like expressions in other languages and <em> to indicate emphasis in the text.
3. That means itâs not a good idea to use <i> to represent things like icons, elements with no semantics like <span> work better for that.
4. Some elements carry no semantic value at all, <div> and <span> are good examples.
5. By default <div> is display: block and <span> is display: inline, donât waste lines of CSS setting or changing that.
6. When building your components, first focus on making sure the HTML is semantic.
7. If you get the semantics right, you can use CSS classes to style things (thinking about plain CSS).
8. Still on semantics, you can think of the hierarchy of information as if you were laying out a book.
9. Use only <h1> to <h6> tags to create headings.
10. A fun fact is that these days you can use <a> to wrap other elements (except another <a>).
11. In the past, when we needed to build, for example, a card with a link, we had to pull off hacks like leaving an <a> inside the card with position absolute 0.
12. If you use component-based libs, donât fall for the temptation of stripping out all the HTML semantics. Keep writing accessible code.
13. We use lang on the <html> tag, but a cool tip is that you can use lang on any element and declare the default language of the text.
14. And more, you can also style any element in CSS based on its lang, like this:
.description[lang=âenâ] { color: red };
.description[lang=âpt-brâ] { color: blue };15. This extends to any attribute on HTML elements, which means you can combine WAI-ARIA with CSS and create some really cool stuff, like this Tooltip in CSS Components.
16. Interestingly, even classes can be used this way, for example:
a[class=âactiveâ]17. Since classes can be used this way, you can also do cool things like selecting only elements that have a certain word somewhere in the class:
span[class*=âicon-â]18. Or even better, matching space-separated words.
span[class~=âicon arrow-rightâ]19. You can also select only elements that start with a certain word:
span[class^=âiconâ]20. With that you can do really cool things, like selecting only secure links (maybe to add a padlock icon?):
a[href^=âhttps://â]21. You can also do things like select all the disabled elements in your project and add styles:
[disabled] { cursor: not-allowed; }22. In the past it was common to add a class, for example, to the last items of a list to reset styles:
<li class=âlastâ></li>li {
border: black solid 1px;
}
.last {
border: 0;
}23. With the arrival of pseudo-classes in CSS3, years ago, thatâs no longer necessary:
:last-child {
border: 0;
}24. But the tip above is pretty bad, the ideal is to not reset properties in CSS at all, that stopped making sense once :not became supported in browsers:
li:not(:last-child} {
border: black solid 1px;
}25. :not is one of my favorite CSS pseudo-classes, Iâve already written a whole article (in Portuguese) about it:
26. Using only CSS you can remove an element from the screen if it has no content:
div:empty {
display: none;
}27. You can even mix pseudo-classes, for example, to give an element a behavior if itâs the last child, but not if itâs also the first child at the same time:
.btn:last-child:not(:first-child)28. You can make some really wild combinations of pseudo-classes and pseudo-selectors, for example, grab a .title class only if itâs not an h2 and .header is not active:
.header:not(.active) + .main .title:not(h2)29. Pseudo-selectors, by the way, help a ton to avoid resetting properties and to do cool stuff with CSS.
30. You can, for example, select only the next element and change the style based on the siblingâs class, something like:
.btn.active + .btn {
margin-left: 20px;
}31. Or even select all the following sibling elements to add styles:
.btn.active ~ .btn {
margin-top: 20px;
}32. We can also combine pseudo-classes and pseudo-selectors to do things like:
input[type=âcheckboxâ]:checked ~ p {
color: red;
}33. From that base, we can build super-interactive CSS by taking advantage of the states of elements like radio and checkbox, and make an element show up or disappear:
p {
display: none;
}
input[type=âcheckboxâ]:checked ~ p {
display: block;
}34. With this you can do surreal things with CSS, without using JavaScript.
This is the foundation of all those little games and components built with CSS only, and even though it looks like witchcraft, you just saw that itâs super simple.
35. Years ago (many years) I wrote an article showing how I built all the CSS Components (in Portuguese):
36. Speaking of selectors, they have a matching performance cost in browsers. And itâs important to take that into account when writing your code.
37. Selector performance, from best to worst, is:
#header.headerheadernav + headermain > h1main header*[type=âtextâ].header:before, header: after
38. Avoid nesting elements by doing things like:
body header ul li39. The ideal, if youâre not using CSS-in-JS, is to use classes to style elements and avoid deep nesting.
40. Iâve already written an article explaining all the advantages of using classes (in Portuguese)
41. Itâs precisely to make CSS less chaotic and to make code easier to maintain that methodologies like BEM or RCSS were created.
42. But they donât solve CSSâs main problem, which is called specificity. Style collisions are the biggest source of problems when we work with CSS on large projects.
43. To solve the specificity problem, our old buddy JavaScript stepped in, bringing solutions like:
- CSS Modules
- CSS-in-JS
They make sure the style doesnât leak into other components.
44. The downside of some CSS-in-JS libs is that they require component-based applications (like React, Angular and Vue) to work.
45. But you can use, for example, CSS Modules if youâre using Webpack in your project, I used this solution in my Kratos Boilerplate and it can work for your static projects:
46. One of the cool things about CSS Modules and other CSS-in-JS libs is that you no longer need to think so hard about class names.
Instead of using: .header__title
You can just use: .title
47. If you develop for modern browsers, after the rise of Flexbox and CSS Grid, you donât need to use float anymore to build grids in your projects.
48. CSS Grid also removes much of the need to bet on grid system libs, like the one from Bootstrap or even PostCSS-based ones like Lost or Jeet.
49. CSS Grid and Flexbox can and should be used together, even though they solve similar problems, each one has its own specific use.
50. Flexbox is one-dimensional and ideal for the inner layout of components.
Like in a header with a logo on the left and a menu button on the right, where you can use:
.header {
align-items: center;
display: flex;
justify-content: space-between;
height: 60px;
}51. CSS Grid is multidimensional and ideal for the macro part of the layout, like grids.
It also works really well for creating a list of cards, for example. Plus it scales easily on mobile.
52. Make good use of media queries. Ideally, you shouldnât build thinking about desktop and then override things on mobile. It works better to use the mobile-first concept and scale up the components as the resolutions get bigger.
53. You can create scopes inside the class through media queries.
That means you can keep everything thatâs generic to all resolutions outside the media queries and, inside them, only whatâs specific to that resolution.
54. Years ago I wrote this article explaining how to create media query scopes (in Portuguese), and the idea hasnât changed much since then:
55. In the past, we used <div> and <span> for a lot of things that should carry semantics. The tags introduced with HTML5 solved a good chunk of those problems.
56. When youâre building a component, always check whether youâre making good use of HTML elements and whether you could use others that make more sense.
57. There are currently around ~110 HTML tags. Itâs pretty unlikely that there isnât one that fits each occasion exactly.
58. <main>, for example, should be used only once in the project and defines the main content inside <body>.
I usually add it as a sibling of the main <header> and <footer> tags.
<body>
<header><header>
<main></main>
<footer></footer>
</body>59. You can have multiple <header> and <footer> elements across the project.
They can be used to define the header or footer of any context, such as inside <article> or <section>, for example.
60. <article> and <section> tend to cause some confusion about their usage. Itâs important to say that you can have an <article> inside a <section> and vice versa.
61. Years ago there was an awesome discussion about article vs section on @frontendbr and I strongly recommend checking it out:
62. Whenever you write an address inside a text, use the <address> element, whose exact purpose is to make that content semantic.
63. Ideally you should use the <nav> tag for every section of the project that represents navigation.
You can also have multiple <nav> elements across the application.
64. Make use of the <noscript> tag. It lets you give feedback to the user if JavaScript isnât available for some reason.
65. You can see a roundup of the most used HTML tags in this section of the MDN (Mozilla Developer Network).
66. By the way, thatâs another tip. Iâm in love with MDN. Itâs the place where I feel most confident validating things, and I always learn something new.
67. And itâs worth remembering that everyone can contribute content and translations to MDN. Golden tip from @larienmf đ
68. You can improve your projectâs semantics and accessibility even more by using WAI-ARIA, which is split into two categories: roles and states / properties.
69. You can, for example, use [role=âdialogâ] for modal components.
<div role=âdialogâ>70. You can also define which are the main <header> and <footer>.
<header role=âbannerâ>
<footer role=âcontentinfoâ>71. Another cool possibility is making purely visual elements invisible to screen readers.
It works well with icons:
<svg aria-hidden=âtrueâ>72. You can provide information about the element when the text isnât available on screen.
Again, an example with an icon:
<svg aria-label=âFacebookâ>73. WAI-ARIA becomes even more important as we build components with elements that have no HTML semantics, for example in components abstracted by JavaScript.
Itâs a way to provide accessibility and meaning to the tags you created.
74. You can even access all the values of WAI-ARIA properties with :before and :after in CSS and do some really wild stuff like this:
đ Criei um exemplo de cĂłdigo usando React, daquela solução em Pure CSS p/ adicionar label no Slider do Material.
— felipe.js (@felipefialho_) November 26, 2018
Observe que uso apenas:
- [aria-valuenow]
- :after
Sem modificar nada no JavaScript do componente.
CSS Ă© incrĂvel, confia đhttps://t.co/7TsG1kkZgH
75. Iâve already written an article about WAI-ARIA with some cool examples (in Portuguese).
76. Never forget that :after and :before in CSS donât work without the content property đ
:before { content: âJĂĄ acabou?â; }
:after { content: âAinda nĂŁoâ; }Worth noting that theyâre inline by default.
77. By the way, I really like :before and :after, they let me do all sorts of things with CSS without touching the HTML.
Think about it: with just 1 HTML element, you actually have 3. That opens up a sea of possibilities.
78. But a fair warning: all the content you add to the content of :before and :after has no semantic value and doesnât render in the HTML.
That means the text wonât be accessible. Use it only for purely visual extras.
79. When you get a project, analyze it and see everything that could be a component. Donât think in whole pages.
Build separate components and make the page be the grouping of them. That applies to SPAs as well as static projects.
80. You donât work alone.
Talk to your team, especially designers, and explain components and how all modern applications are built on them.
That will make your code a lot more on point.
81. The unit I use the most is rem, and to use it as if it were px, just add:
html { font-size: 10px; }And 1.6rem becomes approximately 16px.
82. One advantage of rem is that it scales across different resolutions, since the proportion is based on the root. If you want the measurements to be proportionally smaller or bigger, just decrease or increase the rootâs font-size:
media (max-width: 600px) {
html {
font-size: 10px;
}
}83. Making the font-size fluid automagically:
html {
font-size: calc(#{$minimum-size}px + (#{$maximum-size} â #{$minimum-size}) * ((100vw â #{$minimum-viewport}px) / (#{$maximum-viewport} â #{$minimum-viewport})));
}Confusing? Check out this example I left for you on Codepen:
84. Avoid using magic numbers, whether in CSS or JavaScript. A tip is to create a scale for your CSS variables:
$space-xxs : .4rem;
$space-xs : .8rem;
$space-sm : 1.6rem;
$space : 2.4rem;
$space-md : 3.2rem;`
$space-lg : 4.8rem;85. Watch out for z-index madness. Create variables for it and set up a lint rule to block commits that donât use those variables for z-index.
$zindex-default: 1;
$zindex-footer: 10;
$zindex-header: 30;
$zindex-overlay: 40;86. Easily understanding how em works: itâs based on the parentâs size, that is.
.pai { font-size 10px; }
.filho1 { font-size: .8rem; }
.filho2 { font-size: 1.2rem; }.filho1 will be approximately 8px and .filho2 will be approximately 12px.
87. If you want to test whether a JavaScript variable has a value:
const xis = 'x'
const hasXis = !!xis
console.log(hasXis) // true88. To ensure integrity and avoid bugs, the ideal is to always compare by type:
console.log(1 === '1') // false89. But you can compare values ignoring the type:
console.log(1 == '1') // true90. const variables are not immutable by default:
const felipe = ['corinthiano', 'maloqueiro']
felipe.push('sofredor')
console.log(felipe) // ['corinthiano', 'maloqueiro', 'sofredor']91. For const variables to be immutable you need to add Object.freeze:
const d2k = Object.freeze(['javascript', 'ninja', 'react'])
d2k.push('jquery') // Uncaught TypeError: Cannot add property 3, object is not extensible92. You can easily concatenate strings using template literals:
const f = (s = 'â€ïž') => `I ${s} CSS`
console.log(f())
// I â€ïž CSS93. With the spread operator you can easily concatenate arrays:
const skills1 = [ 'css', 'html' ]
const skills2 = [ 'js', 'ts' ]
const newSkills = [ ...skills1, ...skills2, 'ux' ]
console.log(newSkills) // [ 'css', 'html', 'js', 'ts', 'ux' ]94. You can also merge objects:
const felipe = { name: 'Felipe', company: 'Cubo' }
const xhamps = { nickname: 'Xhamps Monstro' }
const xhampelipe = { ...xhamps, ...felipe }
console.log(xhampelipe)
// { nickname: "Xhamps Monstro", name: "Felipe", company: "Cubo" }95. You can also turn a string into an array with the spread operator:
const s = 'HTML'
const c = [ ...s ]
console.log(c) // [ 'H', 'T', 'M', 'L' ]96. The combo of spread operator and destructuring is simply killer:
const person = { name: 'Felipe', lastName: 'Fialho', age: 28 }
const { name, age } = person
console.log(name, age) // Felipe 2897. If you want to do the opposite and create a new object (or array) with the rest of the original, we have the rest operator:
const person = { name: 'Felipe', lastName: 'Fialho', age: 28 }
const { name, ...restOfPerson } = person
console.log(restOfPerson) // { lastName: "Fialho", age: 28 }98. A tip is to use parameter destructuring in functions, it makes them more descriptive at the call site and saves you from having to guess the order of the parameters.
const person = ({ name, age }) => `${name} tem ${age} anos`
person({ age: '28', name: 'Felipe'})
// Felipe tem 28 anos99. For images, with the CSS object-fit property you can use proportions that were previously only possible with background-image:
img { object-fit: cover; }100. Combining position: relative and :before, you can handle the aspect ratio of images. This is especially useful for handling the proportions of videos and iframes.
I made this example on Codepen for you to check out:
Liked it? đ
