Article Archives

Better Linkable Tabs

I find it's a common desire with "tab" design patterns that there is a way to link to specific tabs. As in, you could give someone a URL and that URL would lead them to that page with the specific desired tab active and displaying the correct content.

If each tab is a completely different URL, it's easy. In the HTML that is served, the appropriate class name is applied to the tab to make it look active, and the appropriate content below is served.

Wufoo uses a tab design pattern inside the app. Each tab is a entirely different page and URL.

If these tabs are "same page" tabs that hide/show different panels of content instantly (or via Ajax), it's a bit harder. A common (and I'd argue semantic) approach to this has been with hash links, e.g.:

http://example.com/#tab-three

Tabs like these are likely "same page" tabs that don't have unique URL's to themselves

With CSS3's :target pseudo class selector, there are ways to make functional tabbed areas with CSS alone (no JavaScript). However, if pure CSS tabs are the goal, this is better.

As much as I've experimented with CSS techniques, I think functional tabbed areas are best accommodated by JavaScript. This is functionality territory, and if we adhere to the traditional model of separation of concerns, it should be handled by JavaScript.

Hash links have a few other problems:

  1. When the page loads with a hash link or the hash links changes, the browser will scroll down so that the element with the ID of that hash is at the top of the page. There is a good chance this is not desirable. The latter is easy to fight with preventDefault(). The former is nearly impossible to deal with cleanly.
  2. Changing the hash tag of a page adds an entry to the browser history, so pressing the back button will go back through previous hashes. There is also a good chance this is not desirable.

Let's solve both problems while accommodating the desire to have a way to link to a specific tab. This is what we are going to do:

  1. Not use hash links but use URL parameters instead (no jump downs).
  2. Use the ultra-hip history.replaceState() so we can change the URL without affecting the back button.

Our URL's will be like:

http://example.com/?tab=tab-three

Rather than re-write JavaScript based tabs from scratch, let's use my existing Organic Tabs demo. We need to adjust very little of the plugin to make this work. We'll add a param parameter so people can choose whatever they want there.

$.organicTabs.defaultOptions = {
    "speed": 300,
    "param": "tab"
};

Then in the part with all the tab-changing functionality, we'll add this one line:

// Change window location to add URL params
if (window.history && history.pushState) {
  // NOTE: doesn't take into account existing params
	history.replaceState("", "", "?" + base.options.param + "=" + listID);
}

The tricky part is that we need to pull in the URL parameter when the page loads and do JavaScript stuff with it. That means we'll need to use a server-side language, and intermingle some of it with our JavaScript. Here I'll use PHP:

Update: We can access the query string entirely through JavaScript, and parse out the parts easily. So instead of the PHP that used to be here (not ideal for many reasons) we'll do this instead:

var queryString = {};
window.location.href.replace(
    new RegExp("([^?=&]+)(=([^&]*))?", "g"),
    function($0, $1, $2, $3) { queryString[$1] = $3; }
);

if (queryString[base.options.param]) {

	var tab = $("a[href='#" + queryString[base.options.param] + "']");

	tab
		.closest(".nav")
		.find("a")
		.removeClass("current")
		.end()
		.next(".list-wrap")
		.find("ul")
		.hide();
	tab.addClass("current");
	$("#" + queryString[base.options.param]).show();
      
};

This code grabs that URL param and make sure the current tab is highlighted and the correct content is shown.

Functional demo:

View Demo   Download Files

Video:

Incomplete-ish

Browser support for history.replaceState (and all the history management stuff) is far from ubiquitous. I'm using a basic feature test here, but not implementing any fallback. The important part, the tab functionality, still works fine. You might wanna do more.

I'm also not taking into account existing URL parameters. If your page is already using them and you also want to use this (e.g. ?foo=bar&tab=tab-one) this would get a bit more complicated. You'd probably snag the entire URL param string and pass it into the plugin. Then parse it apart and re-insert the existing params when you use replaceState().

In Praise of the Forums

Jane Wells of Automattic lays out four reasons why someone may not use forums for a question they have. Then she disputes all four of them while sharing an example of where a forum post get a lot more done than just answers one dude's question.

The bigger the internet gets, the more valuable it is to make Q&A and customer support public.

Sencha Looks at IE 10

Michael Mullany:

...the IE10 HTML5 experience is one of the best we’ve seen on any platform to date.

I've heard from a number of folks that IE 10 will be the most advanced browser to date (support the most standards and new features). We'll see if this stays true when it actually ships.

Notable: transitions, transforms (2D and 3D), animations, shadows, gradients, flexbox and SVG filters.

