CSS Swag: Multi-Column Lists

One of the minor holy grails of XHTML and CSS is to supply a single, semantically logical ordered document that wraps into vertical columns.

The most productive scenario, individually, is usually a single XHTML document whose wrapping is controlled only by the use of CSS. Further, the wrapped document should tolerate text resizing (merely accomplished by the use of styling the whole thing in ems).

CSS and the browsers that give a boost to it don’t however provide us with “vertical wrap,” so we want to build up basic document markup with additional attributes and styling rules to achieve the affect. I’ll take you there—or as close as we will get the usage of in recent years’s browsers—alternatively along the way in which by which let’s check out a large number of ways to accomplish a similar affect.

We’ll be taking footage for something that looks somewhat like this:

CSS Swag: Multi-Column Lists

(Why, you’ve doubtless been bearing in mind, is this text entitled “CSS Swag”?  In searching for a metaphor for the multi-column document styling confirmed inside the above screenshot, I pictured a strip of material that hung down, drew once more up to its initial peak, then draped over again…  A to hand information a coarse google led me to this superb period of time, which I had in the past comparable best with an Australian tramp’s package deal of possessions, and to a great etymology that links swagger to sway.)

Watch your step#section1

I’ll come up with a caution up front. If you want to supply a listing in quite a few columns, you’ll want to compromise. You’ll be able to sacrifice W3C web necessities and use deprecated markup, you are able to are living with markup that’s not up to semantically logical, you are able to tolerate a mixture of presentation with content material subject matter, you are able to say goodbye to browser compatibility, or you are able to use markup that’s heavy with attributes and styling that’s heavy with rules. Every freeway exacts a toll.

While each and every of the ones methods is discreet enough to organize, the acid check out comes when you add or remove document items during internet web page maintenance. How easy to modify is your most popular method? Ideally, we should be capable of simply insert or delete document items and watch the document rewrap itself.

The reality is not so best. No longer just like the horizontal wrap that our browsers care for robotically, vertical wrapping requires us to explicitly state which document items occur by which columns or where the columns should injury. To stick a modified document wrapping as it should be, we will have to rearrange the document items, exchange courses and attributes inside the markup, or tweak rules inside the stylesheet.  The only manner described correct right here that doesn’t need any of that fuss (Approach 1) has other important behavioral problems.  In spite of everything, on account of vertical proportions are so important correct right here, these kind of lists are going to break if we predict that each and every document products will occupy one line, best to have some items wrap to two or additional lines.

So why are we able to hassle?  Well, for the reason that final affect is so cool—and good.  Wrapping a listing into columns can relieve the internet web page buyer of the want to scroll down a chronic document.  A three- or four-column document can fill the width of a internet web page while a single skinny column would possibly simply move away the structure taking a look anemic.  There are as many reasons to wrap lists as there are web designers:  very certainly Further Than A Few.

To art work, then.

First, expunge all white space#section2

The default rendering of an XHTML ordered document in browsers is that of a single vertical collection of items:

   <ol>   <li>Aloe</li>   <li>Bergamot</li>   <li>Calendula</li>   </ol> 

CSS Swag: Multi-Column Lists

To bypass some browser inconsistencies, I’ve taken to marking up my lists like this:

   <ol     ><li>Aloe<li>Bergamot</li     ><li>Calendula</li   ></ol> 

I’ve moved the remainder final angle-bracket > of each and every row to the beginning of the next row.  This assists in keeping each and every document products on a row by itself for the good thing about human readers and at the an identical time effectively eliminates the entire white space between tags, this producing additional consistent rendering during browsers.

(My pet idea as to why Internet Explorer incorporates the white space between list-item tags in its rendering calculations is that it’s a hold-over from that prehistoric technology when document items, like table cells, didn’t have final tags.  Once more then, a browser as it should be paid attention to all text along side white-space from one start-tag <li> to the next.  When final tags were added to the combination, apparently nobody at Microsoft remembered—or deemed it important enough—to keep an eye on the commonsense to stop parsing between one final tag </li> and the next start-tag <li>.)

Moreover, I’m together with a hyperlink to each and every document products.  This allows me to check for abnormalities in rendering anchors when rather a large number of CSS rules are carried out:

     ><li><a href="#">Aloe</a></li 

Practice: most of my examples use ordered lists on account of products collection is paramount in this exercise; unordered lists may, in the end, be substituted.

And but yet one more issue: the example pages hooked as much as this text are all marked up with a strict doctype. I profit from this in all my web art work nowadays on account of apparently that I will get additional consistent results cross-browser with a lot much less weeping and gnashing of teeth.  If you happen to use a transitional doctype or run in quirks mode, likelihood is that you’ll be able to need to tweak the CSS to get the ones how you’ll behave cross-browser.

Approach 1: Floating document items#section3

Of the entire techniques I’m going to provide an explanation for, this one uses the cleanest XHTML markup and probably the most most simple CSS.  Unfortunately, its flaws prevent it from becoming my method of variety.

CSS Swag: Multi-Column Lists

See Example 1.

The process is discreet: give the document items a suite width and glide them left.

The document items wrap horizontally like words in a paragraph.  Generally speaking, when a series of blocks are floated left or suitable, they align horizontally and wrap spherical when they be triumphant within the utmost width of their container.  If merely Three items can have compatibility on one row, as in this example, the document naturally wraps into rows of three columns.

The XHTML markup is a straightforward document with out a explicit courses or other attributes required.  To prevent subsequent internet web page portions from being affected by the glide I’ve contained the document in a <div> and cleared the glide with a (non-semantic) <br />:

 <div class="wrapper">   <ol     ><li><a href="#">Aloe</a></li     ><li><a href="#">Bergamot</a></li     ...     ><li><a href="#">Oregano</a></li     ><li><a href="#">Pennyroyal</a></li   ></ol>   <br /> </div><!-- .wrapper --> 

The a very powerful CSS is brief:

   /* allow room for 3 columns */   ol   {     width: 30em;   }  /* glide & allow room for the widest products */   ol li   {     glide: left;     width: 10em;   }  /* stop the glide */   br   {     clear: left;   }  /* separate the document from subsequent markup */   div.wrapper   {     margin-bottom: 1em;   } 

One of the simplest ways to edit: items may also be added or removed with out a further changes to the XHTML or CSS.

This system fits two of our requirements for a really perfect resolution. The document itself is a simple, single XHTML document and the column-wrapping is controlled only from the stylesheet. However, it falls wanting our serve as for the reason that document collection runs during and then down instead of descending in vertical columns.  Moreover, it doesn’t live to tell the tale well cross-browser: Internet Explorer and Opera suppress the thing markers (ol numbers and ul bullets) when document items are floated left or suitable.

Approach 2: Numbering get a divorce lists with HTML attributes#section4

This tactic—in all probability born of a decided want to tame web design to be as obedient as print design—is to split the document into quite a few sub-lists and get them organized aspect by the use of aspect.

CSS Swag: Multi-Column Lists

See Example 2.

This fashion has quite a few flaws: the semantic integrity of the one document is sacrificed; document wrap, which I consider presentational, is determined only by the use of the HTML markup relatively than by the use of the stylesheet; and products numbering resets to “1” with each and every new document.

That last hurdle, a minimum of, may also be leapt over for many who don’t ideas the usage of deprecated markup.  (To be sure that this markup to validate, you’ll need to use a transitional doctype.)

As Example 2 demonstrates, the now-deprecated HTML attributes delivery and worth let us reset document numbering.  If we omit concerning the W3C recommendation and use deprecated markup, we will mark up separate lists to give you the look of one stable collection.

Proper right here’s an example I’ve pared down to highlight the feature placement:

   <ol     ><li>products</li     ><li>products</li   ></ol>  <ol delivery="3"      ><li>products</li     ><li>products</li   ></ol>  <ol     ><li worth="5">products</li     ><li>products</li     ><li>products</li   ></ol> 

The ones document items will be numbered sequentially 1–6 by the use of browsers and other client agents that still give a boost to the deprecated markup.

The stylesheet’s best activity, then, is to glide the sub-lists aspect by the use of aspect, then clear the glide after the whole column.  (In them olden days forward of we got religion, sub-lists were generally positioned inside of adjacent table cells.)

One of the simplest ways to edit: When document items are added or deleted, some items will need to be moved from one sub-list to each and every different to care for a continuing column length.  If the selection of items in line with column changes, the delivery and worth feature values in XHTML will need to be tweaked to care for proper numbering.  No CSS changes are required.

Approach 3: Numbering get a divorce lists with CSS generated content material subject matter#section5

If you happen to’re splitting your document into chunks, each and every different software for numbering the items contiguously is CSS content material subject matter era, by which a stylesheet causes text to look that doesn’t exist inside the XHTML markup.

CSS Swag: Multi-Column Lists

See Example 3.

Record products numbering and bulleting are actually two instances of content-generation, alternatively they’re the only ones which can be supported universally, most certainly on account of they date once more to early HTML forward of CSS was once as soon as born.  The other kinds of CSS content-generation are ill-supported in in recent years’s browsers: of those tested, best Opera rendered this case as it should be.

The XHTML markup is similar to that all through Approach 2 alternatively even cleaner: the document is divided into two or additional sub-lists, alternatively the delivery and worth attributes are overlooked.

The usage of CSS we suppress common document products numbering, then follow the pseudo-element :forward of to insert incremental values:

   ol li   {     list-style-type: none;   }  ol li:forward of   {     content material subject matter: counter(products) ". ";     counter-increment: products;   } 

Sharp eyes could have caught one refined difference in formatting inside the screenshot above: the numbers generated with :forward of are rendered flush-left, whilst browsers generally align ordered document numbering flush-right.  This affects the alignment of the thing values when the selection of digits changes, as in 9 to 10 above.

One of the simplest ways to edit: When items are added to or removed from the overall document, some items will need to be moved from one sub-list to each and every different in XHTML to care for a continuing column length.  No further exchange is very important to each XHTML or CSS to stay proper numbering.

Unfortunately, this technique may not be good for any cross-browser objective until additional browsers give a boost to the :forward of pseudo-element.  For now, Opera’s the only browser that can render it.

Numbering get a divorce lists with script#section6

While we’re on the subject of content-generation, I’ll add in passing that the items in get a divorce lists can be “physically” numbered contiguously by the use of a script that inserts numbers into the thing values, each server-side all through internet web page era or client-side upon page-load.

A server-side script corresponding to ASP or PHP, learning document products values from a database or a flat document, can prepend a consecutive amount to each and every products as it’s written to the internet web page.  It will if truth be told moreover divide all of the selection of document items by the use of the desired selection of columns and generate the sub-list markup.  The obligation of arranging the sub-lists aspect by the use of aspect may also be left to a static stylesheet.

A client-side script corresponding to JavaScript can in finding the sub-lists the usage of ids or courses and iterate all through the items, striking products numbers, suppressing common ordered document numbering, and splitting one long document into sub-lists as sought after.

It should move without saying (alternatively doesn’t) that any resolution that uses client-side scripting should gracefully degrade in browsers with scripting turned into off.

Wrapping a single document#section7

As we’ve seen, splitting a listing into sub-lists and forcing consecutive products numbering can produce the desired good looks affect, alternatively those solutions aren’t as pleasing to me as one that preserves the integrity of the one document markup.

To wrap a single document into columns, I profit from CSS to grasp each and every products that begins a brand spanking new column and drag it once more up to the level of the main products and then over to a brand spanking new left margin.  Not unusual rendering does the remaining.

Now we’re talkin’ swag!

Listed here are three ways to mark this up:

Approach 4: Wrapping a single document with XHTML#section8

If you happen to’re ready to control where the column-wrap occurs the usage of the XHTML markup, it’s easy enough to mark each and every products in line with which column it belongs to.  An additional class establish marks the main products of each and every column.

CSS Swag: Multi-Column Lists

See Example 4.

Proper right here’s an abbreviated example:

   <ol     ><li class="column1">products</li     ><li class="column1">products</li    »     ><li class="column2 reset">products</li     ><li class="column2">products</li    »     ><li class="column3 reset">products</li     ><li class="column3">products</li   ></ol> 

The stylesheet uses the ones courses to decide the horizontal column positions:

   li.column1 { margin-left: 0em; }   li.column2 { margin-left: 10em; }   li.column3 { margin-left: 20em; } 

Then we mandate the line-height of each and every products and bring the main products of each and every column once more up to the level of the main products:

   li   {     line-height: 1.2em;   }  li.reset   {     margin-top: -6em;   } 

Vertical return = selection of items in a column ∗ peak of each and every products.  In this case, 5 items ∗ 1.2em = 6em.  (Once I’ve tried making the line-height smaller than 1.2em I’ve run into cross-browser discrepancies.)

One of the simplest ways to edit: When items are added to or removed from the document, the XHTML markup will have to be tweaked to supply items the proper column-classes, and the reset class will have to be moved to the main products of each and every column.  When the selection of items in line with column changes, the CSS li.reset{} rule will have to be changed accordingly.

This isn’t my most well liked manner for the reason that column-wrapping is controlled from the XHTML markup relatively than the stylesheet.  One of the simplest ways I check out it, wrapping a listing into vertical columns is a matter of presentation, not content material subject matter, and due to this fact will have to be controlled by the use of the stylesheet inside the interests of preserving aside content material subject matter from presentation.

Wrapping a single document with CSS#section9

In Methods Five and six that follow, the problems at which the document wraps to a brand spanking new column are controlled wholly from the stylesheet.

The cost we pay is a couple of heavy XHTML markup, gravid with class names.  Check this out:

We get able the markup by the use of assigning a novel class to each and every document products:

   <ol     ><li class="aloe">Aloe</a></li     ><li class="berg">Bergamot</a></li     ><li class="cale">Calendula</a></li     ...     ><li class="oreg">Oregano</a></li     ><li class="penn">Pennyroyal</a></li   ></ol> 

(I’m the usage of class instead of identification correct right here so that I’ll have the freedom to include a number of wrapped document on the an identical internet web page; a class may follow to a number of object, alternatively an identification will have to be unique.  The important issue is that each and every products is uniquely identified within its document.)

Inside the stylesheet, we assign a novel left margin to each and every workforce of items that belong in one column:

   li.aloe,   li.berg,   li.cale,   li.dami,   li.elde   {     margin-left: 0em;   }  li.feve,   li.ging,   li.hops,   li.iris,   li.juni   {     margin-left: 10em;   }  li.kava,   li.lave,   li.marj,   li.nutm,   li.oreg,   li.penn   {     margin-left: 20em;   } 

This is reminiscent of the “columnN” courses in Approach 4, alternatively correct right here the verdict of which products belongs to which column is determined purely on the CSS aspect of the street.

Oh, the irony of it all!  The danger of assigning a novel class to each and every document products is enough to make eyes move and toes curl.  After all, the reason we’re the usage of ordered lists inside the first place is to take advantage of the automatic document numbering that our browsers provide.  If we want to establish each and every document products class uniquely, why not merely amount the document items themselves and be completed with it?

Easy, now.  Breathe.  The mission of unique products courses isn’t about numbering the items, it’s regarding the presentation of all of the document—finding ways to steer the browser to wrap it into columns without actually having to chop the document into pieces and paste them aspect by the use of aspect.  In web design we assign courses and ids to internet web page portions automatically to steer CSS presentation; that’s what they’re there for.  Make no mistake, assigning a novel class to each products in a listing is nobody’s idea of trendy code, alternatively it really works, it validates, and it doesn’t (in my humble opinion) make the markup intrinsically ‘un-semantic.’

Whether or not or no longer it’s worth your while to keep an eye on the code for any of the ones techniques when you regulate a listing depends on how so much you want multiple-column lists to art work.  Fortunately, it’s not that big a deal.  Improving small lists by the use of hand is inconspicuous, and for many who’ve got a actually long document that’s again and again changing you should most certainly be generating it from a database inside the first place.  One convenience is that when we’re generating pages from a server-side script we will assign unique document products courses robotically so we don’t want to get our hands dirty.  (Or tired.)

Approach 5: Wrapping a single document the usage of absolute positioning#section10

On account of we’ve referred to now each and every products uniquely within the document, one imaginable approach is solely to position each and every products explicitly.

CSS Swag: Multi-Column Lists

See Example 5.

Practice that this is not a smart cross-browser resolution in recent years for ordered lists, since neither Internet Explorer 6 nor Opera 7 will display document markers when document items are styled {position: absolute;}.

To make this art work for the rest of the browsers, all the document will have to be enclosed within a div with {position: relative}: this offers the absolutely-positioned document items a frame of reference so we will prevent them from simply flying up to the best of the internet web page.  Then it’s simply a query of assigning vertical positioning to each element.  We will do this in rows:

   li   {     position: absolute;   }  li.aloe, li.feve, li.kava { peak: 0.0em; }   li.berg, li.ging, li.lave { peak: 1.2em; }   li.cale, li.hops, li.marj { peak: 2.4em; }   li.dami, li.iris, li.nutm { peak: 3.6em; }   li.elde, li.juni, li.oreg { peak: 4.8em; }   li.penn                   { peak: 6.0em; } 

