This post is not intended to be a kind of cheat sheet; I'm not going to cover every existing CSS property. My intention here, on the other hand, is to present some useful CSS properties in a holistic way, showing how they can be used together and the logic behind them.
I'm not a front-end developer though, so if something here seems a bit strange or confusing, I encourage you to look up on other resources. I hope this post is useful.
Box-model
This one is the basics that you probably already know.
Every single element in a page is nothing but a box containing these properties you see below:
Although important, I feel that most struggles people have have nothing to do with the box model itself, but with positioning each element in relation to each other. So, I will skip box-model for now; even though we'll see a bit of it later.
Part 1 - Display: inline, block, inline-block
We know that elements are built just like blocks in a page. However, are all elements equal when it comes to displaying them in your document?
The answer is no: they can be displayed occupying all the space around them or inside another block element, depending on the default value of their display
property.
Let's see.
Let's say we have a very basic p
tag containing some text. To write another paragraph, we would have to add another p
tag as follows:
display: block
By default, p is an element whose display
property is set to block
. The meaning of it is exactly what you saw above: block elements occupy all the width where they are positioned. That's why we cannot have two p elements side-by-side, without changing their display
property.
display: inline
Let's say we've decided that our lorem ipsum text looks boring without some colors. So, we need to change some stuff inside of p, which is a block element. How to do it?
The answer is: display: inline
. Therefore, in this case, the best element we could use - that is inline
by default - is <span>
.
Our HTML now looks like this:
<p>"<span class="highlight">Lorem ipsum dolor sit amet</span>
,consectetur adipiscing elit, sed do [...]</p>
Basic differences between inline and block
The width of your block
elements will not adjust to the content inside them; whereas it will happen with inline
elements.
In fact, "how to make my div adjust its width to the content inside" is a common question when it comes to CSS, and its answer is often setting the display property to inline-block
(which will have characteristics of both inline
and block
). Look at the answers of this question in Stack Overflow.
Another difference that is worth noting is that block elements have top and bottom margins (remember the box model). That's visible in the image above.
But why do these differences even exist?
A key concept to keep in mind is that block elements are intended to be used as "wrappers" of sections in your page. That's precisely why elements such as <main>, <header>, <article>, <footer>, <div>
, etc are block elements by default. They are supposed to have content inside them; therefore they start a new line and take up the full width available. They are just like drawers.
On the other hand, inline
elements are like the items inside the drawer. Therefore, they occupy only as much width as necessary and are intended to be used inside block elements. It's easy to position they side-by-side.
Some elements that are inline by default are <a>, <button>, <textarea>, <label>, <select>
.
Side note: grid
and flex
are other important values for display, but we'll skip it for now, because a section of this post we'll be dedicated exclusively to grid and flexbox.
Let's add some colors to these paragraphs, first wrapping them in a div.
HTML
<div class="wrapper">
<div class="yellow-div">
<p>"<span class="highlight">Lorem ipsum dolor sit amet</span>, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."</p>
</div>
<div class="blue-div">
<p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."</p>
</div>
CSS
.yellow-div {
background-color: yellow
}
.blue-div {
background-color: blue
}
.wrapper {
width: 800px
}
Now our paragraphs look like this:
Our div now has a width of 800 pixels. But now we face our first problem: what if the width of our screen is less than 800 pixels?
Part 2 - CSS Units
If we wanted that our div had always half the width of the page, it would be a headache to define its value in pixels. That's what would happen with our example: there are a lot of screens that are less than 800 pixels wide. But pixels are only the tip of the iceberg.
Relative lengths
Pixels and centimeters are pretty self-explanatory. They are absolute, fixed length units and do not change in spite of other characteristics.
However, due to their static nature, when dealing with responsive layouts, they are not always the best option. That's why I will focus here on relative units.
em
em
is equivalent to the font-size of parent div. It means that, for example, if the font-size of elements inside yellow-div is set to 14px, then inside yellow-div, 1em is equal to 14px, 1.2em is equal to 16.8px and so on.
rem
This unit is similar to em
, but in this case we take for reference the font size of the root element (often <html>
). So, differently from the example above, we would not use the font-size of only yellow-div. If the font-size of the page is 18px, then 1rem would be equal to 18px in all elements of our HTML.
vh
and vw
These are my favorite units for responsive layout. vh
stands for viewport height and vw
stands for viewport width. They represent either 1% of width or height of page - and they resize accordingly to the viewport size. That's very useful when you want, for example, a div that occupies half the page both in mobile and desktop screens.
So, what about resizing our div to have 50% of the width of our page, despite of the screen size? Let's do it:
.wrapper {
width: 50vw;
}
Look how the proportion is kept in smaller screens:
Looks nice for now. But it could be better if our div was centered horizontally. How to do it?
Part 3 - centering stuff with CSS; an introduction
We are back to the question that opened this post - how to center a div?
The answer for this question varies a lot, actually. But we are going to start with the basics, first with two questions:
1 - Where is the element that you want to center?
2 - What's the nearest reference you are going to use to center it?
The first question is very important at this point, because out HTML has only a div with two paragraphs inside. It's different from a column in a blog template or some design alike. So, our element is floating alone in a HTML document and we are going to center it relative to our viewport.
This case is not the most common; you are probably going to need to center your elements inside of other elements, and therefore the solution would be different. But for now, let's stick with it.
.wrapper {
width: 50vw;
margin: 0 auto;
}
By simply adding margin: 0 auto
, we are able to center our div in this case.
It is responsive as well:
Back to box-model: why the solution above works
Defining margin: 0 auto
does precisely two things: it sets the element's vertical margins to zero and lets the browser decide the horizontal margins - that will be equal in both sides. Of course, the values for the child element will be calculated relative to its parent element - and as we only have this div, the parent element is <body>
and so we are able to center it absolutelly.
However, using margins to center elements only works if:
1 - The element has a defined width
2 - The element is block
(because we cannot define width for inline elements)
So, as you see, this approach is useful - but only for very specific cases.
Side note: margin auto only works for centering things horizontally. It does not work on vertical axis the same way, look at the answers of this question.
And so we get to another question: how to center stuff vertically, if we cannot use margin
?
There are plenty of answers to this question. And to answer them, it's time to use another CSS property.
Part 4 - position
Here things start to get interesting.
In the previous example, let's say that we want to center our div vertically, taking for reference the browser window.
Even though there are other ways to achieve it, we are going to use position
here.
Let's start with the most useful cases: absolute
and relative
.
They set how the element should be positioned relative to:
1 - Its default position in the HTML document - position: relative
2 - Its parent element - position: absolute
When you set position, you can define top
, right
, bottom
and left
properties, that will define the element's final position in the page layout.
What's the difference between them?
In simple words, absolute
takes for reference the ancestor element and relative
takes for reference the default position that the element would occupy in the page, if position is not set (normal flow). Look at the previous image and observe how elements are positioned. Relative will take for reference exactly these positions.
absolute
is kinda tricky
When we say takes for reference the ancestor element, what exactly it means?
Basically, the reference for a absolute-positioned element is its nearest positioned element, what is, the nearest element whose position is different from static (the default value).
When we don't have this positioned element, though, the reference used will be the root element (<html>
). Let's see it in practice:
Questionably centering with position
So, we want our div to be centered vertically in terms of the browser window. If we use the root element for reference, absolute
would be the right choice, right? To test it, we are going to use the same logic of applying 50vh.
.wrapper {
width: 50vw;
margin: 0 auto;
position: absolute;
bottom: 50vh;
}
Now our layout is broken because our element's margins are being ignored.
In fact, that's precisely what is intended to happen. When you use the absolute positioning, your element is removed from the document flow, what means that its box is ignored.
The margins are still there, but they have no effect now that our element is not part of the layout anymore.
But we still want our div to be part of the layout. So, let's use position: relative
instead.
To do so, we can't use 50vh
as our distance from the bottom, because now our reference is not the distance from the bottom of browser window anymore, but the default position of the element. So, setting bottom: 50vh
with position relative would make our element disappear from the page.
Then, we can use the distance from top to do it. However, this distance certainly is not 50vh anymore.
Why? Because it's not 50vh from top of page, but 50vh from where the element should normally be.
A way around this problem is to define the position value to 50vh - half the height
. If the div has a height of 200px, our CSS now looks like:
.wrapper {
height: 200px;
width: 50vw;
margin: 0 auto;
position: relative;
top: calc(50vh - 100px);
}
And our div is now vertically centered.
An important property: absolute
inside relative
It would be nice if we could position one element in terms of its parent div just like the drawer analogy, right? In fact, this is possible combining absolute and relative elements.
It happens exactly because absolute
(the yellow div, in this case) takes for reference the closest positioned element. And this element, here, is our wrapper
div.
Look how we can define the properties above:
.yellow-div {
position: absolute;
right: 0;
height: 100px;
width: 100px;
background-color: yellow
}
Now, right: 0
positions the yellow-div in terms of its parent div.
Important: there are other values for position. I will not cover them here, but I encourage you to research a bit about them.
Part 5 - back to display
: flexbox and grid
The first part of this post introduced inline
and block
.
Now, it's time to see the pinnacle of layout: flexbox and grid.
Flex and grid are display
values that, when applied to an element, allow you to organize the elements inside it as you want. You can organize them in rows, columns, or in personalized areas.
A little disclaimer: I will not describe their utilities in detail because it's probably out of the scope of this post; but I will list the recommended resources to learn each one.
Differences between them
In most cases, their usage overlap and choosing between one or another is more of a personal choice.
But observe the two layouts below:
grid
- take a brick and divide it
In the first layout, we have the content splitted in several sections. One example of it would be a blog page, where each section have a purpose - one of them may wrap the blog posts, another may show the recent posts, author information and so on.
With grid, you can easily define what's called grid areas. It makes grid
very powerful when you want to divide your content in independent, heterogeneous elements. I like to think as grid being a way to divide your content in blocks and straightforwardly personalize their structure. Simply put, it's a method to draw a block and divide it in any way you want, by cutting it into lines.
To learn it in practice, play all the phases of this game and try to create/replicate a layout of your choice using what you understood.
flex
- organize your items like on a shelf
The second layout presents more homogeneous elements.
The logic of flexbox is a bit different from grid: you can imagine the wrapper div with display: flex
being a shelf whose children elements are the items on it.
For this reason, flex
is a good choice when you want to organize similar items - like the buttons in a navbar, the images of a gallery, homogeneous content in general. Some properties of flex allow you to choose the order in which the items appear and if they are displayed in rows on in columns. flex
also presents the easiest way to center vertically and horizontally the contents of a div:
.random-div {
display: flex;
justify-content: center;
align-items: center;
}
To learn it, the strategy is the same as with grid, play this game instead and try to create/replicate a layout of your choice using what you understood.
After all, how to master CSS?
Personally, I believe that the only answer to this question is to create different front-end projects and practice. Nowadays, it's rare to use pure CSS as you have bootstrap, tailwind and many other frameworks - for example, I used tailwind for my blog!
But using frameworks does not mean that knowing pure CSS is useless. After all, to decide which class to apply to an element, you first have to understand the document flow and what exactly you intend to do.
Frameworks are just a way to prevent you from reinventing the wheel every single day, but they don't write the entire layout for you - you'll eventually need to fix the wheel when it breaks anyway.
Top comments (1)
Really nice article. Thanks a lot!