Dynamically labeling blockquotes with CSS

Written by Adrian Holovaty on December 20, 2002

I'm experimenting with using CSS to automatically label blockquotes with their source URLs. Here's an example blockquote:

As ever in web design there has to be a bug and some hacking in response.

If your browser can handle it, you'll see a line appended at the bottom of the quote. That line uses the cite attribute of the blockquote tag to display the quote's source. (See the W3C specification for more on these tags.) It works for me in Mozilla 1.2 and Opera 7, both on Windows.

Here's a screenshot of what it looks like:

Screenshot of blockquote

Here's the CSS code that makes this happen:

blockquote[cite]:after {
  content: "Quote from: " attr(cite);
  display: block;
}

In essence, that says, "Let's look at each blockquote in the document. If if contains a cite attribute, let's pop some text after it. Specifically, that text should be 'Quote from: ', followed by the actual contents of the cite attribute (which will be a Web address). And finally, make sure that inserted text appears on its own line."

I also added a bit of formatting. It's pretty self-explanatory:

border-top: 1px solid #669;
color: #669;
margin: 1em 0 0;
padding: .5em 0 0;
font-size: .8em;
font-weight: bold;

I'm not quite sure how useful this is, because the printed URL isn't a clickable hyperlink. (Does anybody know a way to make it so?) In Mozilla 1.2 for Windows, it can't even be selected by the mouse cursor for copying/pasting, so it's doubly unuseful. (It can, though, be selected in Opera 7.) Another potential problem: Long URLs might look funky and break the page layout somehow.

Still, it's always fun to find new ways to use style sheets.

Comments

Posted by David Wertheimer on December 20, 2002 at 11:15 a.m.:

Don't you think that gets in the way? Hyperlinks exist to bury URLs--why wouldn't [source] be sufficient?

Posted by David Wertheimer on December 20, 2002 at 11:16 a.m.:

Not to gripe or anything, of course; experimentation is wise. Just wondering whether this is a step forward or backward.

Posted by Adrian on December 20, 2002 at 12:32 p.m.:

Good call, David. I think a [source] link would be much better than simply displaying the URL. Thing is, I'm not sure whether that's possible with CSS. As far as I can tell, CSS allows you to access the URL itself but doesn't allow you to wrap code around it in order to turn it into a link.

Of course, I'd be delighted if someone figured it out.

Posted by paul hammond on December 20, 2002 at 1:14 p.m.:

Javascript and the DOM are much more flexible when creating effects like this, and probably the only way to do a clickable [source] link.

I've created a proof of concept which shows how this could work.

Comments or improvements are welcome

Posted by Michael Z. on December 20, 2002 at 2:37 p.m.:

Use this in your print style sheet. It's a great way to make the contents of the title attribute more accessible there.

If you want the URL to be visible in all media, then it's part of your content. You might as well just put a link in instead of using a title attribute (or make your content management system to do it for you).

Posted by Mark on December 20, 2002 at 3:01 p.m.:

Michael Z. has it. I use generated content exclusively in my print style sheet, to expose URLs which would otherwise be invisible. I do it for selected normal links, but using it for the cite attribute of BLOCKQUOTE and Q is great too.

Posted by Simon Willison on December 20, 2002 at 3:46 p.m.:

It seems myself and Paul had exactly the same idea :)

Posted by Rob Ballou on December 20, 2002 at 5:11 p.m.:

Just a thought: looking at the W3 specifications that you linked to, blockquotes also have the "title" attribute. If there was a way to make a hypertext link, you could use the "title" attribute as the link text and the "cite" attribute as the URI (which is all that is supposed to be in a "cite" attribute).

Posted by Adrian on December 20, 2002 at 5:29 p.m.:

Good idea, Rob. That would have the side effect (I believe) of displaying a tooltip when you mouse over the blockquote. Which isn't necessarily a bad thing, right?

Simon and Paul: Thanks a lot for your DOM tools. I'll definitely implement one of 'em here.

Posted by Simon Willison on December 20, 2002 at 5:44 p.m.:

Rob's idea of using the title attribute is very interesting. On the one hand, it would add valuable additional information to the blockquote "Source" link (I've been setting the cited URL as the title attribute of the Source link so users get a tooltip showing where it goes when they mouse over it). However, I'm not sure I like it so much from a semantic markup point of view - the title of the page or article the quote came will occasionally have little to do with the part extract quoted in the blockquote.

I did think about having the blockquote javascript quietly load the various Source pages in an invisible iframe once the inital page had loaded and then quietly extract the title from each page and add it as a title attribute on the source link once the information had been grabbed - it would be quite a subtle effect (most people would probably never realise it was happening) and would mean that within 10-15 seconds of the page loading the titles would have been quietly added in the background. I quickly decided against it as the bandwidth overhead / additional client side processing required did not seem a valid trade off for such a small improvement.

Posted by mpt on December 23, 2002 at 6:56 a.m.:

The reason you can't select the URI in Mozilla is the same reason you can't select list numbers, bullets, or <q></q> quote marks.

Posted by Joe Clark on January 13, 2003 at 5:07 p.m.:

Um, you can right-click on a blockquote in Mozilla and select Properties. The cite URL will be listed and clickable.

Posted by Garrett Smith on April 29, 2003 at 11:23 p.m.:

The original idea is good, although I am frustrated by not being able to select the text in the generated content.

"Good call, David. I think a [source] link would be much better than simply displaying the URL. Thing is, I'm not sure whether that's possible with CSS. As far as I can tell, CSS allows you to access the URL itself but doesn't allow you to wrap code around it in order to turn it into a link.

