24 ways

to impress your friends

DOM Scripting Your Way to Better Blockquotes by Jeremy Keith

Block quotes are great. I don’t mean they’re great for indenting content – that would be an abuse of the browser’s default styling. I mean they’re great for semantically marking up a chunk of text that is being quoted verbatim. They’re especially useful in blog posts.

<blockquote>
     <p>Progressive Enhancement, as a label for a strategy for Web design, 
     was coined by Steven Champeon in a series of articles and presentations 
     for Webmonkey and the SxSW Interactive conference.</p>
 </blockquote>

Notice that you can’t just put the quoted text directly between the <blockquote> tags. In order for your markup to be valid, block quotes may only contain block-level elements such as paragraphs.

There is an optional cite attribute that you can place in the opening <blockquote> tag. This should contain a URL containing the original text you are quoting:

<blockquote cite="http://en.wikipedia.org/wiki/Progressive_Enhancement">
     <p>Progressive Enhancement, as a label for a strategy for Web design, 
     was coined by Steven Champeon in a series of articles and presentations 
     for Webmonkey and the SxSW Interactive conference.</p>
 </blockquote>

Great! Except… the default behavior in most browsers is to completely ignore the cite attribute. Even though it contains important and useful information, the URL in the cite attribute is hidden.

You could simply duplicate the information with a hyperlink at the end of the quoted text:

<blockquote cite="http://en.wikipedia.org/wiki/Progressive_Enhancement">
     <p>Progressive Enhancement, as a label for a strategy for Web design, 
     was coined by Steven Champeon in a series of articles and presentations 
     for Webmonkey and the SxSW Interactive conference.</p>
     <p class="attribution">
          <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">source</a>
     </p>
 </blockquote>

But somehow it feels wrong to have to write out the same URL twice every time you want to quote something. It could also get very tedious if you have a lot of quotes.

Well, “tedious” is no problem to a programming language, so why not use a sprinkling of DOM Scripting? Here’s a plan for generating an attribution link for every block quote with a cite attribute:

  1. Write a function called prepareBlockquotes.
  2. Begin by making sure the browser understands the methods you will be using.
  3. Get all the blockquote elements in the document.
  4. Start looping through each one.
  5. Get the value of the cite attribute.
  6. If the value is empty, continue on to the next iteration of the loop.
  7. Create a paragraph.
  8. Create a link.
  9. Give the paragraph a class of “attribution”.
  10. Give the link an href attribute with the value from the cite attribute.
  11. Place the text “source” inside the link.
  12. Place the link inside the paragraph.
  13. Place the paragraph inside the block quote.
  14. Close the for loop.
  15. Close the function.

Here’s how that translates to JavaScript:

function prepareBlockquotes() {
     if (!document.getElementsByTagName || !document.createElement || !document.appendChild) return;
     var quotes = document.getElementsByTagName("blockquote");
     for (var i=0; i<quotes.length; i++) {
          var source = quotes[i].getAttribute("cite");
          if (!source) continue;
          var para = document.createElement("p");
          var link = document.createElement("a");
          para.className = "attribution";
          link.setAttribute("href",source);
          link.appendChild(document.createTextNode("source"));
          para.appendChild(link);
          quotes[i].appendChild(para);
     }
 }

Now all you need to do is trigger that function when the document has loaded:

window.onload = prepareBlockquotes;

Better yet, use Simon Willison’s handy addLoadEvent function to queue this function up with any others you might want to execute when the page loads.

That’s it. All you need to do is save this function in a JavaScript file and reference that file from the head of your document using <script> tags.

You can style the attribution link using CSS. It might look good aligned to the right with a smaller font size.

If you’re looking for something to do to keep you busy this Christmas, I’m sure that this function could be greatly improved. Here are a few ideas to get you started:

About the author

Jeremy Keith is an Irish web developer living in Brighton, England where he works with Clearleft. He is joint leader of the WaSP DOM Scripting Task Force and he has written a book about DOM Scripting. He likes music, food, and liquid layouts. All he wants for Christmas is universal support for max-width.

