Using a teeny-weeny bit of jQuery to add CSS inline backgrounds for blocks of text
For as long as I can remember I’ve always used a particular style of typography design when working with print based material. It’s nothing groundbreaking, and I’m sure you have used it as well.
It goes something like this:
Ah yes, ‘the coloured-background-blocks behind text effect/style’ I hear you say. Indeed.
And for as long as I’ve been using it, I’ve tried to find an easy way to replicate the style in web development. Working with static pages and small chunks of text this has normally been easy enough, but recently I was using the style in a WordPress theme and it needed to work without having to mess with snippets of HTML every time the style was required.
The problem with creating inline text element backgrounds
The problem is just that! Inline text elements. Strong, em, i or b (yes, i and b are valid HTML5 inline elements)—all cool, but they should only be used where semantically/stylistically necessary/appropriate. If we consider a block level paragraph or header tag then we have an immediate issue; a CSS applied background colour covers the entire block element, not just the text itself.
Marking up the print based example above, one might do the following:
<p id="block-demo"> Mos Eisley spaceport: You will never find a more wretched hive of scum and villainy. We must be cautious. </p> <p id="inline-demo"> <strong> Mos Eisley spaceport: You will never find a more wretched hive of scum and villainy. We must be cautious. </strong> </p>
With a bit of CSS:
p {
width: 190px;
font: 16px sans-serif;
color: #FFF;
}
p#block-demo {
background: #F00;
}
p#inline-demo strong {
background: #F00;
}
Which gives us this:
- A block level paragraph with a background
Mos Eisley spaceport: You will never find a more wretched hive of scum and villainy. We must be cautious.
- An inline element (strong) with a background, within a block level paragraph
Mos Eisley spaceport: You will never find a more wretched hive of scum and villainy. We must be cautious.
You can see the problem. Block level elements just fail at creating the effect. And while you can accomplish the look with inline elements, you have to use inappropriate markup; i.e. using a semantic inline element to create a style hook for an entire block element! Not good.
A simple solution for creating inline backgrounds for block level text
The technique of creating inline backgrounds for block levels of text is based on the second method outlined above. Using jQuery one can easily wrap an inline element around a given amount of block level text, using the wrapInner() function—like so:
<p> <strong>Han Solo:</strong> Han Solo. I'm captain of the Millennium Falcon. Chewie here tells me you're lookin' for passage to the Alderaan system? </p> <p> <strong>Obi-Wan:</strong> Yes indeed, if it's a fast ship. </p> <p> <strong>Han Solo:</strong> Fast ship? You've never heard of the Millennium Falcon? </p> <p> <strong>Obi-Wan:</strong> Should I have? </p> <p> <strong>Han Solo:</strong> It's the ship that made the Kessel Run in less than twelve parsecs. I've outrun Imperial starships. Not the local bulk cruisers mind you, I'm talking about the big Corellian ships now. She's fast enough for you old man. What's the cargo? </p>
…plus a teeny-weeny bit of jQuery:
$(document).ready(function(){
$('#text-backgrounds p').wrapInner('<span>');
});
…and a bit of CSS:
p {
width: 190px;
font: 16px sans-serif;
color: #FFF;
}
p span {
background: #F00;
}
…gives us:
Han Solo: Han Solo. I’m captain of the Millennium Falcon. Chewie here tells me you’re lookin’ for passage to the Alderaan system?
Obi-Wan: Yes indeed, if it’s a fast ship.
Han Solo: Fast ship? You’ve never heard of the Millennium Falcon?
Obi-Wan: Should I have?
Han Solo: It’s the ship that made the Kessel Run in less than twelve parsecs. I’ve outrun Imperial starships. Not the local bulk cruisers mind you, I’m talking about the big Corellian ships now. She’s fast enough for you old man. What’s the cargo?
What happens here is that after the document has loaded jQuery simply wraps a span tag around all of the text within the the specified paragraph tags.
Because this takes place after the document has loaded we ensure that our markup is left neat and untouched. This is progressive enhancement at its most simple level.
With an inline element in place we now have a hook to use in our CSS—just as in the above example where I used the strong element.
Using the span inline element
The most important consideration with this technique was ensuring that an appropriate inline element was used, keeping semantics in mind.
The span element is much the same as the div element, in that it intended to be used within markup to group content and has no default style properties. Unlike the div element though, span is an inline element. This makes it perfect for use here as it doesn’t disturb a document semantically, where as an element such as strong or em would carry meaning. Similarly using b or i would require overriding their default style properties.
Considering padding with the inline-backgrounds
At this point I’m sure most will have observed that the inline backgrounds do not have any padding, unlike the image example right at the start of this article. This is because of an issue that arises when an inline element has padding and spans over more than one line of text. Actually, the issue only concerns left and right padding.
This is what happens should some padding be applied to the above technique.
Han Solo: It’s the ship that made the Kessel Run in less than twelve parsecs. I’ve outrun Imperial starships. Not the local bulk cruisers mind you, I’m talking about the big Corellian ships now. She’s fast enough for you old man. What’s the cargo?
The result is that the top and bottom padding is visible on every line, as you would hope, but that the left and right padding is only visible at the start and end of the span. This is entirely correct, and not a CSS bug, but does highlight an issue where some extra steps are required to fully incorporate padding on every line.
Creating an inline-background jQuery plugin that allows for padding
In order to allow for padding, two steps are required:
- Markup your text with line breaks at the end of each line
- Use jQuery to wrap span tags around text between every line break
At this point the jQuery function becomes a little larger, at several lines, so I’ve created a plugin for using the technique.
Taking some of our previous markup and adding some line breaks:
<p> <strong>Han Solo:</strong> It's the ship that made<br> the Kessel Run in less than twelve parsecs.<br> I've outrun Imperial starships. Not the local<br> bulk cruisers mind you,<br> I'm talking about the big Corellian ships now.<br> She's fast enough for you old man. What's the cargo? </p>
…and using the following plugin:
(function($){
$.fn.inlinebackgrounds = function() {
$.each(this, function(i,t) {
var split = $(t).html().split('<br>');
var output = '';
$.each(split, function(i,o){
output += '<span>'+o+'</span>';
if (i < (split.length - 1)) {
output += '<br>';
}
});
$(t).html(output);
});
}
})(jQuery);
Line 3 – the plugin initially loops through each tag that has been passed to the plugin (in the above example this would be the paragraph tag).
Line 4 – next the plugin uses the JavaScript split() method to create an array of text segments, the amount of which will be determined by the number of line break tags.
Line 5 – because the plugin is going to concatenate the output html the plugin creates an empty variable to avoid a first instance of ‘undefined’.
Line 6-11 – the main part of the plugin goes through the aforementioned array of text segments and wraps each segment with our now familiar span tags. Importantly; the plugin appends a break tag to the end of each segment (after the span tag) other than the very last one. I’m sure there is a more elegant way of achieving this, by retaining the split delimiter but I couldn’t figure it out.
Line 12 – finally the plugin replaces the original input with the modified output.
The result is nice inline text backgrounds that include padding:
Han Solo: It’s the ship that made
the Kessel Run in less than twelve parsecs.
I’ve outrun Imperial starships. Not the local
bulk cruisers mind you,
I’m talking about the big Corellian ships now.
She’s fast enough for you old man. What’s the cargo?
I should quickly mention the use of line breaks. This seems like the easiest method of achieving the padding friendly version of this technique. But it goes without saying, there is a labour trade-off here in that you’re going to have to carefully consider where your line breaks are in each paragraph tag.
One final note is that, depending on your font-size, you will need to tweak and adjust line-height to ensure that your text doesn’t overlap. I’ve found using rgba() backgrounds useful here as you can see where overlapping occurs very easily.
The alternative I considered to the above plugin was using jQuery to determine the length of each line and create the span tags that way. It seemed an overly complex route to take for a simple end product. It may not even be possible, but if it is…it sounds like overkill.
-
http://www.simonrichardson.info Simon
-
http://www.dotvoid.com Danne
-
Danne
-
Danne
-
Anonymous
-
http://twitter.com/CodeMonkeyG CodeMonkeyG
-
Anonymous
-
http://twitter.com/indextwo Lawrie Malen
-
Sam Croft
-
Peter
-
http://samcroft.co.uk/ Sam Croft
-
Peter
-
http://samcroft.co.uk/ Sam Croft
-
http://twitter.com/guiiipontes Guilherme Pontes
-
http://samcroft.co.uk/ Sam Croft
-
http://www.facebook.com/OwenMelbz Owen Melbourne
-
drtimofey
-
martijn de valk
-
http://samcroft.co.uk/ Sam Croft
-
http://www.facebook.com/davidmarkclements David Clements
-
http://samcroft.co.uk/ Sam Croft
-
http://profiles.google.com/aaron.face.taylor Aaron Taylor
-
Alejandro