Shawn Erquhart
Shawn Erquhart

Reputation: 1858

How do you vertically center absolute positioned text w/o declaring container size and w/o JS?

I initially had vertically centered text using the table/table-cell display method, which worked great. The problem came when I switched to a percentage height for the container and used a block level image (sibling to the text in question) to set the size of the container. I can no longer get the absolutely positioned text to equal the container height without declaring a static container size. Obviously this is simple to solve with JS, but I'd prefer not to go that route.

I'm also using picturefill.js to serve images, so using the image as a css background isn't an option (unless anyone has suggestions to make it work).

Here's the fiddle:

http://jsfiddle.net/rHZdQ/

And here's the code:

HTML

<div class="tile">
  <a href="#">
    <img src="#">
    <div class="header-container">
      <h2>title</h2>
    </div>
  </a>
</div>

CSS

.tile {
  position: relative;
}

img {
  display: block;
}

a {
  display: block;
  position: relative;
}

.header-container {
  display: table;
  height: 100%;
  left: 0;
  position: absolute;
  top: 0;
  width: 100%;
}

h2 {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
  z-index: 199;
}

Upvotes: 2

Views: 1003

Answers (2)

Marc Audet
Marc Audet

Reputation: 46805

Centering Text in an Absolutely Positioned Image Overlay Using CSS

Consider the following HTML snippet:

<div class="tile">
    <div class="image-container">
        <img src="http://placekitten.com/400/400">
    </div>
    <div class="header-container">
        <div class="panel">
            <h2><span>percentage sized div</span></h2>
        </div>
    </div>
</div>

and apply the following CSS rules:

.tile {
    border: 3px solid #555;
    position: relative;
    margin: 6px;
    float: left;
}
.image-container img {
    display: block;
    height: 100%;
    width: 100%;
}
.header-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
.header-container .panel {
    display: table;
    width: 100%;
    height: 100%;
}
.header-container .panel h2 {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}
.header-container .panel h2 span {
    display: inline-block;
    padding: 5px;
    border-radius: 5px;
    background-color: rgba(255,255,255,0.5);
}

The parent/containing block is div.tile, and it has two child elements, .image-container which is in-flow, and .header-container which is absolutely positioned and hence out-of-flow.

Since .tile is floated, it shrinks-to-fit the content, which is the image in .image-container, with the dimensions determined by the native height and width of the image.

To create the overlay, .header-container is absolutely positioned to the top and left of its relatively positioned parent, with 100% width and height which forces it to extend to the containing block (see yellow outline).

Within .header-container, create an anonymous table by setting display: table to .panel, and specify 100% width and height so it extends and fills the .header-container.

Finally, define an anonymous table-cell on .panel's nested <h2> element, and apply text-align: center and vertical-align: middle to center the text post horizontally and vertically.

Note that the table-cell will extend the full width and height of the table so if you want to style the text with a border or background, you need to wrap it an inline-block element (the <span> in my example).

You can view the code at: jsFiddle Demo

Upvotes: 4

Stevenson
Stevenson

Reputation: 93

Does your .header-container need to be width:100%? Can you use pixels instead?

If you use pixels and you do the following, then it will center it:

.header-container {
  display: table;
  height: 100%;
  left: 50%;
  position: absolute;
  top: 0;
  width: 400px;
  margin-left:-200px;
}

Basically, margin-left has to be equal with half the width and a minus in fornt and then left:50%

UPDATE:

After informing me that it has to be only with percentage, the Jquery would be this:

$(document).ready(function() {

    var minus = '-';
    var headerwidth = $(".header-container").width();
    $(".header-container").css('margin-left',minus+(headerwidth/2)+'px');
    $(".header-container").css('left','50%');

});

Upvotes: 1

Related Questions