Text Blocks Over Image

Avatar of Chris Coyier
Chris Coyier on

Get affordable and hassle-free WordPress hosting plans with Cloudways, now offering 40% off for 4 months, and 40 free migrations.

Someone recently asked me about this technique and my first reaction was that it was probably a little too mundane to cover as a tutorial. But then I got to thinking that there is actually a few interesting things happening here and the style is trendy enough people might be interested.

The idea is just to overlay some text over an image, but as blocks that stick out from the left with an even amount of padding all the way around the variable-length text. Here is a screenshot example:

 

View Demo

 

The Schematics

The HTML

<div class="image">

      <img src="images/3754004820_91a5c238a0.jpg" alt="" />
      
      <h2>A Movie in the Park:<br />Kung Fu Panda</h2>

</div>

Putting the image in as a background image of the wrapping div would be easier, but in this scenario I see the images as content, and thus belongs in the HTML. We’ll use that wrapping div as a container for absolute positioning.

The CSS

.image { 
   position: relative; 
   width: 100%; /* for IE 6 */
}

h2 { 
   position: absolute; 
   top: 200px; 
   left: 0; 
   width: 100%; 
}

This is going to put our text right up on top of the image nicely, but it doesn’t accomplish the transparent black box we want to achieve behind the text. For that, we can’t use the h2, because that is a block level element and we need an inline element without an specific width.

Let’s wrap the inside h2 of the in a span:

<h2><span>A Movie in the Park:<br />Kung Fu Panda</span></h2>

The use that span to style the text and background:

h2 span { 
   color: white; 
   font: bold 24px/45px Helvetica, Sans-Serif; 
   letter-spacing: -1px;  
   background: rgb(0, 0, 0); /* fallback color */
   background: rgba(0, 0, 0, 0.7);
   padding: 10px; 
}

Problem

When an inline element breaks, the block breaks immediately after the last character in the line, and begins immediately flush left on the next line. Padding, in this case, does not help us.

To solve this, we’ll apply some more spans on either side of the <br /> element to simulate that padding.

<h2><span>A Movie in the Park:<span class='spacer'></span><br /><span class='spacer'></span>Kung Fu Panda</span></h2>

Those new spans we’ll use to apply padding:

h2 span.spacer {
   padding:0 5px;
}

Fixing Semantics

At this point the design is accomplished, but there there is an awful lot of extra HTML elements added purely for design reasons. Namely, all those spans. jQuery can jump in and save us here. Simply remove all the spans from the markup, and dynamically apply them like this:

$(function() {
    
    $("h2")
        .wrapInner("<span>")

    $("h2 br")
        .before("<span class='spacer'>")
        .after("<span class='spacer'>");

});