Code formatting (snippet)

I had a question sent to me asking about formatting code for viewing on a web page purely using HTML and CSS and without using JavaScript or any syntax highlighter of some sort. My initial answer would be that this isn’t usually a good idea since the <pre> and <code> tags are still probaby the best option for displaying code, however it isn’t really that hard to do.

To show code with line numbers, the best way would be to put it into an <ol> (ordered list) and each line into <li> tags.

The CSS portion is fairly straightforward…

/* Code Formatting */
ol.code
{
	margin: 1em 0;
	padding:0 0 0 3em;
	background:#f5f5ff;
	border:1px solid #eee;
}

ol.code li
{
	margin: 0;
	padding: .1em 0 .1em .3em;
	background: #fff;
	white-space: pre-wrap;
	border: 1px solid #eee;
	border-width: 0 0 0 1px;
}

ol.code li:nth-child(even)
{
	background: #f8f8ff;
}

And the HTML (used to display the same code above)…

<ol class="code">
	<li>/* Code Formatting */</li>
	<li>ol.code</li>
	<li>{</li>
	<li>	margin: 1em 0;</li>
	<li>	padding: 0 0 0 2.2em;</li>
	<li>	background: #f5f5ff;</li>
	<li>	border: 1px solid #eee;</li>
	<li>}</li>
	<li></li>
	<li>ol.code li</li>
	<li>{</li>
	<li>	margin: 0;</li>
	<li>	padding: .1em 0 .1em .3em;</li>
	<li>	background:#fff;</li>
	<li>	white-space:pre-wrap;</li>
	<li>	border:1px solid #eee;</li>
	<li>	border-width:0 0 0 1px;</li>
	<li>}</li>
	<li></li>
	<li>ol.code li:nth-child(even)</li>
	<li>{</li>
	<li>	background: #f8f8ff;</li>
	<li>}</li>
</ol>

You can see a running example added to the Basic theme.

The down side to this is that this means if you copy the code off the formatted view, all your line breaks and even some spacing would be lost. There’s still a need to provide an alternative like a textarea view or side <pre> tag. One idea would be to use jQuery UI tabs to switch between formatted and raw views since this way at least you’re reusing existing code as much as possible.

Update

After a couple of back and forth emails, I wrote a very simple jQuery plugin that will turn any text block into a formatted and raw view via a simple tab interface. This is meant to be as fast and as lightweight as possible so it doesn’t have any syntax highlighting.

/*
jQuery fast code format (non-syntax highlighting) plugin
*/

(function($) {
	$.fn.codeformat = function(options) {
		var settings = $.extend({
			rawText : "Raw",
			formattedText: "Formatted"
		}, options);
		
		return this.each(function(i) {
			var c = $(this);
			
			var oc = c.text().split("\n"); // Get each line of code
			var ol = '<ol class="code">'; // <ol> wrapper
			
			// This is faster than "append()";
			$.each(oc, function(j, v) {
				ol += '<li>'+ v +'</li>';
			});
			ol += '</ol>'; // Finish <ol>
			
			// Container
			var w = $('<div id="codeview'+ i +'" class="codeformat" />');
			
			// Tab controls
			var u = $('<ul><li><a href="#codeview'+ i +'f">'+ settings.formattedText +'</a></li>'+
				'<li><a href="#codeview'+ i +'r">'+ settings.rawText +'</a></li></ul>');

			// Formatted and Raw view containers
			var fv = $('<div id="codeview'+ i +'f" class="codeview" />');
			var rv = $('<div id="codeview'+ i +'r" class="codeview" />');
			
			w.insertBefore(c)	// Put the container before the current code view
			u.appendTo(w)	// Put the tabs into the container
			fv.insertAfter(u);	// Put formatted view right after tabs
			rv.insertAfter(fv);	// Put raw view after formatted view
			
			fv.append(ol);	// Insert code lines into formatted view
			c.appendTo(rv)	// Put the current code block into raw view
			
			// Tab controls
			u.find('a:[href="#codeview'+ i +'f"]').bind('click', function(e) {
				if(rv.is(':visible')) {
					fv.toggle();
					rv.toggle();
					$(this).addClass("active");
					u.find('a:[href="#codeview'+ i +'r"]').removeClass("active");
				}
				e.preventDefault();
			});
			u.find('a:[href="#codeview'+ i +'r"]').bind('click', function(e) {
				if(fv.is(':visible')) {
					fv.toggle();
					rv.toggle();
					$(this).addClass("active");
					u.find('a:[href="#codeview'+ i +'f"]').removeClass("active");
				}
				e.preventDefault();
			});

			// Set initial view (show formatted)
			$('#codeview'+ i +'r').toggle();
			$('a:[href="#codeview'+ i +'f"]').addClass("active");
		});
	};
})(jQuery);

 

And the updated CSS

/* Code Formatting */
div.codeformat
{
	padding: .3em;
}

div.codeview
{
	background:#fff;
	color:#444;
	border:1px solid #ddd;
}

/* Code format tabs */
div.codeformat ul:first-child
{
	margin:.4em .2em .3em .2em;
	padding:0;
	list-style:none;
	min-height:1.8em;
}

div.codeformat ul:first-child li 
{
	margin:.3em .3em 0 .5em;
	padding:0;
	float:left;
}

div.codeformat ul:first-child li a
{
	padding:.4em .6em;
	text-decoration:none;
	font-weight:bold;
	color: #999;
	background: #f5f5ff;
	border-radius: 5px 5px 0 0;
	border:1px solid #ddd;
	border-width: 1px 1px 0 1px;
}

div.codeformat ul:first-child li a.active
{
	color: #444;
	background:#fff;
	padding:.4em .6em .5em .6em;
}

code, pre
{
	margin: 1em 0;
	font-family: Monospace;
	font-size:100%;
	overflow-x: scroll;
}
code
{
	white-space: pre;
}
div.codeformat code, div.codeformat pre
{
	margin:.2em .5em;
}

ol.code
{
	margin: 0 !important;
	padding: 0 0 0 3em;
	background: #f5f5ff;
	font-family: Monospace;
}

ol.code li
{
	margin: 0;
	padding: .2em 0 .2em .3em;
	background: #fff;
	white-space: pre-wrap;
	border: 1px solid #ddd;
	border-width: 0 0 0 1px;
}

ol.code li:nth-child(even)
{
	background: #f8f8ff;
}

 

To use this, just add jQuery and the plugin to your page and call the following on any <pre> or <code> block

$('code').codeformat();

You can checkout the updated running example.

Advertisements

One thought on “Code formatting (snippet)

  1. Pingback: Basic: The community version « This page intentionally left ugly

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s