Written by

If you’ve spent much time reading this blog, you’ve probably noticed the sexy rainbow texture on the text of the headers and links.

There are several ways to accomplish this, each with their own pros and cons. That’s what I’ll cover in this post.

First, you’ll need a texture that works well with your design.

After a lot of trial and error, I chose this texture because it was pretty and stood out against the light background.

ProTip: You may need to use a bolder font weight to let the texture shine through.

What It Looks Like

All of these methods should give you nearly identical results, but in the unlikely event your browser doesn’t support any of them, here you go:

Text clipping with CSS or SVG preview.

Method One

This is probably the most commonly-suggested way to clip text, but I feel there are better ways.

I ♥ CSS
Live demo

Pros

  • Good support (currently at 80.76%), but not as good as SVG.
  • Background can be anything from solid colors, gradients, or photographs.
  • SEO (Search Engine Optimization) and screen reader friendly.
  • Text can be selected.

Cons

  • Both background-clip AND text-fill-color must be supported by your browser or the text may be invisible. You should check for support before applying this technique.
  • No support for extra text enhancements like text-shadow, but supports workaround of filter: drop-shadow() (but please don’t use that unless absolutely necessary, as this increases processing and memory usage significantly!)
  • In supported browsers, the text is completely invisible until the background image starts downloading. The problem may be compounded if using a custom web font. Causes FOIT (Flash Of Invisible Text) regardless.
  • No Internet Explorer/Edge support at all.

Usage

<style>
/* Remember to -vendor-prefix these properties! */

@supports (background-clip: text) and (text-fill-color: transparent) {
	.text-clip {
		color: #000000;
		background: transparent 50% 50% no-repeat;
		background-image: linear-gradient(transparent, transparent), url("/path/to/texture.jpg");
		background-clip: text;
		text-fill-color: transparent;
	}
}
</style>
<div class="text-clip">I ♥ CSS</div>

Method Two

This uses a <pattern> inside of a SVG element.

Assuming you’ll want to use this technique on more than one blog of text in a page, it would be ideal to separate the text from the texture.

I ♥ SVGI ♥ SVG
Live demo

Pros

  • Allows extra text enhancements like text-shadow, which may help with legibility.
  • Background can be anything from solid colors, gradients, or photographs.
  • SEO (Search Engine Optimization) and screen reader friendly.
  • Text can be selected.

Cons

  • Text inside SVG <text> elements do not wrap. This limits your message to *very* short phrases.
  • None of these methods require a seamlessly repeating image, but in some cases, the pattern can "bleed" and reveal the borders of the image. This is not a problem at all if the image is seamless, but if it happens, use either fewer words or increase the dimensions of the image in the code.

Usage

<style>
text {
	/* To normalize text. Both text layers need to in the exact same position, and placed directly over the pattern. */
	font-family: inherit;
	font-weight: inherit;
	line-height: inherit;
	text-align: center;

	/* To center text within the viewing area. */
	alignment-baseline: central;
	dominant-baseline: central;
	text-anchor: middle;
}
</style>
<!-- Text -->
<svg class="text-clip" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400" width="800" height="400" preserveAspectRatio="xMidYMid meet">
	<!-- Show text while image is downloading. Include a very small stroke matching the background if it’s a solid color; this will help prevent color bleed. -->
	<text x="50%" y="50%" fill="#000000" stroke="#FFFFFF" stroke-width="1">I ♥ SVG</text>

	<!-- Fill the text shape with the pattern. -->
	<text x="50%" y="50%" fill="url(#text-clip)">I ♥ SVG</text>
</svg>
<!-- Texture -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 800 400" width="0" height="0" preserveAspectRatio="xMidYMid meet">
	<defs>
		<pattern id="text-clip" patternUnits="userSpaceOnUse" width="800" height="400">
			<image xlink:href="/path/to/texture.jpg" width="800" height="400" />
		</pattern>
	</defs>
</svg>

Method Three

This uses the new clip-path CSS property along with an image inside of a SVG element.

This was the most challenging of all to set up for the inline demo. Some property was clashing with the clipping of the element, preventing it from showing. When that finally worked, the text was incredibly small and I had to dramatically increase it to the same size as the others.

Hopefully, it will be easier for you, if you decide to use this method.

Live demo

Pros

  • Allows extra text enhancements like text-shadow, which may help with legibility.
  • Background can be anything from solid colors, gradients, or photographs.

Cons

  • Text inside SVG <text> elements do not wrap. This limits your message to *very* short phrases.
  • No support for extra text enhancements like text-shadow or filter: drop-shadow()
  • This is not search engine or screen reader friendly.
  • Text cannot be selected.

Usage

<style>
/* Remember to -vendor-prefix this property! */

.text-clip {
	clip-path: url("#text-clip");
}
</style>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 800 400" width="800" height="400" preserveAspectRatio="xMidYMid slice">
	<defs>
		<clipPath id="text-clip" width="800" height="400">
			<text x="50%" y="50%">I ♥ SVG</text>
		</clipPath>
	</defs>
