Task
You have the task of centering a block in the center of the screen both vertically and horizontally. Let's assume this will be a popup. In this recipe, we will consider all existing ways to solve the problem as of now.
Ready Solution
Below are all possible ways to center an element. Choose one of them.
Centering with grids:
.parent { display: grid; place-items: center;}
.parent { display: grid; place-items: center; }
Centering with flexbox, method one:
.parent { display: flex; justify-content: center; align-items: center;}
.parent { display: flex; justify-content: center; align-items: center; }
Centering with flexbox, method two:
.parent { display: flex;}.child { margin: auto;}
.parent { display: flex; } .child { margin: auto; }
.child { margin-inline: auto; margin-block-start: 50vh; transform: translateY(-50%);}
.child { margin-inline: auto; margin-block-start: 50vh; transform: translateY(-50%); }
Absolute positioning when height is known:
.child { height: 200px; margin-inline: auto; inset-inline: 0; /* Top margin 50% minus half the height */ inset-block-start: calc(50% - 100px);}
.child { height: 200px; margin-inline: auto; inset-inline: 0; /* Top margin 50% minus half the height */ inset-block-start: calc(50% - 100px); }
Absolute positioning when height is unknown:
.child { margin-inline: auto; inset-inline: 0; inset-block-start: 50%; transform: translateY(-50%);}
.child { margin-inline: auto; inset-inline: 0; inset-block-start: 50%; transform: translateY(-50%); }
Solution Breakdown
Before breaking down each of the solutions, let's understand the starter code. In all examples, we will set 100% height for <html>
and <body>
to stretch the page height.
Also, in all examples, logical properties are used wherever possible to keep the code modern.
As the block that we will be centering, we will use the tag <dialog>
. It is currently customary to create popups using this.
Note that this element has absolute positioning by default. We will override the positioning to static so that it does not interfere. Also, note that the examples use the HTML tag <dialog>
with explicitly set values for width and height. When applying to other tags, ensure that they have values set for width
and height
.
Starter code:
<body class="parent"> <dialog class="child" open> <h1>Hello, this is WebGuide!</h1> </dialog></body>
<body class="parent"> <dialog class="child" open> <h1>Hello, this is WebGuide!</h1> </dialog> </body>
html { height: 100vh;}body { min-height: 100%;}dialog { position: static;}
html { height: 100vh; } body { min-height: 100%; } dialog { position: static; }
Grids
The most modern and elegant way to center an element is by using grids.
We make the parent — in this case, .parent
— a grid container.
.parent { display: grid;}
.parent { display: grid; }
After this, we can use grid container properties to align nested elements along the vertical and horizontal axes:
.parent { display: grid; justify-items: center; align-items: center;}
.parent { display: grid; justify-items: center; align-items: center; }
Or use a shorthand to combine two properties into one:
.parent { display: grid; place-items: center;}
.parent { display: grid; place-items: center; }
Flexbox. First method
We use flexbox to center. There are two ways here. In the first case, we will set properties for the parent.
We make the parent a flex container:
.parent { display: flex;}
.parent { display: flex; }
We set properties to center along the vertical and horizontal axes:
.parent { display: flex; justify-content: center; align-items: center;}
.parent { display: flex; justify-content: center; align-items: center; }
Flexbox. Second method
When the parent is a flex container, the child can have automatic margins on all sides.
.parent { display: flex;}.child { margin: auto;}
.parent { display: flex; } .child { margin: auto; }
Margin and Transformation
In this method, we use a combination of margins and transformation. To start, we will center the block along the horizontal axis with automatic margins, and push it down from the top by 50%:
.child { margin-inline: auto; margin-block-start: 50vh;}
.child { margin-inline: auto; margin-block-start: 50vh; }
The top margin is 50% of the screen height, but this shifts the element just below the center.
To position the element exactly in the center, we need to use the transform
property with the translate
function as its value.
.child { margin-inline: auto; margin-block-start: 50vh; transform: translateY(-50%);}
.child { margin-inline: auto; margin-block-start: 50vh; transform: translateY(-50%); }
When transforming, percentages are calculated based on the actual size of the element being transformed. Therefore, our block rises exactly by half of its height.
Absolute Positioning with Known Height
Let's return absolute positioning to our dialog and try to center it in that state. Don't forget to set position
for the parent so that the child is positioned relative to the edges of the parent.
To start, let's break down the example when the element has a fixed height:
.parent { position: relative;}.child { position: absolute; height: 200px;}
.parent { position: relative; } .child { position: absolute; height: 200px; }
First, we need to set the coordinates of position measurement to zero on all four sides. We will use the logical property inset
.
.child { position: absolute; height: 200px; inset: 0;}
.child { position: absolute; height: 200px; inset: 0; }
In reality, we only need zeros for the horizontal axis. For vertical alignment, we will use the familiar technique of automatic side margins.
For the vertical axis, we want to push the element down from the top by 50% minus half the height of the element. In our case, that is 125 pixels. We will use the function calc
:
.child { position: absolute; height: 250px; margin-inline: auto; inset-inline: 0; inset-block-start: calc(50% - 125px);}
.child { position: absolute; height: 250px; margin-inline: auto; inset-inline: 0; inset-block-start: calc(50% - 125px); }
Absolute Positioning without Known Height
In this variant, the height of the element is not fixed. This means we have nothing to subtract from 50% for the top margin. We use transform
, which calculates percentages based on the element size.
.child { position: absolute; margin-inline: auto; inset-inline: 0; inset-block-start: 50%; transform: translateY(-50%);}
.child { position: absolute; margin-inline: auto; inset-inline: 0; inset-block-start: 50%; transform: translateY(-50%); }