New Poll: What’s Your Favorite Page Title Separator?

Just for silly kicks, let's keep on with the page title polls, this time with perhaps the most trivial of all choices. The poll is embedded on the site in the sidebar. Let everyone know what your favorite page title separator is. The en-dash? The vertical pipe? THE DOUBLE COLON‽

Watch Ryan Singer Think Through a Design Problem

High quality video training marketplace PeepCode has a series of screencasts called Play by Play where they record masters of their trade doing their thing.

In this one, we get to watch a user experience designer think through a design problem. This is the rarest of all design tutorials. I think it's because it feels weird both teaching and being taught this stuff directly, but watching people work it out themselves is instructional as heck.

Fancy Scrolling Sites

In the last year or so, there's been enough sites that do fancy things when you scroll down that it's kind of a trend. I thought I'd blog it, you know, for the sake of history. (more…)

CSSOff Kickoff on Oct. 20th!

The PSD for the CSSOff is going to drop on October 20, 2011. You'll have exactly 2 weeks (until November 3) to code up and submit your final conversion. Follow the title link to the official page where you can check out the amazing prizes, read up on the rules, and sign up to compete.

FitVids.js

Super lightweight jQuery plugin to make all videos fluid width, while maintaining their original aspect ratio. Explanation, video, and discussion on Dave's site.

Why Browsers Read Selectors Right to Left

When I first learned that browsers read CSS selectors from right to left it felt kinda weird and confusing. Boris Zbarsky explains why it's done that way in a way that makes perfect sense. Part of the reason:

...most of the selectors it's considering don't match the element in question. So the problem becomes one of deciding that a selector doesn't match as fast as possible; if that requires a bit of extra work in the cases that do match you still win due to all the work you save in the cases that don't match.

steps()

Lea Verou makes a "typing" animation with the CSS3 sub-property steps which allows you to specify how many keyframes an animation uses. Knowing the number of keyframes means you can know exactly that the CSS will be like at that keyframe and you can plan accordingly. Another example: animated "sprite sheet" by simurai.

Tabs with Round Out Borders

Rounded corners are now trivially easy to achieve via border-radius. But that only allows us to cut into the shape. What if we want to connect a shape to another with a rounded outward corner. Much easier to explain with a graphic:

The top corners are easy, just border-radius. The bottom corners, less easy.
View Demo   Download Files

Clean HTML

Of course, on the web, just about anything visual is possible. Worst-case-scenario you can use images. Our goal here, as ever, is to use no images (quick! accessible! easy to update!) and use completely clean semantic HTML (quick! accessible! easy to update!). So here's the markup:

<ul class="tabs group">
  <li class="active"><a href="#one">One</a></li> 
  <li><a href="#two">Two</a></li> 
  <li><a href="#three">Three</a></li>
  <li><a href="#three">Four</a></li> 
</ul>

A class of active indicates which tab reflects the current page.

How this is going down

The reason this is tricky is that we need a shape to stick out of the tab element. To get this done while keeping our markup clean, we'll use pseudo elements. If you need a refresher, you can learn about them here and here. Essentially, they can add extra elements to the page that we can style, directly through CSS. Every element can have two - :before and :after. Ultimately we'll be using four per tab, which is possible because each tab is make from two elements, the list item and the anchor link.

Let's visualize this step by step, without looking out any code just yet.

1) Natural State

List items are naturally block level and anchor links are inline, so the layout is like this.

2) Float

By floating the list items to the left, the list items will line up next to each other and shrink to the size of the anchor links inside them.

3) Same Size

The list items themselves have no margin or padding, so really the list items and anchor links are the exact same size, directly on top of each other.

4) Just one

Let's focus on just one of them...

5) Circles


We'll use two of our four available pseudo elements to place circles on the bottom left and bottom right of the tab.

6) Squares

With the other two pseudo elements we'll make smaller squares.

7) Colorize the tab and content

The "active" tab and the content will share the same background color.

8) Colorize the pseudo elements

The squares match the color of the active tab, the circles match the background behind them.

9) Stacking

With z-index, we'll make sure the circle sits on top and cuts off the color of the square.

10) No borders

The borders were just for illustration, really it would look more like this.

11) Finishing

Add the same concept to the outer tabs and round the tops with border-radius and it's done!

CSS

This is a big ass block of CSS, but I've tried to comment it up so that each part makes sense.

