Article Archives

New Poll: alt Text Usage

Alt text has come up a bunch of times for me recently. One reader wrote to me asking if people really use them anymore. He does and said "I feel alone in carrying out the good fight." ALA posted a reminder about when using alt text is unnecessarily repetitive. I ran across this flowchart in the comments there. The A11Y Project has a tip page on them. So I figured it would make for a good poll this round. If nothing else to raise a bit more awareness.

(more…)

Credit Card Info in One Field

Credit card numbers, expiration dates, and CVV's are all numbers, so why not collect them all in one field and leave the number keypad open the whole time? Good idea, Zachary Forrest. via Luke.

Related: if you use Stripe, that might be literally all you need to collect payment. But other payment processors often require more info (like address) so not collecting that info is dangerous (should you need to switch someday).

And speaking of UI experiments, this is an interesting take on the select menu.

Navigation in Lists: To Be or Not To Be

If you Google around on whether or not you should use lists as the markup for navigation on websites, you'll find no debate. Every article suggest that yes you should. The vast majority of tutorials you read will use lists for navigation. The vast majority of templates you see will use lists for navigation. But is this ubiquitous markup pattern absolutely correct? Let's see.

Note: make sure to check out the wrapup post of what we learned about all this after this post came out.

(more…)

2013 CSS Wishlist

I'm pretty happy with CSS. I know it's common to complain about CSS and how it was never meant to build web pages like we do now and it's ill-suited to many tasks and yadda yadda. But I dunno. I work with it every single day and I feel like it's getting the job done pretty well. Maybe I don't have those fancy big thinker thoughts that can foresee alternate universes where more perfect languages exist. Or something.

As Hakim says:

So what does 2013 hold for CSS? Tab Atkins works directly on the CSS specs and has outlined his own plan for the year. It all sounds like good stuff to me. In particular I like the focus on flexbox and grid. Those will give very powerful layout tools that will serve us as long as the web is 2D. And the focus on native @extend which would be amazing.

Honestly, I trust Tab's own instincts on how CSS needs to be evolved more than my own since he's so involved in it and has a mind for systems. You can't just jam in everything any ol' author tells you they want or you'll end up with a mess. Now, that being said, as an author, here's some things I'd like them to jam in there.

1. I'd like to be able to select an element based on if it contains another particular selector

For instance, select a blockquote if it contains a paragraph.

blockquote::contains("p") {
  /* Not like this, since it's not a pseudo element, but something like it */
}

I feel like this comes up all the time and it seems weird it's not possible. This is in the same vein as the parent selector that I also still want and is a whole can of worms.

2. I'd like to be able to select an element based on the content it contains

Content, meaning literally text content whether it's in another element or not. Like:

h1::match-string("coyier") {
  /* Not this again, since it's not a pseudo element, but something like it */
}

I feel like I should be able to target elements if they contain my name if I want to. Or imagine a site like Twitter. You should be able to style a tweet that contains a certain word a certain way if you want. Or search results.

3. I'd like multiple pseudo elements

As in:

.speech-bubble::before(2) {
  /* Or ::before::before or something, smart people can decide */
}

As we've discussed here, it's a good idea. Web components / Shadow DOM is cool but it's too complex for something as simple as just needing one extra meaningless element to tack on and complete some visual design tidbit.

4. I'd like to be able to animate/transition something to height: auto;

As in:

.flash-message {
  height: 0;
  opacity: 0;
  transition: all 0.2s ease;
}
.flash-message.loaded {
  height: auto;  /* nope */
  opacity: 1;    /* yep */
}

The browser would be able to know the height of an element if it had height: auto; (instead of whatever it currently has) on it, right? So figure it out and animate to that value.

5. I'd like a good bit of the stuff from Sass

In order of how awesome it would be:

  1. @extend - i.e. this selector inherits the stuff from this selector
  2. @mixin / @include - i.e. reusable/alterable chunks
  3. nesting - i.e. .module { background: black; h2 { color: white; } }

I would draw the line at things like loops that take CSS too far into programming and instant readability. I'm not even huge on variables being native, although I think it's too late on that one. The color functions would be sweet if they could be done in a simple, obvious, readable way.

6. I'd like ::nth-letter, ::nth-word, etc

::nth-everything, really. Letters, words, lines, and with all their cousin selectors. For fancy stuff like this:

article.poem p:first-child::nth-line(-n+2) {
  font-variant-caps: small-caps;
  color: red;
}

I understand the biggest blocker here is languages. For instance in some languages one character represents and entire word and that fuzzies these concepts. It seems to me like things that could be overcame though.

The greatest of all wishes...

Would be that all major browsers, mobile included, built in fancy auto updating that upgrades the browser without any user intervention at all. Like Google Chrome desktop. Five years from now it would be sweet if we didn't even talk about browser versions at all anymore. We referred to them just by name, because obviously everyone using them is on the latest version.

Smashing Mag CSS Q&A: Final Edition

Maybe not the last one ever ever, but the last one for now in this series of five or so we did in this round. Includes questions about CSS performance, choosing class names, getting the right line numbers in the dev tools when using preprocessors, how to think about @extend, and more!

Don’t Stop The Music: Links on Pages Playing Audio

Over at ShopTalk, we've gotten a number of requests from folks that wished links in our show notes would open in a new tab. They've gotten burned by clicking a link on the page while listening to a podcast via our embedded player. When the browser leaves our page and goes to the link, the audio stops playing. We can do something about that.

(more…)

CSS-Tricks Chronicle X

The next conference I'll be at is Webstock. I leave for it in a few weeks. It's in New Zealand, about as far away from home as I can get without going into space. I'm going a week early to check out the area a bit.


I fly straight to In Control after that, in Florida.


The Pastry Box Project has kicked off anew in 2013 with a fresh group including me. Here's my first entry. And here's the fundraiser to turn 2012 into a book.


Lots going on at CodePen!

Lots more coming as well. Several big features under development and a list a mile long for more.


I cleaned up the Bookshelf around here, with my latest greatest recommended reading on front end development and design.


I'm embarrassed to say it took me this long, but I've finished writing all the articles that go with all the videos in The Lodge. There are over 150 videos and that was a lot to write! It almost takes as long to write the descriptions than to shoot the videos.


I've started to record an entire brand new series for The Lodge. More on that soon.


Two free videos have been posted since the last Chronicle. One about GitHub pull requests and the other introducing CodePen PRO. Hoping to shoot one or two new ones in the next few days.

Understand the Favicon

Jonathan T. Neal digs in. The low down: most browsers can deal with PNG, but if you specify an ICO, it will use that anyway. IE (even 10) don't support PNG, so you need ICO. So, use ICO. Apparently this is the best app for creating an ICO with multiple formats (32x32 and 16x16).

Media Fragments URI – Spatial Dimension

The following is a guest post by Fabrice Weinberg Fabrice is the kind of guy who likes to explore the cutting edge of CSS and web technologies. This post is no exception!

I'd like to take a look at the Media Fragments URI Specification. In particular, the spatial dimension part. The temporal dimension portion was implemented last year in Chrome and Firefox but the spatial dimension isn't supported in any current browser as of the time of writing.

To be clear: this topic is highly experimental. The only way to use it today would be to use the polyfill I wrote, which only works in Chrome and Firefox. Basically: don't use it in production!

To give you some idea of what it's all about, you can think of the temporal dimension as an offset at which the audio/video-tag starts to play it's content. You can find a working example here.

The spatial dimension is the same concept, but for images. We can describe the exact part of an image we want to display.

How does it work?

The Media Fragments URI is syntax with which it is possible to only select a certain portion of an image. It looks like this:

#xywh=160,120,320,240        # => results in a 320x240 box at x=160 and y=120
#xywh=pixel:160,120,320,240  # => results in a 320x240 box at x=160 and y=120
#xywh=percent:25,25,50,50    # => results in a 50%x50% box at x=25% and y=25%

Essentially, a hash you append to media URLs.

Example

If you append these "fragments" to an image URL like this:

http://placekitten.com/500#xywh=160,120,320,240

The result would look like this:


As the spec states, we get an image 320x240 in size with an offset of 160x120 to the upper left corner.

What is it good for?

An improvement for CSS Sprites

I wouldn't say it's "better" to use Media Fragments to replace CSS Sprites. Rather, it extends the possibilities by overcoming a common problem. It's not possible to create a repeating background that's repeated on more than one axis with regular image sprites. Even one axis is complicated.

With Media Fragments, we would be able to do a repeating background-image from an image within a sprite.

A demo:


For the image in the demo, I combined this pattern with some Twitter Bootstrap icons. The traditional technique for CSS Sprites is used for icons and a Media Fragment for repeating background.

Image Animations

Another use case is the possibility to build image animations like discussed in the article Animated GIFs the Hard Way by Jon Skinner for the Sublime Text 2 product page. But I don't think is usable in production because I agree that JavaScript is better suited for this kind of animation. I just like to push CSS to its limit.

Creating the Polyfill

Hunting for a solution to test the Media Fragments URI in current browsers, I looked for a way to simulate its behavior. You can see the complete polyfill on an example Pen.

Firefox

The solution for Firefox was quite simple. A CSS function called -moz-image-rect does exactly what we want and it has been implemented since March 2011 in Firefox (version 4 at that time).

WebKit

For WebKit there is a great thing called CSSCanvas (-webkit-canvas drawing). You can think of it like a background-image that is a canvas and can be accessed with JavaScript. But the bad thing is that there's no published spec for this feature, so it will be WebKit-only for some time (although Firefox has something similar: -moz-element). There is also a bug in the current Google Chrome release Version (23) Bug 16199 which is fixed in Google Chrome Canary. This bug won't affect the polyfill as there is only a problem with correctly refreshing the canvas on animated content.

Code sample:

div {
    background: -webkit-canvas(name_of_canvas);
}

Then use this canvas as a drawing context in JavaScript.

var ctx = document.getCSSCanvasContext("2d", "name_of_canvas", 100, 100);

What we have done here is to retrieve the drawing context for the canvas defined in our CSS by its name "name_of_canvas" and defined it's width and height to be 100px each.

Here is a working sample (WebKit only for obvious reasons):


Conclusions

In the end, I just combined these two core techniques to create the polyfill. If someone knows a way to extend the browser support, I would be glad to hear it.

Why so much work?

I like to play with new things. So new they they aren't even in the browser yet! I hope you do too. That's all for now. If you have some questions I'll be happy to answer in the comments.

Thanks to Tim Pietrusky for comments and corrections on earlier versions of this tutorial.

Internet Users Demand Less Interactivity

“Every time I type a web address into my browser, I don’t need to be taken to a fully immersive, cross-platform, interactive viewing experience,” said San Diego office manager Keith Boscone. “I don’t want to take a moment to provide my feedback, open a free account, become part of a growing online community, or see what related links are available at various content partners.”

Zooming Squishes

There has been some talk recently about turning off responsive design: Bruce Lawson, Webmonkey, and I also I wrote about it a while back. To be clear, I'm a big fan of responsive design, but I hope we can all agree there is no sense being dogmatic about a tool.

As fate would have it, I got an email from a reader:

I work with a 13" MacBook Air and I use zoom a lot while surfing around because I haven't the best eyesight.

Your site is difficult to do this because, the global % width is squeezing the content in. I found this "bug" in a lot of RWD websites. It makes it hard for me to access to the content.

They are right. A few zooms isn't a big deal, but when you get to four or five the content gets pretty garbled up.

Just out of curiosity, I asked: "Would it be better for you if the page expanded wider than the width of the browser window? So you'd have to horizontally scroll as well?"

Yes, I prefer scrolling horizontally. I think if I'm the cause of breaking the page by zooming in, It's also my responsibility also to scroll horizontally.

That's interesting to hear, since horizontal scrolling is one of those universally reviled things by web designers that we try and avoid at all costs. Even in the fixed width days. Should we bump up to *gasp* 1024px wide sites? No! It might cause horizontal scrolling!

To be clear, I still think it's a bad thing, it's just interesting that someone feels "responsibility" to do it if they "break" the page. It's a bummer they need to feel like they need to "break" the site to be able to read it at all.

This is my fault. But EM-Based media queries can fix! Kinda!

My media queries were in pixels. If changed them into EMs, then as you zoom in, the EM size changes, and the media queries should take effect where the pixel ones would not. So that's what I did and it works great! But please note: you have to refresh the screen to see the media query take effect, it doesn't happen as you zoom. I wish it would, but I also suspect people who do this a lot know to refresh. Also in my experience, at least Chrome is particularly persistant with your preferred zoom level on a site-by-site basis.

My base font size is 16px, so I just did a "Find in Project" for every single one of them and converted them.

@media (max-width: 1200px) { }

became

@media (max-width: 75em) { }

Fortunately I use fancy Sass @content mixins, so the vast majority of them were changed by changing one mixin.

Note that I even notch down my font-size for smaller widths, but the browser zoom is more than enough to actually make the text larger.

Also credit where credit is due, Lyza Gardner showed us the advantages of em-based media queries nearly a year ago.

Too big of an assumption?

So now I've "fixed" this and the layout no longer "breaks" when zoomed in. But is this absolutely better for the reader who wrote to me? They specifically told me they preferred horizontal scrolling and that's not the solution I delivered. I'm assuming that a non-broken layout without horizontal scrolling is even better. But who knows, maybe they don't like the mobile layout, even thought I don't limit what you can do. Always a dance.

The Accessibility Project

Dave Rupert heads up a new project:

For many web developers, accessibility is complex and somewhat difficult. [The Accessibility Project] understands that and we want to help to make web accessibility easier for front end developers to implement.

Wireframe.cc

