DiggingIntoWordPress

by Chris Coyier & Jeff Starr

Making an Expanding Code Box

Posted by on

On blogs that like to share snippets of code like this one, it is common to use the <pre> tag to wrap the code so that the spacing/indenting is maintained and long lines do not wrap. While this is desirable behavior, it can be undesirable to have those un-wrapped lines break out of their containers awkwardly and overlap other content.

On Digging Into WordPress, we use JavaScript (jQuery) to solve this problem. One solution could potentially be to use only CSS and expand the width with something like pre:hover, but JavaScript is more elegant:

  • Expands only when needed
  • Expands only to as wide as needed
  • Expands with animation

The CSS

The <pre> tag is naturally block-level, so this is what we’ll use to style our code blocks and hide the overflow.

pre { 
  background: #eee; 
  padding: 10px; 
  border: 2px solid #c94a29; 
  overflow: hidden;
  margin: 0 0 15px 0; 
  width: 563px; 
  font-family: Courier, Monospace;
}

The jQuery

The real trick here is that the code blocks are wrapped not only in <pre> tags but also in <code> tags. The code may ultimately get cut off by the pre block, but that inner code tag still has a natural width that can be measured by JavaScript. Here is the logic:

  1. When a pre block is hovered…
  2. Measure the internal code blocks width
  3. If that width is wider than the pre block…
  4. Expand the pre block to be wide enough to accommodate
  5. On mouseOut, return the pre block to its original size
$j("pre").hover(function() {
	var codeInnerWidth = $j("code", this).width() + 10;
    if (codeInnerWidth > 563) {
		$j(this)
			.stop(true, false)
			.css({
				zIndex: "100",
				position: "relative"
			})
			.animate({
				width: codeInnerWidth + "px"
			});
		}
	}, function() {
			$j(this).stop(true, false).animate({
				width: 563
		});
	});

Couple of things of note here. The “codeInnerWidth” is calculated on every hover, because different blocks will have different inner widths. The width of the pre blocks are hard-coded though. Calculating that on every hover leads to problems like fast mouse-in-mouse-outs expanding the box and re-calculating it’s size to be larger than it was originally. The stop function prevents queuing up of animations. Also note the $j being used is just because we are using jQuery in noConflict mode:

var $j = jQuery.noConflict(); 

Demo

Update (2013/09/14): demo removed for new theme design.

None of the code blocks so far have been long enough for you to see it in action, so here is a demo block (RSS readers, obviously you need to see this on our site to see it work).

This is a really long line of code that is even longer than the world super-cala-frag-alistic-espee-ala-dosis

17 Responses

  1. Actually this is a nice trick you have here on DiW… I also like the sidebar which slides to the right when you hover on it. It’s also jQuery right?

    • I don’t know about this site specifically (didn’t look at the source) but it can be done using jQuery’s .animate pretty simply.

  2. Benjie July 9, 2009

    I check your CSS tricks site Chris…It’s pagerank is still 6

  3. This is awesome — I am thinking about using it at Perishable Press. Thanks for posting in tutorial format.

  4. Dave Blencowe July 9, 2009

    I have recently been playing with jQuery and have considered using it for the pre/code tags on my site. I like the idea you have implemented here and might use something similar for my site, although I would prefer to use an expand button I think.

  5. Hmm, I prefer the scrollbar. This’ll be annoying if you got a lot of code on one line, you’ll have to scroll to the right and keep your mouse on the code, but I guess it works good with a little bit of code.

  6. Chris Reynolds July 9, 2009

    Very nice little effect!

  7. Awesome! Thanks for the explanation. Again, nicely done!

  8. It’s nice. But I just want to point out a problem(?). I visited this site with a pretty small screen and when the code expanded a horizontal scroll was needed. That’s fine. But it gets a bit tricky when one tries to copy the code inside the block.
    I guess this could be solved by having a neat little “copy-this-code”-button though.
    Well anyway thanks for sharing!

  9. Sorry, I know it’s not really adding to the conversation, but this is really cool. Thanks for sharing.

  10. Matthew Muro July 10, 2009

    Personally, I like using the built-in WordPress shortcode [sourcecode language='whatever']. You get a scroll bar and code highlighting.

    • I thought that was only for WordPress.com accounts.. is that functionality also built into self-hosted installations?

      • Matthew Muro July 10, 2009

        Jeff, you’re right. I guess it would help to compare my self-install to the WordPress.com blog before hitting submit.

        WordPress.com just uses the SyntaxHighlighter plug-in globally (or at least, it’s based off this code).

  11. In your demo, s/world/word/ig.

  12. The copy problem is realy not a problem and is easilly solved. Include an extra empty line infront of the code and after the code. This way you place the mouse pointer above the line you need, keep the left mouse pressed and drag down passed the line you need included in the copy. Pretty basic copy behaviour, however you need the extra lines unless you drag outside the box to get the same effect.

    vertical scrollbar is never nice, however wordwrap with code is worse! Nice function, will definately include this behaviour on my own blog when I get the time.

  13. Really interesting pieces of code. Thanks !

  14. I think it’s better to set the overflow via jQuery, so without JavaScript you can also read the Code.

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry