Advanced Articles

Fluid Width Equal Height Columns

Last updated in February 2015 by Marie Mosley.

Equal height columns have been a need of web designers forever. If all the columns share the same background, equal height is irrelevant because you can set that background on a parent element. But if one or more columns need to have their own background, it becomes very important to the visual integrity of the design.


THE PROBLEM: Three columns with different amounts of content only grow as tall as they need to individually.

THE DESIRE: Columns are all equally tall, matching the height of the tallest.

If a design is NON-fluid width, this task becomes considerably easier. The best technique for a fixed width layout is Dan Cederholm's Faux Columns where the columns are wrapped in a container element (which you probably already have anyway) and that container has an image background applied to it which repeats vertically to simulate the look of equal height columns, even if the elements themselves haven't actually grown.

When fluid width and multiple columns comes into play, this task becomes more difficult. We can no longer use a static image to simulate the look of multiple columns. All hope is not lost though. Below we will investigate a number of different techniques for accomplishing fluid width equal height columns.

Doug Neiner Method

Doug came up with this on the fly a few month ago during a little nerd chat we had. The idea is to use CSS3 gradients to create the columns. Gradients?! Indeed. We normally think of gradients as a color morphing into another color over distance. However, we create gradients with CSS by declaring "color-stops" which are specific locations where the color will be exactly as specified at that point. The trick is to use overlapping color stops. That way you can get one color to stop and another to begin with no visible "gradient".

Check out how you can get a five-column background, by declaring one color stop at the 0% and 100% mark, and doubles at the 20%/40%/60%/80% marks.