I'm not hugely into wireframing, but I can see the value in some workflows. This tool for it is deliciously simple. I like the UI touch where if you resize the "browser" window small enough it turns into a phone.

HTML5 Drag and Drop Avatar Changer with Resizing and Cropping

In any app that has user avatars, users should be able to change those avatars. Anything to make that easier is desirable. Many apps start with a user's Twitter avatar, Facebook avatar, or Gravatar. That's a smart move. Avatars give users a sense of ownership over a virtual space so any way to get them to have their desired avatar is good for engagement.

Let's create a page where a user can update their avatar with as little friction as possible: they just drop an image anywhere on the page and it's done.

(more…)

Interview with Ian Hickson

Bruce Lawson interviews the editor of the HTML spec. A candid look into how the web evolves and its future by someone who has a lot more power in shaping it than we do. You know it's going to be good when the first question is:

If you could wipe out any web technologies from existence, which would you choose?

And the answer is: everything.

Rethinking Dynamic Page Replacing Content

The following is a guest post by Jesse Shawl.

In May of 2012, Chris updated a previous post about dynamic page replacing content. This article is an update to that update, which uses the HTML5 history API for a better user experience.

Here's a quick recap of the best practices:

  1. Works fine with JavaScript disabled.
  2. It is possible to "deep link" to specific content.
  3. The browsers back button and forward button work as expected.

The Problem With URL Hashes

For one individual user, the existing demo meets the criteria just fine, but URLs are permanent addresses, and they're going to be shared.

Consider the following scenario:

  1. I've got a fancy browser with Javascript enabled. I'm browsing the demo site, and I find a great product I'd like to share with a friend.
  2. I copy the url "http://example.com/#awesome-product", and send it to my friend.
  3. My friend doesn't have javascript enabled. She opens the link in her browser, and is confused that the awesome product doesn't load as expected.
  4. She gets confused/frustrated and swears never to visit example.com again.

THIS IS BAD UX!

Today, we'll be improving the existing demo such that the dynamic page replacing content doesn't rely on the hash.

View Demo   Download Files

Modernizr for Progressive Enhancement

Note: The following examples build upon the previous demo. Download the files here to follow along.

If you're not using Modernizr yet, go get it (I'll wait). It's the easiest way to detect browser features with JavaScript.

Since we'll be playing with the HTML5 history API, we only need to check the "History" checkbox. Download the custom build here.

Include it in the <head> of our html file:

<script src='js/modernizr.js'></script>

Testing for HTML5 history support is super easy:

// dynamicpage.js

$(function() {
    if (Modernizr.history) {
        // history is supported; do magical things
    } else {
        // history is not supported; nothing fancy here
    }
});

First, we're going to set up everything to manipulate the browser's history, and then we'll add all the fancy loading provided from the previous demo.

Manipulate the History with HTML5 History API

The HTML5 history.pushState() method allows us to:

  1. Change the URL
    • without a hash
    • without a page refresh (this is where the dynamic page replacing content happens)
  2. Update the browser's history stack
    • so we can navigate through the history with back and forward button clicks.

The pushState() method takes three parameters:

history.pushState(stateObject, "title", URL);

We're only going to be supplying the URL in this example, but you can learn more about the history API over at the Mozilla Developer Network.

After changing the URL, we'll want to set up a function to load the content - loadContent() seems like a good name.

$(function() {

  if (Modernizr.history) {

    // history is supported; do magical things

    // hijack the nav click event
    $("nav").delegate("a", "click", function() {

      _href = $(this).attr("href");

      // change the url without a page refresh and add a history entry.
      history.pushState(null, null, _href);

      // load the content
      loadContent(_href); // fear not! we're going to build this function in the next code block

    });

  } else {

    // history is not supported; nothing fancy here

  }

});

And now, we just need to code up the loadContent() function, which is a matter of taking code from the original example.

Code dump:

// set up some variables
var $mainContent = $("#main-content"),
    $pageWrap    = $("#page-wrap"),
    baseHeight   = 0,
    $el;

// calculate wrapper heights to prevent jumping when loading new content
$pageWrap.height($pageWrap.height());
baseHeight = $pageWrap.height() - $mainContent.height();

function loadContent(href) {

  $mainContent
    .find("#guts")
    .fadeOut(200, function() { // fade out the content of the current page
      $mainContent
        .hide()
        .load(href + " #guts", function() { // load the contents of whatever href is
          $mainContent.fadeIn(200, function() {
            $pageWrap.animate({
              height: baseHeight + $mainContent.height() + &quot;px&quot;
            });
         });
      
      $("nav a").removeClass("current");

      $("nav a[href$='" + href + "']").addClass("current");

    });

  });

}

Handle browser back and forward button clicks

At this point, content is loaded in a fancy ajaxy way, but clicking on your back button won't take us back... yet.

The history API gives us access to the popstate event, which fires everytime the history stack changes (read: back and/or forward buttons are clicked.) Anytime this event fires, we just need to call our loadContent() function:

$(window).bind("popstate", function() {
    link = location.pathname.replace(/^.*[\\/]/, ""); // get filename only
    loadContent(link);
});

A Little Homework Assignment

At the time of this writing, the popstate event happens on page load in Chrome. This means two requests are being made:

  1. The original http request for whateverpage.html
  2. The request made by $.load in our loadContent() function

There are a couple of different ways to handle this, but I'll let you decide which works best.

“Never Having to Leave DevTools”

Speaking of workflow stuff, check out this short video by Remy Sharp showing us how you can use Chrome DevTools as a code editor. Literally edit JavaScript and save it back to disk without ever leaving the browser.

How to Create Retina-Caliber Favicons

John Gruber shows us tools and steps for creating retina ready favicons.

When I looked into this a few months ago only Safari was even supporting them, but it appears as if Chrome is now too, so I'd say it's time. Firefox and Opera still do not.

John recommends making an .ico with both 16x16 and 32x32 versions. The theory being that you can hand-craft a 16x16 aesthetically better than a browser can scale down your 32x32. For my simple favicons, I've found the scale-down perfectly fine, which has the benefit of a smaller file as well.

ShopTalk Episode 49

This week Dave and I were joined by David Walsh, a long time fellow blogger and now Mozilla employee. We talk about em-everywhere, analytics discrepancies, tendonitis, and more! Thanks to In Control and Lynda.com for sponsoring.

PPK on Gradients

The problem with gradients is that they are a syntactic nightmare. The gradient spec writers and browser makers changed their mind not once but twice. Thus we have three sets of syntax, and all three occasionally crop up even today. I call these old, middle, and new syntax.

I still haven't totally grokked the new syntax where linear gradients start with "to" or an angle.

Style Injection is for Winners

By "style injection", I mean being able to see styling changes immediately after authoring them without having to manually refresh your browser window. This isn't a brand new concept, I just mention it now because it's so awesome that if it's not a part of your workflow you should consider updating yours to include it.

(more…)

In Search of the Perfect Radius