Your comments

  1. § JB:

    Is the cite attribute appropriate to use as a semantic hook for the “posted by…” footer often following a comment on a blog? This page’s example (as well as all others I’ve seen) use it to reference text quoted from an external page, but it always bugs me that I’ve not semantically linked the poster’s name with what they’ve said on my site’s coments… Any thoughts?

  2. § Remi Prevost:

    Well, it looks a lot like Dunstan Orchard experiments with blockquotes but still useful ;-)

  3. § CornedBee:

    OT, but the tab order down here is weird.

    To the point. As for the third question (“how would I do that?”):

    quote.nextSibling ? quote.nextSibling.insertBefore(cite) : quote.parentNode.appendChild(cite);

    To this date, I just use CSS2 generated content for displaying the value of the cite attribute. I don’t make links out of it, partly because on the site where I do this I try to avoid JavaScript even when it’d enhance usability (such as the ability to click or at list copy the link in Mozilla), partly because it’s not always a link – I use the cite attribute for whatever source attribution fits.

  4. § Si:

    What a great idea! I’ve been using blockquotes on a fair few of my latest projects and it always seemed strange that the browser did nothing with the cite property.

    BTW, wouldn’t the text in the cite link be better presented with a name or title for the source, for example, “Source: Progressive Enhancement – Wikipedia, the free encyclopedia”?

  5. § Jeremy Keith:

    CornedBee: You’re almost there, but the syntax for insertBefore is actually more complex than that (unnecessarily so in my opinion). But your thinking is spot on: use either insertBefore (if the quote has a nextSibling) or appendChild (if the quote is the lastChild).

    Si: Yes, a more descriptive link text would be good. That was why I suggested reusing a quote’s title attribute, if one exists.

  6. § anty:

    I always refused to search for the meaning of blockquote, but today I’ve learned it unintentionaly. Thank you for this explanation!

  7. § kerri:

    What about user agents that don’t support JavaScript? (Oh, come on, you knew someone was going to ask.)

  8. § Drew McLellan:

    Kerri – there’s no problem if the UA doesn’t support JavaScript, or if JavaScript is turned off. The blockquote is still shown as normal, and the source information is still there in the cite attribute.

    The whole point of unobtrusive scripting techniques is that if there’s no scripting support available the user still has a fully functional page with all the information available to them. They just don’t get any little extras.

  9. § trovster:

    I see what you mean, CornedBee, about the tabindex being wrong, it tabs from the label (http://) to the “back to home page link” in the header.

    Hmm, I wonder how much of the content which I brough in book-form will appear for free (so soon) after it was published?

    The third example which uses class=”attribution”, should be using the cite ELEMENT, and is exactly how I markup my blockquotes already. It might be tedious (not really) to add it manually, but I think it’s important information for the user, regardless of JavaScript. I see a blockquote in an interesting article, I might want to read that site or article.

  10. § Jules:

    Slightly OT but in your third code block, you use < p class="attribution" > ... < /p > but shouldn’t you use the < cite > tag?

    Very cool script, thanks.

  11. § Jonathan Fenocchi:

    Wild idea (well maybe not that wild), but what about turning this into a Greasemonkey script? It is, after all, an attempt to alter the default UI that your browser provides, isn’t it? Hence, a developer shouldn’t necessarily have to account for such preferences. Additionally, there are no doubt a number of sites who may prefer not to display the source (for whatever reason), and a Greasemonkey script would make this preference available to the viewer. Just a thought.

    Great article, though, Jeremy. Well done.

  12. § Dustin Diaz:

    Aww yea. Well written in Jeremy fashion. addLoadEvent prevails, and we’ve got a handy new function to handle our blockquotes.

    This is great man. Always lookin’ for ways to help us become lazier. I love it.

  13. § david aronson:

    That´s great, except for the fact that it´s totally insane to have to script all kinds of workarounds for shitty browsers to even use correct markup, im seriously thinking about going back to tables

  14. § Scott Sauyet:

    This is useful, although far from new for anyone who’s been reading about unobtrusive Javascript techniques. Simon Willison published an article about this on Sitepoint two years ago this month.

    —Scott
  15. § Jeremy Keith:

    Jules: You’re quite right. The cite element would be perfect in this context. cite contains a citation or a reference to other sources

    Jonathon: Turning this into a greasemonkey script sounds like a great idea! Actually, it probably wouldn’t be that hard to turn into a regular bookmarklet so even non-Firefox uses could enjoy it.

    David: I have no idea what on earth you are getting at. What have tables got to do with anything in this example?!

    Scott: I never claimed this was anything new. Here’s a quote for you to attribute: There is nothing new under the sun. ;-)

  16. § Micah:

    > It might be tedious (not really) to add it manually

    Phil Ringnalda calls that markupsturbation. I thought it was appropriate, anyway.

  17. § zcorpan:

    Jeremy Keith: The cite element is not for quotes. ;-)

  18. § Keith Bell:

    Jeremy, this is the kind of small, useful enhancement for which I love JavaScript and the DOM. In response to a couple of your points:

    “Should the text inside the generated link be the URL itself?”

    “If the block quote has a title attribute, how would you take its value and use it as the text inside the generated link?”

    Using either the URL or the value of a title attribute would be better. Imagine a page with many blockquote elements, each with their own cite attribute citing a different source: then there would be many instances where the same link text (“source” in your example) points to different URLs. This would be bad from an accessibility point of view: think how the Links List would sound in a screen reader (“Source”, “Source”, “Source”, “Source”... with no context).

    “Should the attribution paragraph be placed outside the block quote?”

    It would be better if it were outside. First, because the attribution is not part of the quotation. Second, in a Note following section 9.2.2, the HTML 4.01 specification says that user agents should not insert quotation marks in the default style for the blockquote element. However, it also recommends that “style sheet implementations provide a mechanism for inserting quotation marks before and after a quotation delimited by BLOCKQUOTE”. If such an implementation were available and used, then the attribution paragraph would appear before the closing quotation mark, which would look wrong presentationally in addition to being wrong semantically.

    CornedBee: I understand your reasoning in using the cite attribute for whatever source attribution fits, even when it is not a link. Indeed, it would seem to me more sensible that the cite attribute could be used that way. However, HTML 4.01 at section 9.2.2 states specifically that the value of the cite attribute is a URI—so technically, anything that is not a URI is not a valid value for cite.

  19. § Mathias:

    Why use an “attribution” paragraph when you can use an ADDRESS element?

  20. § Aaron Gustafson:

    Nice one Jeremy.

    There’s also a fun way to do it using generated content in CSS. True, you can’t link it, it is unselectable and it (say it with me now) doesn’t work in IE, but it requires no JS. For example, check out these blockquotes (about 2/3 the way down the page).

  21. § William:

    this technique improve SEO ?

    see ya !

  22. § Dustin Diaz:

    William,

    This technique does not produce better or worse SEO. It’s a usability and possible accessibility enhancement.

  23. § Ben Boyle:

    This will work:

    quote.insertBefore(cite, quote.nextSibling);

    http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-952280727

    Specifically: If refChild is null, insert newChild at the end of the list of children. So insertBefore works like appendChild when the second argument is null. Very useful :)

  24. § Ben Boyle:

    oops, make that: quote.parentNode.insertBefore(cite, quote.nextSibling);

  25. § Brian LePore:

    Jules: While yes, he should use the cite tag instead of using the class method, cite is not a block level element, so he’ll have to create the link, insert that into a cite tag and then insert that into a paragraph tag.

  26. § Dave:

    Well Done Jeremy Again! Keep churning it out regardless of were it comes from. Love the book by the way.

Commenting is closed for this article.

24 ways: day 5