One of the simplest ways to edit:  When the selection of items in line with column changes, the stylesheet will need to be changed.  When items are added to or removed from the document, the stylesheet will have to be edited to re-determine which items live by which columns.  Every new document products will have to be assigned a novel class in XHTML.

Totally positioning each products in a listing is a control-freak’s dream, this kind of approach many of us took when we first were given right here to the web from print design and hadn’t however discovered to let move.  To create multiple-column lists it isn’t very important to position each products, as Approach 6 will display, alternatively I’m along side it correct right here for the sake of completeness.  It does ’injury’ differently from Approach 6 and which may be one basis for choosing it:

If any document products is long enough to wrap spherical to a second line, how does that affect the structure of the document?  When document items are certainly positioned as in Approach 5, the overall structure will keep unchanged, alternatively the document products that wraps will be overlaid by the use of the next products inside the document which will claim its position without regard to earlier text, since absolute positioning takes each and every products out of the drift.  In contrast, in Approach 6 beneath each and every column of document items descends by the use of common drift; a listing products that wraps will push down subsequent items, lengthening the column it’s in.  On account of that method assumes a suite column peak, the vertical return will then be insufficient to put across the next column once more up to the best, creating a staggered structure.

There may be other ramifications of absolute positioning that can affect our variety: for example, some browsers don’t permit the patron to highlight text in absolutely-positioned blocks.

Approach 6: Wrapping a single document the usage of common drift#section11

In spite of everything, correct right here’s the process I want to use: a single semantically-logical document whose column-wrapping is controlled only from CSS, relies on common drift, and works in most modern browsers.

CSS Swag: Multi-Column Lists

See Example 6.

As inside the previous method, each and every document products is given a novel class establish in XHTML, and the left margin of each and every column is stipulated in CSS.

What differentiates this system is that correct right here we use those unique products courses to put across the main products of each and every column once more up to the best the usage of a harmful margin-top:

   li   {     line-height: 1.2em;   }  li.feve,   li.kava   {     margin-top: -6em;   } 

All over again, vertical return = selection of items in a column ∗ peak of each and every products.  In this case, 5 items ∗ 1.2em line-height = 6em.

One of the simplest ways to edit: when items are added to or removed from the document, the distinctiveness of products class names will have to be maintained in XHTML and the stylesheet will have to be tweaked to shift items to their proper columns.

Gettin’ fancy#section12

With just a bit further styling and a couple of background pictures, the document can get able to party without breaking the multi-column drift.

CSS Swag: Multi-Column Lists

See Example 7.

Where to now?#section13

There are many ways to turn a multiple-column document.  As we’ve seen, quite a lot of them require a compromise of web necessities or browser-compatibility, along with some pretty furry markup and styling.  Your best option, in my opinion, is to give you the XHTML markup sufficient “hooks” to allow the column-wrapping to be controlled only from CSS.

What we actually need is for some vibrant bulb to go back along and decide how to take a look at this with spare markup—and actually claim that holy grail.

Now, move forth and swag!

Browsers & helpers#section14

The examples for this text look significantly the an identical (with the exception of where specifically well-known inside the text) in House home windows browsers Firefox 1.0, Internet Explorer 6, Mozilla 1.7.2, Netscape 7.1 & 6.2, and Opera 7.23, and in Macintosh browsers Firefox 1.0, Internet Explorer 5.2, and Safari 1.0.3.

A lot much less a success with the ones methods are House home windows Internet Explorer 5.x and former, Linux Konqueror 3, and Netscape 4.x.  Perhaps with coaxing they might be persuaded to go back along as well.

Because of Angela Marie, B.J. Novitski, Bruno Fassino, Ingo Chao, Larry Israel, and Zoe M. Gillenwater for their helpful grievance and browser peeks.

Angel Wing {{photograph}} in example seven by the use of Sophie Arés Pilon.

You’ve “moved fast and broken problems.” Proper right here’s some helpful advice from Jeremy Wagner to fix them responsibly. A key aspect of being a manager is helping your stories achieve success. Lara Hogan shares how in this excerpt from Resilient Regulate. , I spotted that the folks next to me may well be severely impacted by the use of my art work. I was having a to hand information a coarse lunch inside the airport… Retraining slender assumptions about shoppers’ gender identities is a step in opposition to higher coverage, privacy, and validation for everyone. In this excerpt from Regularly Wisdom Construction, Lisa Maria Martin introduces the structural audit.