CSS Layout Centering Techniques
Tags: css, javascript, beginners
Published: 2018-02-06 20:33:21

Centering elements with CSS sometimes can be tricky. There are plenty of techniques that you could use but what technique you should use depends on the element and the content. Some questions that you might ask yourself when trying to center an element could be:
<ul>
 	<li>Is it an inline or a block element?</li>
 	<li>Is it just one line of text or multiple lines?</li>
 	<li>Does it have a fixed width and height or its size is unknown?</li>
</ul>
These are likely the most common questions to ask yourself when you want to center an element.

I'm gonna divide the techniques by horizontal, vertical and both.
Let's get to the code.
<h2><b>Horizontal Centering</b></h2>
<b>Text-align</b>

<span style="font-weight: 400;">That's the simplest horizontal centering technique that you could use for text and inline-* elements.</span>
<pre class="EnlighterJSRAW" data-enlighter-language="css">p { text-align: center; }</pre>
In case you want to center an inline element you should apply it on its parent and not directly on that element:
<pre class="EnlighterJSRAW" data-enlighter-language="css" data-enlighter-title="CSS" data-enlighter-group="ta">.parent { text-align: center; }</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="html" data-enlighter-title="HTML" data-enlighter-group="ta">&lt;div class="parent"&gt;
 &lt;strong&gt;I'm Centered&lt;/strong&gt;
&lt;/div&gt;</pre>
<span style="font-weight: 400;">In case we have an inline-block element we could make it full width and apply <code>text-align: center;</code> on it directly instead of it's parent.</span>
<pre class="EnlighterJSRAW" data-enlighter-language="css">strong {
 display: inline-block; 
 width: 100%;
 text-align: center;
}</pre>
<a href="https://codepen.io/AlanFall/pen/aqOGXw/">Pen</a>
<br/>

<strong>Margin Auto</strong>

This is the most common technique for centering horizontally block elements, it's widely used by many frameworks like <a href="https://getbootstrap.com/">Bootstrap</a>. You just set the left and right<code>margin</code> to auto, make sure you have also set a width:
<pre class="EnlighterJSRAW" data-enlighter-language="css">.block-box { 
 width: 600px;
 margin: auto;
}
</pre>
<a href="https://codepen.io/AlanFall/pen/zRGaoP/">Pen</a>

<strong>Absolute Position</strong>

A common technique for both horizontal and vertical centering is using an absolute positioned element as child of a relative parent.

What we do is basically position our child element left by 50% and we shift it back by half of its size using a negative 50% <code>translateX</code> in order to get it centered.
<pre class="EnlighterJSRAW" data-enlighter-language="css" data-enlighter-group="absh" data-enlighter-title="CSS">.parent { position: relative; }
.centered-element {
 position: absolute;
 left: 50%;
 transform: translateX(-50%);
}</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="html" data-enlighter-group="absh" data-enlighter-title="HTML">&lt;div class="parent"&gt;
 &lt;div class="centered-element"&gt;I'm Centered!&lt;/div&gt;
&lt;/div&gt;
</pre>
That's also a nice way to center elements of unknown width (and height).

An alternative to that, -if you have elements of known width- would be to use a negative <code>margin-left</code> instead of <code>translateX</code>:
<pre class="EnlighterJSRAW" data-enlighter-language="css">.centered-element { 
 position: absolute;
 width: 600px;
 left: 50%;
 margin-left: -300px; // Shift it back by half of it's size.
}</pre>

<a href="https://codepen.io/AlanFall/pen/VQLdOo/">Pen</a>

<strong>Flex</strong>

If you don't care about support of older browsers, a nice way to horizontally(and vertically) center an element or a bunch of elements is by using flex.
<pre class="EnlighterJSRAW" data-enlighter-language="css">.parent { 
 display: flex; 
 justify-content: center;
 height: 100vh;
}</pre>
<em><strong>Note:</strong> Make sure you haven't set the <code>flex-direction</code> property to column otherwise you'll have the opposite effect (vertical center).</em>

<a href="https://codepen.io/AlanFall/pen/GQJBpZ/">Pen</a>

<h2>Vertical Centering</h2>
<strong>Absolute Position</strong>

