Archive for the ‘CSS’ Category

January 26th, 2011

Transparency in Web Design

How is it done? Let’s take a gander at four different ways. Each of them handling the illusion in a different way, and each completely appropriate depending on the situation at hand.

Totally Friggin Fake It


From the Spectrum Theme website

The end result of any web design is basically an illusion anyway. You can always create your transparent effects in Photoshop or whatever other graphics editor and export flat graphics. In Photoshop, transparent effects can be created by changing a layers opacity level, fill level, or blending mode, just to name a few.

Opacity


This entire button has opacity applied to it, to emphasize that it is currently “disabled”.

You can make any element transparent by using the opacity parameter of CSS.

#anything { opacity: 0.5;  /* 50% transparent */ }

If you need to support older browsers, see here.

Do note that all descendants of the element with opacity also become transparent. There is no way to “force” any descendant to be come any less transparent as the parent is.

RGBa / HSLa


From the Like Architects site

Using RGBa for a color value in CSS, you can set a transparency level on any color. This has the distinct advantage over opacity in that it doesn’t have any affect on descendants. It is also nice in that creating faded out variations of a color is as easy as changing the final alpha value. Speaking of color variations, that is even easier to do with HSLa, and is still able to handle transparency.

#anything { background: rgba(0,0,0,0.5);  /* 50% transparent */ }
#anything { background: hsla(0,0,0,0.5);  /* 50% transparent */ }

PNG


From a Dribbble

When “Saving for web” from Photoshop, you have two choices for PNG’s: PNG-8 and PNG-24. PNG-8 is like a GIF in that you can have transparency in pixels, but a pixel is either fully transparent or fully opaque, no in-between. PNG-24’s, while far bigger in file size, support full alpha-transparency.

In the example above, the shadows from the content areas are from PNG-24s so that the texture in the background can change and the shadows will still be the same.

May 31st, 2010

Tricks

Drag things, pick colors, make a nice class for your buttons… introducing the Button Maker.


Boy, that’s a nice button right there.

I’m saying “CSS3″, because these make use of gradients, shadows, and rounded corners which contribute greatly to their button-ness. In older browers that don’t support these properties, the fallback is solid-color background, no shadows, and square corners. Not a big deal.

I hope this is painfully obvious, but to use this Button Maker thing, you just adjust the settings until you have a nice looking button, then press the button and it will give you the CSS. Copy and paste at your leisure. Now you can use the class name “button” on HTML elements to make them look like buttons. The CSS isn’t formatted real pretty. If someone has an idea on how to make that better, please do let me know.

The super-awesome empowering concept…

…in regards to how the Button Maker preview works.

It’s easy to change the CSS of an element on-the-fly with JavaScript. But how can we change the :hover state? The answer is that we can’t really, at least not really easily. We could attach a mouseenter event that would apply some new CSS that would override the old, and a mouseleave event that would put it back. That’s a lot of overhead for something so relatively small. It gets even more complicated if we wanted to control the :active state as well.

This Button Maker shows you a live working version of the button you create, complete with :hover and :active states. It is done without attaching any JavaScript events to the button itself. So how is it done? I did it with a technique I ripped off from Doug Neiner who presented it (as small part of a totally different application) at jQConf.

OK OK I’ll get on with it. The idea is to append a <style> element into the <head> which overrides the existing CSS (in-document CSS automatically overrides linked CSS for selectors with the same specificity value). Then when something changes, you literally rip the whole style tag out, and replace it.

Appending a new style:

$("head").append("<style type='text/css'></style>");

Text variable where the CSS will be kept. Keep this text up to date when options change.

var cssText = "";

Use the replaceWith() function to rip out existing style element and apply a new one:

$("style").replaceWith("<style type='text/css'>" + cssText + "</style>");

The ripping-out part is important. Originally I tried putting an ID on the style element and replacing the content within it on the fly. It did replace the content, but those changes were not reflected on the page. Apparently in order to force the browser to re-render with the new CSS, you have to literally remove it and put it back.