Of course, I'd be delighted if someone figured it out."

This is a bad idea. Links are for links. Several follow-uppers posted javascript code to do this. Javascript is for behavior. Javascript is not for adding links. Javascript is not for content management.

If you want a link, use a link. Here's how:

<blockquote cite='http://dhtmlkitchen.com/services/dhtml/index.jsp#content2'>

Scripts which generate HTML with document.write (or otherwise) are slower to load,

less accessible, harder to maintain and modify, and search-engine hostile. By avoiding

document.write, we avoid these pitfalls.

<div>

Quoted from:

<a href="http://dhtmlkitchen.com/services/dhtml/index.jsp#content2"

>The DHTML Standard</a>

</div>

</blockquote>

Posted by prawnFresh on May 13, 2003 at 12:07 p.m.:

Well the idea is good, but the actual implementation isn't. I've used what you have shown us here in my print css:

a[href]:after {

content: " (url: " attr(href) ")";

}

This will allow users who print documents out to see the URL of any links directly after the links. Now I believe this is a very good use for what you have show us.

Posted by Peter on October 18, 2004 at 5:49 p.m.:

But if you're rendering some other XML (not HTML), how do you tell CSS how to insert the image?

If I have <graphic file="foo.jpg"/> I have tried graphic:before { url(attr(file)) }; but it doesn't work.

Posted by Claudiu on November 4, 2004 at 10:34 a.m.:

Unfortunately the css solution is not working in IE.. that'a a shame and is too bad. Until IE will not implement that method for print versions purposes, I think it's useless.

Posted by Ricardo Carrasco on December 15, 2004 at 2:44 p.m.:

This is a bookmarklet that converts text to a clickable URL

javascript:s=document.body.appendChild(document.createElement('script'));s.language='javascript';void(s.src='http://slayeroffice.com/tools/text2link/text2link.js');

this is a great comment setup here btw

Posted by xavier on January 6, 2006 at 11:12 a.m.:

Thanks for an informative an useful explanation of the 'cite' attribute. I hadn't gotten mine to work correctly until I read this post.

Posted by Joanne Cheng on March 4, 2006 at 2:15 a.m.:

Hello.

How are you all.

I am good.

I'M GOING TO FAIL MY TECH CLASS :(

Because I don't understand what cite is.

This is terrible.

Crackers!

Posted by Chris Tom on March 4, 2006 at 2:17 a.m.:

I WOULD AGREE JOANNE!

Crackers are indeed very interesting. However, I would not blame them for your failing tech. You failed tech because you waited until friday to do your project. Therefore, you are a silly person, and crackers are indeed not to blame.

Perhaps we could agree to share the blame with carrots, however. Carrots are orange and distracting.

I blame carrots. And you.

But more carrots.

Posted by Mark on July 31, 2006 at 7:52 p.m.:

um, besides the carrots... has anybody gotten it to work without some javascript?

Posted by The CSS is commented out on August 11, 2006 at 10:58 a.m.:

I was shocked when I saw that your technique didn't work in Opera 9, because I use the exact same technique and it does work (for several Opera versions). After looking at your css in /css/default.css, I notice that the CSS for the cite attribute is commented out, so that is the reason it is not working.

I would also love to have a way to actually turn the source URL into a link instead of just having it displayed after the blockquote. I tried this:

content: "< a href=\""attr(cite) "\" > Source< /a >;";

But alas, it actually displays the HTML as text.

/*

#content div.blogentry blockquote[cite]:after {

content: "Quote from: " attr(cite);

display: block;

border-top: 1px solid #669;

color: #669;

margin: 1em 0 0;

padding: .5em 0 0;

font-size: .8em;

font-weight: bold;

}

*/

Posted by IE alternative on August 15, 2006 at 4:35 p.m.:

For those of you that want the same functionality, you can use Simon Willison's script. This means that for IE JavaScript will be required to see the effect, while in other browsers only CSS will be required, but at least it will be available to IE users that do have JavaScript enabled. This has the added benefit of turning the cite into a clickable link.

To make the look for IE with this script consistent with the CSS version, I changed the script to use:

newlink.appendChild(document.createTextNode('Source: ' + cite));

instead of

newlink.appendChild(document.createTextNode('Source'));

and

quotes[i].appendChild(newdiv);

instead of

quotes[i].parentNode.insertBefore(newdiv, quotes[i].nextSibling);

Then use CSS to style each similarly:

blockquote[cite]:after { /* for browsers that can do generated content */

p.blockquotesource a { /* This is an IE-only element that is inserted with blockquotes_IE.js */

/*

* blockquotes.js

*

* Simon Willison, 20th December 2002

*

* Explanation:

* http://simon.incutio.com/archive/2002/12/20/#blockquoteCitations

* Inspired by Adrian Holovaty:

* http://www.holovaty.com/blog/archive/2002/12/20/0454

* Alternative implementation of the same idea by Paul Hammond:

* http://www.paranoidfish.org/boxes/2002/12/20/

*/

Posted by anonymous on August 15, 2006 at 4:37 p.m.:

I forgot to mention - since you only want the script firing for IE, you need to use a conditional comment in the HEAD to target that browser:

<head>

<!-- Conditional Comment for Internet Explorerer. Any IE-specific css or javascript will go here -->

<!--[if lt IE 7.0]>

<script type="text/javascript" src="blockquotes_IE.js"></script>

<![endif]-->

</head>

Comments have been turned off for this entry.