A bunch of research from Rakesh on the correct values for nested border radii. The conventional wisdom is Inner Radius = Outer Radius – Border Width. This holds true here, but what if that yield a negative value. Also see this tool by Joshua Hibbert.

All You Need to Know About CSS Transitions

Alex Maccaw with a bunchload of up to date information on CSS transitions. Includes some clever stuff like a trick to avoid transitioning width (not very performant) by instead moving the element and exposing more of it underneath.

I also learned from this that apparently there is an entire new spec for Web Animations.

Progressive JPGs: A New Best Practice

There are two kinds of JPGs in this world: baseline and progressive. Progressive is just better. Ann Robson shows us why.

Experimenting locally with a throttled bandwidth, an 80K progressive jpeg beats a 5K baseline jpeg (the same image, downsized) to the page in Firefox on Windows. This should blow your mind. Sure, the progressive jpeg’s first pass is low-resolution, but it contains as much information, or more, as the small image. And if you are zoomed out, perhaps on a mobile device, you will not notice it’s low-res. That’s responsive images working for us right now!

And that's just one reason. Sadly, her research suggests better than 9/10 JPGs on the internet are baseline. Fairly small sample size, but still.

The Design Lesson

I like these thoughts by Andy Rutledge:

In graphic design, nothing is what it actually is. Everything other than content is representative of something else.

A line isn't a line, it's a boundary. Don't need a boundary? Or is that boundary already clear by some other means? Don't use a line.

Same goes for boxes, gradients, white space, scale, font, and any other design element there is.

Thank You (2012 Edition)

I always feel a huge, hearty "THANK YOU" is in order at the end of the year. Especially this year, since this is the first year I've been able to go out "on my own" entirely thanks to you and the support you've shown the site. The highest of fives to you.

And now for the annual goal review and statistics dump. We've done this in 2007, 2008, 2009, 2010, and 2011 if you're interested in a trip down memory lane.

(more…)

The Making of the Interactive Treehouse Ad

It's likely obvious to anyone visiting this site: Treehouse is our primary sponsor. I like that. Not only because they offer structured learning that compliments the learning material I have here, but also because having a single main sponsor means we can spend more time integrating ads into the site in a fun way.

In talking to the folks over at Treehouse, they told me they had some new jQuery based content worth promoting. I thought I'd create a little interactive area to kind of wet people's whistle on what jQuery can do, and get them excited to learn more about it.

Let's go through how it was built.

The Idea

  1. Have a "canvas" (not <canvas>, just an area where things happen)
  2. Have a series of five bits of simple jQuery code
  3. Click a button, code runs, something happens in canvas
  4. You can see the code you are about to execute
  5. It should be visually clear the code you see is what is running and making the changes
  6. The whole time, the canvas area is a clickable ad for Treehouse (users aren't required to interact with the jQuery stuff, it's still just an ad)
  7. You can start over with the interactive steps when completed

Here's what we end up with. Demo on CodePen:

The HTML

Relevant bits commented:

<div class="ad">
   
  <!-- Our jQuery code will run on elements in here -->
  <div class="canvas" id="canvas">
    <a id="treehouse-ad" href="http://teamtreehouse.com" target="_blank">Team Treehouse!</a>
    <img src="//css-tricks.com/wp-content/themes/CSS-Tricks-10/images/mike-standard.png" alt="Mike">
  </div>
  
  <div id="code-area-wrap">

    <h3>jQuery 
      <!-- We'll increment the "step", so we need an element to target -->
      <span id="step-counter">1/5</span>
    </h3>

    <!-- Code is visually displayed in here -->
    <pre class="code-area" id="code-area">var treehouse = 
$('#treehouse-ad')
  .addClass('button');</pre>

  </div>
  
  <div class="run-code-wrap">

    <!-- This will be pressed to run the code -->
    <a href="#" class="button" id="run-code">Run Code</a>

  </div>
  
</div>

The CSS

Not much interesting here, so let's not dwell on it. Essentially I made the ad re-use styles already in use on CSS-Tricks, so the ad feels at home. The block of code uses the same code styling as anywhere else on the site. The module has a bar on top like all other modules. The button is the global button style. That kind of thing.

I put a dotted border around the "canvas" as I thought that gives it a bit of an editable/target kind of feel.

The JavaScript

Now we need to make this thing work. Which means...

  1. When button is clicked...
  2. Execute the code
  3. Increment the step
  4. If it's the last step, put stuff in place to start over

The Structure

The JavaScript we write is essentially a "module". It's all related to each other. We should give it some structure to make that obvious. The best way I know how is to make an object that contains it all.

var TreehouseAd = {

  // Everything related to this ad goes in here.

};

That usually ends up something like this:

var TreehouseAd = {

  importantVariableOne: "foo",
  importantVariableTwo: "bar",

  init: function() {
    // The one function that will get called to kick things off

    this.bindUIActions();
  },

  bindUIActions: function() {
    // bind events here
    // have them call appropriately named functions
    
    $("button").on("click", function(event) {
       TreehouseAd.doSomething(event, this);
    });
  },

  doSomething: function(event, target) {
    // do something
  }

};

TreehouseAd.init();

Using structure like this makes for more readable code, more testable code, and just all around feels better than a bunch of disparate functions and variables (spagetti).

The "Steps"

We'll have five steps. As in, the different bits of jQuery that execute and do different things to our ad canvas.

  1. Add a "button" class to the link
  2. Move it up a little bit (demonstrating animation)
  3. Change the text of the button
  4. Add a new element
  5. Add class to the entire ad, giving it a finished feel

We'll also need to do two things with each bit of code:

  1. Display it
  2. Execute it

We'd rather not maintain the code in two separate places, so let's just not. We'll store the five different code bits in an array (giving it some structure, rather than five separate variables). Each item in the array is a string of code. We can grab that string and display it, or grab that string and eval() it.

I know. eval() is evil. We could avoid it by maintaining the code sample in different places. Or is there a better idea?
var TreehouseAd = {

   ...

   codeText: [

      "code for step 1",
      "code for step 2",
      ...
   ],

   ...

}

That ends up like:

codeText: [

  "treehouse = \n\
  $('#treehouse-ad')\n\
    .addClass('button');",
  
  "treehouse.animate({\n\
  top: '-40px'\n\
});",
  
  "treehouse.text(\n\
  'Learn jQuery at Treehouse!'\n\
);",
  
  "$('<div />', {\n\
  id: 'tagline',\n\
  text: "Hi, I'm Mike."\n\
}).insertAfter(treehouse);",
  
  "$('#canvas')\n\
 .addClass('all-done');\n\n\
console.log('Thanks for playing!')" 
  
],

Notice all the slashes and 'n's at the end of the lines? A string that ends in "\" in JavaScript just means "this string to be continued on next line." It doesn't end up in the string itself. "\n" means "new line," in our case, we need that so the code is formatted correctly when we place it inside the <pre> element. It won't effect the eval().

