site icon

Hi, I’m Chris

I am a web developer teaching
regular people how to code

~ Welcome to my blog ~

Centre any text over an image: without Flexbox

When building websites, one of the CSS issues you will undoubtedly come across at some point is to centre text over an image, both horizontally and vertically. This post will show you an easy way to do this without using the CSS Flexbox.

First, we need some HTML to work with:

<section>
  <img src="https://res.cloudinary.com/djn1ticju/image/upload/v1577899697/business.jpg" alt="">
  <p>centered text</p>
</section>

Pretty basic but we simply have a section containing an image and some text. Without and CSS input, the text would sit below the image in the browser.

This is because by default, elements will take up space in the order they are in the HTML, so it makes sense that we have an image followed by the text below.

One way we can change this, is to set the CSS position of the text to be absolute.

Absolute will remove the element from the flow of the page, meaning it effectively won’t take up any space, and we can position it anywhere we want.

img {
  max-width: 100%;
}

p {
  position: absolute; /* <====== */
  font-size: 60px;
  color: white;
}

This will leave the text on the page, but it no longer takes up any space.

It’s also not in a good position, so we can move it using the CSS properties of top, right, bottom and left to re-position it.

We want the text to be in the middle, so it makes sense to set it 50% from the top, and 50% from the left:

  img {
  max-width: 100%;
}

p {
  position: absolute; 
  font-size: 60px;
  color: white;
  top: 50%;
  left: 50%;
}

But 50% from the top and left of where?

When we take the text out of the document flow using absolute, and set the top and left as we have done, these top and left values are set from the browsers viewport.

So, we have effectively set the text 50% from the top corner of the browser.

On this small example, the image is similar size to the viewport, so it may still appear to be in the centre. But, on a larger page with more content, this may not be positioned as expected.

There is a way we can override this though, and this is to set any other element to have a position of relative, such as our image:

img {
  max-width: 100%;
  position: relative; /* <====== */
}

p {
  position: absolute;
  font-size: 60px;
  color: white;
  top: 50%;
  left: 50%;
}

Now when we position the text, it is set from the image.

This now leaves us close to the middle, but not quite perfect because it has been pushed over 50% from the left, and 50% from the top, but it does not account for the width and height of the text.

Instead, we want it to be moved over 50% to the centre of the text.

We can do this by moving the text back by 50% of its width and height, this percentage unit will also still centre the text regardless of its size:

img {
  max-width: 100%;
  position: relative;
}

p {
  position: absolute;
  font-size: 60px;
  color: white;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Leaving us with a perfect text overlay.

You can also check out a working demo here.


- By Chris Dixon

Chris Dixon is a web developer and teacher. Teaching thousands of students mainly in Vue.js React.js, WordPress and web development.