BenM
BenM

Reputation: 53198

Vertical Alignment with position: absolute

I am trying to center-align text (that may or may not span several lines) within a <div> that has position: absolute applied to it.

Please consider the following markup:

<div class="item">
    <img src="test.jpg" />
    <div class="overlay">
        <a href="#">Some long content</a>
    </div>
</div>

The CSS applied is as follows (please note that this is the LESS version):

.item {
    position: relative;

    img {
        position: relative;
        z-index: 1;
    }

    .overlay {
        position: absolute;
        z-index: 2;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        background: rgba(0,0,0,.5);
        text-align: center;

        a {
            color: #fff;
        }
    }
}

As well as being center-aligned horizontally, I'd like for the text within .overlay to be vertically aligned to the middle. I've tried adding the following:

.item {
    display: table;

    .overlay {
        display: table-cell;
        vertical-align: middle;
    }
}

I've also tried inline-block but nothing helps, since the element is absolutely positioned. I cannot use the usual line-height trick here, since the text may span several lines, and specifying a large line height will break the layout.

Does anyone know of a (relatively) cross-browser method to solve this issue? It needs to work in IE9+, FF and Chrome. If possible, I'd like to avoid adding any additional markup or 'divitis'.

I've put together a jsFiddle to demonstrate my issue (you'll also see the usual tricks work fine when the position != absolute):

jsFiddle Demo

Upvotes: 2

Views: 187

Answers (3)

Lokesh Suthar
Lokesh Suthar

Reputation: 3202

If using absolute position, I find this solution to work every time

.item .overlay{
   top:50%;
   -webkit-transform:translateY(-50%);
}

Upvotes: -1

streetlogics
streetlogics

Reputation: 4730

Just make the absolute positioned element a "positioning" container, and put the actual element containers inside, like so - http://jsfiddle.net/Ggbtt/4/

HTML:

<div class="item">
    <img src="http://placehold.it/350x150.jpg" />
    <div class="overlay">
        <div class="inner-container">
            <div class="inner-cell">
                <a href="#">Some long content</a>
            </div>
        </div>
    </div>
</div>

CSS:

.item {
    position: relative;
    width: 350px;
    display: table;
}
    .item .overlay {
        position: absolute;
        z-index: 2;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        background: rgba(0,0,0,.5);
        text-align: center;
        width: 100%;
        height:100%;
        vertical-align: middle;
    }
        .inner-container{
            width: 100%;
            height: 100%;
            display:table;
        }
        .inner-cell {
            display:table-cell;
            vertical-align: middle;
            text-align: center;
        }
            .item .overlay a {
                color: #fff;
            }

Upvotes: 0

DaniP
DaniP

Reputation: 38252

Use a pseudo-element like :before and inline-block this way:

.item .overlay:before {
  content:" ";
  display:inline-block;
  vertical-align:middle;
  height:100%;
}
.item .overlay a {
  display:inline-block;
  vertical-align:middle;
  color: #fff;
}

Check this Demo Fiddle

You may need to handle the space between those inline-block items HERE I use margin-right

Upvotes: 2

Related Questions