.tabs li { 
  /* Makes a horizontal row */
  float: left; 
	
  /* So the psueudo elements can be
     abs. positioned inside */
  position: relative; 
}
.tabs a { 
  /* Make them block level
     and only as wide as they need */
  float: left; 
  padding: 10px 40px; 
  text-decoration: none;
  
  /* Default colors */ 
  color: black;
  background: #ddc385; 
  
  /* Only round the top corners */
  -webkit-border-top-left-radius: 15px;
  -webkit-border-top-right-radius: 15px;
  -moz-border-radius-topleft: 15px;
  -moz-border-radius-topright: 15px;
  border-top-left-radius: 15px;
  border-top-right-radius: 15px; 
}
.tabs .active {
  /* Highest, active tab is on top */
  z-index: 3;
}
.tabs .active a { 
  /* Colors when tab is active */
  background: white; 
  color: black; 
}
.tabs li:before, .tabs li:after, 
.tabs li a:before, .tabs li a:after {
  /* All pseudo elements are 
     abs. positioned and on bottom */
  position: absolute;
  bottom: 0;
}
/* Only the first, last, and active
   tabs need pseudo elements at all */
.tabs li:last-child:after,   .tabs li:last-child a:after,
.tabs li:first-child:before, .tabs li:first-child a:before,
.tabs .active:after,   .tabs .active:before, 
.tabs .active a:after, .tabs .active a:before {
  content: "";
}
.tabs .active:before, .tabs .active:after {
  background: white; 
  
  /* Squares below circles */
  z-index: 1;
}
/* Squares */
.tabs li:before, .tabs li:after {
  background: #ddc385;
  width: 10px;
  height: 10px;
}
.tabs li:before {
  left: -10px;      
}
.tabs li:after { 
  right: -10px;
}
/* Circles */
.tabs li a:after, .tabs li a:before {
  width: 20px; 
  height: 20px;
  /* Circles are circular */
  -webkit-border-radius: 10px;
  -moz-border-radius:    10px;
  border-radius:         10px;
  background: #222;
  
  /* Circles over squares */
  z-index: 2;
}
.tabs .active a:after, .tabs .active a:before {
  background: #ddc385;
}
/* First and last tabs have different
   outside color needs */
.tabs li:first-child.active a:before,
.tabs li:last-child.active a:after {
  background: #222;
}
.tabs li a:before {
  left: -20px;
}
.tabs li a:after {
  right: -20px;
}

That's that!

View Demo   Download Files

Should work in just about any decent browser and also IE 9 and up. Should also fall back fine (just no round-outs) in older browsers.

Steve Smith Method

About the exact time as I was creating this to include in a talk I was doing about pseudo elements. Steve Smith of Ordered List published a very similar method. Steve's method has borders around the tabs, mine has tabs butted up against each other. Both cool if you ask me.

Adaptive Images

Project from Matt Wilcox for serving the right images to the right devices (i.e. small images to small browser windows, large images to large browser windows). Small browser windows, regardless of bandwidth considerations, shouldn't get a giant image scaled down they should get an image just the size they need it.

This is similar to an earlier project by the Filament Group, but this takes more of a "just works" approach in that it doesn't require you to do anything special or even create the different versions of the images yourself.

Fold Out Popups

The trick with using hidden checkboxes/radio buttons, the :checked pseudo class selector, and adjacent sibling (~) combinators really enables some neat functional possibility with pure CSS1. If you need a primer, we recently used this to build a functional tabbed area.

Let's exploit it again to build "fold out popups". That is, links/buttons you can click to reveal tooltip-like rich HTML popup content.

View Demo   Download Files

HTML Structure

We need a checkbox for the on/off clickable functionality (don't worry, it's hidden). Then right after it is a label. Like any good label, the for attribute matches the inputs id attribute. That way we can click it to toggle the checkbox.

The label contains within it a number of spans. The .box span is the container for the rich HTML popup. In other words, put whatever you want in there. Well, whatever you want that are inline elements. It's tempting to use a div and header tags and stuff, but some browsers don't dig that and will render those things outside of the label instead of within. Making the .box outside of the label wouldn't be too big of a deal, as we could chain ~ selectors to get it to hide/show anyway, but having them within means we'll be able to position the popup relative to the position of the label, like a "popup" should.

<input type="checkbox" id="popup" class="popUpControl">
<label for="popup">
   Click me!
   <span class="box">
       Super cool popup content
   </span>
</label> 

CSS Basics

Our goal with the .box is to absolutely position it relative to the label it's within, so it pops up attached to it. By default, it will be hidden by having zero opacity. We'll also scale it down to nothing, skew it, and add transitions. Then when we reveal it by way of the checkbox becoming checked, we'll scale it back up, remove the skew, and make it visible by bringing the opacity back up to 1.