.five-columns {
  background-image: -webkit-gradient(linear,
    left top,
    right top,
    color-stop(0, #eee),
    color-stop(20%, #eee),
    color-stop(20%, #ccc),
    color-stop(40%, #ccc),
    color-stop(40%, #eee),
    color-stop(60%, #eee),
    color-stop(60%, #ccc),
    color-stop(80%, #ccc),
    color-stop(80%, #eee),
    color-stop(100%, #eee)
	);
  background-image: -webkit-linear-gradient(
    left,
    #eee,
    #eee 20%,
    #ccc 20%,
    #ccc 40%,
    #eee 40%,
    #eee 60%,
    #ccc 60%,
    #ccc 80%,
    #eee 80%,
    #eee 100%
	);
  background-image: -moz-linear-gradient(
    left,
    #eee,
    #eee 20%,
    #ccc 20%,
    #ccc 40%,
    #eee 40%,
    #eee 60%,
    #ccc 60%,
    #ccc 80%,
    #eee 80%,
    #eee 100%
	);
  background-image: -ms-linear-gradient(
    left,
    #eee,
    #eee 20%,
    #ccc 20%,
    #ccc 40%,
    #eee 40%,
    #eee 60%,
    #ccc 60%,
    #ccc 80%,
    #eee 80%,
    #eee 100%
	);
  background-image: -o-linear-gradient(
    left,
    #eee,
    #eee 20%,
    #ccc 20%,
    #ccc 40%,
    #eee 40%,
    #eee 60%,
    #ccc 60%,
    #ccc 80%,
    #eee 80%,
    #eee 100%
	);
}

This CSS is applied to a wrapper of all the columns. Because we are using percentages for these color stops, this simulated five-column background-image will stretch and shrink just as you expect it to in a fluid width design. You can think of this as a modern day extension of Faux Columns.

The markup itself is a series of columns inside that wrapper.

<div class="five-columns group">
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
</div>

Notice the "group" class which is the clearfix class to make the parent wrapper retains its height despite containing only floated children (it would normally collapse).

See the Pen Doug Neiner Method (Five Columns) by mariemosley (@mariemosley) on CodePen.

I think this is a rather clever take on the idea. Do note that that only modern Gecko and WebKit browsers support CSS3 gradients so your Opera and Older IE visitors will not see the column backgrounds. However, the column structure should remain intact even down to IE 6.

This method allows for source order independence by using negative and positive left margins to jockey columns into position. Here's a demo of the Doug Neiner method where the column that is first in the source order is moved to the middle.

See the Pen Doug Neiner Method (Three Columns, Dif Widths, Source Order Altered) by mariemosley (@mariemosley) on CodePen.

Nicolas Gallagher Method

Nicolas Gallagher published a gem of an article about using CSS2 pseudo elements to achieve a number of effects that are otherwise difficult to pull off or that require additional HTML clutter.

The idea is to set the parent wrapper with relative positioning. This sets the context for absolute positioning within. Then, we make each of three columns one-third the width of the parent and position them relatively within, pushing them over with relative positioning as needed. This also allows for source order independence.

Two of the visible background coloration columns are generated by absolutely positioned block-level pseudo elements (:before and :after) which are again one-third of the width, but 100% of the height of the parent. These two "columns" have a negative z-index value so they can sit below the visible text content of the column. The third "column" is actually just the background color of the wrapper showing through. Since the height of the wrapper will be set by the height of the tallest column, this works.

.pseudo-three-col {
  position: relative;
  background: #eee;
  z-index: 1;
  width: 100%;
}
.pseudo-three-col .col {
  position: relative;
  width: 27%;
  padding: 3%;
  float: left;
}
.pseudo-three-col .col:nth-child(1) { left: 33%; }
.pseudo-three-col .col:nth-child(2) { left: -33.3%; }
.pseudo-three-col .col:nth-child(3) { left: 0; }
.pseudo-three-col:before, .pseudo-three-col:after {
  content: " ";
  position: absolute;
  z-index: -1;
  top: 0;
  left: 33.4%;
  width: 33.4%;
  height: 100%;
  background: #ccc;
}
.pseudo-three-col:after {
  left: 66.667%;
  background: #eee;
}

See the Pen Nicholas Gallagher Method by mariemosley (@mariemosley) on CodePen.

Using Tables

I bet some of you are starting to think like this by this time. Hey, I don't blame you. Sometimes a tried and true method that gets the job done is the way to go. One way to sure-fire accomplish the idea of fluid width equal height columns is a dang ol' row of table cells. Just in case you forgot how that looks, it's like this:

<table id="actual-table">
  <tr>
    <td>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
    </td>
    <td>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
    </td>
    <td>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
    </td>
    <td>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
    </td>
    <td>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
    </td>
  </tr>
</table>

Give each table cell a percentage width that totals up to 100% and you'll be set. Even if you then apply padding to the cells, the table will arrange itself correctly.

#actual-table { border-collapse: collapse; }
#actual-table td {
  width: 20%;
  padding: 10px;
  vertical-align: top;
}
#actual-table td:nth-child(even) {
  background: #ccc;
}
#actual-table td:nth-child(odd) {
  background: #eee;
}

See the Pen Actual Table by mariemosley (@mariemosley) on CodePen.

Now let's say that table markup gives you the heebie-jeebies. You can actually use plain ol' div markup but still force it to behave like a table. In that case we'd do something like this:

<div id="css-table">
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p></div>
</div>

And then use CSS tables:

#css-table {
  display: table;
}
#css-table .col {
  display: table-cell;
  width: 25%;
  padding: 10px;
}
#css-table .col:nth-child(even) {
  background: #ccc;
}
#css-table .col:nth-child(odd) {
  background: #eee;
}

Besides using comfortable markup, we actually save some markup because we can go right from the table to the table cells. No element needs to simulate a table-row.

See the Pen CSS Table by mariemosley (@mariemosley) on CodePen.

So are CSS tables the answer to our dreams? They are kinda cool, but they aren't supported in IE 7 so if you are interested in going this route I'd recommend just using actual table markup instead. There is really no significant advantages to using CSS tables.

The most significant disadvantage of both table methods is source-order dependance. There is really no way to have the first column in the source order appear anywhere else than the first column.

One True Layout Method

One of the most classic layouts of all time is the one true layout. In one of the demos, equal height columns is tackled. It's a rather clever technique that still works great today. The idea, as usual, uses a wrapping element for all the columns. This wrapper is set to have hidden overflow, which not only clears the floated columns, but hides anything sticking outside of it. This is particularly important, because we are going to be forcing the height of the columns to be extremely tall, and then cutting them off with the hidden overflow. The magical voodoo here is that while we force the columns taller with a huge amount of bottom padding, we suck the height of the wrapper back up with an equal amount of negative bottom margin. This gives us just the effect we need.

The markup is nothing we haven't seen before:

<div id="one-true" class="group">
  <div class="col"><h3>I am listed first in source order.</h3><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
</div>

Then the CSS is just floated columns with the margin/padding trick.

#one-true { overflow: hidden; }
#one-true .col {
  width: 27%;
  padding: 30px 3.15% 0;
  float: left;
  margin-bottom: -99999px;
  padding-bottom: 99999px;
}
#one-true .col:nth-child(1) { margin-left: 33.3%; background: #ccc; }
#one-true .col:nth-child(2) { margin-left: -66.3%; background: #eee; }
#one-true .col:nth-child(3) { left: 0; background: #eee; }
#one-true p { margin-bottom: 30px; } /* Bottom padding on col is busy */

Note that the padding on the bottoms of the columns is generated by the content within pushing down, as we can't count on bottom padding on the column itself, as it's busy with its fancy trick. Source order independence here is just like we've already covered, with jockeying around with left margins.

See the Pen One True Layout Method by mariemosley (@mariemosley) on CodePen.

Flexbox Method

Flexbox can handle this situation readily. Here is a reference for all the features and browser support and such.

The markup, again, is perfectly clean:

<div class="flexbox">
  <div class="col"><h3>I am listed first in source order.</h3><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p></div>
  <div class="col"><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p></div>
</div>

The CSS requires a few vendor prefixes (or use Autoprefixer) to kick off the flex layout:

.flexbox {
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  overflow: hidden;
}

From there, we can equalize their widths pretty easily:

.flexbox .col {
  flex: 1;
}

The align-items property can be set to stretch to make sure they are equal height, but that's the default! So we don't have to set it at all.

Saving the best for last, we can alter the location of the columns just by setting their order to the desired location. It's best to explicitly set all columns where you want them to be; I found setting only certain ones was problematic. Still, being able to change location without layout hacks is awesome.

.flexbox .col:nth-child(1) {
  background: #ccc;
  order: 1;
}
.flexbox .col:nth-child(2) {
  background: #eee;
  order: 0;
}
.flexbox .col:nth-child(3) {
  background: #eee;
  order: 2;
}

See the Pen Flexbox Method by Chris Coyier (@chriscoyier) on CodePen.

JavaScript Options

Of course there are also JavaScript solutions for equal heights columns. We explored that a bit in "Equal Height Blocks in Rows", and there's a good CodePen demo by Michah Godbolt that illustrates this method.

If you'd like to go the jQuery plugin route, check out matchHeight, which helps you equalize the height of selected elements.

Quick Notes

  • Using percentages for layout isn't perfect in WebKit
  • In this demo I used things like :nth-child to target some columns. You'll likely get better cross browser compatibility if you give your columns specific class names and use those class names instead. I was more interested in investigating the theory here, and some of the fancy modern techniques only work in browsers where :nth-child would work anyway.
  • Bonus tip: you can use a Faux Columns-like technique with fluid width columns if you only have two columns. This is in use on the current (v7) design of CSS-Tricks. The layout is 2-column fluid, and the background color of the sidebar comes from this image. The column is able to grow, because the placement of that background uses percentages to get it to adjust correctly as the container element grows in width.
    background: url(sidebar.png) repeat-y 61.7% 0;
  • Flexible layout model is very different from the CSS3 layout module. Apparently the wind is blowing toward flexible layout as far as actual implementation.

Box Sizing

The box-sizing property can make building CSS layouts easier and a lot more intuitive. It's such a boon for developers that here at CSS-Tricks we observe International Box-Sizing Awareness Day in February.

But, how is it so helpful and beloved that it deserves its own internet holiday? Time for a little bit of CSS history.

Box Model History

Since the dawn of CSS, the box model has worked like this by default:

width + padding + border = actual visible/rendered width of an element's box

height + padding + border = actual visible/rendered height of an element's box

This can be a little counter-intuitive, since the width and height you set for an element both go out the window as soon as you start adding padding and borders to the element.

Back in the old days of web design, early versions of Internet Explorer (<= IE6) handled the box model differently when it was in "quirks mode". The "quirks" box model worked like this: width = actual visible/rendered width of an element's box height = actual visible/rendered height of an element's box The border and padding values were moved inside the element's box, cutting into the width/height of the box rather than expanding it.


The box at the top shows the default box model. The box at the bottom shows what was once the "quirks mode" interpretation of the box model.

Some people preferred this "quirky" interpretation of the box model and considered it more intuitive. It's a valid point. Having the actual visible width of a box turn out differently from what you declared in the CSS is a bit mind bending.

But, in the days of fixed-width design, it wasn't particularly complicated to work with the default box model once you understood it. You could do a bit of arithmetic to figure out how many pixels you needed to trim off of an element's declared width or height to accommodate its padding and border. The problem for present-day developers is that those absolute pixel lengths don't translate to responsive design, so the same math doesn't apply anymore.

As responsive design (or, as it was once known, "fluid" or "liquid" layout) started to gain popularity, developers and designers wished for an update to the box model. The great designer Jon Hicks, known for his excellent fluid width designs, had this to say on the subject in the CSS Wishlist we put together in 2008:

I would love a different box model! I find it bizarre that padding and border add the width of an object, and would love to be able to give something like a textarea 100% width and 3px padding without worrying what it’s going to do the layout. Perhaps something like padding-inside as a new selector?

In that vein I also wish I could specify a 100% width for an element, minus a set fixed width. Again, very useful when creating fluid designs with form elements!

Present-Day box-sizing

Those wishes were granted when the box-sizing property was introduced in CSS3. Though box-sizing has three possible values (content-box, padding-box, and border-box), the most popular value is border-box.

Today, the current versions of all browsers use the original "width or height + padding + border = actual width or height" box model. With box-sizing: border-box;, we can change the box model to what was once the "quirky" way, where an element's specified width and height aren't affected by padding or borders. This has proven so useful in responsive design that it's found its way into reset styles.

At this point you may be asking yourself, "Is it possible that Old IE did something right?" Plenty of people think so.

Demo

This demo shows how border-box can help make responsive layouts more manageable. The parent div's width is 50%, and it has 3 children with different widths, padding, and margins. Click the border-box button to get all the children in the right place inside the parent.

See the Pen Box Sizing Layout Demo by CSS-Tricks (@css-tricks) on CodePen.

Good, Better, and (Probably) Best box-sizing Reset Methods

The "Old" border-box Reset

The earliest box-sizing: border-box; reset looked like this:

* {
  box-sizing: border-box;
}

This works fairly well, but it leaves out pseudo elements, which can lead to some unexpected results. A revised reset that covers pseudo elements quickly emerged:

Universal Box Sizing

*, *:before, *:after {
  box-sizing: border-box;
}

This method selected pseudo elements as well, improving the normalizing effect of border-box. But, the * selector makes it difficult for developers to use content-box or padding-box elsewhere in the CSS. Which brings us to the current frontrunner for best practice:

Universal Box Sizing with Inheritance

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}

This reset gives you more flexibility than its predecessors — you can use content-box or padding-box (where supported) at will, without worrying about a universal selector overriding your CSS. We went into more depth on this technique and the reasoning behind it in "Inheriting box-sizing Probably Slightly Better Best Practice". One potential gripe with it is that box-sizing isn't normally inherited, so it's specialized behavior, not quite the same as something you'd normally put in a reset.

Vendor Prefixes

Every current browser supports box-sizing: border-box; unprefixed, so the need for vendor prefixes is fading. But, if you need to support older versions of Safari (< 5.1), Chrome (< 10), and Firefox (< 29), you should include the prefixes -webkit and -moz, like this:

html {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
*, *:before, *:after {
  -webkit-box-sizing: inherit;
  -moz-box-sizing: inherit;
  box-sizing: inherit;
  }

Known Issues

box-sizing: border-box; is supported in the current versions of all major browsers. The less-commonly used padding-box is only supported in Firefox at the moment. There's more comprehensive information about browser support in our box-sizing almanac entry.

There are a few issues with older versions of Internet Explorer (8 and older). IE 8 doesn't recognize border-box on elements with min/max-width or min/max-height (this used to affect Firefox too, but it was fixed in 2012). IE 7 and below do not recognize box-sizing at all, but there's a polyfill that can help.

Fix Inserted HTML5 Content with HTML5 innerShiv

When working with HTML5 today, many of you know that you'll need to include the "HTML5 shiv" to ensure that CSS will recognize and be able to style those elements in browsers that aren't yet hip to HTML5.

<!--[if IE]>
  <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->

Credit for that to Remy Sharp, Jon Neal, John Resig and anybody else who contributed to that idea. Also for the benefit of those non-hip browsers, it's best to reset many of the HTML5 elements to block-level as they should be:

article, aside, figure, footer, header, hgroup,
menu, nav, section { display: block; }

Now we're all set to use and style HTML5 elements. But wait! What happens if we dynamically add HTML5 to the page via JavaScript.

var s = document.createElement('div');
s.innerHTML = "<section>Hi!</section>";
document.body.appendChild(s);

Or in jQuery:

$("body").append("<section>Hi!</section>");

Hip browsers do fine, but Internet Explorer will once again not recognize the new element and not apply CSS to it.

Joe Bartlett has written a great work-around to the problem called HTML5 innerShiv and I thought more people should be aware of it.

Update January 2013: This is now included in the canonical html5shiv project, you should use that. The rest of this project is a bit outdated. You don't need to do it this way anymore if you use the html5shiv.

Using it

Please note that this script does not require jQuery. It's just vanilla JavaScript and will work with any library or library at all.

1. Download

Download the script and insert it onto your page. Or copy and paste the script into other JavaScript you are already loading if you want to avoid an extra HTTP Request.

2. Wrap all HTML content in innerShiv function before inserting

Here is the same jQuery example as above, made to work using innerShiv:

$("body").append(innerShiv("<section>Hi!</section>"));

Quick demo.

Guidelines for URI Design

This is a guest post by Jacob Gillespie who started an interesting thread on Forrst about this topic. I invited him to post it here, to which he graciously accepted.

Over the past several years, I have taken an interest in usability and web design. One of the areas that seems to be often overlooked when it comes to design of a site is the design of the URIs on that site. Modern CMS systems allow for varying degrees of URI customization, but the defaults are often not as usable as they could be, and URIs are often placed last in the design process.

Clean URIs are one component of a clean website, and it is an important one. The majority of end-user access to the Internet involves a URI, and whether or not the user actually enters the URI, they are working with one nonetheless.

First, I would like to talk about the guiding principles behind URI design, then talk about the practical implementation of the principles.

(more…)

Understanding border-image

The new CSS3 property border-image is a little tricky, but it can allow you to create flexible boxes with custom borders (or drop shadows, if that's your thing) with a single div and a single image. In this article I explain how the border-image shorthand property works in today's browsers.

(more…)

CSS Content

CSS has a property called content. It can only be used with the pseudo elements :after and :before. It is written like a pseudo selector (with the colon), but it's called a pseudo element because it's not actually selecting anything that exists on the page but adding something new to the page. This is what it looks like:

.email-address:before {
   content: "Email address: ";
}

With this CSS in place, we could have this HTML:

<ul>
   <li class="email-address">chriscoyier@gmail.com</li>
</ul>

And the output would be like:

• Email address: chriscoyier@gmail.com

Maybe that example doesn't get you drooling, but pseduo element content can be quite useful and do cool things. Let's go through some ideas and considerations.

(more…)

Efficiently
Rendering CSS

I admittedly don't think about this idea very often... how efficient is the CSS that we write, in terms of how quickly the browser can render it?

This is definitely something that browser vendors care about (the faster pages load the happier people are using their products). Mozilla has an article about best practices. Google is also always on a crusade to make the web faster. They also have an article about it.

Let's cover some of the big ideas they present, and then discuss the practicalities of it all.

(more…)

Pointer Events & Disabling Current Page Links

It is a long-standing web design standard that the logo in the header area links to the homepage of the site. Another standard is that when displaying the navigation of a site, to highlight in some way the "current" page, if it is present in the navigation. I think those are great standards. The logo-link thing is so ubiquitous that your users will likely automatically try it if you've coded it that way or not. The current navigation thing is just good ol' horse-sense for grounding a users and making them feel good about their current location in a websites hierarchy.

But here is another good design standard: don't have links to the same page you are on, on that page.

The idea here is twofold:

  1. When you see a link, it looks like a link, it behaves like a link, that says "click this and be taken elsewhere." If the link takes you back to the same page you are on, that's kinda weird.
  2. It is a waste of server resources to reload a page for no reason.

How can you accomplish this without a bunch of development work and changing markup? CSS of course!

(more…)

More than one way… (delegate edition)

There was a question in the forums about affecting non-hovered items. The effect they were after is that they had an unordered list of items and when they were rolled over, they would all dim (lower opacity) except the one hovered.

This can be done with CSS, using pseduo-selectors.

ul li:not(:hover) { opacity: 0.5; }

However we know that pseudo-selectors don't have very good cross-browser support. And for that matter, opacity doesn't either. jQuery is pretty good at mitigating cross-browser problems, so l thought I might give that a spin. In attempting it, I had a nice little learning journey.

(more…)

We have a pretty good* newsletter.