Centring text, literally

May 6, 2024

Earlier this year, I posted the essay Centring text. This title is confusingly punny. Recently, murid said that they were disappointed to find it wasn't a tutorial about centring text using CSS. Oops! The pun was intended (how can you title something "centring text" without realising the double meaning?) but the confusion definitely was not. So, to make up for my misdeeds with wording, let me dedicate a blog post to centring text, literally.

First, let me say that I'm not a CSS expert! Case in point, I'm off to a bad start with this disclaimer: I think what people would recommend these days are grid and flex (at the very least, these CSS features are the most modern), but I don't tend to use these so I won't really cover them. I'll include a short description of the two at the end, just so you get a picture of what's missing from this post.

grid and flex aside, I can't possibly cover every trick there is in CSS. In this post, I'll show the two most useful approaches that I've found. If they aren't working out for you, feel free to get in touch, either on my NeoCities profile or email at the bottom of this page.

Before we get started, here's a list for your reference:

the HTML tags and CSS properties mentioned in this blog post (in order of appearance)

CSS property text-align: center

The simplest, most straightforward approach is to apply the CSS text-align: center to the element with text in it. For example, check out this div to which I've done exactly that:

Here's some text. Can you tell it's centred? Doesn't it look good? I'll write a whole bunch of nonsense here just to take advantage of the fact that it's centred and attention-grabbing.

(Feel free to inspect the source code! Any website that discourages you from doing so, whether explicitly or implicitly by having so much back-end faff that the web source is uninformative, isn't really adhering to the spirit of the web.) (By the way, can we all recognise the US-centric nature of CSS (and, indeed, much of programming)? Where's the centre element for all my fellow Canadians?)

What's happened is that I've told the element holding the text, in this case the div, to align the text in a certain way. The default is generally left-align, especially with languages that are read left to right.

CSS property margin

Well, that was easy! But, wait. As you can see from the example above, the width of the box takes up the whole width of the text. What if you didn't want the box to be so wide? Let's see what happens if we also add a width property to the div that holds our text:

I've modified the width of this box by adding the CSS width: 50%, so now it takes up half the original width. Again, feel free to inspect the source!

Now, we may or may not have a problem. The text inside the box is still centred within the box, but the box itself isn't centred in the context of the surrounding text. That's because the box is in turn an element of something. In this case, it's the main tag in my web layout, but it could be anything. What's important is that the outer element is left-aligning its contents: just look around at the surrounding text that's all left-aligned. So it takes the box, treats it just like anything else (except that it's big and tall and has got stuff inside; in this way, websites are kind of like fractals), and left aligns it. To visualise it a bit:

main element
Body text that's inside the main element. It's left-aligned, because the main element left-aligns its text, and we would like the text to stay left-aligned.
div element
I've modified the width of this box by adding the CSS width: 50%, so now it takes up half the original width. Again, feel free to inspect the source!

More text, if there's more text to go after the box with the centred text. Just so it's easy to see that this outer stuff is left-aligned.

Situations like this one are usually when people get stuck. How can they get the box holding the centred text to be centred itself? The easy answer is to tell CSS to add an "automatic margin" to the left and to the right of the box that you want to position in the middle.

I've modified the horizontal margins of this box by adding the CSS margin-left: auto; margin-right: auto, so now it lies in the middle of its surrounding context. Again, feel free to inspect the source!

margin tells the browser how much space to put around and element: its margin relative to the other stuff on the page. It's got four predictable sub-properties: margin-top, margin-bottom, margin-left, and...well, I'll let you guess the last one. For example, applying margin-bottom: 10px tells the webpage that you want some space below the element. Actually, exactly ten pixels of space. Anything that follows should jump some space so that there's a ten-pixel gap between the bottom of the element and everything else.

If you put auto, then you're asking the webpage to automatically create some margin space. By asking the webpage to do it for both margin-left and margin-right, the webpage will evenly divide the available horizontal space and put half on the left and half on the right. In other words, you've centred your element!

Let's see what happens if we remove the text-align: center but we keep the horizontal margin property.

I've still got margin-left: auto; margin-right: auto, but now the text-align is just the default. Again, feel free to inspect the source!

Now, the box containing the text is centred on the page (the horizontal margins are automatically chosen so that they're equal), but the text inside the box is actually left-aligned. Usually when people say they want to centre text on a page, this result is actually what they're looking for because they're trying to build a website layout. For example, my own website has this look, and so do most others.

The problem is, of course, that they will search for "how to centre text on a page" and the tempting, juicy CSS property that comes back is text-align: center. As we've seen, this property is a total red herring. People try it out, it doesn't do what they want, and they (understandably!) get frustrated. Most importantly, they don't know what to search or try next. Certainly, margin wouldn't come to mind. Thinking about positioning a box with text inside of it in terms of the margins it's got to the left and to the right? Totally unintuitive.

(As a little side-tip, it helps a lot when building a layout to just put borders around everything at first. Then you can clearly see the size and boundaries of all your elements. It'll also help you conceptualise them as boxes, and start to think about their margins or other spatial relationships with each other. Bonus: assign each a different colour so you can really tell them apart! Once the layout is done, just nix them.)

For manually positioned objects

I actually didn't mention one (semi-important) thing. This margin approach works if the box has the property display: block. You can always add this property yourself. It basically tells the webpage that it should display the element "as though it's a paragraph": at full width (unless you modify it, like we did above), with a line break before and a line break after. That means that your element still is in the flow of your page. In other words, whatever you have in your HTML file before your box will display before your box, and whatever you have in your HTML file after your box will display after your box.

What about something like a navigation bar? You might want to position your nav bar youself, ignoring what canonically appears before and after it in the HTML file. For example, you might want it to appear at the top of the screen, the first thing displayed, even if you've got a bunch of text written into your HTML document before the nav element.

This type of positioning is position: absolute. If you do that, then, the nav bar isn't displayed "like a paragraph", in the flow of the page's content. It's more like a post-it note, that's been plucked out of the HTML and stuck somewhere onto the page.

Then, how can you centre this type of element on the page? The first instinct might be something like left: 50%, which tells the webpage to take 50% of the window's width and move the box this distance from the left side of the window. That works well enough, except for one thing. Let's take a look.

browser window

home blog

The left edge of the textbox is placed in the middle of the "browser window". Usually you want the centre of the textbox to be placed in the middle of the browser window. With modern CSS, that's easy enough to achieve! Just tell the webpage to move the box back left: transform: translateX(-50%). This property tells the webpage to move the box itself along the X axis (horizontally) by 50% of its own width. The negative sign means go left (positive means go right). Let's put it all together:

browser window

home blog

It works!

The navigation bar is just one example, of course. In general, this approach will work on something with position: fixed, position: absolute, etc. (Again, how I wish we had these tools years ago. I would have had the dopest website among my high school friends.)

grid and flex

Both grid and flex are good for building a full site layout, something complex with multiple elements, but overkill if you're just trying to centre one block of text.

grid is elegant and powerful. If you are trying to put position lots of elements precisely, grid is really the best way to go, by far. It accomplishes everything that we were all trying to accomplish with table tags in HTML back in the day. (Believe me, back when I was spending hours struggling with a table-based layout, I would have died for the modern grid.)

As for flex, even though I've used it several times in the past, I really just have to admit that I simply don't get it. It's too complicated. I have to look it up anew every time. As far as I understand, it's basically a worse version of grid. The only reason to use it is that it's older, so supported by more browsers.

send a comment