Again, we could use the same absolute positioning technique we used previously but instead of setting the left position to 50% we set the top position to 50% and we shift it up using a negative 50% <code>translateY</code>:
<pre class="EnlighterJSRAW" data-enlighter-language="css">.parent { position: relative; }
.centered-element {
 position: absolute;
 top: 50%;
 transform: translateY(-50%);
}</pre>
<a href="https://codepen.io/AlanFall/pen/VQLBjY/">Pen</a>


<strong>Table Cell</strong>

A nice way for vertical centering would be to use vertical-align: middle. Of course this is tricky because you have to apply it on elements of a parent that is set to<code> display: table</code> and children to <code>display: table-cell</code>.
<pre class="EnlighterJSRAW" data-enlighter-language="css">.parent { 
 display: table;
 height: 100vh; 
}

.centered-element {
 display: table-cell;
 vertical-align: middle;
}</pre>
<em><strong>Note:</strong> Make sure that the parent element has height otherwise this won't work.</em>

<a href="https://codepen.io/AlanFall/pen/PQqBbW/">Pen</a>


<strong>Line-height</strong>

This technique is okay if you want to center single words and not whole paragraphs or lines of text. If you have a single word inside an element you could vertically center it by setting a fixed height on that element and a<code> line-height</code> equal the height of the element:
<pre class="EnlighterJSRAW" data-enlighter-language="css" data-enlighter-group="line-heightv" data-enlighter-title="CSS">.box { 
 width: 600px;
 height: 600px;
 line-height: 600px;
}</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="html" data-enlighter-group="line-heightv" data-enlighter-title="HTML">&lt;div class="box"&gt;
 &lt;strong&gt;I'm Centered&lt;/strong&gt;
&lt;/div&gt;</pre>
<a href="https://codepen.io/AlanFall/pen/zRGLPQ/">Pen</a>


<strong>The Ghost Element</strong>

In this technique, we have two inline-block elements: a container with a "ghost" pseudo element set to full height and a child that is set to<code> vertical-align: middle;</code> This way the child element aligns with the ghost element -which has also <code>vertical-align: middle</code>
<pre class="EnlighterJSRAW" data-enlighter-language="css">.container { font-size: 0; }
.container::before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}
.container strong {
 display: inline-block;
 vertical-align: middle;
 font-size: 1rem;
}</pre>
<em><strong>Note:</strong> The ghost element creates an empty space usually on the left side so make sure to add a negative margin (<code>margin-right: -0.25em</code>) or a <code>font-size: 0</code> on the parent container and a <code>font-size: 1rem</code> on the child.</em>

<a href="https://codepen.io/AlanFall/pen/xYGJWK/">Pen</a>



<strong>Flex</strong>

We've seen how to align horizontally with flex. We can do the same for vertical centering by using the <code>align-items</code> property.
<pre class="EnlighterJSRAW" data-enlighter-language="css">.parent { 
 display: flex; 
 align-items: center;
 height: 100vh;
}</pre>
<em><strong>Note:</strong> again, make sure you haven't set the <code>flex-direction</code> to <code>row</code>, otherwise you'll have the opposite effect. (horizontal centering).</em>

<a href="https://codepen.io/AlanFall/pen/YeXjeW/">Pen</a>


<h2>Horizontal &amp; Vertical Centering</h2>
We can combine all the techniques we used previously to center in both axis.

From all the techniques we used, the absolute positioning and the flex technique will give us both Horizontal and Vertical centering.

<strong>Absolute Position</strong>

We position the element to 50% in both top and left and we shift back in both positions by using a negative translate of 50%:
<pre class="EnlighterJSRAW" data-enlighter-language="null">.centered-element {
 position: absolute;
 top: 50%;
 left: 50%;
 transform: translate(-50%, -50%);
}</pre>
<a href="https://codepen.io/AlanFall/pen/qxdyLb/">Pen</a>


<strong>Flex</strong>

Again, using the same flex technique we use both<code> align-items</code> and <code>justify-content</code> set to center.
<pre class="EnlighterJSRAW" data-enlighter-language="null">.parent { 
 display: flex; 
 align-items: center;
 justify-content: center;
 height: 100vh;
}</pre>
<a href="https://codepen.io/AlanFall/pen/MQKxam/">Pen</a>


Have something to add? Feel free to throw it on the comments section.

<em>Thanks to <a href="http://www.pvgr.eu/" target="_blank" rel="noopener">PVGR</a> for the useful info and corrections.</em>