The Animation

To make it visually clear what is going on when you press the "Run Code" button, I thought having the code kind of slide up and fade into the "canvas" would be a cool idea. The steps then become:

  1. Make a clone/duplicate code area directly on top of existing one
  2. Animate position upwards while fading out
  3. Remove clone when done
  4. Wait to change code text until animation has completed

I think of this action as one "chunk" of functionality. Meaning it deserves it's own function as part of our object.

var TreehouseAd = {

  ...

  codeArea: $("#code-area"),
  delay: 400,

  animateCode: function() {

   this.codeArea
    .clone()
    .addClass("clone")
    .insertAfter(this.codeArea)
    .animate({
      top: "-60px",
      opacity: 0
    }, TreehouseAd.delay, function() {
      $(".clone").remove(); 
    });

  },

  ...

};

The Guts

The final code ends up like this. This has the logic in it for running the code and resetting and all that.

var TreehouseAd = {
  
  step: 0,
  delay: 400,
  codeArea: $("#code-area"),
  counter: $("#step-counter"),

  init: function() {
    this.bindUIActions();
  },
  
  codeText: [
  
    "treehouse = \n\
    $('#treehouse-ad')\n\
      .addClass('button');",
    
    "treehouse.animate({\n\
    top: '-40px'\n\
  });",
    
    "treehouse.text(\n\
    'Learn jQuery at Treehouse!'\n\
  );",
    
    "$('<div />', {\n\
    id: 'tagline',\n\
    text: "Hi, I'm Mike."\n\
  }).insertAfter(treehouse);",
    
    "$('#canvas')\n\
   .addClass('all-done');\n\n\
  console.log('Thanks for playing!')" 
    
  ],
  
  bindUIActions: function() {
    
    $("#run-code").on("click", function(e) {
      e.preventDefault();
      TreehouseAd.animateCode();
      TreehouseAd.runCode();
    });
                      
  },
                      
  animateCode: function() {
      
   this.codeArea
    .clone()
    .addClass("clone")
    .insertAfter(this.codeArea)
    .animate({
      top: "-60px",
      opacity: 0
    }, TreehouseAd.delay, function() {
      $(".clone").remove(); 
    });
      
  },
    
  runCode: function() {
    
    setTimeout(function() {
  
      if (TreehouseAd.step < 5) {
         
        eval(TreehouseAd.codeText[TreehouseAd.step]);
        
        TreehouseAd.step++;
        
        TreehouseAd.counter.text((TreehouseAd.step+1) + "/5");
        TreehouseAd.codeArea.text(TreehouseAd.codeText[TreehouseAd.step]);
                
      }
      
      if (TreehouseAd.step == 6) {
          
        // reset canvas
        treehouse
          .text("Team Treehouse!")
          .removeClass()
          .removeAttr("style");
        
        $("#tagline").remove();
        $("#canvas").removeClass("all-done");
        $("#run-code").text("Run Code");
        
        TreehouseAd.step = 0;
        TreehouseAd.codeArea.text(TreehouseAd.codeText[TreehouseAd.step]);
        TreehouseAd.counter.text((TreehouseAd.step+1) + "/5");
        
      }
      
      if (TreehouseAd.step == 5) {
        
        $("#run-code").text("Start Over");
        TreehouseAd.codeArea.text("");
        TreehouseAd.counter.text("Done!");
        
        TreehouseAd.step++;
        
      }
    
    }, TreehouseAd.delay);
    
  }
  
}; 

TreehouseAd.init();

The End

Again, the demo on CodePen:

You can also see a modified version of it live on this site! We've changed it up a few times already for funzies. Probably will keep doing so. Big thanks to Treehouse for letting me do fun stuff like this. Check them out if you are a fan of CSS-Tricks.

5 Use Cases for Icon Fonts

The following is a guest post by Tim Pietrusky. Tim knows this site has long been a proponent of using fonts for icons, and had his own interesting use cases to share. While creating the demos, to make things easier for himself, he created a free service for icon font hosting. It makes for a nice gift to the community as well. I'll let him tell you about it...

Icon fonts are great:

  • You can CSS the crap out of them and they don’t mind
  • They look good on any display or resolution
  • There is only one HTTP request for any size set of icons

Let's look at 5 typical uses cases for icon fonts.

Before we start

We won't be using any vendor prefixes to keep the example code clean and readable. We will be using things like animations, transitions, and transforms, all of which require vendor prefixes to ensure the best browser support. How you want to deal with vendor prefixes is up to you.

As you will see in the examples, I use the icon fonts hosting service weloveiconfonts.com. This is my own project. Here’s the story: I wanted to write an article about icon fonts and searched for a free icon fonts hosting service, but found none. So I created this service to be able to write this article.

1. CSS Loader

There are quite a few awesome, pure CSS loaders out there and you can even create your own at cssload.net. Another way of doing this is with icon fonts. You can use a character that looks like a loading symbol and animate it with CSS.

This is the basic HTML. The first three loaders are children of div.wrapper and and single elements. The forth (div.complex) is a combination of two icons.

<div class="wrapper">
  <span class="fontelico-spin1"></span>
  <span class="fontelico-spin3"></span>
  <span class="fontelico-spin5"></span>
</div>

<div class="complex">
  <span class="fontelico-emo-devil"></span>
  <span class="fontelico-spin4"></span>
</div>

Import the icon font Fontelico into your CSS:

@import url(http://weloveiconfonts.com/api/?family=fontelico);
[class*="fontelico-"]:before {
  font-family: 'fontelico', sans-serif;
}

Add the animation named load to the elements, whichs spins them around (from 0deg to 360deg), scales up and down a little bit, and changes the color.

/* Normal (left) */
span {
  float: left;
  text-align: center;
  margin: 0 5em;
  animation: load 1.337s infinite ease-out reverse;
}
/* Fast (center) */
.wrapper span:nth-child(2) {
  animation: load .5s infinite linear;
}
/* Steps (right) */
.wrapper span:nth-child(3) {
  animation: load 1.25s infinite steps(18, end) forwards;
}
@keyframes load {
  0% {
    transform: rotate(0) scale(1, 1);
    color: rgba(0, 0, 0, .5);
  }
  10% { color: rgba(0, 120, 0, .5); }
  20% { color: rgba(0, 120, 120, .5); }
  30% { color: rgba(120, 120, 0, .5); }
  40% { color: rgba(0, 0, 120, .5); }
  50% {
    transform: rotate(180deg) scale(1.85, 1.85);
    color: rgba(120, 0, 0, .5);
  }
  100% {
    transform: rotate(360deg) scale(1, 1);
    color: rgba(0, 0, 0, .5);
  }
}

The last loader (div.complex) combines two icons and stacks them on top of each other. The first child is the devil element (using the animation named rotate) and the second child is the spin icon (using the animation named scale).

.complex span:nth-child(1),
.complex span:nth-child(2) {
  position: absolute;
  margin: 0;  
  width: 1em;
  height: 1em;
}
/* Devil icon  */
.complex span:nth-child(1) {
  animation: load 1.25s infinite steps(18, end) forwards;
}
/* Spin icon */
.complex span:nth-child(2) {
  font-size: 3em;
  left: -.35em;
  top: -.35em;
  color: rgba(0, 0, 0, .3);
  animation: devil 3s infinite linear reverse forwards;
}
@keyframes devil {
  0% {
    transform: scale(-1.85, 1.85);
  }
  50% {
    transform: scale(1.85, -1.85);
  }
  100% {
    transform: scale(-1.85, 1.85);
  }
}

Demo on CodePen:

2. SocialCount meets Style

People love using social sharing buttons on their sites to make it easier for visitors to spread the word. But when you combine Facebook, Twitter and Google+ you are facing an 309KB empty cache load size. That’s where the SocialCount jQuery plugin comes in. SocialCount is progressively enhanced, lazy loaded, and mobile friendly.

The default styling is simple and the iframe that contains the buttons is tiny. Let's enhance these buttons with some fancy CSS.

This is the HTML that was created with the SocialCount markup generator. Just an unordered list with with links and icons.

<ul
  class="socialcount"
  data-url="http://www.google.com/"
  data-counts="true"
  data-share-text="Google is a search engine">
 
  <li class="facebook">
    <a href="https://www.facebook.com/sharer/sharer.php?u=http://www.google.com/" title="Share on Facebook">
      <span class="count entypo-thumbs-up"></span>
    </a>
  </li>

  <li class="twitter">
    <a href="https://twitter.com/intent/tweet?text=http://www.google.com/" title="Share on Twitter">
      <span class="count entypo-twitter"></span>
    </a>
  </li>

  <li class="googleplus">
    <a href="https://plus.google.com/share?url=http://www.google.com/" title="Share on Google Plus">
        <span class="count entypo-gplus"></span>
    </a>
  </li>

</ul>

Import the icon font Entypo into your CSS:

@import url(http://weloveiconfonts.com/api/?family=entypo);
[class*="entypo-"]:before {
  font: 2.5em/1.9em 'entypo', sans-serif;
}

We'll override the default styling provided by SocialCount by:

  • Adding a transition
  • Scaling the iframe
  • Setting a custom background on the buttons
Editor's note: The CSS below is in SCSS format of Sass. A number of the following demos use this. If you want to see the regular CSS, you can visit the CodePen demo links provided and click the word "SCSS" in the header of the CSS editor to see the compiled CSS.
.socialcount {
  > li {
    width: 33%;
    border-radius: 0;
    transition: all .3s ease-in-out;
    cursor: pointer;
   
    &:hover [class*="entypo-"]:before {
      opacity: 0;  
    }
  }
 
  iframe {
    transform: scale(1.65, 1.65);    
  }
 
  .button {
    top: 50%;
    margin: -.75em 0 0 0;
    height: 2em;
  }
 
  .facebook {
    background: rgba(59, 89, 152, .7);
  }
   
  &.like .facebook iframe {
    width: 8em;
  }
 
  .twitter {
    background: rgba(0, 172, 237, .7);  
  }
 
  .googleplus {
    background: rgba(172, 0, 0, .7);  
  }
}

Demo on CodePen:

3. Enhanced lists

The following three examples are all based on this simle HTML.

<div>
  <h2>Title</h2>
  <ul class="style">
    <li data-text="">Text</li>
    <li data-text="">Text</li>
    <li data-text="">Text</li>
  </ul>
</div>

Import the icon font Font Awesome into your CSS:

@import url(http://weloveiconfonts.com/api/?family=fontawesome);
[class*="fontawesome-"]:before {
  font-family: 'FontAwesome', sans-serif;
}

Add the default styling for list, list elements, pseudo elements, and the button. Instead of using a class to set the icon on the list elements, we change the content property of the element, creating a pseudo element.

ul {
  list-style: none;
  padding: 0;
   
  li {
    position: relative;
    min-height: 2em;
    padding: .3em .3em .3em 1.5em;
    transition:
      background .3s ease-in-out,
      color .3s ease-in-out,
      box-shadow .1s ease-in-out,
      height .25s ease-in-out
   ;
   
    button {
      position: absolute;
      left: 1.45em;
      bottom: .35em;
      opacity: 0;
      height: 0;
      border: none;
      font-size: .8em;
      cursor: pointer;
      transition: all .4s ease-in-out;
    }
   
    &:before {
      position: absolute;
      top: .425em;
      font-family: 'FontAwesome', sans-serif;
      margin: 0 .35em 0 -1.35em;
      vertical-align: bottom;
    }
    &:hover {
      button {
        opacity: 1;
        height: 2em;
      }
     
      &:before {
        color: rgba(255, 255, 255, 1);
        right: 0;
        transform: scale(2.5, 2.5) translate(-.25em, .15em);
      }
      &:after {
        position: absolute;
        content: attr(data-text);
      }
    }
  }
}

3.1 Stuff You Love

The first examle is very easy. A heart instead of the default list-style and a special hover: The icon is moved to the right and the ::after pseudo-element gets the text of the data-attribute data-text.

.love {
  li {  
    &:before {
      /* fontawesome-heart */
      content: "\f004";
    }
    &:before,
    &:after {
      color: rgba(220, 20, 20, .6);
    }
    &:hover {
      background: rgba(220, 20, 20, .6);
   
      &:after {
        width: 2em;
        right: .445em;
      }
    }
  }
}

3.2 Downloads

This is a custom list of downloads with extended markup: A link and a button for every list element. The button is hidden by default and shown on hover.

.downloads {
  li {
    border-bottom: .15em solid rgba(0, 0, 0, .3);
   
    &:before {
      /* fontawesome-download-alt */
      content: "\f019";
      color: rgba(50, 50, 50, .5);
    }
    &:hover {
      background: rgba(0, 140, 0, .7);
      height: 4em;
   
      &:after {
        right: .35em;
      }
     
      &:before {
        color: rgba(255, 255, 255, .2);
      }
    }
  }
}

3.3 Your account

A UI concept for a user menu. When you hover over a list element, the icon is moved to the right and the box-shadow fills the whole background. Every list element has its own icon based on the :nth-child selector and the content property.

.account {
  padding: .75em;
  border: .15em solid rgba(0, 0, 0, .2);
  background-color: rgba(0, 0, 0, .7);
  background-image: radial-gradient(center, ellipse cover, rgba(104,104,104,0.6) 0%,rgba(23,23,23,0.7) 100%);
  box-shadow: inset 0 0 .35em 0 rgba(0, 0, 0, .2);
  color: rgba(255, 255, 255, .6);
  backface-visibility: hidden;
   
  li {  
    cursor: pointer;
       
    &:nth-child(1):before {
      /* fontawesome-heart-empty */
      content: "\f08a";
    }
    &:nth-child(2):before {
      /* fontawesome-glass */
      content: "\f000";
    }
    &:nth-child(3) {
      margin-bottom: 1em;
     
      &:before {
      /* fontawesome-comment */
        content: "\f075";
      }
    }
    &:nth-child(4) {
      margin-bottom: .5em;
     
      &:before {
      /* fontawesome-cog */
         content: "\f013";
      }
    }
    &:nth-child(5):before {
      /* fontawesome-signout */
      content: "\f08b";
    }
    &:hover {
      color: rgba(255, 255, 255, 1);
      padding-left: 1.5em;
      box-shadow: inset 0 0 0 10em rgba(255, 255, 255, .5);
   
      &:before {
        color: rgba(255, 255, 255, 1);
        transform: none;
      }  
    }
  }
}

Demo of all three list types on CodePen:

4. Emocons.js jQuery Plugin

Emojons.js is a jQuery plugin which searches the content of an element for specific character sequences. All matches are replaced with a span and the HTML class of the corresponding icon. For example, a chat app:

<div class="chat">
    :D :) ;) :'( :o :/ :( B) :P :|
    :beer: :devil: :shoot: :coffee: :thumbsup: :angry: :ueber-happy:
</div>

Then call the Emocons.js plugin method on your element:

$('.chat').emocons();

All elements inside chat are now transformed into something like this

<span class="fontelico-emo-grin go" title=":D"></span>

Import the icon font Fontelico into your CSS:

@import url(http://weloveiconfonts.com/api/?family=fontelico);
[class*="fontelico-"]:before {
  font-family: 'fontelico', sans-serif;
}

When Emocons.js transforms a string into an emoticon, it adds the class go (which calls an animation) to the span element.

.go {
  animation: hey .55s 1 linear;
}
@keyframes hey {
  0% {
    transform: scale(1, 1);
  }
  50% {
    transform: scale(1.85, -1.85);
  }
  100% {
    transform: scale(1, 1);
  }
}

Some of the emoticons get a special style (e.g. a color change) or add something via an ::after pseudo element.

.fontelico-emo-devil {
  color:rgba(180, 0, 0, .9);
}
.fontelico-emo-beer:after {
  box-shadow:
    -.475em .75em 0 .275em rgba(220, 220, 0, 1),
    -.185em .675em 0 .175em rgba(220, 220, 0, 1)
  ;    
}
.fontelico-emo-coffee:after {
  box-shadow:
    -.475em .78em 0 .235em rgba(222, 184, 135, 1),
    -.215em .715em 0 .155em rgba(222, 184, 135, 1)
  ;    
}
.fontelico-emo-shoot:after {
  border-radius: .15em;
  box-shadow: .315em .525em 0 .1em rgba(0, 0, 0, 1);    
}
.fontelico-emo-angry:after {
  border-radius: .15em;
  box-shadow: -.695em .455em 0 .085em rgba(0, 220, 0, .6);
  z-index: 2;
}

Demo on CodePen:

5. Parallax Movie #1337

The last example is just for fun. It’s just an experiment to create an endless parallax movie with one icon font. The he HTML consists of many elements to create the scene:

  • The setting: sky, ground, night and sun
  • Fixed element: bicycle
  • Animated elements: Trees, giraffe, shopping cart, buildings and heliport
<div class="night"></div>
<div class="wrapper">
  <div class="sun">
    <div class="maki-fast-food"></div>
  </div>
 
  <div class="sky"></div>
  <span class="maki-bicycle"></span>
   
  <span class="maki-tree-1" data-child="1"></span>
  <span class="maki-tree-1" data-child="2"></span>
  <span class="maki-tree-1" data-child="3"></span>
   
  <span class="maki-giraffe"></span>
  <span class="maki-grocery-store"></span>
   
  <span class="maki-commerical-building" data-child="1"></span>
  <span class="maki-commerical-building" data-child="2"></span>
   
  <span class="maki-heliport"></span>
   
  <div class="ground"></div>
</div>

Import the icon font Maki into your CSS:

@import url(http://weloveiconfonts.com/api/?family=maki);
[class*="maki-"] {
  position: absolute;
  margin: 0;  
  color: #fff;
  font-size: 2em;
}
[class*="maki-"]:before{
  font-family: 'maki', sans-serif;
}
*:after {
  position: absolute;
  top: 0;
  right: 0;
  content: '';
  z-index: -1;
  width: 0;
  height: 0;
}

The wrapper rotates the whole scene -3deg.

.wrapper {
  height: 140%;
  width: 120%;
  transform: rotate(-3deg) translate(-10%, -15%);    
}

When the sun goes down, the night rises.

.night {
  position: absolute;
  z-index: 5;
  width: 100%;
  height: 100%;
  animation: night 45s infinite forwards;
}
@keyframes night {
  0%, 30%, 100% {background:rgba(0, 0, 0, 0);}  
  55% {background: rgba(0, 0, 0, .6);}
}

The sky and the ground both use the same background-position animation, but at different speeds.

.sky {
  position: relative;
  z-index: 0;
  background: url(http://subtlepatterns.subtlepatterns.netdna-cdn.com/patterns/bedge_grunge.png);
  height: 50%;    
  width: 100%;
  animation: rollin-bg 25s linear infinite forwards;
}
.ground {
  position: absolute;
  z-index: 1;
  background: url(http://subtlepatterns.subtlepatterns.netdna-cdn.com/patterns/blackorchid.png);
  height: 50%;    
  width: 100%;
  animation: rollin-bg 7s linear infinite forwards;
}
@keyframes rollin-bg {
  0% { background-position: 100%; }  
  100% { background-position: 0; }
}

Moving an element along a circle is an awesome article from Lea Verou which is used here to animate the burger-sun.

.sun {
  position: absolute;
  z-index: 1;
  left: 50%;
  top: 10%;
  width: 2em;
  height: 2em;
  font-size: 4em;
  line-height: 1;
  animation: circle 45s linear infinite;
  transform-origin: 50% 3.85em;
}
.sun [class*="maki-"] {
  color: rgba(240, 180, 0, .2);
  text-shadow: 0 0 .35em rgba(240, 240, 0, .7);
}
.sun > div {
  animation: inner-circle 45s linear infinite;
}
@keyframes circle {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@keyframes inner-circle {
  from { transform: rotate(0deg); }
  to { transform: rotate(-360deg); }
}

This is the only element which has no animation. But it should look like it’s moving.

.maki-bicycle {
  left: 50%;
  z-index: 4;
  margin: -.85em 0 0 -.5em;
  color: rgba(30, 30, 140, .95);
}

And here are the animated elements which use all the same rolling animation at different speed.

.maki-tree-1[data-child="1"] {
  margin: -1em 0 0 5%;
  z-index: 5;
  animation: rollin 5s linear infinite;
  font-size: 2.4em;
  color: rgba(0, 110, 0, .8);
}
.maki-tree-1[data-child="2"] {
  margin: -1em 0 0 85%;  
  z-index: 2;
  animation: rollin 12s linear infinite;
  font-size: 1.6em;
  color: rgba(0, 110, 0, .5);
}
.maki-tree-1[data-child="3"] {
  margin: -1em 0 0 25%;  
  z-index: 2;
  animation: rollin 17s linear infinite;
  font-size: 1.2em;
  color: rgba(0, 110, 0, .3);
}
.maki-giraffe {
  margin: .25em 0 0 5%;  
  z-index: 6;
  animation: rollin 12s linear infinite reverse;
  font-size: 10em;
  color: rgba(255, 255, 10, .9);
}
.maki-giraffe:after {
  right: -3em;
  content: '\e82a \e82a \e82a \e82a \e82a';
  font: .2em 'Maki', sans-serif;
  letter-spacing: .2em;
  width: 3em;
  color: rgba(0, 0, 0, .6);
  box-shadow:
    0 .45em 0 .75em rgba(255, 255, 255, .4),
    1em .35em 0 .75em rgba(255, 255, 255, .4),
    2.25em .25em 0 1.05em rgba(255, 255, 255, .4)  
  ;
  border-radius: 50%;
  transform: translate(2.3em, .55em) rotateY(-180deg);
}
.maki-grocery-store {
  margin: -.35em 0 0 5%;
  z-index: 5;
  animation: rollin 22s linear infinite;
  font-size: 4em;
  color: rgba(220, 0, 10, .7);
}
.maki-commerical-building[data-child="1"] {
  margin: -1em 0 0 5%;
  z-index: 3;
  animation: rollin 6s linear infinite;
  font-size: 7em;
  color: rgba(120, 0, 120, .8);
}
.maki-commerical-building[data-child="2"] {
  margin: -1em 0 0 5%;
  z-index: 2;
  animation: rollin 14s linear infinite;
  font-size: 4em;
  color: rgba(0, 120, 120, .4);
}
.maki-heliport {
  margin: -3.5em 0 0 2em;  
  z-index: 1;
  color: rgba(30, 30, 30, .45);
  font-size: 1.25em;
  animation: rollin 26s linear infinite reverse 2s;
}
@keyframes rollin {
  0% {margin-left:105%}  
  100% {margin-left:-15%;}
}

Demo on CodePen:

Further reading

Thanks for your time! And of course this isn't all you can do with icon fonts. Don't be afraid to experiment yourself.

How To Deal With Vendor Prefixes

If you write CSS you almost surely need to be using vendor prefixes on some parts of the code you write in order to ensure the best browser support. Whether that is prefixed properties like -prefix-transform, prefixed at-rules like @-prefix-keyframes, or prefixes values like -prefix-linear-gradient, it's a daily chore of CSS authors.

Not only is it part of our jobs, it's an easy thing to screw up. I recently looked around at a bunch of big websites specifically looking for little nitpicky CSS3 errors and I was able to find one on any site I looked at.

So how do we author CSS so that we always are using the correct prefixes all the time?

Hand Author - Refer to CSS3Please

Hand authoring means the CSS that your sites uses in production ("live") is the CSS file that you edit yourself in a text editor. Going this route means you'll need to be including all the right vendor prefixes right in that authored file yourself. A bit tedious and error-prone for me liking, but likely scenario for most websites in the world.

If this is the case for you, your best bet is referencing an up-to-date resource like CSS3 please!. You can edit the values right on that site and copy-and-paste right into your own stylesheets.

If you do this, it means the onus is on you to keep things up to date. Prefixes aren't as volatile they once were, but a look every few months is certainly warranted.

Hand Author - Don't Prefix - Let -prefix-free do it client side

You still hand-author the CSS, but you only use the un-prefixed properties/values/at-rules. -prefix-free is a bit of JavaScript that runs, looks through all your CSS, and appends to the page new styles with the proper prefixes needed to make those styles work, if necessary.

This is holy war territory. It makes CSS files smaller! Yeah but it runs the risk of flashes of un-CSS3'd elements! It requires JavaScript for styles, crossing the streams! Yeah but it's only 2k! It's progressive enhancement at its finest since it will stop prefixing when browsers stop needing it!

You decide.

It's also worth noting that jQuery's .css() method will do some prefixing for you.

$("body").css({
  
  // Will NOT prefix
  "background": "linear-gradient(#ccc, #666)",

  // Doesn't need to, so won't
  "box-shadow": "inset 0 0 5px black",

  // WILL prefix
  "transform" : "rotate(5deg)"

});

I'm not a fan of applying CSS through JavaScript usually, but good to know as there are always exceptions to rules.

Hand Author - Fix up with Prefixr

If you prefer not hand authoring the prefixes but ultimately your workflow deploys hand-authored CSS, you could run your CSS through Prefixr before deploying. It essentially parses your CSS, finds things that need prefixing, and does it for you.

It's very smart in that you don't have to have CSS that is specifically void of prefixes (like -prefix-free requires). For example if you just happen to be missing one of the required three prefixes, it will see that and only add the missing one.

It also has ways to be added to workflows via the command line or popular text areas.

Preprocess - Use mixins

One of the big reasons to use CSS preprocessors at all is because of the help with vendor prefixing.

If you use Sass, Compass or Bourbon have robust sets of CSS3 mixins for you.

If you use LESS, I have a set of them or you could look at this roundup comparing some others.

Hand Author - Don't Prefix - Post Process with Autoprefixer

This is a really great way to do it. It's all laid out in this article. Essentially you just forget about prefixing and this build step will add the prefixes for you according to the lastest and greatest information from CanIUse.

"Don'ts"

One mistake I sometimes see is that people just use all the major prefixes on every CSS3 property. It appears they have a generic mixin that they just put everything through that slaps on the prefixes. If you've seen something like -o-border-radius, that's what I mean. That has never existed and never needs to go into your CSS.

Another mistake is letting CSS get stale. As I mentioned earlier, it's worth a look at CSS older than a couple of months to make sure it's up to snuff. If you see anything outdated on this site, please let me know and I'll update it right away.

ShopTalk Episode 48

#CROSSOVER time with Jen Simmons from The Web Ahead! Jen, Dave and I talk about The Web Behind, the Instagram debacle, getting better, being critical of yourself, and more. Thanks to Lynda.com and InControl for sponsoring.

CodePen PRO

Big day for me and the CodePen team! Many, many months of development have given birth to CodePen PRO, a set of eight brand new features. Things like Collab Mode, where you can literally write code and chat with other people in real time.

CSS Hypenation

PPK: Hyphenation works!

Eric Meyer on places to avoid it.

In my own experience in the CSS-Tricks v10 redesign, at one point I had hyphenation turned on everywhere and got loads of complaints of certain versions of Firefox over-hyphenating things. Nearly every other sentence had a hyphenated word where it really didn't need to be.

Fastbook

Zuck was all like "HTML5 is too slow" and Sencha is all like "Whatever child take a peep at this."

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