.box {
	position: absolute;
	left: 0;
	top: 100%;
	z-index: 100;
	
	/* Prevent some white flashing in Safari 5.1 */
	-webkit-backface-visibility: hidden;

	-moz-border-radius:    20px; 
	-webkit-border-radius: 20px; 
	border-radius:         20px; 
	
	width: 260px; 
	padding: 20px;
	opacity: 0;
			    
	-webkit-transform: scale(0) skew(50deg);
	-moz-transform:    scale(0) skew(50deg);
	-ms-transform:     scale(0) skew(50deg);
	-o-transform:      scale(0) skew(50deg);
	
	-webkit-transform-origin: 0px -30px;
	-moz-transform-origin:    0px -30px;
	-ms-transform-origin:     0px -30px;
	-o-transform-origin:      0px -30px;
	
	-webkit-transition: -webkit-transform ease-out .35s, opacity ease-out .4s;
	-moz-transition:    -moz-transform    ease-out .35s, opacity ease-out .4s;
	-ms-transition:     -ms-transform     ease-out .35s, opacity ease-out .4s;
	-o-transition:      -o-transform      ease-out .35s, opacity ease-out .4s;
}

.popUpControl { 
	display: none; 
}
.popUpControl:checked ~ label > .box {
	opacity: 1;
	-webkit-transform: scale(1) skew(0deg);
	-moz-transform:    scale(1) skew(0deg);
	-ms-transform:     scale(1) skew(0deg);
	-o-transform:      scale(1) skew(0deg);
}

The actual CSS for the box has some additional styling, but this the important functional stuff. Snag the download that accompanies this tutorial for the complete set of CSS.

Changing Text of Button When Open

This isn't vital to the idea here, but another neat trick in this demo is changing the text of the button when the popup is open. This works by actually hiding the text inside the button when :checked and inserting new text. The basics:

<input type="checkbox">
<label>
   <span>Default text</span>
</label>
[type=checkbox]:checked ~ label span { 
   display: none; 
}
[type=checkbox]:checked ~ label:before { 
   content: "Text to show when checked";
}