</svg>
<img class="text-clip" src="/path/to/texture.jpg" alt="I ♥ SVG" />

ProTip: Because of the hassle and drawbacks associated with this version, I would recommend you NOT use method three.

Method Four

I saved the best for last. A technique I pioneered myself; one that I’ve never seen anyone else do, so I’m really freakin’ happy about this! 😍

This is the technique I use on this very blog.

The trick is to trick the browser into blending the colors right out of the visible spectrum of light. This technique will progressively enhance your text with the new CSS mix-blend-mode property.

I ♥ CSS
Live demo

Pros

  • Displays text naturally as if no effect is applied until the background image is downloaded, and then it simply adds to the text.
  • Progressively enhanced if browser supports it. Graceful fallback if browser doesn’t. This is the only method that offers progressive enhancement! Others will fail badly, leaving behind unreadable or invisible text.
  • Effect done entirely with pseudo elements, so no need for extra markup! :after is optional, but it may greatly improve legibility.
  • SEO (Search Engine Optimization) and screen reader friendly.
  • Text can be selected.
  • The highlighted text selection automatically captures your background texture and removes it from your text (as long as you style ::selection with background and color properties). Super cool!
  • Supports Internet Explorer/Edge.

Cons

  • Browser support isn’t bad (currently at 76.98%). Support can be increased by including method one as a fallback.
  • No support for extra text enhancements like text-shadow or filter: drop-shadow()
  • The color values of each pixel are changed, and in some cases quite dramatically. Experiment with different images. Use solid black as the text or background color for slightly more accurate colors.
  • Requires either block-level elements or white-space: nowrap on inline elements. For inline elements, the text cannot wrap or the effect will disappear.
  • Must be used on an extremely bright, solid-color background. However, you can adjust the mix-blend-mode properties to work with other solid-color backgrounds. Experiment with this.

Usage

<style>
/* Remember to -vendor-prefix these properties! */

@supports (mix-blend-mode: lighten) and (mix-blend-mode: soft-light) {
	.text-clip {
		position: relative;
		display: block;
	}

	.text-clip:before,
	.text-clip:after {
		position: absolute;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
		content: " ";
		display: block;
		width: 100%;
		height: 100%;
	}

	.text-clip:before {
		background: 50% 50% no-repeat url("/path/to/texture.jpg");
		background-size: cover;

		mix-blend-mode: lighten;
	}

	/* Improves legibility. Tweak this to fit your needs! */
	.text-clip:after {
		background: #000000;
		opacity: 0.2;

		mix-blend-mode: soft-light;
	}
}

/* Inversing the foreground and background colors will capture the texture automatically, inside the selected text. See method four "Pros" and remember to -vendor-prefix this as well. */
::selection {
	background: #F50808;
	color: #FDFCFB;
}
</style>
<div class="text-clip">I ♥ CSS</div>

Bonus Method

Naturally, you can do this with image editors like Adobe Photoshop or GIMP.

While this method is definitely the most compatible cross-browser, it is not true text clipping. I recommend it if the stylized text is essential for your message.

I ♥ CSS
Live demo

Pros

  • Excellent support (currently at 97.86%), but even better if your container uses the exact dimensions of your image. It uses background-size to make your image responsive or high-density/Retina screen compatible.
  • If your image is transparent, the background can be anything from solid colors, gradients, or photographs. Otherwise, probably use a solid background image for a smaller filesize.
  • SEO (Search Engine Optimization) and screen reader friendly.
  • Supports Internet Explorer/Edge.

Cons

  • The text is completely invisible until the background image finishes downloading.
  • Text can be selected, but the selection of the text is not visible and it is very difficult to select.
  • Text cannot be easily changed later.
  • The edges of the text may not be as crisp as the other methods.
  • The file size may be larger, especially if using transparency.

Usage

<style>
/* Remember to -vendor-prefix these properties! */

.text-clip {
	background: transparent 50% 50% no-repeat url("/path/to/texture.jpg");
	background-size: contain;

	/* Put text off screen for screen readers */
	direction: ltr;
	text-indent: -9999em;
	overflow: hidden;
}

/* To support high-density and Retina screens, include this @media query. */
@media (min-device-pixel-ratio: 2), (min-resolution: 192dpi), (min-resolution: 2dppx) {
	.text-clip {
		background-image: url("/path/to/texture@2x.jpg");
	}
}
</style>
<div class="text-clip">I ♥ CSS</div>

Wrap Up

Some of these methods require a great deal of TLC when it comes to sizing the content inside, particularly the SVG examples.

If you use any of the above methods or if you have more to add to this list, leave a comment below or send me an email and I’ll be happy to add it to the list. :)

I ♥ SVG
Not every business needs a cutting edge experience, but when you want exceptional quality front-end web development work, remember me. Send me an email and we can talk about the details.