In this article, we will present 12 Common CSS Mistakes and how to solve the problems in the simplest and most up-to-date way
The CSS design language can be frustrating – every small change has unexpected effects and the use of different devices and browsers must be taken into account. So how do you do it right? All the answers are in the following guide
CSS is considered a difficult design language because when defining properties on an element, it can have unexpected effects. In addition, CSS can be frustrating because it forces you to deal with the web thoroughly – you need to consider using different devices, different browsers, considering users who need accessibility, etc.
Despite the difficulty, it is important to know the CSS in depth so as not to fall into the traps that could cause, for example, the layout to break completely. Here are 12 Common CSS Mistakes – and how to avoid them by using standard CSS work.
1. Using hard-coded numbers and colors
.icon {
color: #f66035;
}
.button {
color: #f66035;
}
What should be done if we then want to change the color of all the elements? We will have to look for all the places where the color is set and update them. Instead, we can set a CSS variable that will save the color and then
we can use it:
:root {
--main-color: #5c4bde;
}
.icon {
color: var(--main-color);
}
.button {
color: var(--main-color);
}
Great use for CSS variables is theming.
You can also configure CSS variables in javascript:
If you are interested to know How to Add Dark Mode to the site using Javascript and localStorage read my article
document.querySelector(':root').style.setProperty('--main-color', '#5c4bde');
Anyone using an SCSS preprocessor can also configure SCSS variables, but they cannot be accessed in javascript because they disappear during compilation to CSS.
2. Concentration of an element using absolute position
Example:
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%)
}
An element with an absolute position is placed in an independent layer and exits the natural flow of the page. Therefore it is better to use flexbox:
.parent {
display: flex;
align-items: center;
justify-content: center;
}
3. z-index is very large
I’m sure you’ve seen the following code:
.block {
z-index: 9999999999;
}
First, the maximum value of the z-index is 2147483647, so there is no point in putting a higher value. Second,
z-index only effects elements that are in the same Stacking Context, that is, in the same set of elements. An element in one group cannot be above an element in another group that is higher in the axis z, even if it has a higher z-index.
There are various scenarios that make an element the root of a new group. The order of the elements within a group is determined according to the following order, from the back to the front:
- An element with a non-static position and with a negative z-index
- Element with position static (no meaning to put z-index on this type of element)
- An element with a non-static position and no z-index
- An element with a non-static position and a positive z-index
There are several possible solutions for z-index management.
4. Using important! excessively
Example:
.block {
width: 50px !important;
height: 50px !important;
color: blue !important;
}
Using !important should be a last resort, for example when you want to override the CSS of an external directory. Overuse of important makes it difficult to make future changes, tweak and maintain our styles, as it breaks the natural cascade process of CSS – the algorithm that decides which of the two conflicting CSS settings will be more powerful.
Instead of being important, it is better to increase the specificity of the selector in question, for example:
.main .block {
width: 50px;
height: 50px;
color: blue;
}
It is also recommended to use classes over inline style, because inline style causes contiguity between the structure and the design, and in addition, the only way to override it is through important.
For a good understanding of Specificity see Specifishity and try the Specificity Calculator.
5. Definition of font without fallback
Example:
.block {
font-family: Helvetica;
}
In a perfect world, the same fonts would be installed in every operating system, but in practice, this is not the case. Therefore it is always advisable to put a reserve font in case the font we wanted does not exist:
.block {
font-family: Helvetica, Arial, sans-serif;
}
Interesting fact: Currently Helvetica is supported on Mac by 100% and Windows by 7.34%.
6. Animation using a change of top / left
Example:
.parent {
position: relative;
}
.child {
position: absolute;
left: 0;
transition: left 0.4s;
}
.child-new-location {
left: 50px;
}
The browser performs three steps in changing CSS:
- Layout – Calculates how much space each element takes and where to place it
- Paint – the process of filling the pixels on layers
- Composite – The process of drawing the layers on the screen in the correct order
Each step also activates the following steps. In order to maintain good performance, it is advisable to choose features that will run as few steps as possible.
Each feature triggers different steps, depending on the browser type. In the example before us left runs all three stages. In contrast, transform only runs the last step – Composite, so you should set up the animation with transform.
.parent {
position: relative;
}
.child {
position: absolute;
transform: translateX(0);
transition: transform 0.4s;
}
.child-new-location {
transform: translateX(50px);
}
The opacity and transform properties activate only the last step and can be used to perform most of the animations.
Note: When you put a transform on an element it becomes a containing block, that is, if there is a child element with a fixed position, the child will be placed relative to it instead of relative to the viewport.
7. Use Physical Properties instead of Logical Properties
Many use physical properties such as margin-top and padding-left, for example:
.block {
margin-right: 10px;
}
If we want to add support in right-to-left languages as well as in Arabic, so that in Hebrew the margin will be to the left of the element instead of to our right, we would write it like this:
.block {
margin-right: 10px;
}
html[dir="rtl"] .block {
margin-right: 0;
margin-left: 10px;
}
logical properties come to our aid to save us the dual definition:
.block {
margin-inline-end: 10px;
}
In this short way, the margin will work as expected in Arabic as well.
8. margin collapsing
For example, we will define a space of 20px for each paragraph from top to bottom:
p {
margin: 20px 0;
}
In this case, the distance between the paragraphs will be 20px and not 40px, since the margin-top of one paragraph and the margin-bottom of the paragraph above it unite and the greater value is the one determined (in this case both have the same value).
To overcome this, you can use a gap instead of a margin if the parent is flex/grid, or alternatively by creating a Block formatting context – for example by setting display: flex on the parent.
9. Improper use of display
span {
display: block;
}
It happens that they try to fix the UI by changing the display without understanding its meaning. It is recommended to know the box model and the differences between the types of display:
inline-block | inline | block | |
Causes a line drop | no | no | yes |
The element will expand in the direction of the row to fill the available space of the parent | no | no | yes |
Width and height characteristics affect | yes | no | yes |
padding/border/margin will cause other elements to be pushed out of the element | yes | Only laterally | yes |
10. Using Responsive Design instead of Fluid Design
Example:
.block {
width: 100px;
}
@media (max-width: 600px) {
width: 50px;
}
Instead of defining for each breakpoint the width of the element, we can use responsive units of measure such as vw / vh / fr /% and responsive methods like min/max/clamp. For example, in the previous example we can just write like this:
.block {
width: 25%;
}
Using media query is designed to offer a different view in different screen sizes, for example – in a desktop to display a three-column layout, in a tablet to display a two-column layout, and in mobile to display a single column.
11. Non-responsive width setting
Suppose we have a button with text inside it, defined as:
button {
width: 60px;
}
In case our text is translated into another language, the text may slide out of the button. Of course, we would like to adjust the size of the button to its content, so it is recommended to put min-width or padding instead of width.
12. Layout change while loading an image
Example:
img {
max-width: 100%;
height: auto;
}
The advantage of the definition in the example is that the size of the image does not exceed the size of the parent containing it, and its aspect ratio is also preserved. But because the height of the image is not fixed, the browser does not know how much space to allocate to the image before it is loaded, which causes the layout to jump when it is loaded.
To solve the problem you can set a new property called aspect ratio:
img {
width: 100%;
aspect-ratio: 16 / 9;
}
The browser knows how to calculate the height of the image by calculating the width and the ratio of height to width, so you can avoid the layout jump while loading the image.
Today this property is currently only supported on chrome and edge. For unsupported browsers, you can add the width and height attributes to the img tag, which helps the browser calculate aspect ratio and does not compromise the responsiveness of the image because CSS is more powerful than the attributes.
By the way, you can use feature query – @supports to set rules only for browsers that support the desired feature.