Yet another "hack" (bad, as generated content isn't very accessible or selectable). But hey, we're still having fun right?

1 Yeah but... JavaScript

This definitely walks "separation of concerns" line. Even though I've created this in "pure" CSS, I actually think this type of behavior is probably better suited to JavaScript. And by "use JavaScript", this is what I would actually do:

  1. Toggle a class name for "open" and "closed" on the .box, rather than use the checkbox.
  2. Change the text through the JavaScript, not use CSS generated content.

But everything else should stay in the CSS. The styling, the transitions, the transforms... That stuff is style not functionality.

Boy I'm a hypocrite hey?

Credit

Thanks to Victor Coulon who sent me this idea that I riffed on for this.

When (and when not to) use an anchor tag?

Interesting question from reader Don Wilson:

I'm curious to know your opinion. When should we use anchor tags and when should we use something else?

I have generally used the `a` tag liberally whenever I wanted something to be clickable. I looked up the definition and it appears that I am using the `a` tag where it is not meant to be used. I looked through the GMail source and they are using `div` elements for most of their clickable things.

I think that my usage has come from writing HTML from before Javascript was widely used for events. Anyways, I'm not sure now where I should draw the line for the `a` tag. What's your opinion?

I think if you are going to put a href attribute on the anchor that actually does something even if JavaScript is disabled, then the anchor is the right choice. If the app is totally JavaScript dependent all behavior is attached via JavaScript, I guess it doesn't really matter what element you use. Maybe it's even better not to use an anchor since the behavior probably bears no resemblance to what anchor links do. You could probably talk me out of that though. The thing is, anchors give you ("for free") lots of the visual functionality that you want with deep browser support. So...

If you chose not to use anchor links for clickable functional elements, then:

  • Use cursor: pointer; so users get the cursor that looks like you can click like they are used to.
  • Use the tabindex attribute on the element so keyboard users can tab to it.
  • Define :hover, :active, and :focus styles.

View Demo

Functional CSS Tabs Revisited

TL;DR Backstory

The idea of "CSS Tabs" has been around for a long time. If you Google it, a lot of what you get is styled CSS tabs, but less stuff on the building of an actually functional tabbed area. At least, functional in the sense as we think of tabbed areas today: click a tab, see a new content area with no page refresh.

Tackling functional CSS tabs has less of a deep history. Brad Kemper was messing around with it in 2008 trying to utilize the :checked pseudo selector with radio buttons and adjacent sibling combinators. This is a really cool technique that can be utilized to do things like an expand/contract tree style menu or visually replace form elements with graphics (pioneered by Ryan Seddon).

I personally tried messing with functional tabs a while back, and came up with seven different ways to do it. Most of them centered around the use of the :target pseudo class selector and most of those techniques sucked. One was OK. They all had one major flaw and that was that URL hashes needed to be used, which "jumps" the page down to the element with the matching ID, and that is totally unexpected, jerky, and just a bad overall experience.

Working with the radio-button/:checked technique is way better, but there was a long-standing WebKit bug that prevented pseudo class selectors and adjacent sibling combinators from working together. Good news! That's fixed as of stable browser releases Safari 5.1 and Chrome 13.

So let's get this thing done the :checked way, which I think is the cleanest way to do it for now and for the next few years.

Is that a tabby cat? GET IT?!

HTML Structure

A wrapper for the whole group, then each tab is a div that contains the radio button (for the functionality), a label (the tab), and a content div.

<div class="tabs">
    
   <div class="tab">
       <input type="radio" id="tab-1" name="tab-group-1" checked>
       <label for="tab-1">Tab One</label>
       
       <div class="content">
           stuff
       </div> 
   </div>
    
   <div class="tab">
       <input type="radio" id="tab-2" name="tab-group-1">
       <label for="tab-2">Tab Two</label>
       
       <div class="content">
           stuff
       </div> 
   </div>
    
    <div class="tab">
       <input type="radio" id="tab-3" name="tab-group-1">
       <label for="tab-3">Tab Three</label>
     
       <div class="content">
           stuff
       </div> 
   </div>
    
</div>

CSS Layout

Basically:

  1. Hide the radio buttons (we don't need to see them, we just need them to be checked or unchecked).
  2. Float the tabs so the labels fall into a row-of-links structure.
  3. Absolutely position the content areas exactly on top of each other.
  4. When a radio button is :checked, make the adjacent content area sit on top with z-index (visually revealing it and hiding the others).
.tabs {
  position: relative;   
  min-height: 200px; /* This part sucks */
  clear: both;
  margin: 25px 0;
}
.tab {
  float: left;
}
.tab label {
  background: #eee; 
  padding: 10px; 
  border: 1px solid #ccc; 
  margin-left: -1px; 
  position: relative;
  left: 1px; 
}
.tab [type=radio] {
  display: none;   
}
.content {
  position: absolute;
  top: 28px;
  left: 0;
  background: white;
  right: 0;
  bottom: 0;
  padding: 20px;
  border: 1px solid #ccc; 
}
[type=radio]:checked ~ label {
  background: white;
  border-bottom: 1px solid white;
  z-index: 2;
}
[type=radio]:checked ~ label ~ .content {
  z-index: 1;
}

This is pretty darn lightweight CSS and it's totally expandable to any number of tabs just by adding more "tab" divs in the HTML.

JavaScript

There isn't any, captain!

Why this way is awesome

  • It doesn't use :target so no page-jump-suck and back-button-hijacking.
  • It's accessible. The weird radio buttons are hidden with display: none so screen readers won't see them and be confused (presumably) and none of the actual content is hidden with display: none;
  • It works in Safari 5.1+, Chrome 13+, Firefox 3.6+, Opera 10+, and IE 9+. Maybe a little deeper on Chrome, Firefox, and Opera, but Safari and IE are definitely correct.

Why this way isn't awesome

  • It requires a set height to the tabbed area which sucks. I feel like there may be a way to fix this though I just haven't quite gotten it yet.
  • The radio button thing is a bit hacky.
  • It doesn't have the deepest browser support (IE 9 is kinda a lot to ask). If you need deeper go JavaScript.

Get it, Got it, Good

Just for funzies I added some transitions to the tabs in the live demo. I got the idea from Jacob Dubail who forked the idea into a slideshow kinda thing.

View Demo   Download Files

The Awesome Theoretical Future - display: stack;

As I mentioned, the radio button thing is a little hacky. It's cool that we are now able to do this and the experience is pretty good, but the way we have to code isn't elegant or intuitive. Tab Atkins, who writes CSS specs, thinks display: stack is probably the future for a tabbed user interface through CSS.

Bootstrap

HTML/CSS framework from Twitter (Mark Otto and Jacob Thornton). Pretty comprehensive: nice clean design and typography, grid system (fluid or fixed), form elements, buttons/navigation, alerts, tooltips, LESS support... I think a web app startup could do a lot worse than starting with this to get up and running quickly.

Don’t Fear the Internet

Incredibly well done set of introduction to web design tutorial videos by Jessica Hische & Russ Maschmeyer. Kinda like my The VERY Basics video, but far more professional. Will be recommending this to every single person asking me how to get started into HTML and CSS.

Launch of Deals for Designers

Update: It was fun while it lasted, but this area of the site is gone now.

Believe it or not, I'm pretty conscientious of the advertising on this site. How much of it there is, what it's for, where it's placed, and how it behaves. I do try and make money from the site, but I always say no to the most annoying stuff. On this site: ads look like ads, there are no disguised text links, no super shady companies, no flash, and no popups/popunders or otherwise aggressively placed ads (e.g. "after title before content").

With the limited space available, there are more companies that want to advertise than can fit on the site. It sucks saying no to good companies that want to give you money, especially now as I have moved into a rather expensive area of the country.

And thus was born the idea for Deals for Designers. This is a new page of the site that is full of promotions for companies that are offering a deal of some sort on their product or service. This way I can say yes to more companies wanting to advertise, but hopefully not annoy folks or break any of my rules.

I think this is a win for everyone. Readers like you can check this page out if they are in the market for some kind of web design product or service (e.g. hosting, themes, training, etc) and want to save money. Companies can get some promotion. I can earn money in the case that company has an affiliate program.

Here are the facts:

  1. Companies don't pay to be on this page.
  2. If they have an affiliate program, I use it.
  3. I either use or would use all of these products/services.

I'd like to grow it out, so if you'd like your company on there get in touch. And the rest of you, go check it out (ooooh the ads are even responsive =)).

How I Think Posting HTML In Comments Should Work

People post a good bit of HTML in the comments of articles on this site. They are trying to demonstrate something, ask for troubleshooting help, show alternate techniques, etc. This is excellent. I want to encourage this as much as possible. Unfortunately people are often confused on how to do it correctly and get frustrated when it comes out wrong. (more…)

A Really Nice Way To Handle Popup Information

Doug Neiner gave a fantastic talk at this year's Front End Design Conference. He covered a lot of stuff there, which you can see in his slides, but I'd like to highlight one thing in particular: the way he handled popup information in the demo. I'm going to try and re-explain it...

Let's say our goal is this: hover over an image to display extra information (like the title of the image and a URL).

Pretty darn simple design pattern right? Well, not really. There are a lot of subtle things to consider. Let's start from the simplest possible way and improve it.

Simplest way: hide/show with CSS

If our markup is:

<figure>
   <img src="image.jpg" alt="cool image">
   <figcaption>
        <h3>Cool Image</h3>
        <a href="http://coolplace.com">http://coolplace.com</a>
   </figcaption>
</figure>

We'll use the <figcaption> as the popup info. We'll hide it by default, then display it when the image is rolled over:

figcaption {
   display: none;
}
figure:hover figcaption {
   display: block;
}

But... it's so abrupt.

Fade in/out

We can chill it out with CSS transitions.

ficaption {
   opacity: 0;
  -webkit-transition: opacity 0.3s ease-out;  
     -moz-transition: opacity 0.3s ease-out;  
      -ms-transition: opacity 0.3s ease-out;  
       -o-transition: opacity 0.3s ease-out;  
          transition: opacity 0.3s ease-out;  
}
figure:hover figcaption {
   opacity: 1; 
}

We could get even fancier there if we wanted by applying different durations.

But... popups come up even if we are just quickly moving our mouse past and likely not interested in seeing popups.

"Hover Intent"

If we get JavaScript involved, we can get a little fancier. There is a jQuery plugin called hoverIntent which can be useful in preventing unwanted hover behavior. It imparts a bit of a delay before an event is fired, so quickly mousing over things won't trigger a popup but slowing down and stopping on an image will.

You could apply that like this:

$("figure").hoverIntent(function() {
   $("figcaption", this).fadeTo(400, 1);
}, function() {
   $("figcaption", this).fadeTo(400, 0);
});

But... now all the images use hoverIntent, which means that the slight delay to see the popup can be very annoying if you are specifically trying to browse the images and see the information. As Doug put it "my brain can think faster than that."

And finally: The Really Nice Way (doTimeout)

We like first part of hoverIntent, where quick mouseovers don't trigger the popup, but once we trigger one popup we want subsequent popups to happen quickly with no delay. If the user leaves the image area for a little bit, the delay is imparted again.

This makes use of the doTimeout plugin by Ben Alman. Admittedly, this gets a bit complex:

var li_cache, over = false;

$( "figure" )
	.delegate( "figcaption", "mouseenter", function ( e ) {
		var $li = $( this ), speed;

		if ( li_cache === this && over ) {
			$.doTimeout( "hoverOut" );
			return;
		}

		if ( over ) {
			$.doTimeout( "hoverOut", true );
			speed = 0;
		} else {
			$.doTimeout( "hoverOut" );
			speed = 500;
		}

		$.doTimeout( "hoverIn", speed, function () {
			over = true;
			$li.find( "div" ).fadeTo( 200, 1.0 );
		});
	})
	.delegate( "figcaption", "mouseleave", function ( e ) {
		var $li = $( this );

		$.doTimeout( "hoverIn" );
		$.doTimeout( "hoverOut", 500, function () {
			over = false;
			$li.find( "div" ).stop( true ).fadeOut();
		});
	});

Super nice. This improves the popup information reveal in such a natural and subtly enjoyable way that it's kind of a shame it's so difficult to implement. But it's worth it.

Doug's GitHub Repo

Go grab the GitHub Repository for this. Doug did a great job putting this together and it's educational as heck. You can see the progression through all the different hover functionalities just by commenting/uncommenting some function names. Beyond that, this example covers using jQuery templating, "Mockjax" (hijacking AJAX requests for local development) and more.

Seriously, I'm not even going to post a live demo, go download his repo and open the index.html file in a browser.

Blogging. You can do better.

That's my (solo) panel name for SXSW Interactive 2011. I'll love you forever if you upvote it to increase my chances of getting to do it this year. It was denied city last year. I haven't talked much about blogging before but I have a few things to say about it that I think are worthwhile.

#100

I finally shot the 100th video. No big fireworks, just more front end learnin'! In this one we look at a Photoshop design and mark it up in HTML5 as semantically as we can.

Transitions and Animations on CSS Generated Content

Generated content means pseudo elements added to the page via the ::before and ::after. The support for applying transitions or animations to these in the current browser landscape is not great. I think this is a huge bummer, so I'm just making this blog post my permanent home to track the progress on this.

(more…)

Flip flop navigation with box-flex

Jeremy Keith shows us how to put the navigation on the bottom of the page in a vertical layout for small screens and the top of the page in a horizontal layout for large screens by fiddling with the the box-direction and box-orientation in a flex box layout.

The flex box spec is being rewritten and I hope that gets done and out the door so the awkward transitional phase between the different syntaxes is as short as possible.

Persistent Headers

This is some code to get the header of some content area to stay visible at the top of the screen as you scroll through that content. Then go away when you've scrolled past that relevant section.

(more…)

Design v9

Rolled out a new design folks! A lot of folks were surprised it happened so soon after the last one, but actually it's been about 8 months, which is pretty average for this site, if a little slow. I've updated the design history page just for longevity.

New (v9)

Old (v8)

Some notes

Just for fun

There is no huge agenda behind the design. Mostly I just thought it would be fun. It's kinda what I do. Although... there are some new areas of the site coming up that this will help motivate.

Fonts

I stuck with Myriad (I quite like as body copy) and Kulturista both via Typekit. Although I'm hoping to replace with Whitney and Vitesse as soon as the HF&J web font service rolls around.

Responsive

The old design used media queries, but this one is closer to "responsive" because it's also fluid, which means it's probably going to do OK on lots of devices I didn't even plan for. For example, I didn't even test it on the iPad but I hear it's alright. I also chucked some transitions on a few elements so when the media queries hit and change those values they animate to their new position/size. I used three weird-ish breakpoints. Default is for browsers above 1200px (most of my traffic), first break point is that. Then breaks again at 1024px and then at 860px (which is basically the mobile version).

IE support

Design is passable in IE 8+. It's a wreck at this moment in IE 6 & 7. I plan to fix up IE 7 when I get a minute and serve the universal IE 6 stylesheet for IE 6.

Thingies used

  • Site runs on WordPress. Also now running Yoast's SEO Plugin.
  • Forums run on Vanilla.
  • Fonts by Typekit.
  • Search by Google Custom Search. You can use the back-button to get back to search results again finally!
  • Advertising by BuySellAds.
  • jQuery for doin' stuff. E.g. more options/less options in subscribe area in sidebar.
  • Respond.js to make the media queries work in IE 6-8-9.
  • Modernizr to conditionally apply some styles more cleanly. E.g. where gradient rollovers are used, do something else for IE 7-8-9.

Stay tuned for more stuff coming soon!

Comments turned off. There is already a forum thread going on the new design, so let's consolidate discussion there.

The details and summary elements

Tom Leadbetter from HTML5 doctor shows us all about the summary and details element. I think this will be a particularly useful pair of elements, especially as browser support grows, with its baked in hide/show functionality.

Making Video Fluid Width

Me:

In a world of responsive and fluid layouts on the web one media type stands in the way of perfect harmony: video.

I wrote an article for Net Magazine where I tackle making video (from any source) work in fluid width environments.

Indeterminate Checkboxes

Checkbox inputs can only have two states: checked or unchecked. They can have any value, but they either submit that value (checked) or don't (unchecked) with a form submission. The default is unchecked. You can control that in HTML like this:

<!-- Default to unchecked -->
<input type="checkbox">

<!-- Default to checked, XHTML -->
<input type="checkbox" checked="checked" />

<!-- Default to checked, HTML5 -->
<input type="checkbox" checked>

Visually, there are actually three states a checkbox can be in: checked, unchecked, or indeterminate. They look like this:

Here are some things to know about indeterminate checkboxes:

You can't make a checkbox indeterminate through HTML. There is no indeterminate attribute. It is a property of checkboxes though, which you can change via JavaScript.

var checkbox = document.getElementById("some-checkbox");
checkbox.indeterminate = true;

or jQuery style:

$("#some-checkbox").prop("indeterminate", true); // prop is jQuery 1.6+

The indeterminate state is visual only. The checkbox is still either checked or unchecked as a state. That means the visual indeterminate state masks the real value of the checkbox, so that better make sense in your UI!

Like the checkboxes themselves, indeterminate state looks different in different browsers. Here's Opera 11.50 on Mac:

Use Case

The reason I'm writing this at all is because I just had a use case come up for this state: nested checkboxes. Each checkbox may have child checkboxes. If all those children are checked, it may be checked. If none are checked, it is unchecked. If some of them are checked, then it's in an indeterminate state (in this case symbolically meaning "partially" checked).

See the Pen Indeterminate Checkboxes by Chris Coyier (@chriscoyier) on CodePen.

This demo isn't perfect. It only checks one level "up" for determining indeterminate state. Ideally it would check up recursively until the top. If you wanna fix it to do that, I'll update the code and credit you.

TheNotary refactored the code a bit for their purposes, you can check that out at their fork repo.

Rotating amongst the states

Jon Stuebe was messing around with the idea of rotating the state between unchecked, indeterminate, and checked with a click. Here's some jQuery to do that:

var $check = $("input[type=checkbox]"), el;
$check
   .data('checked',0)
   .click(function(e) {
       
        el = $(this);
                
        switch(el.data('checked')) {
            
            // unchecked, going indeterminate
            case 0:
                el.data('checked',1);
                el.prop('indeterminate',true);
                break;
            
            // indeterminate, going checked
            case 1:
                el.data('checked',2);
                el.prop('indeterminate',false);
                el.prop('checked',true);                
                break;
            
            // checked, going unchecked
            default:  
                el.data('checked',0);
                el.prop('indeterminate',false);
                el.prop('checked',false);
                
        }
        
    });

See the Pen Rotate Through Indeterminate Checkboxes by Chris Coyier (@chriscoyier) on CodePen.

Reader Casual Trash sent me in a library-free and far more succinct version of rotating through all three visual states which utilizes the readonly attribute that checkbox inputs can have.

<!-- Inline click handler, just for demo -->
<input type="checkbox" id="cb1" onclick="ts(this)">
function ts(cb) {
  if (cb.readOnly) cb.checked=cb.readOnly=false;
  else if (!cb.checked) cb.readOnly=cb.indeterminate=true;
}

See the Pen Rotate Through Indeterminate Checkboxes by Chris Coyier (@chriscoyier) on CodePen.

New Poll: Site Title Structure

The new poll is up in the sidebar of the site. This time it's about the structure of page titles. Literally, the <title></title> tag in the head of a site that gives the browser window/tab its title. I'm just asking for your "favorite", as in, personal preference. Take that how you will, we can discuss the reasonings in the comments and in the poll wrap-up post. (more…)

Prefixr

Jeffrey Way has created an app which looks through your CSS and adds all the missing CSS3 vendor prefixes. It's smart enough to do it right no matter which ones you've added or forgotten. Cooler, it has an API which allows you to it without ever leaving your favorite text editor.

The Future of CSS Layouts

Peter Gasston shows us: columns, flexbox, grid, template, positioned floats, exclusions, and regions. This stuff is going to be a big deal in a couple of years and it will be very interesting to see which of these get popular and which ones die off.

icon-closeicon-emailicon-linkicon-menuicon-searchicon-tag