Take it, shake it

I’ll provide the source for the thing in case you want to run it locally for whatever reason. Or even better, because you want to make it cooler. If you do, please share.

View Demo   Download Files

May 7th, 2010

Tricks

I’ve added two new buttons to all of the code snippets in the Snippets section of the site. Now a button to add directly to Snippets.app and a button to directly copy to the clipboard join the Coda and Textmate buttons.

Read on for some more details about them, and remember, you can help the Snippets section grow by submitting yours.

Snippets.app button


One-click adding to Snippets.app

Snippets.app supports a URL protocol thingy. That is, once the application installed, browsers on your system know that when a URL is entered that begins with “snippets:” (instead of like http://) that it should launch (or ask you to launch) Snippets.app and do something with that URL.

Their format is:

snippets:add?code=[ENCODED-CODE-HERE]&name=[SNIPPET-NAME]&relatedurl=[REFERENCE-URL]&author=[AUTHOR-NAME]

You’ll only see this once if you check the box.

Since all my code snippets are in <pre> elements, this is how I add the Snippets.app button to each code block (simplified):

$("pre").each(function() { $preblock = $(this); $codeblock = $preblock.find("code"); $snippets_link = "snippet:add?code=" + encodeURIComponent($codeblock.text()) + "&name=" + $title + "&relatedurl=" + encodeURIComponent(document.location.href); $("<a class='snippet-button'>Add to Snippets.app</a>").attr("href",$snippets_link).appendTo($preblock); });

Copy to Clipboard

This button is powered by the awesome Zero Clipboard. For a while after Flash 10 came out, copying to clipboard from the web was borked as Flash 10 had some new security restrictions that blocked the previous methods (Yeah, apparently Flash is needed to have this work correctly). Zero Clipboard stepped it up and fixed it somehow.


One-click copying to clipboard

One particular challenge here was with the rollover technique I’m using to display the “tooltip” like text for each button. On the three other buttons, I do a simple thing where I append a span to the anchor link on hover, and remove it on the hover callback:

$(".snippet-button").hover(function() { $el = $(this); $el.append("<span>" + $el.text() + "</span>"); }, function() { $(this).find("span").remove(); });

The span is styled and positioned with CSS.

The problem is, Zero Clipboard works by positioning a completely transparent flash embed over top of the button. This means there is no traditional hover even fired when the mouse goes over this area. Fortunately, Zero Clipboard provides event listeners which you can have fire callback functions for you. See the last two lines:

ZeroClipboard.setMoviePath( '/path/to/ZeroClipboard.swf' );

$(".copy-clip").each(function(i) {

clip = new ZeroClipboard.Client();

$el = $(this); $parent = $el.parent();

clip.glue($el[0], $parent[0]);

txt = $el.parent().find("code").text(); clip.setText(txt);

clip.addEventListener('complete', function(client, text) { // provide some user feedback of success });

clip.addEventListener('mouseOver', copyMouseOver); clip.addEventListener('mouseOut', copyMouseOut);

});

Those two functions, copyMouseOver and copyMouseOut are used to do the same span-applying-and-removing business the other buttons use. The one tricky-dick thing left is that these functions need to know which parent element to deal with, in the case of multiple snippets on a single page. Fortunately they automatically pass the object to the function which is loaded with info about that element, including the ID, which I use to specify which code snippet button we are talking about:

function copyMouseOver(passed) { $("#copy-" + passed.id).append("<span>Copy to Clipboard</span>"); };

I wanted to make sure there was a bit of user feedback when a clip was successfully copied to the clipboard, so you’ll notice that the clip itself quickly fades down and back up after a successful copy. Somewhat subtle but I think it’s fairly satisfying.

Coda and TextMate

Not much has changed here. I covered how to add Coda buttons in a previous tutorial. David Walsh covered the TextMate button, which requires some fancy server side action.

Seem to work OK?

Give it a test and let me know… I’ve heard some musings of FAIL on Twitter but all the buttons seem to work OK for me. If you want to do a FAIL report, please attempt to be helpful and explain which button isn’t working, the browser/version/platform, and what actually happens.

Macity Mac Mac Mac

Yeah all the integrations are Mac software. Sorry about that, that’s just how I roll. If there was a PC program that supported a URL protocol thingy, I’d check it out and see what I could do about integrating it. For now, the copy to clipboard thing should be useful still.

Media Fusion

Multiple Login Forms with Highlighting

Posted: 23 Feb 2010 05:12 AM PST

This is a little specific… but I figured what the heck maybe it will be useful for someone. I recently had occasion to make multiple different login forms on a single page. With CSS we know we can apply styling to active inputs with :active. That’s useful… and we’ve covered how to do both input and label highlighting before. But now we need go one step up and highlight the current form itself.

continue reading…

May 6th, 2010

Tricks

This is an update to original Chat Room we published here on CSS-Tricks. In some ways, the technology is the same. We are going to employ PHP to talk to the server, jQuery to keep the chat rolling, and the chats themselves will be stored in .txt files just like the first version.

What is changed is the addition of some new features:

  • Usernames are unique to users currently chatting
  • You can see a “currently chatting” user list
  • There are multiple rooms for chatting

 

A Little MySQL

While the first version of this used no database at all, we are going to employ a little MySQL for this version. There is a file in the download called Setup.sql for use in building the initial database. MySQL isn’t for the chats themselves, but for two other things:

  • Keeping track of active users
  • The rooms

When someone comes in to chat, they choose a username. Using some jQuery, it makes an AJAX request to see if that username is currently in use in the database. If it is in use, you get a warning:

Otherwise, it says it’s cool:

If it is cool, and you click to join the chats, that username will be put into the database and thus further checks for it’s name will tell others that name is unavailable. Idle users are removed from the database.

Adding/Editing/Removing Rooms

The names of the chatrooms are kept in the database. To add a new chatroom, just add a new row to the database with the name of the chatroom and the filename of the text file you intend to store the chat:

Then it’s just a matter of making sure the text file is on the server in the right place with proper server-writeable file permissions (see the download for properly location).

jQuery

I’m sure you’ve noticed by now we haven’t been looking at any actual code. This is on purpose. All the code is available in the download (see below). It is not so incredibly much that it’s overwhelming, but I think it’s too much for a standard written tutorial/overview. Instead, let’s overview what it’s responsible for:

Username checking: On the homepage of the chat, when you choose your username, jQuery is there watching that text input. When you type a character (on keyup) it asks a certain PHP file (via AJAX) if that username is in use. The PHP file responds with a yes or no, and a message is appended to the screen accordingly.

Message box: When a user types into the textarea for sending a message, the jQuery watches that box and ensures the text is under a certain number of characters (set via maxlength attribute on the textarea)

Sending message: When the return/enter key is pressed in the chat box the value of it is sent for processing. PHP writes the text to the text file.

Updating the chat: Every few seconds, jQuery asks a PHP file to poll the text file to see if there are any new lines, if there are, they are displayed.

Features it doesn’t have

  • You can’t kick people out
  • It doesn’t do special characters

You wanna add that stuff in? I’d love it and I’ll update this.

Demo and Download

View Demo   Download Files

FAIR WARNING: Anonymity on the internet brings out the absolute worst in people. I want to keep a live demo for this on the site because it’s fun to play with and so you can all check it out. But I guarantee that people are going to abuse it. There will be foul words, porn, and probably even some unbelievable racism. Believe me, I’d like to knock these people down and put out a cigar in their eyeball as much as you do, but hey, whattayagonnado?

Credits

Special thanks to Kenrick Beckett who created the original code that powered this and Jason Lengstorf for looking it over and tidying some things up security-wise.

March 17th, 2010

Create a CSS3 Button That Degrades Nicely

There was a time where creating a nice looking, scalable button required heavy use of images, the sliding doors technique and even some javascript. As it stands a lot of the modern browsers support the css we would like to use to create a nice looking button. Firefox, Safari and Opera all have support for rounder corners, box shadows and text shadows. What used to take six steps and lots of extra mark-up, images and css, now only takes three steps and some simple CSS3.

One of the great perks regarding this technique is that in the event that a user doesn't have a browser that supports the CSS that we will be using, they will still see a nice beveled button – it simply won't look quite as nice.

What We are Going To Do

To create a nice button we have a few major components:

  • A nice background gradient
  • Rounder corners
  • Some nice borders to give it a 3D effect
  • A drop shadow
  • A text shadow (for a nice touch)

In the end we will have a button that looks just like this, only with out using any images behind a few pixel background gradient (and when CSS gradients are supported we can even remove that!).

screenshot

The HTML

 <p><a href="#">Example Button</a></p> <p><a href="#">Example Button</a></p> <p><a href="#">Example Button</a></p>

As you can see the HTML is very basic, we essentially just need an anchor tag and text. The paragraph is there just to be semantic.

The CSS

 .css3button a { background: url(background.gif) bottom repeat-x #9eabb3; padding: 5px 10px 5px 10px; text-align: center; font-weight: bold; color: #fff; text-decoration: none; border: 1px inset #aaa; -webkit-border-radius: 8px; width: auto; -moz-border-radius: 8px;  -khtml-border-radius: 8px;  border-radius: 8px; -moz-box-shadow: 1px 1px 1px #666;  -webkit-box-shadow: 1px 1px 1px #666;  box-shadow: 1px 1px 1px #666; text-shadow: rgba(0,0,0, .5) 0px -1px 0px;       border-top: inset 1px #ccc; border-left: inset 1px #ccc; border-bottom: solid 1px solid #000; border-right: 1px solid #666; }

.css3button a:hover  { background: #999; text-shadow: rgba(0,0,0, .5) 0px 1px 0px; } 

The CSS is a bit more complicated, but still fairly simple. We are really just adding a repeating background image, adding some rounded corners, as well as box and text shadows. The borders add a bit more depth / shading and ensures that if the CSS properties are not supported that the element still retains a beveled appearance.

background

The background image is simple gradient to give the button some depth, in this case I used the following image:

That Simple

That is how easy it is. If you want to play around with the borders you can end up with some pretty nice effects as well.

More Examples

February 22nd, 2010

Multiple Class / ID and Class Selectors

Can you spot the difference between these two selectors?

#header.callout {  }

#header .callout { }

They look nearly identical, but the top one has no space between “#header” and “.callout” while the bottom one does. This small difference makes a huge difference in what it does. To some of you, that top selector may seem like a mistake, but it’s actually a quite useful selector. Let’s see the difference, what that top selector means, and exploring more of that style selector.

Here is the “plain English” of “#header .callout”:

Select all elements with the class name callout that are children of the element with an ID of header.

Here is the “plain English” of “#header.callout”:

Select the element which has an ID of header and also a class name of callout.

Maybe this graphic will make that more clear:

Combinations of Classes and IDs

The big point here is that you can target elements that have combinations of classes and IDs by stringing those selectors together without spaces.

ID and Class Selector

As we covered above, you can target elements by a combination of ID and class.

<h1 id="one" class="two">This Should Be Red</h1>
 #one.two { color: red; }

Double Class Selector

Target an element that has all of multiple classes. Shown below with two classes, but not limited to two.

<h1 class="three four">Double Class</h1>
.three.four { color: red; }

Multiples

We aren’t limited to only two here, we can combine as many classes and IDs into a single selector as we want.

.snippet#header.code.red { color: red; }

Although bear in mind that’s getting a little ridiculous =)

Example

So how useful is all this really? Especially with ID’s, they are supposed to be unique anyway, so why would you need to combine it with a class? I admit the use cases for the ID versions are slimmer, but there are certainly uses. One of those is overriding styles easily.

#header { color: red; } #header.override { color: black; } 

The second targets the same element, but overrides the color, instead of having to use:

.override { color: black !important }

or perhaps prefacing the selector with something even more specific.

More useful is multiple classes and using them in the “object oriented” css style that is all the rage lately. Let’s say you had a bunch of divs on a page, and you used multiple various descriptive class names on them:

<div class="red border box"></div> <div class="blue border box"></div> <div class="green border box"></div> <div class="red box"></div> <div class="blue box"></div> <div class="green box"></div> <div class="border box"></div>

They all share the class “box”, which perhaps sets a width or a background texture, something that all of them have in common. Then some of them have color names as classes, this would be for controlling the colors used inside the box. Perhaps green means the box has a greenish background and light green text. A few of them have a class name of “border”, presumably these would have a border on them while the rest would not.

So let’s set something up:

.box { width: 100px; float: left; margin: 0 10px 10px 0; } .red { color: red; background: pink; } .blue { color: blue; background: light-blue; } .green { color: green; background: light-green; } .border { border: 5px solid black; }

Cool, we have a good toolbox going here, where we can create new boxes and we have a variety of options, we can pick a color and if it has a border or not just by applying some fairly semantic classes. Having this class name toolbox also allows us to target unique combinations of these classes. For example, maybe that black border isn’t working on the red boxes, let’s fix that:

.red.border { border-color: #900; }

Border color on red box changed because it had both the red class and border class

Based on this demo page.

Specificity

Also important to note here is that the specificity values of selectors like this will carry the same weight as if they were separate. This is what gives these the overriding power like the example above.

Browser Compatibility

All good current browsers support this as well as IE back to version 7. IE 6 is rather weird. It selects based on the first selector in the list. So “.red.border” will select based on just “.red”, which kinda ruins things. But if you are supporting IE 6, you are used to this kind of tomfoolery anyway and can just fix it with conditional styles.

February 16th, 2010

Tricks

CSS has the ability to target HTML elements based on any one of their attributes. You probably already know about classes and IDs. Check out this bit of HTML:

<h2 id="first-title" class="magical" rel="friend">David Walsh</h2>

This single element has three attributes: ID, class, and rel. To select the element in CSS, you could use and ID selector (#first-title) or a class selector (.magical). But did you know you can select it based on that rel attribute as well? That is what is known as an attribute selector:

h2[rel=friend] { /* woohoo! */ }

There is a lot more too attribute selectors though, so let’s look closer at all the different options and try to cover some “real world” scenarios on when they might be useful.

Attribute Exactly Equals Certain Value

In the example we used above, the attribute of the h2 element was “friend”. The CSS selector we wrote targeted that h2 element because it’s rel attribute was exactly “friend”. In other words, that equals sign means just just what you think it does… an exact match. See another basic example:

<h1 rel="external">Attribute Equals</h1>
h1[rel=external] { color: red; }

A great real world example of this is styling a blogroll. Let’s say you had a list of links to friends sites like this:

<a href="http://perishablepress.com">Jeff Starr</a> <a href="http://davidwalsh.name">David Walsh</a> <a href="http://accidentalninja.net/">Richard Felix</a>

Then you wanted to style each link slightly differently. The traditional way would probably be to give each link a class name in which to target, but that requires additional markup which is always a nice thing to avoid (semantics and all). Another way might be to use :nth-child, but that requires their order to never change. This is the perfect use for attribute selectors… the links already have a unique attribute in which to target!

a[href=http://perishablepress.com] { color: red; }

I believe the most common use of regular attribute selectors is on inputs. There are text, button, checkbox, file, hidden, image, password, radio, reset, and submit (did I miss any?). All of them are <input>’s, and all of them are very different. So doing something like input { padding: 10px; } is a bad idea most of the time. It’s very common to see things like:

input[type=text] { padding: 3px; } input[type=radio] { float: left; }

It’s really the only way to get your hands on certain types of inputs without screwing up the others and without adding extra markup.

Attribute Contains Certain Value Somewhere

This is where it starts getting more interesting. The equals sign in attribute selectors may be prefaced by other characters which alter the meaning a bit. For example, “*=” means “match the following value anywhere in the attribute value.” Look at this example:

<h1 rel="xxxexternalxxx">Attribute Contains</h1>
h1[rel*=external] { color: red; }

Remember that classes and ID’s are attributes too, and can be used used with attribute selectors. So let’s say you were writing CSS for a site where you couldn’t control the markup and a sloppy developer had three DIVs you need to target:

<div id="post_1"></div> <div id="post_two"</div> <div id="third_post"></div>

You could select them all with:

div[id*=post]  { color: red; }

Attribute Begins with Certain Value

<h1 rel="external-link yep">Attribute Begins</h1>
h1[rel^=external] { color: red; }

A real world example of using this would be, say, that you wanted to style every single link to your friends site different than other links. Doesn’t matter if you are linking to their homepage or any subpage, any links to them you want to style up.

a[href^=http://perishablepress.com] { color: red; }

That will match a link to their homepage, but also any other subpages as well.

Attribute Ends with Certain Value

We can select based on how attribute values begin, why not end?

<h1 rel="friend external">Attribute Ends</h1>
h1[rel$=external] { color: red; }

Honestly I struggle a bit to find the perfect real world example of using this, but I do like that it exists. Perhaps you could use it to look for links that end in characters that will likely have no significant effect:

a[href$=#], a[href$=?] { color: red; }

Attribute is within Space Separated List

You probably already knew that you could apply multiple classes to elements right? Well if you do that, you can still use .class-name in CSS to target any one of them. Attribute selectors aren’t that easy. If your rel attribute has multiple values (e.g. values in a space separated list) you’ll need to use “~=”:

<h1 rel="friend external sandwich">Attribute Space Separated</h1>
h1[rel~=external] { color: red; }

You might be thinking, why would I use this when *= would also match this and be more versatile? Indeed it is more versatile, but it can be too versatile. This selector requires the spaces around the value where as *= would not. So if you had two elements one with rel=home friend-link and one with rel=home friend link you are going to need the space-separated selector to target the second one properly.

Attribute is within Dash Separated List

The dash separated list is very similar to the space separated list above, both in it’s use and how it’s nice to have for stricter enforcement beyond what *= can do.

 <h1 rel="friend-external-sandwich">Attribute Dash Separated</h1>
h1[rel|=external] { color: red; }

Multiple Attribute Matches

Vital to note is that you can use multiple attribute selectors in the same selector, which requires all of them to match for the selector itself to match.

<h1 rel="handsome" title="Important note">Multiple Attributes</h1>
h1[rel=handsome][title^=Important] { color: red; }

Browser Support

Every single example above works in all modern browsers: Safari, Chrome, Firefox, Opera, and IE. Internet Explorer has perfect support for all of these down to version 7, but zero support in 6. To test in your browser, see the test page. If the line/selector style is in red, it works.

February 16th, 2010

Tricks

These “sliding” style navigation bars have been around a while, I just thought I’d take a crack at doing it myself as the opportunity came up recently. Turns out it’s really pretty darn easy. I put two examples together for it.

The Idea

The idea is to have a highlight of some kind (a background or an underline) follow you around as you mouse over the different links in the navigation. This will happen with jQuery and it’s animation abilities. As such, the “magic line” will only be appended via JavaScript. Once added to the list and styled, as you mouse over the different links, it figures out the left positioning and the width and animates to match.

HTML

Typical list here…. It has the “group” class because it’s going to be a horizontal row and will need the clearfix so it has height. The ID is for the JavaScript to target it.

<div class="nav-wrap"> <ul class="group" id="example-one"> <li class="current_page_item"><a href="#">Home</a></li> <li><a href="#">Buy Tickets</a></li> <li><a href="#">Group Sales</a></li> <li><a href="#">Reviews</a></li> <li><a href="#">The Show</a></li> <li><a href="#">Videos</a></li> <li><a href="#">Photos</a></li> <li><a href="#">Magic Shop</a></li> </ul> </div>

Notice the .nav-wrap div around it. That is used because of the styling, the bars go full width of the screen the but the navigation is centered within. This centering brings up an issue when we start the JavaScript.

CSS

Do the ol’ inline list elements with floated left anchors to get the list horizontal and avoid stairstepping. The magic line is absolutely positioned under the bar, so that it doesn’t cause jitter (mouse over a link, animates over, mouse is now on magic line not the link, animates back, etc.) Everything else is purely stylistic.

.nav-wrap { margin: 50px auto;  background-color: rgba(0,0,0,0.6); border-top: 2px solid white; border-bottom: 2px solid white; } #example-one { margin: 0 auto; list-style: none; position: relative; width: 960px; } #example-one li { display: inline; } #example-one li a { color: #bbb; font-size: 14px; display: block; float: left; padding: 6px 10px 4px 10px; text-decoration: none; text-transform: uppercase; } #example-one li a:hover { color: white; } #magic-line { position: absolute; bottom: -2px; left: 0; width: 100px; height: 2px; background: #fe4902; }

jQuery JavaScript

  1. When DOM is ready…
  2. Set up variables including current left offset of the navigation
  3. Set up resize function on the window to reset that offset should it change (because of the centering)
  4. Append the magic line to the nav
  5. Set up position and width of the magic line for the current page item
  6. Also set the original width and position as data, so it can be used to animate back to
  7. On hover, calculate the new width and new left position and animate to it
  8. On the hover callback (mouse out), animate back to original
$(function(){ var $el, leftPos, newWidth, $mainNav = $("#example-one"), pageOffset = $mainNav.offset().left;

// Fixing the offset if the window changes size $(window).resize(function() { pageOffset = $mainNav.offset().left; });

$mainNav.append("<li id='magic-line'></li>"); var $magicLine = $("#magic-line");

$magicLine .width($(".current_page_item").width()) .css("left", $(".current_page_item a").offset().left - pageOffset) .data("origLeft", $magicLine.offset().left - pageOffset) .data("origWidth", $magicLine.width());

$("#example-one li").find("a").hover(function() { $el = $(this); leftPos = $el.offset().left - pageOffset; newWidth = $el.parent().width(); $magicLine.stop().animate({ left: leftPos, width: newWidth }); }, function() { $magicLine.stop().animate({ left: $magicLine.data("origLeft"), width: $magicLine.data("origWidth") }); }); });

Issues

Opera is weird about it. It makes the original width of the magic line the full width of the nav bar and shortens it from the right on hovers. I haven’t been able to figure it out. If you do, awesome, let me know I’ll update this article and demos.

Alternate Version

Check out the demo link below for an alternate version that uses a background instead of a line, and animates color as well as position and width. Basically the same, except the CSS is slightly different and the JavaScript pulls the color of the new list item from a rel attribute in the HTML.

Color animations in jQuery require the color plugin. I was just moaning about how it doesn’t work with RGBa color, and someone sent me a patch that does, which is included in the download. I’m really sorry, but I can’t remember their name! Speak up if it was you and I’ll update this and credit the patch to you.

All Yours

As always, feel free to do whatever you want with it. Preferably, use it in corporate projects and earn wheelbarrows of cash.

View Demo   Download Files

 

February 10th, 2010

How nth-child Works – CSS-Tricks

There is a CSS selector, really a pseduo-selector, called nth-child. Here is an example of using it:

ul li:nth-child(3n+3) { color: #ccc; }

What the above CSS does, is select every third list item inside unordered lists. That is, the 3rd, 6th, 9th, 12th, etc. But how does that work? And what other kinds of things can you do with nth-child? Let’s take a look.

It boils down to what is in between those parentheses. nth-child accepts two keywords in that spot: even and odd. Those should be pretty obvious. “Even” selects even numbered elements, like the 2nd, 4th, 6th, etc. “Odd” selects odd numbered elements, like 1st, 3rd, 5th, etc.

As seen in the first example, nth-child also accepts equations in between those parentheses. The simplest possible equation? Just a number. If you put simply a number in the parentheses, it will match only that number element. For example, here is how to select only the 5th element:

ul li:nth-child(5) { color: #ccc; }

Let’s get back to the “3n+3″ from the original example though. How does that work? Why does it select every third element? The trick is understanding the “n” and algebraic equation that represents. Think of “n” as starting at zero and then a set of all positive integers. Then complete the equation. So the 3n is “3xn”, and the whole equation together is “(3xn)+3″. Now substituting in the zero and positive integers, we get:

(3 x 0) + 3 = 3 = 3rd Element
(3 x 1) + 3 = 6 = 6th Element
(3 x 2) + 3 = 9 = 9th Element
etc.

How about the :nth-child(2n+1)?

(2 x 0) + 1 = 1 = 1st Element
(2 x 1) + 1 = 3 = 3rd Element
(2 x 2) + 1 = 5 = 5th Element
etc.

Hey wait! That’s the same as “odd”, so probably don’t need to use that one very often. But wait now. Haven’t we exposed our original example as being overly complicated? What if instead of “3n+3″, we used “3n+0″, or even simpler “3n”.

(3 x 0) = 0 = no match
(3 x 1) = 3 = 3rd Element
(3 x 2) = 6 = 6th Element
(3 x 3) = 9 = 9th Element
etc.

So as you can see, the matches are exactly the same, no need for the “+3″. We can use negative n values, as well as use subtraction in the equations. For example, 4n-1:

(4 x 0) – 1 = -1 = no match
(4 x 1) – 1 = 3 = 3rd Element
(4 x 2) – 1 = 7 = 7th Element
etc.

Using “-n” values seems a little weird, because if the end result is negative there is no match, so you’ll need to add to the equation to get it back positive again. As it turns out, this is a rather clever technique. You can use it to select the “first n elements” with “-n+3″:

-0 + 3 = 3 = 3rd Element
-1 + 3 = 2 = 2nd Element
-2 + 3 = 1 = 1st Element
-3 + 3 = 0 = no match
etc.

Sitepoint has a nice reference guide, which includes this handy-dandy table which I’ll shameless republish here:

n 2n+1 4n+1 4n+4 4n 5n-2 -n+3
0 1 1 4 - - 3
1 3 5 8 4 3 2
2 5 9 12 8 8 1
3 7 13 16 12 13 -
4 9 17 20 16 18 -
5 11 21 24 20 23 -

Browser Compatibility

nth-child is one of those rather unfortunate CSS attributes that is caught between nearly full cross-browser compatibility, except for completely zero support in IE, even IE 8. So when it comes to it’s use, if the end result is “progressive enhancement” in some fashion (e.g. applying a cool color palette to table rows, for example), then by all means, go for it. But you probably shouldn’t use it if you are doing something more important, like relying on it for site structure. For example, removing the right margin from every third box in a three by three grid of boxes, so they will fit properly.

One saving grace here is that if you are using jQuery, which supports all CSS selector including :nth-child, the selector will work, even in Internet Explorer.

Still not getting it?

I’m not a big fan of the phrase “I’m a visual learner”. Of course you are, everybody is. Visual aids are enormously helpful in situations just like this. To help, I put together a little nth-child tester page. There, you can type in equations and see the results of what it selects below.