I enjoyed Erik D. Kennedy's post 7 Rules for Creating Gorgeous UI (Part 2). In it, his Rule 4 is: Learn the methods of overlaying text on images. I thought we could take a look at all his points, code them up, and note anything that comes up technically.

Tinting

The image should be dark, and not have a lot of contrast-y edges.

Picking an image is up to you, but let's say it isn't particularly dark. You could darken it in an image editing program, or, with CSS, overlay a transparent color. Probably the cleanest way to do that is to use multiple backgrounds, but that isn't super obvious how to do. The trick is using a gradient that doesn't gradient-ize (doesn't fade from color to color, is just solid).

.darken {
  background-image: 
    linear-gradient(
      rgba(0, 0, 0, 0.5),
      rgba(0, 0, 0, 0.5)
    ),
    url(shoes.jpg);
}

See the Pen Darken Image with Multiple Backgrounds by Chris Coyier (@chriscoyier) on CodePen.

And while a black overlay is simplest and most versatile, you can certainly find colored overlays as well.

Indeed with this method you can color however you want from the comfort of CSS:

See the Pen Darken Image with Multiple Backgrounds by Chris Coyier (@chriscoyier) on CodePen.

White Text

The text has to be white — I dare you to find a counter-example that’s clean and simple. Seriously. Just one.

I find this to be true as well, at least when trying to be classy whatsoever. Garbage magazines tend to go with yellow.

See the Pen myPMGB by Chris Coyier (@chriscoyier) on CodePen.

Full Page Images

One way in which it's rather unavoidable to set text on an image is when you make the entire screen fill with a background image. We've covered how to do that before, you're best bet is:

body {
  background: /* do whatever tinting and stuff here */;

  /* This will ensure everywhere is covered */
  background-size: cover;
}

See the Pen zxqdev by Chris Coyier (@chriscoyier) on CodePen.

And by the way, if you wanted to cover the entire screen like this, but then be able to scroll down for more, you could set the top area as having a height of 100vh units.

See the Pen myPMvp by Chris Coyier (@chriscoyier) on CodePen.

Browser support varies a bit there. You might wanna have a fixed height fallback and/or do it with JavaScript.

Text-in-a-box

This is dead simple and very reliable. Whip up a mildly-transparent black rectangle and lather on some white text. If the overlay is opaque enough, you can have just about any image underneath and the text will still be totally legible.

Works with any contrast-y color combination.

See the Pen Darken Image with Multiple Backgrounds by Chris Coyier (@chriscoyier) on CodePen.

With a single line of text, this is easy. But if there is any chance of the text breaking, it's harder. You could leave the title as display: block; but it's not as elegant perhaps as inline. But with inline, you need to take care that the spacing around the line breaks isn't awkward.

We've covered this before. I think it's coming down to box-decoration-break as being the way forward:

.title { 
  background-color: black;
  color: #fff; 
  display: inline;
  padding: 0.5rem;
  
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

See the Pen Multiline Padding with box-decoration-break by Chris Coyier (@chriscoyier) on CodePen.

Blurring

A surprisingly good way for making overlaid text legible is to blur part of the underlying image.

One way to do that is to to have a section of the area inherit the same background, position it the same (fixed attachment is one way), then blur it.

.module {
  background: url(http://s3-us-west-2.amazonaws.com/s.cdpn.io/3/skyscrapers.jpg);
  background-attachment: fixed;
  overflow: hidden;
}
.module > header {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  padding: 20px 10px;
  background: inherit;
  background-attachment: fixed;
}
.module > header::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: inherit;
  background-attachment: fixed;
  -webkit-filter: blur(12px);
  filter: blur(12px);
}

See the Pen yyOodm by Chris Coyier (@chriscoyier) on CodePen.

That's using a color bar in addition to the blur, but you don't necessarily have to. You could blur it enough it works OK:

See the Pen ZYWXEY by Chris Coyier (@chriscoyier) on CodePen.

Softening just part of the image like this Erik is calling a scrim.

A scrim is a piece of photography equipment that makes light softer. Now it's also a visual design technique for softening an image so overlaid text is more legible.

Floor Fade

The floor fade is when you have an image that subtly fades towards black at the bottom, and then there's white text written over it.

This is perhaps fairly obvious since we've been using gradients to tint, but...

.module {
  background: 
    linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0),
      rgba(0, 0, 0, 0.6)
    ),
    url(skyscrapers.jpg);
}

See the Pen ByKwaq by Chris Coyier (@chriscoyier) on CodePen.

You can possibly get away with less image darkness if you combo it with a little text shadow:

.title {
 text-shadow: 0 1px 0 black;
}

In closing...

  1. It's pretty fun to find other ways and play with combining these techniques
  2. I'm sure you'll find browsers in which these demos fail. Maybe we can use the comment thread to discuss fallback possibilities.