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.
Pingback: Basic: The community version « This page intentionally left ugly