Search code examples
htmlcssvertical-alignmentcenteringrollover

How do I center text on top of an image in both dimensions?


Thank you all for your prompt feedback, it has been very helpful. One issue remains: Neither line-height, nor padding seem to be able to center both text that is long enough to wrap around and text that fits neatly on one line in the middle of the picture when applied in a table cell.

Oddly enough, the padding solution provided below by SwDevMan81 works flawlessly when applied to a div, but not a table cell...

I apologize in advance for my naivety; this is my first foray into HTML and CSS.

The code for the table is as follows:

<table border="1">
    <tr>
        <td class="imgcontainer">
            <a href="#">
                <img src="http://www.bigjimsburgers.com/burger.jpg" alt="" />
                <span class="desc">
                    Very long text that wraps around and is centered properly
                </span>
            </a>
        </td>
        <td class ="imgcontainer">
            <a href="#">
                <img src="http://www.bigjimsburgers.com/burger.jpg" alt="" />
                <span class="desc">
                    misaligned text
                </span>
            </a>
        </td>
    </tr>
    <tr>
        <td class="imgcontainer">
            <a href="#">
                <img src="http://www.bigjimsburgers.com/burger.jpg" alt="" />
                <span class="desc">
                    misaligned text
                </span>
            </a>
        </td>
        <td class ="imgcontainer">
            <a href="#">
                <img src="http://www.bigjimsburgers.com/burger.jpg" alt="" />
                <span class="desc">
                    Very long text that wraps around and is centered properly
                </span>
            </a>
        </td>
    </tr>
</table>

<style type="text/css">
    .imgcontainer {
        overflow: hidden;
        text-align: center;
    }

    .imgcontainer img {
        float: left;
        background: #fff;
        width: 200px;
        height: 200px;
    }

    .imgcontainer a .desc {
        display: none;
        font-size: 1.0em;
    }

    .imgcontainer a:hover {
        cursor: pointer;
        text-decoration: none;
    }

    .imgcontainer a:hover .desc {
        display: -webkit-box;
        display: -moz-box;
        display: box;
        -webkit-box-align: center;
        -moz-box-align: center;
        box-align: center;
        background: #DDD;
        filter: alpha(opacity=75);
        opacity: .75;
        -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=75)";
        position: absolute;
        width: 200px;
        height: 200px;
    }
</style>

Solution

  • You need not apologise for naivete. Vertical Centering is one of the most misunderstood parts of CSS.. and unfortunately, while there is an easy solution - to use the table display properties - they are not supported by IE7 and below..

    So some form of hack is necessary for them, what is your support requirements?

    The optimal IE solution I have involves a hack to both the HTML and CSS (and extra HTML element is helpful for them)

    Here's the code that should work without IE6/7 support:

    HTML is as yours above

    CSS:

    table {
      table-layout: fixed;
      width: 403px;
      border-collapse: collapse;
      border-spacing: 0;
    }
    
    .imgcontainer {
      text-align: center;
      padding: 0;
      vertical-align: middle;
      border: 1px solid #000;
    }
    
    .imgcontainer img {
      float: left;
      width: 200px;
      height: 200px;
      border: 0;
    }   
    
    .imgcontainer a {
      display: block;
      width: 200px;
      height: 200px;
      overflow: hidden;
      cursor: pointer;
      text-decoration: none;
    }  
    
    .imgcontainer a:hover img {
      margin-right: -200px;
    }
    
    .imgcontainer a .desc {
      display: table-cell;
      vertical-align: middle;
      border-spacing: 0;
      border-collapse: collapse;
      width: 200px;
      height: 200px;
      padding: 10px;
      background: #cfc;
    }
    
    .imgcontainer a:hover .desc {
      background: #DDD;
      opacity: .75;
      -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=75)";
    }
    

    Working Example : HERE


    and: with optimal IE6/7Support

    add an <i></i> element between the img and span in the HTML like this:

    <td class ="imgcontainer">
        <a href="#">
            <img src="http://www.bigjimsburgers.com/burger.jpg" alt="" />
                <i></i>
            <span class="desc">misaligned text</span>
        </a>
    </td>
    

    Then conditional CSS : (add to a sheet that comes after the main stuff above)

    <!--[if LTE IE 7]>
    <style type="text/css" media="screen">
    .imgcontainer i {
      display: inline-block;
      width: 200px;
      height: 200px;  
      line-height: 200px;
      background: #DDD;
      filter: alpha(opacity=75);    
      vertical-align: middle;
      margin-right: -200px;
    }
    
    .imgcontainer a .desc {
        display: none;
        width: 180px;
        height: auto; 
    }
    
    .imgcontainer a:hover .desc {
        display: inline-block;
        background: transparent;    
    }
    
    </style>
    <![endif]-->
    

    OR - without the extra HTML element or proper vertical centering

    If you don't want to add the extra HTML <i></i> element for IE6/7 you could combine the first solution with a top padding solution, which won't perfectly vertically centre the text but should provide a graceful fall-back for IE6/7.

    in which case the IE conditional CSS would look like this:

    <!--[if LTE IE 7]>
    <style type="text/css" media="screen">
        .imgcontainer a .desc {
            display: none;
            padding: 40px 10px 10px 10px;
            width: 180px;
            height: 150px; /* if adding to top padding, adjust height accordingly */
        }
    
        .imgcontainer a:hover .desc {
            display: inline-block;
            filter: alpha(opacity=75);      
        }
    </style>
    <![endif]-->
    

    Update

    as per comments, to make this work and retain border-spacing on the parent table you would remove the table CSS

    table {
    /*
      table-layout: fixed;
      width: 403px;
      border-collapse: collapse;
      border-spacing: 0;
    */
    }
    

    and then ADD border-spacing: 0; to the a

    .imgcontainer a {
      display: block;
      width: 200px;
      height: 200px;
      overflow: hidden;
      cursor: pointer;
      text-decoration: none;
      border-spacing: 0;
    }  
    

    adding the above means the span which is set to display: table-cell; doesn't inherit the border-spacing on the parent table

    Working example with border-spacing