Article Archives

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."

CSS-Tricks Chronicle IX

In the search box on CSS-Tricks.com you can now limit searches to just "articles" which has been a long-needed feature. I'm having that return results from the blog, the snippets, or the alamanac - which are all essentially the same format.


I posted the slides yesterday for my talk A Modern Web Designer's Workflow, and today Future Insights released the video of it from Future of Web Design New York.

And here's another version of it from a smaller/longer WordPress focused event.


I was interviewed alongside Dave Rupert in a recent Responsive Design Weekly email.


There is a new ad for Treehouse in the sidebar of the site (lower down on smaller screens). I wanted it to be a fun interactive experience. Treehouse has some new content on using jQuery, so I focused on that. Below the simple advertisement is a bit of jQuery code and a "Run Code" button. You can click the button to run that bit of code on the advertisement. It does different things like affect the markup, add classes, and animate things. It's just to wet your whistle for what jQuery can do and hopefully you'll be enticed to learn more.

I plan to do a tutorial on how it was made since there is some interesting stuff going on there I think.


ShopTalk has being going strong. We've had some great episodes lately. I feel like having Zeldman on in the first year is a pretty big milestone.

We added Disqus comments to all episodes on ShopTalk now, so the conversation can continue after the show is over.

And the biggest ShopTalk news? We have T-Shirts now!


I posted a new video where I answer a bunch of forums posts. Might make a bit of a series about it since it was pretty fun to do.


The RSS subscribers to this site, as reported by FeedBurner, crossed the 100,000 mark for the first time. Gosh I hope FeedBurner doesn't shut down. I'm not sure there is any clean way to update every subscribers subscription URL should that happen.

Facebook likes for this site crossed 10,000.

Speaking of the new video and RSS and stuff, there is a page for all subscription options, should you want to customize what you get from CSS-Tricks.


Random non-web things...

I've been making the jump off iTunes into Rdio and it's awesome. I can't believe I held out for so long.

I've been playing a bit of Guild Wars 2 and it's real fun. Character "Skcirt" (tricks backwards) on Kaineng.

I just finished reading The Night Circus which I enjoyed quite a bit. Started into A Discovery of Witches which is starting out good too (Vampires and Witches in academia!).

FooTable: a jQuery Plugin for Responsive Data Tables

The following is a guest post by Brad Vincent where he introduces his new jQuery plugin for helping make data tables responsive. Responsive data tables has been a recurring topic around here, first with my early exploration and then a roundup. I thought this new jQuery plugin approach was worth a discussion for a number of reasons: a lot of people like utilizing flexible plugins like this rather than hand-crafting one-off solutions, it's a slightly different UI approach than the ones I've seen so far, and functionality is entirely handled in JS (CSS is just for styling).

These days, everyone is jumping on the responsive bandwagon. Apart from responsive layouts, everything is going responsive: sliders, lightboxes, galleries, you name it! But then one day, when I was working on an HTML table with a lot of columns, I thought "How is this going to look on my iPhone?". And then I searched for "responsive tables" and found Chris' roundup post on a few solutions out there.

So Why Create FooTable?

There have been quite a few solutions for responsive data tables, including:

  1. Zurb’s that scrolls the table horizontally on smaller devices.
  2. Dave Bushell’s that flips the table on it’s side.
  3. Filament Groups’s solution lets the user select the columns to show.
  4. Stewart Curry’s one hides less important columns.
  5. Chris Coyier’s one which groups the data for each row in a list and the columns disappear.

I liked what some of the responsive table solutions were doing, but none of them "hooked" me completely. So I got together with my friend Steve, who is a jQuery guru, and we started on a new jQuery plugin. We really liked the concept of disappearing columns, but we still wanted the ability to see that hidden data somehow. We also liked Chris' concept about inverting the columns to become rows, so we decided to combine both concepts and FooTable was born.

How Does FooTable Work?

FooTable is very simple:

  1. It hides certain columns of data at different resolutions (we call these breakpoints).
  2. Rows become expandable to show the data that was hidden.

Configuration Via Data Attributes

Steve and I have both worked with other table plugins, like the amazing datatables.net, but we found them really difficult and unintuitive to configure. So we came up with the concept of using data attributes to tell FooTable how to do things. It also makes it easier for other developers supporting your code to see what you are doing. For example, check out the following simple table head markup:

<table class="footable" data-filter="#filter">
  <thead>
    <tr>
      <th data-sort-initial="descending" data-class="expand">
        First Name
      </th>
      <th data-sort-ignore="true">
        Last Name
      </th>
      <th data-hide="phone,tablet">
        Job Title
      </th>
      <th data-hide="phone,tablet" data-type="numeric">
        DOB
      </th>
      <th data-hide="phone" data-type="numeric">
        Status
      </th>
    </tr>
  </thead>

  ...

</table>

You can quite easily tell, just from the markup, that the table will work in the following way:

  1. The table will be filtered by an input with id "filter" (data-filter="#filter")
  2. The table will be sorted initially by the First Name column and it will be sorted in descending order (data-sort-initial="descending")
  3. The Last Name column cannot be sorted (data-sort-ignore="true")
  4. The Job Title and DOB columns will be hidden on phone and tablet (data-hide="phone,tablet")
  5. The Status column will be hidden on phones (data-hide="phone")
  6. The DOB and Status columns use numeric data (data-type="numeric")

Now that's more like it!

Editor's note: Using data-* attributes to control plugin behavior is very popular lately (See Twitter Bootstrap). Would love to hear thoughts on that in the comments.

Usage

You've seen the markup, which is the data table itself with built-in configuration on how it should behave.

You'll also need jQuery, the plugin itself, and your authored code to call the plugin. The code below is just for illustration on how it might work. In production you'd likely be combining all these scripts.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" type="text/javascript"></script>
<script src="js/footable-0.1.js" type="text/javascript"></script>
<script type="text/javascript">
    $(function() {
      $('table').footable();
    });
</script>

It's also likely that you have your own breakpoints. That is very easy to configure as you call the plugin.

$('table').footable({
  breakpoints: {
    mamaBear: 1200,
    babyBear: 600
  }
});

Then use those values in your data-hide attributes instead.

Built For Extensibility

Another cool feature of FooTable is the way in which it can be extended. We did not want to bloat the core code as we added more and more features down the line. Also, each project has it's own requirements, and we realise that you will not need every feature of FooTable in every project. So Steve came up with an awesome plugin architecture within the plugin, that allows Footable to be extended with ease. For example, to make your table sortable, all you need to do is include the file footable.sortable.js. We have only released the sorting add-on to date, but we are busy with the filtering add-on and hope to create a bunch more. We are also hoping the community will help us here and come up with really cool add-ons. You can check out this template code to see how it's done.

Last, but not least....demos!

Do we need box-shadow or border-radius prefixes anymore?

Straight forward question by Jay Hughes:

I didn't specifically have a post about this, so let's do it!

Short Answer

Specifically for box-shadow and border-radius, probably not.

You only need them if:

  1. It's a rare situation where the square-corner or no-shadow fallback hurts the experience.
  2. And your site has significant traffic of Firefox 3.6-, Safari 4-, iOS 3.2-, or Android 2.3-

Long Answer

Let's explore a bit deeper. First, you can see exactly what browsers support what features at Can I use....

Second, you should only make decisions about feature support based on statistics from your own site and nothing else.

border-radius

Firefox 3.6- needs -moz-. From 4 up, unprefixed is fine. On this site, that's 0.3% of the 30% or so that use Firefox.

Safari 4- needs -webkit-. That's even smaller for this site. 0.1% of the 10% or so using Safari.

iOS 3.x needs -webkit- too, which means an iPhone 3GS or iPad 1 that have never been upgraded, which is the smallest number yet.

Again, it's your sites stats that matter, but I'd guess most sites are well under 1% for all this combined.

Not to mention, a non-rendering border-radius is the poster child for "who cares" fallbacks.

box-shadow

Box shadow is similar but slightly more strict. Exactly the same for Firefox and iOS. Safari needs -webkit- in 5.0-, but was fixed just three months later in 5.1 (which shipped with OS X 10.7).

The most significant difference is that Android 2.3 needs -webkit-. Can I Use listed it as needed on 4.0, but I sent in a correction and they fixed within hours, so that's good to know! Even on this site, I'm looking at 0.5%, which is way higher than those other browsers. If you're site is specifically mobile-y, I bet this number is much higher.

It's likely that the fallback of not having box shadows is no big deal, but I have seen a situation where it mattered so hey.

Nine Ways to Improve User Experience in Mobile Design

The following is a guest post by Ben Terrill. Ben works for Mobify and leads the team that helps their huge customers (like Starbucks and Threadless) have excellent mobile and tablet experiences. Ben is co-author of the e-book 50 Ways to Please Your Customers: A guide to mobile web design best practices.

Julie Szabo from Mobify wrote to me to help promote the book a bit. Ya'll know I rarely do that - so just to be clear: this isn't a sponsored post, no money changed hands, and the book is good and free.

I suggested they write up some stuff as a guest post and they obliged with some "best of" excerpts from the book. I added a few bits here and there where I had additional info to share. Enjoy!

At Mobify, we recently analyzed data from more than 200 million visitors to our e-commerce customers’ sites, and found that 27% of site visits came from people shopping on smartphones and tablets. For some countries, such as Brazil, we found that nearly half of all e-commerce traffic came through mobile devices.

It’s now a reality that every company and publisher on the web needs a mobile web strategy. We wrote an e-book on how to build a great mobile site, and here are nine tips from the book for optimizing your site for all those mobile site visitors.

ebook-screenshot

Hint and reveal (AKA: progressive disclosure)

Mobile devices are small and most websites present a lot of information. Use progressive disclosure to show users which actions they can take to discover the content they’re after. Don’t overload them with mountains of information at all once. Instead, let them expand or reveal content as they need it.

Accordions can play sweet music

Accordions can prove to be an effective tactic for showing content without stretching the page to infinity and beyond. Use them in the right context. Maintain that context. Make sure you provide a consistent expand and collapse cue.

accord
Example from Brad Frost's pattern library on CodePen.

Carousels make users happy


Carousels can be the perfect solution for image showcases, hero images and related content. Be sure to show your users how many items are in the carousel and their current place in those items. If you are auto-advancing your slider, make sure you stop auto-advancing when the user starts interacting.

royalslider

RoyalSlider is responsive, touch enabled, and stops autoplay at first interaction.

Respect the fat fingers and tipsy taps of your users

None of us are as dexterous as we’d like to be on our mobile devices. We can all have a touch of “fat fingers” symptoms. So design your actions accordingly. Make the touch targets big. We recommend 40px by 40px. Give targets lots of margin too. We recommend at least 10px margins around the targets. Primary actions should always be big and tappable.

Editor's note: Apple recommends 44x44. More info.

Save time with font-based icons

We ♥ icons! They spice up your designs. To avoid managing a sprite sheet with both retina assets and smaller icons, opt for a font-based icon set like: Font Awesome; glyphish; iconsweets; or symbolset. Or, make your own. Here’s how.

Editor's note: Resources on this site include an article about the proper HTML to use for icon fonts, a round up of different icon fonts, and a screencast about making your own.

Use some asset management magic

Generate retina icons and use the CSS background-size attribute to size them down for non-retina devices. They'll still look great and won't take up that much more space than the smaller versions.

Editor's note: Retina media queries are pretty easy. That way you can serve retina images only to screens that can use them. Non-retina screens = 1x images at full size, Retina screens = 2x images at half size.

Know your usable viewport size then keep it fluid

Sure the screen size on an iPhone 4 may be 320px by 480px (or 960px by 640px of pixel density in Apple’s marketing) but what’s the real screen size with the browser chrome? That’s actually what your user will experience. (Answer: 320px by 414px.) Know your usable screen size and keep your design fluid to take advantage of it in both portrait and landscape orientations. Use it and make your users happy.

viewable-screen

Make your default font size at least 14 px


Even if that seems really big, it’s the right thing to do. The only time to go smaller (and just to a minimum of 12 px) is on very precise labels for forms.

Embrace the wide world of device APIs

When making a desktop site mobile we sometimes forget that smartphones and other mobile devices access user location, can make phone calls, take pictures and much more. Don’t confine your creativity to what’s on your desktop site.

BERG Cloud Buttons

The buttons at BERG Cloud are pretty sweet looking. It's not a hugely big deal, but the way they have created them uses two separate images (not sprited) and two internal spans. In this tutorial we will recreate them with some modern tricks. We'll use no images (more efficient), less markup (more semantic), and function smoother (no javascript controlling states).

(more…)

CSS Next

Divya Manian runs through many of the latest stuff coming in CSS. Including several things I'm hearing about for the first time, like specifying unicode range for an @font-face and canvas-as-background.

If you can't get enough, this talk by Tab Atkins (only works in Chrome) covers even more upcoming stuff, including more I'd never heard of. Things like image-interpolation (determines how images scale, like keeping sharp pixel boundaries), setting font-size with ex which is based on x-height (will be awesome for icon fonts), and an attr() function which allows you to use attribute values in styles.

ShopTalk Episode 46

Another RAPIDFIRE episode where Dave and I just do as many questions as possible. Including: why does Prototype still exist? What is good UX for target="_blank"? and the semantics of <cite>.

Sauce Mac App

I quite like Browserstack, but Sauce has some pretty compelling features as well, like video recording of your testing sessions. Now Sauce has a native Mac app, which means you can do your old browser / cross platform / device emulation testing right from a dedicated app.

Rebuilding CSSLoad.net

The following is a guest post by Timur Gafforov. Timur is the creator of CSSLoad.net - a site for building custom loading graphics. He ran another site that did this with GIFs, but was inspired to re-do it with CSS animation. This is that story.

Background

The idea of CSSLoad.net appeared when I first learned about the keyframe animations in CSS. I had already had a project dedicated to loading animation graphics at the time, but this was much more inspiring as with native animations there are fewer limits than there is with raster images. Any size, any speed, any colors and other features with no server load. All the animations run with the loading of the page. This is what my users of preloaders.net had been requesting for years.

I created a first version of the site, but it was not very useful as it provided to little control over animations. A year after the launch, idea for a second version of the project came to me after seeing "Bouncy Animated Loading Animation" article here on CSS-Tricks. That gave me the inspiration to rework the CSSload.net project and launch the second version. The big idea was to provide users not only with the loading animations in pure CSS, but also give them more freedom to generate the animation they need with the least effort. And, voila, the second version is ready!

Thanks to Chris for the idea and Jacques for providing the Window 8 loading animation idea in the same post. Let us dig a little deeper now.

Reusing Tools

As I said, I had experience in loading image animations generator development, so I thought: why re-invent the wheel? I took some form goodies I used on preloaders.net - jQuery, Color Picker, Tigra Slider and some code snippets of my own (like my own "size scroller"). As a matter of fact, I make my own plugins often as this can be very useful in terms of code productivity and reduced code size. Only coding exactly what you need is often better than using one-size-fits-all solutions.

Now the form controls for choosing loader components are ready. I will skip that code here, as you can see it one the website and it's pretty boring. We can move on to the "cream" of the application: the CSS animations generator.

Picking Options

Having taken some ideas from my own image animations and others from around the web I created several CSS loaders. I made a list of what should be changable by the user:

  • colors
  • animation speed
  • size
  • ability to reverse the animation
chooser

The UI for all choices.

Simple Example

Here is an example of one specific loader animation. I'll keep the code un-prefixed for simplicity, but the code the site generates uses all the proper prefixes.

#noTrespassingOuterBarG {
  height: 20px;
  width: 160px;
  border: 1px solid #000000;
  overflow: hidden;
  background-color: #FFFFFF;
}

.noTrespassingBarLineG {
  background-color: #000000;
  float: left;
  width: 14px;
  height: 120px;
  margin-right: 24px;
  margin-top: -28px;
  transform: rotate(45deg);
}

.noTrespassingAnimationG {
  width: 236px;
  animation-name: noTrespassingAnimationG;
  animation-duration: 1.3s;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}

@keyframes noTrespassingAnimationG {
  0% {
    margin-left: 0px;
  }
  100% {
    margin-left:- 38px;
  }
}
<div id="noTrespassingOuterBarG">
  <div id="noTrespassingFrontBarG" class="noTrespassingAnimationG">
    <div class="noTrespassingBarLineG">
    </div>
    <div class="noTrespassingBarLineG">
    </div>
    <div class="noTrespassingBarLineG">
    </div>
    <div class="noTrespassingBarLineG">
    </div>
    <div class="noTrespassingBarLineG">
    </div>
    <div class="noTrespassingBarLineG">
    </div>
  </div>
</div>

More Considerations

Before developing any application, you must consider constraints and limits. In this case I decided these were reasonable:

  • Total animation duration can not be less than 0.
  • The size of the main and inner DIVs can not be less than 5px.
  • The animation should be work in as many browsers as possible.
  • The names of CSS classes must be different from what a user would usually use. I added a "G" as in Generated to the end of each class name.

A Function Per Animation

Everything else is pretty simple. Each animation has it's own function with the same list of parameters: firstColor, secondColor, width, height, animationSpeed, isReverse and one common function that decides what function to call. Each control calls this common function upon change. Here is an example function:

function noTrespassing(firstColor, secondColor, width, height, animationSpeed, isReverse) {

  var toReturn='';

  if (isReverse) {
    var begin = Math.round(width*38/160) * (-1);
    var end = 0;
  }
  else {
    var begin = 0;
    var end = Math.round(width*38/160) * (-1);
  }

  toReturn += '<style>#noTrespassingOuterBarG{height:'+height+'px;width:'+width+'px;border:'+Math.ceil(height/20)+'px solid #'+firstColor+';overflow:hidden;background-color:#'+secondColor+'}.noTrespassingBarLineG{background-color:#'+firstColor+';float:left;width:'+Math.round(width*14/160)+'px;height:'+Math.round(width*120/160)+'px;margin-right:'+Math.round(width*24/160)+'px;margin-top:-'+Math.round(width*28/160)+'px;';

  toReturn += addPrefix('[prefix]transform:rotate(45deg);');

  toReturn += '}.noTrespassingAnimationG{width:'+Math.round(width*236/160)+'px;';

  toReturn += addPrefix('[prefix]animation-name:noTrespassingAnimationG;[prefix]animation-duration:'+animationSpeed+'s;[prefix]animation-iteration-count:infinite;[prefix]animation-timing-function:linear;');

  toReturn += '}#noTrespassingFrontBarG{}';

  toReturn += addPrefix('@[prefix]keyframes noTrespassingAnimationG{0%{margin-left:'+begin+'px;}100%{margin-left:'+end+'px;}}');

  toReturn += '</style><div id="noTrespassingOuterBarG"><div id="noTrespassingFrontBarG" class="noTrespassingAnimationG"><div class="noTrespassingBarLineG"></div><div class="noTrespassingBarLineG"></div><div class="noTrespassingBarLineG"></div><div class="noTrespassingBarLineG"></div><div class="noTrespassingBarLineG"></div><div class="noTrespassingBarLineG"></div></div></div>';

  return toReturn;
}

The variables in this function speak for themselves. You can see how the code of the animation is changed in regards to a particular form element change event. I guess there is no need to go deep into detail here, except for the addPrefix function. This function simply replaces the [prefix] part of the code with required prefixes through a loop of global prefixes array variable that is changed upon selection in the code dialog box.

That's it! The rest you can find in the code source code of the project. We hope to receive some suggestions, questions, and of course, criticism.

Bootleg.css

Ryan Seddon recreates most of the Bootstrap JavaScript plugins without JavaScript. The :checked selector is the workhorse, like we've covered here, but Ryan is the OG of checkbox hacks. These things might get more powerful and more semantic if this goes well.

ShopTalk Episode 45

This week Dave and I were joined by Harry Roberts and where we continue the discussion on IDs, how preprocessors help Harry's framework Inuit.css, visualizing how CSS transforms work, and more. Big thanks to InControl 2013 for sponsoring.

Fly in Newly Added Content to a Page

Say that for any reason, a new module of content needs to appear on a page. By simply appending that new module into the DOM it will instantly appear. That might be enough of an "entrance" - or it might be too subtle. I'd think when you add new content to a page, you want people to see it. Animation might be the ticket. It technically slows down the entrance of the new content, but the visual effect will certainly make it more noticeable. Let's write some code to make all new modules added to a page "fly in."

(more…)

Viewport Resizer

There are many like it, but this one by Malte Wassermann is a really good one. It goes the extra mile, for example, by injecting the correct meta tags, sending the right user agent, and refreshing the page in its newly resized viewport.

“Bad Code”, Dogmatism, etc.

  1. In a Q&A article on Smashing Magazine I answered a question about how to look at CSS and determine if it's good or bad.
  2. Harry Roberts expounded upon my answer with lots more specific examples about bad things you can find in CSS (e.g. magic numbers, qualified classes, too vague of selectors). Harry says in this article:

    Use IDs in HTML for fragment identifiers and JS hooks, but never in CSS.

  3. Jeffrey Zeldman reacts to this and defends using IDs. Jeffrey compares abandoning ID's to OOCSS and avoiding descendant selectors.
  4. We have Jeffrey on ShopTalk to discuss. We don't spend too much time disagreeing - but instead focus on a much bigger agreement: being too dogmatic about these things is the worst possible stance.
  5. Totally coincidentally, we have Harry Roberts on ShopTalk next week.

Now my turn again. I love blogging.

I feel like if anyone gets off-put by Harry's writing, this article or any others, it's that he sometimes comes off as being dogmatic. If that term doesn't mean anything to you, just think of it as inflexible thinking. This is the way things are dammit and that's that. Having strong opinions is awesome, having inflexible ones is not. Writing about what works for you is awesome, writing iron-clad manifesto's is not.

I've met Harry. He's a nice guy. I'm not sure how dogmatic he is in his thinking (I doubt much). We'll talk about that on ShopTalk.

Jeffrey called "bunk" on the decree that ID's should never be used:

Say it with me: There is nothing wrong with id when it is used appropriately (semantically, structurally, sparingly). There is plenty wrong with the notion that class is always preferable to descendant selectors and semantic, structural ids.

To me that edges just as close to dogmatism as Harry did. And I'm guilty of this as well. I wrote about this in my article "A Line In The Sand, A Story About Meaty Chili and Using Classes":

I'm not going to use ID's to style things. No compromise. Even if an ID might seem like it could save me in a short term way, the long term benefits of never using them are greater.

Avoiding ID's altogether has lead to a better CSS authoring experience for me. I probably should have framed it more like that, but hey.

I feel like Jeffrey thinks that avoiding ID's means over-classing everything else, giving up on the cascade, and not using intelligent selectors that encourage clean markup. I don't think ID's have anything to do with those things. Over-classing is dumb, don't do that, and don't think that that's what OOCSS means (I think of it like: find a pattern, give that pattern a class). The cascade is still useful, but in limited ways. You could argue it hurts as much as it helps. And finally, I'm all about descendant selectors. They work equally well with classes as with ID's. Better, I'd argue, since the class is re-usuable.

I also feel Jeffrey has a deeper perspective on this as Harry or I might. As we talked about on ShopTalk show, Jeffrey worked through some eras where markup was extremely nasty and helped usher in an age of clean markup that we're used to seeing today. I can understand being nervous if he feels things move back the other direction.

Writing More Autonomous JavaScript

The following is a guest post by Matt Holt from SmartyStreets. Matt wrote to me about a new plugin they developed for verifying addresses, as he knew we've gone down the road of address trickery around here before. He wasn't trying to promote their product so much as share a philosophy of plugin development, but I thought a guest post could do both. He obliged.

Street addresses are complicated. They should be easy.

They’re hard because:

  1. An address is not a single unit of data; it involves 2 to 6 different pieces
  2. Addresses are irregular and unpredictable (can’t be matched with regular expressions)
  3. An address can be sort-of valid without being fully valid
  4. Addresses are often the source of confusion for customers at checkout

At SmartyStreets, we addressed the problem (pun intended) by creating an event-based, highly autonomous jQuery plugin which hooks into an authoritative address API. We affectionately call it jQuery.liveaddress.

You can see it in action on this LiveAddress documentation page.

in-action

Actual implementations can be seen on ProCPR, Tortuga Rum Cakes, and other checkout, sign up, and contact forms. The end results make me want to see more autonomous jQuery plugins that just work without the need for meddling or configuration.

An autonomous script/app/plugin doesn’t need its hand held. It does its own thing, broadcasts what it is doing, and it just works. Here I’ll briefly focus on two aspects of the autonomous plugin:

  • Plug-and-play
  • Event-based

Plug-and-play

Unlike web apps, jQuery plugins need to adapt to their environment. jQuery’s selector engine, Sizzle, takes a lot of the pain away, but in our case, addresses can’t just be “selected.” They have to be identified, or “mapped.”

As such, jQuery.liveaddress is rather atypical: it isn’t just a function you can call directly on a set of matched elements, nor does it support chaining. To be truly plug-and-play, our plugin has to automatically find the elements in a form which pertain to address data: street, city, state, zip code, etc. The plugin scans your page for such elements and automatically arranges them into Address structures which are managed by Form objects. Everything is monitored internally for changes. We call this process “auto-mapping.”

Here’s how our old Javascript implementation was initialized. It didn’t have auto-mapping and it wasn’t very well engineered:

QadApi({
    timeout: 10,
    key: "HTML-KEY",
    busySubmit: false,
    autoClean: false,
    submitId: "submit",
    allowPost: false,
    properCase: true
    // ... other service-related configuration ...
  },
  {
    busyId: "QadBusy"
    // ... other CSS-related configuration ...
  },
  [
    {
      name: "Javascript Example",
      street: "street",
      city: "city",
      state: "state",
      zip: "zipcode"
    }
    // ... other addresses to be mapped, if any ...
  ]
);

Compare that with jQuery.liveaddress, which auto-maps:

var liveaddress = $.LiveAddress("YOUR-API-KEY");

See the difference?

On web pages with clear input name and id attributes, or even <label> tags and placeholder attributes, auto-mapping works remarkably well. You wouldn’t believe the gnarly-looking forms I saw during testing where name and id had nothing to do with the field itself, and of course, there were no <label> tags. (Designers: take note!) For such cases, we do provide a way for fields to be mapped manually, either during initialization or afterward, using selector strings:

liveaddress.mapFields([{
  id: 'billing',                // IDs are not part of the address
  street: '#street1',
  street2: '#street2',
  city: '#city',
  state: '#state',
  zipcode: '#zip'
}]);

Remember, if your plugin does or assumes something automatically, make sure the developer can override it and take control.

A jQuery plugin should not be like your kitchen table from IKEA (significant assembly required). Can’t it just work right out of the box? Whatever that means for your particular script, so be it: just don’t make me configure it whenever possible!

Event-based

Consider the likely case where you want to step in the middle of the address validation process and do something. If no events are raised, how do you know that an address was just validated? You’d have to go into the script’s source and finagle your own hack in the middle of it. Events are the elegant - and correct - solution to this.

We’re lucky that Javascript makes events such a routine thing! (Sort of.) Use events. Fire them off when cool (or un-cool) stuff happens.

jQuery makes events a breeze, and even maintains a reference to each bound handler. So while we’re all used to binding to events using jQuery, don’t forget to raise them also:

$(someElement).trigger(eventName, extraData);   // or use triggerHandler()

When raising events, be sure to pass in any data related to the event so that the handler has state (context).

jQuery.liveaddress raises up to 14 custom events during its lifetime. This has been immensely useful and powerful, as you’ll see below.

In fact, jQuery.liveaddress binds to its own events internally. This means you have the power to stop the process at any point and under any condition. For example, to prevent the user from submitting an address which is missing a secondary (apartment) number:

liveaddress.on("AddressAccepted", function(event, data, previousHandler) {
  
  if (data.response.isMissingSecondary()) {

    data.address.abort(event);      // reset some things internally
    alert("Don't forget your apartment number!");
  
  } else {
                
    previousHandler(event, data);   // continue the process

  }

});

Notice this on() function is invoked on the liveaddress object, and is not jQuery’s usual on(). When you bind a handler using jQuery’s on(), that handler gets fired after the ones previously bound. Since the plugin binds to its own events first and each handler chains to the next event, your own handler won’t be fired until the whole process is already complete.

To remedy, the custom on() function provided by jQuery.liveaddress will un-root the previous handlers, lay yours down, then plant the other handlers on top of it. This means yours is fired first. As you can see above, to continue the validation process, simply invoke the previous handler which is passed in as an argument. If you want the last word, just don’t call the previous handler.

6 address fields 1 address field

A quick aside before we wrap up. This is for the designers.

As has been said, street addresses are complicated. They require anywhere from 2 to 6 form fields, they’re frequently in a different order, everyone fills them out differently, and there are often mistakes during entry. Yes, verifying the input is important, but I’m not here to promote that. Instead, have you considered combining all the fields into a single one?

Users are more comfortable typing an address in a natural or intuitive format, as if they were writing it on an envelope. This tends to reduce input errors and makes for a pleasant experience.

While there are caveats with parsing address strings, it’s still a considerable improvement to your visitor’s experience. In this way, users can enter a freeform address and you can store the individual components if necessary.

Conclusion

We’ve looked at a couple different ways to make Javascript not like a high-maintenance girlfriend. Combined with semantic markup, scripts can be easier to use, smarter, and more intuitive. Ideally, they broadcast their actions by raising events, so that other code can know what’s going on and hook into them. The more automated your script is, the more robust it must be in hostile environments, like shopping cart checkout pages, or pages with highly dynamic content and features. Autonomous scripts adapt to their circumstances when possible, and fail gracefully if they can’t.

Women & Tech

We will ask a group of clever women out for coffees to pick their brains and share our conversations. We're not endorsing the obvious; we want to get under the surface of what it's like to be a woman working in tech.

By a cracking team.

CSS-Tricks Chronicle VIII

I catch a plane a week from tomorrow for Honolulu, Hawaii (first time!) where I'll be doing a couple of events. A half-day workshop and a talk (both about workflow) at InControl then another talk at CSS Dev Conf. Lots of prep to do this week.


The whole CodePen team is working super hard lately for a major release. Our biggest yet. Can't share a date yet but it won't be too much longer.


There was no link anywhere on the site (other than buried in blog posts) for the Store. I updated the footer to do a big of a callout for it until I can decide on a better permanent place for it.

That photo is of Sara Cope. She and my friend Camden Sabat took some sweet Merch pics for me. Flickr set:


Someone called me out on a really old crappy WordPress-related article on this site. I was thinking of just taking it down because it really was pretty crappy. But instead, I updated each section of it and refuted my own dumb recommendations.


For the first time, I created an RSS feed for the Gallery. It just outputs titles, full size images, descriptions, and direct links when I have them. Normally I'd FeedBurner a feed like this to save bandwidth and give me metrics on it. But FeedBurner's future seems very up in the air. I think I'll just directly host it for now and see how it goes.

The RSS feed for Snippets (this one is older, thus IS on FeedBurner) was broken. Really dumb little thing about the XML header being output one line down instead of as the first line of the file. RSS XML is some finicky stuff. That's fixed now and it barfed up a backlog of snippets onto Twitter.


Fox level subscribers have until December 5th to download videos from The Lodge. I originally wanted to offer video downloads to any Lodge subscriber, but costs are too high. Bear level subscribers will have access to all downloads of everything. Fox level subscribers have access to all videos, you'll just need to watch them directly on the site.


I get to be part of The Pastry Box Project next year.


Mixture is definitely worth keeping an eye on, folks. Especially for those folks who really have gotten into fancied local development (e.g. static site generators, CodeKit, running local servers, etc). It's on Windows too...


Estelle Weyl interviewed me for the Webstock Blog. I'll be at Webstock in Feburary. I'm going to interview Estelle right back and post it on this blog.


I'm on the second video on this The Next Web post that was shot immediately after I spoke at FOWD New York. There is a weird ad first, but the video kicks in after that.

ShopTalk Episode #43

This week Dave and I were joined by the fellas from the Bizcraft show, Gene Crawford and Carl Smith. #CROSSOVER. We talk about working remotely, client overages, local vs. international SEO, learning as it relates to design, and much more.

Thanks much to InControl 2013 (use SHOPTALKSHOW for $100 off) and Lynda.com (use that link for a free week) for sponsoring.

Responsive Menu Concepts

The following is a guest post by Tim Pietrusky. I know Tim from his prolific work on CodePen and from being a helpful community member there. He wrote to me with this guest post about responsive menus which I'm more than happy to share with you below. Not only is it a timely concept, but one of the concepts improves upon a clever CSS trick we've covered here in the past.

When it comes to responsive design we are faced with various techniques on how to best handle altering our navigation menus for small screens. The resources seem endless. That’s why I’m going to show you four main concepts and discuss the advantages and disadvantages of all of them.

Three of them are made with pure CSS and one uses a single line of JavaScript.

Before We Start

In the code presented in this article, I don’t use any vendor-prefixes to keep the CSS easier to see and understand. The more complex CSS examples use SCSS. Each example is hosted on CodePen where you can see the compiled CSS if you wish.

All menu concepts in this article are based on this simple HTML structure which I call basic menu. The role attribute is used to specify the particular concept (full-horizontal, select, custom-dropdown and off-canvas).

<nav role="">
  <ul>
    <li><a href="#">Stream</a></li>
    <li><a href="#">Lab</a></li>
    <li><a href="#">Projects</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>​

To address small screens I use the same media query on all concepts.

@media screen and (max-width: 44em) {

}

1. Full Horizontal

This is the most simple approach because you just need to make the list elements full width on small screens.

<nav role="full-horizontal">
  <ul>
    <li><a href="#">Stream</a></li>
    <li><a href="#">Lab</a></li>
    <li><a href="#">Projects</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>​
@media screen and (max-width: 44em) {
  nav[role="full-horizontal"] {
    ul > li {
      width: 100%;
    }
  }
}

This is what it looks like on a small screen with a custom style.

full-horz

Advantages

  • No JavaScript
  • No extra HTML
  • Simple CSS

Disadvantages

  • Reserves too much screen-space

Demo

On CodePen:

2. Select

This concept hides the basic menu on small screens and shows a select menu instead.

To achieve this we need to extend our basic markup and add a select. To get the select working we also add some JavaScript which alters window.location.href when the onchange event on the select occurs.

<nav role="select">
  <!-- basic menu goes here -->
  
  <select onchange="if (this.value) window.location.href = this.value;">
    <option value="#">Stream</option>
    <option value="#">Lab</option>
    <option value="#">Projects</option>
    <option value="#">About</option>
    <option value="#">Contact</option>
  </select>
</nav>​

We hide the select on big screens.

nav[role="select"] {
  > select {
    display:none;  
  }
}

On small screens, we hide the basic menu and show the select. To help the user recognize that this is a menu we’re also adding a pseudo-element with the text “Menu”.

@media screen and (max-width: 44em) {
  nav[role="select"] {
    ul {
      display: none;
    }

    select {
      display: block;
      width: 100%;
    }

    &:after {
      position: absolute;
      content: "Menu";
      right: 0;
      bottom: -1em;
    }
  }
}

This is what it looks like on a small screen with a custom style.

num-2

Advantages

  • Doesn’t need much space
  • Uses native controls

Disadvantages

  • Needs JavaScript
  • Duplicate content
  • Select is not styleable in every browser

Demo

On CodePen:

3. Custom Dropdown

This concept hides the basic menu on small screens and shows an input & label (to use the Checkbox Hack) instead. When the user clicks on the label, the basic menu is shown underneath.

<nav role="custom-dropdown">
    <!-- Advanced Checkbox Hack (see description below) -->
    
    <!-- basic menu goes here -->
</nav>​

Problem with the Checkbox Hack

There are two problems with the default Checkbox Hack:

  1. Doesn’t work on mobile Safari (iOS < 6.0). It’s not possible to click the label on iOS < 6.0 to toggle the input due to a bug. The only solution is to add an empty onclick to the label.
  2. Doesn’t work on the default Android browser (Android <= 4.1.2). Once upon a time there was a WebKit Adjacent/General Sibling & Pseudo Class Bug which prevented the use of pseudo-classes combined with adjacent (+) or general (~) sibling combinators.
h1 ~ p { color: black; }
h1:hover ~ p { color: red; }

This has no effect because the checkbox hack uses the pseudo-class :checked combined with the general sibling. And since this was fixed in WebKit 535.1 (Chrome 13) and the actual WebKit on Android 4.1.2 is 534.30, the normal checkbox hack doesn’t work on any Android device to date.

The best solution is to add a WebKit-only fake animation on the body element.

All stuff combined creates the Advanced Checkbox Hack:

<!-- Fix for iOS -->
<input type="checkbox" id="menu">
<label for="menu" onclick></label>
/* Fix for Android */
body { 
  -webkit-animation: bugfix infinite 1s; 
}
@-webkit-keyframes bugfix { 
  from { padding: 0; } 
  to { padding: 0; } 
}

/* default checkbox */
input[type=checkbox] {
  position: absolute;
  top: -9999px;
  left: -9999px;
}

label { 
  cursor: pointer;
  user-select: none;
}

Reference: Advanced Checkbox Hack

For large screens, we hide the label:

nav[role="custom-dropdown"] {
  label {
    display: none;
  }
}

For small screens, we hide the basic menu and show the label. To help the user recognize that this is a menu we’re also adding a pseudo-element with the text “≡” (converted to “\2261” to use it as content on the pseudo-element) to the label. When the user clicks on the input, the basic menu gets shown and the list elements are expanded to full width.

@media screen and (max-width: 44em) {
  nav[role="custom-dropdown"] {
    ul {
      display: none;
      height: 100%;
    }

    label {
      position: relative;
      display: block;
      width: 100%;
    }

    label:after {
        position: absolute;
        content: "\2261";
    }
    
    input:checked ~ ul {
      display: block;
    
      > li {
        width: 100%;
      }        
    }
  }
}

This is what the menu looks like on a small screen with a custom style.

closed

Closed
open

Open

Advantages

  • Doesn’t need much space when closed
  • Custom styling
  • No JavaScript

Disadvantages

  • Bad semantics (input / label)
  • Extra HTML

Demo

On CodePen:

4. Off Canvas

This concept hides the basic menu on small screens and shows a HTML input & label (to use the Advanced Checkbox Hack, see 3. Custom Dropdown for more infos) instead. When the user clicks on the label, the basic menu flies in from the left and the content moves to the right – the screen gets divided: menu ~80 % and content ~20 % (depends on resolution and css units).

<input type="checkbox" id="menu">
<label for="menu" onclick></label>

<!-- basic menu goes here -->

<div class="content">
  <!-- content goes here -->
</div>

On large screens, we hide the label.

label {
  position: absolute;
  left: 0;
  display: none;
}

On small screens, we hide the basic menu outside the viewport and show the label / input. To hide the menu we specify a width ($menu_width) and add a negative position to it. To help the user recognize that this is a menu we’re also adding a pseudo-element with the text “≡” (converted to “\2261” to use it as content on the pseudo-element) to the label.
When the user clicks on the input, the basic menu flies in from the left and the content moves to the right.

@media screen and (max-width: 44em) {
  $menu_width: 20em;

  body {
    overflow-x: hidden;
  }
    
  nav[role="off-canvas"] {
    position: absolute;
    left: -$menu_width;
    width: $menu_width;
    
    ul > li {
      width: 100%;
    }
  }

  label {
    display: block;
  }

  label:after {
    position: absolute;
    content: "\2261";
  }

  input:checked ~ nav[role="off-canvas"] {
    left: 0;
  }

  input:checked ~ .content {
    margin-left: $menu_width + .5em;
    margin-right: -($menu_width + .5em);
  }
}​

This is what the menu looks like on a small screen with a custom style.

offcanvas-closed

Closed
offcanvas-open

Open

Advantages

  • Doesn’t need much space when closed
  • Custom styling
  • No JavaScript
  • Convention from Facebook / Google+ app

Disadvantages

  • Bad semantics (input / label)
  • Extra HTML
  • Absolute position to the body = Feels like fixed position

Demo

On CodePen:

Does it Work on IE?

All of the techniques used above have one goal: Create responsive menus for modern browsers! And because there is no IE 8 or lower on any mobile device we don’t need to worry about it.

How to Use the Webshims Polyfill

The following is a guest post by Daniel Herken. Daniel is the author of the upcoming book The Cross Browser Handbook. He emailed me recently to share that as well as to offer to write a guest post. He was excited about Webshims Lib - kind of an "everything" polyfill. The following is that guest post, introducing that library and it's basic use.

In this post I'll be talking about the HTML5 and CSS3 feature polyfill library called Webshims Lib and how to use it correctly.

Polyfill?

In web development, we call scripts that emulate parts of the HTML5 or CSS3 specification "polyfills". A polyfill can be nearly anything - a JavaScript library that adds support for CSS3 selectors to old versions Internet Explorer (i.e. Selectivizr) or a high end Flash based solution to enable the <audio> and <video> tag all the way back to IE 6 (i.e. html5media).

Introducing Webshims

The Webshims Lib is one of the most complete polyfills out there. It is based on jQuery and Modernizr. Including this one script will enable many features across the whole range of desktop browsers.

Webshims enables HTML5 and CSS3 features like semantic tags, canvas, web storage, geolocation, forms and multimedia. Reading through this big list, the first thing that might come to mind is how huge this library must be. Meaning a huge download size and long script execution time. But here is the kicker, Webshims will automatically detect which features the users browser supports and it only loads what is necessary to simulate everything else. This way it will not slow down users who already run a modern browser like Firefox or Chrome. You can even reduce the amount of features to load if you don’t need everything.

How to Use Webshims

To use the webshims lib you need to include the dependencies jQuery and Modernizr alongside Webshims Lib.

<script src="scripts/jquery-1.8.2.min.js"></script>
<script src="scripts/modernizr-custom.js"></script>
<script src="scripts/webshim/polyfiller.js"></script>

Now you need to initialize Webshims and, if needed, tell it which features you want to use.

<script>
    // Polyfill all unsupported features
    $.webshims.polyfill();	
</script>
<script>
    // Polyfill only form and canvas features
    $.webshims.polyfill('forms canvas');	
</script>

And that's it! Webshims will automatically detect and polyfill missing features depending on the user's browser. If you are curious the full feature list is:

  • json-storage
  • es5
  • geolocation
  • canvas
  • forms
  • forms-ext
  • mediaelement
  • track
  • details

Example

Let’s do an example using the <video> tag. First let's create the basic page without Webshims or any other polyfill.

<!DOCTYPE html>
<html>
<head>
  <title>Video native</title>
</head>
<body>
  <video width="480" height="360" controls="controls">
    <source src="Video.mp4" type="video/mp4">
    <source src="Video.webm" type="video/webm">	
  </video>
</body>
</html>

Modern browsers will display this video correctly, but Internet Explorer 6, 7 or 8 will not.
Now we change the example to embed the Webshims Lib. You can see that it's not necessary to edit anything else.

<!DOCTYPE html>
<html>
<head>
  <title>Video including polyfill</title>
  <script src="scripts/jquery-1.8.2.min.js"></script>
  <script src="scripts/modernizr-custom.js"></script>
  <script src="scripts/webshim/polyfiller.js"></script>
  <script>
    $.webshims.polyfill('mediaelement');
  </script>
</head>
<body>
  <video width="480" height="360" controls="controls">
    <source src="Video.mp4" type="video/mp4">
    <source src="Video.webm" type="video/webm">	
  </video>
</body>
</html>

The modern browser will display its native <video> tag player but now this functionality is also available in Internet Explorer 6+. You can try the demo here.

Conclusion

As the example has shown, it's really simple to use the Webshims Lib. There is no need to alter your code and it does not slow down users which use a modern browser. It enables everyone to enjoy all features your page provides. Head over to the Webshims homepage for the download, documentation and more demos.

Stairway Navigation (A jQuery Plugin?)

On a whim the other day I thought I'd build out an idea for navigation I had. It's nothing but a visual effect in which the hovered (or active) navigation item becomes the tallest "stair" and other items before and after it step down. It's simple, but it's not something you see very often. Probably for one major reason: you can't select "previous" elements in CSS.

(more…)

Ratchet

From the Twitter Bootstrap clan:

Prototype iPhone apps with simple HTML, CSS and JS components.

I wonder if they can make a business out projects like these.

Why Ems?

I've long sized text only in px. Even when it was patently uncool to do so - the days in which smart people cared about the fact that text set in px couldn't be resized in IE 6-8. I've switched over to using ems now. I haven't moved every single project over yet, but my mind has switched. Why? I finally found some compelling reasons that I now grok.

(more…)

Off Canvas Menu with CSS :target

"Off Canvas" patterns are different ways to approach layout where content on the web isn't just laid out in a vertical column. For instance, navigation could be positioned hidden off the left edge of the "canvas" (visible browser window) and slid in on demand. Anthony Colangelo created jPanelMenu to do just that. Hakim El Hattab's Meny is fancier but similar in what it accomplishes.

They both use JavaScript. I thought it would be fun to try and recreate Anthony's jPanelMenu using only CSS. It's do-able - with several advantages and disadvantages.

(more…)

<picture> Demos

If you've ever thought "Meh, what is <picture> actually going to help with?" - here is a page of demos for you to see.

Inspector Web and the Mystery of the Shadow DOM

A video from JSConf EU 2012 in which Angelina Fabbro teaches us about the brand new shadow DOM, which is shipping now in Chrome Canary under a flag. Essentially, shadow DOM is a way for us to build modules (little sub-documents) inside a single element that are protected from the parent document. This will help semantics, make CSS easier, make more robust re-usable elements, and more. I think this will be big in years to come.

The Facebook Loading Animation in CSS

The following is a guest post by Fabrice Weinberg. I know of Fabrice through his excellent work on CodePen. He draws inspiration from seemingly anywhere and recreates things meticulously through CSS. He sent me this tutorial which walks through his techniques for recreating one of his most popular Pens, which I'm more than happy to publish! I learned a few tricks in here.

Hey everyone! CSS3 is just plain awesome. The development is fast and the possibilities are endless. Today I want to show you how to make an awesome animation using multiple background images and linear gradients in CSS. We will build the Facebook loading animation using just a single HTML element.

For simplicity, you will not see any vendor prefixes in the CSS. Before we dive into creating the Facebook loading animation I will explain the basic techniques.

background-image

We all know the background-image property. You give it a url() pointing to an external image file (or a data URI) to make that image appear as the background of any HTML element.

Now it's possible to use a linear-gradient or radial-gradient as a background image. This opens up a whole new world of backgrounds that can be generated using just code. I am not going to explain the syntax (you can get that from those past two links), but I will give you some tips that will help you create awesome patterns and nearly any shape.

The trick that comes in handy is the ability to add more then one background image at a time.

div {
  background-image: 
    background-image
    [, background-image]* /* optional additional backgrounds */
}

See MDN: background-image for more information. To see what others have created using these properties have a look at this Gallery.

How to draw with linear-gradient

Lets get you started with some basic linear-gradient to get to know its syntax.

background-image: linear-gradient(90deg, blue, red);

To see the syntax and all its possibilities so you should look at the MDN: linear-gradient.

This will result in this:

You see a nice gradient between blue and red. But to always draw a gradient would be quite boring. Woudn't it be awesome to generate patterns like this:

sharpcolor

So lets make it! Look at the pattern above. You see four different colors, each color needs 1/4th of the width. Expressed as percentage, we get 25% (100%/4). For such simple patterns I recommend you to use percentages so the pattern will dynamically adapt to the size of the element.

To translate the image pattern to linear-gradient we will start with the left-most color. Blue, in this case.

background-image: linear-gradient(90deg, blue 25%);

This will result in a blank background image. To get linear-gradient to work we have to add at least two colors. Let's add the next color, green:

background-image: linear-gradient(90deg, blue 25%, green 25%);

This first color value is special because "blue 25%" doesn't mean that the blue color starts at 25%. In this case "blue 25%" means that the color blue is spread to 25%.

What we get is this:

Exactly what we want, a sharp separation of blue and green. But as you may notice we have to write 25% for both the blue and the green color. During development this is quite annoying because you have to change both values to maintain the sharp separation.

While playing with linear-gradients I found a nice little way to make this a bit easier:

background-image: linear-gradient(90deg, blue 25%, green 0);

Now we just set the position of the color green to "0". What we achieve with this is that green will always start at the exact same position as the previous color, in this case blue. The result is the same as before but now you only have to change one value to change the size of the blue rectangle. Adding the remaining colors becomes quite easy because we know how to create a sharp color cut now.

background-image: linear-gradient(90deg, blue 25%, green 0, green 50%, red 0, red 75%, yellow 0);

You can see now why the first color value is special. For every other color we have to define it twice. Once for the start position and the other time to specify how far it will spread.

Result:

How can we make shapes?

To create some basic shapes with the background-image property we will start with this:

.squareandcircle{
  width: 40px;
  height: 30px; 
  background-image: linear-gradient(90deg, blue, blue),
                    radial-gradient(center, circle, green 10px, transparent 0);

  background-size: 15px 15px,
                   20px 20px;

  background-position: 0    0,
                       20px 10px;

  background-repeat:no-repeat;
}

squareandrect

We used multiple background images in combination with background-size and background-position to create a square and a circle.

So how does it work?

Starting with background-image

First we have to create the background images. For simplicity we use the most basic linear-gradient and the most basic radial-gradient.

Now further to the next property: background-size

The background-size property will set the size for each previously created background image in the same order as they were created.

So in our case the size of the linear-gradient is 15x15px. And for the radial-gradient it's 20x20px.

Position of each background: background-position

Know we have two images on of a square with a size of 15x15px and one of a circle which fits in a 20x20px square. But these images are on top of each other. To move them around we need background-position.

For background-position we have to define an offset for each background image relative to the upper left corner of the element.

Here the first image (the square) will be in the upper left corner and the circle will be 20px to the left and 20px down from that. Keep in mind that we move each image from the top left corner of the element.

background-repeat

The last thing unexplained bit is background-repeat which is pretty simple. We don't want our generated images to repeat in any direction so we set it once to no-repeat. If we only add one value to it this value will be used by all background images we create.

So how do we make animations with this?

It's quite easy. We create our shape with background images and then use the animation property to animate the whole thing by changing the background size and/or position.

Just a simple example before we do the Facebook loading animation. We start with some basic markup like this:

.square {
  width: 40px;
  height: 30px; 
  background-color: gray;
  background-image: linear-gradient(90deg, blue, blue);
  background-size: 15px 15px;
  background-position: 0 0;
  background-repeat: no-repeat;
}

Which looks like:

rect

Let's animate this in six steps, moving the square from the upper right corner than down to the bottom right corner and back to the bottom left corner.

Basic math tells us that we need 16.6% of time for each frame (100%/6 ~ 16.6%) in our keyframe animation. On every frame we modify the background position to create the illusion our square would move.

We will end up with quite a bit of CSS:

@keyframes move {
    16.6% {
      background-position: 0 0;
    }
    33.2% {  
      background-position: 12.5px 0;
    }
    49.8% {
      background-position: 25px 0;
    }
    66.4% {
      background-position: 25px 15px;        
    }
    83% {
      background-position: 12.5px 15px;      
    }
    99% { 
      background-position: 0 15px;               
    }
}

To see the animation we have to add the animation to our square element like this:

.square{
  width: 40px;
  height: 30px; 
  background-color: gray;
  background-image: linear-gradient(90deg, blue, blue);
  background-size: 15px 15px;
  background-position: 0 0;
  background-repeat: no-repeat;

  animation: move 1s steps(1, start) infinite;
}

The steps function is awesome. You can read more about it here.

See it in action:


The animation you see embedded here may be stopped, to see it in action visit the Pen.

Try to play with it to understand all the possibilities you have. In fact what we get here is an open canvas on which we can draw nearly every shape and animate it in any way.

The Facebook loading animation.

Now its time to make some more complicated animation using these techniques.

Take a look at the original gif of the Facebook loading animation.

orig-loading

In the GIF, we see vertical stripes going from left to right while shrinking and losing color.

How can we archive this in CSS? Let me first say this: I will not explain how to create every single on of these stripes. I will only explain to create the first one, from there on it shouldn't be to hard to understand the rest of it.

Let's zoom in a bit on the first stripe:

zoomedstripe

The first shape is 4px wide and 16px long. There is a 1px border around a 3x16px solid colored rectangle. For simplicity the border we will create will also have a solid color. To create such a shape we have to generate two background images using linear-gradient. One for the left border the solid inner rectangle and the right border and one for the upper and lower border. We start with the linear-gradient for the left border the solid inner rectangle and the right border.

#facebook {
  width: 16px;
  height: 16px;    

  background-image: linear-gradient(90deg, #8490c6 1px, #aeb5da 0, #aeb5da 3px, #8490c6 3px);  
  background-size: 4px 16px;
  background-position: 0 0;

  /* Just to make it a little bigger*/
  zoom: 5; 
}

The result:

cssstripe1

To finish this shape we than have to add another background image to create the upper and lower border:

#facebook {
  width: 16px;
  height: 16px;    
  background-image:
            linear-gradient(0deg, #8490c6 1px, transparent 0, transparent 15px, #8490c6 15px),
            linear-gradient(90deg, #8490c6 1px, #aeb5da 0, #aeb5da 3px, #8490c6 3px);      

  background-size: 4px 16px,
                   4px 16px;

  background-position: 0 0,
                       0 0;

  background-repeat: no-repeat;

  /* Just to make it a little bigger*/
  zoom:5;
}

It's not necessary to repeat the values of background-size and background-position because they are the same, but for further development its better to write them.

And now we have this:

cssstripe2

We need to make six of these stripes in slightly less color and size. How to make these should be clear by now.

#loader {
    zoom: 1; /* Increase this for a bigger symbol*/
    width: 16px;
    height: 16px;

    background: linear-gradient(0deg, #f4f5fa 1px, transparent 0, transparent 8px, #f4f5fa 8px),   /* 6  */
                linear-gradient(90deg, #f4f5fa 1px, #f6f9fb 0, #f6f9fb 3px, #f4f5fa 3px),

                linear-gradient(0deg, #ececf5 1px, transparent 0, transparent 8px, #ececf5 8px),   /* 5  */
                linear-gradient(90deg, #ececf5 1px, #f2f3f9 0, #f2f3f9 3px, #ececf5 3px),

                linear-gradient(0deg, #e7eaf4 1px, transparent 0, transparent 8px, #e7eaf4 8px),   /* 4  */
                linear-gradient(90deg, #e7eaf4 1px, #eef1f8 0, #eef1f8 3px, #e7eaf4 3px),

                linear-gradient(0deg, #b9bedd 1px, transparent 0, transparent 10px, #b9bedd 10px), /* 3  */
                linear-gradient(90deg, #b9bedd 1px, #d0d5e8 0, #d0d5e8 3px, #b9bedd 3px),

                linear-gradient(0deg, #9fa6d2 1px, transparent 0, transparent 15px, #9fa6d2 15px), /* 2  */
                linear-gradient(90deg, #9fa6d2 1px, #c0c5e1 0, #c0c5e1 3px, #9fa6d2 3px),

                linear-gradient(0deg, #8490c6 1px, transparent 0, transparent 15px, #8490c6 15px), /* 1  */
                 linear-gradient(90deg, #8490c6 1px, #aeb5da 0, #aeb5da 3px, #8490c6 3px); 
  
    background-repeat: no-repeat;

    background-size: 
               4px 9px,   /* 6 */
               4px 9px,

               4px 9px,   /* 5 */
               4px 9px,

               4px 9px,   /* 4 */
               4px 9px,

               4px 11px,  /* 3 */
               4px 11px,

               4px 16px,  /* 2 */
               4px 16px,

               4px 16px,  /* 1 */
               4px 16px;

  background-position-x: -4px; /* Hide All */
  background-position-y: 3px, 3px, 3px, 3px, 3px, 3px, 2px, 2px, 0, 0, 0, 0;
}

All six stripes are hidden because they are moved -4px on the x-axis.

Let's think of the original gif again. It contains eight steps moving each stripe further and further to the left. So what we need to make is an animation containing eight steps while each step needs 12.5% of the time (100%/8). On every step, each stripe will move 6px to the right. If the position of the stripe on the x-axis is greater than 16px, it is off the canvas and we can place it at -4px to hide it.

You may have noticed the use of background-position-y. This saves us quite a lot of code because we only have to move the stripes on the x-axis we never have to change the y-coordinates, therefore we only have to write the coordinates for the position on the x-axis in our keyframe animation.

@keyframes wait {
  12.5% {
    background-position-x: -4px,-4px,   -4px, -4px,  -4px,-4px,
                           -4px,-4px,   -4px, -4px,   0,   0;
  }
  25% {
    background-position-x: -4px, -4px,  -4px, -4px,  -4px,-4px,
                           -4px, -4px,   0,    0,     6px, 6px;
  }
  37.5% {
    background-position-x: -4px, -4px,  -4px, -4px,  -4px, -4px,
                            0,    0,     6px,  6px,  12px, 12px;
  }
  50%{
    background-position-x: -4px, -4px,  -4px, -4px,   0,    0,
                            6px,  6px,  12px, 12px,  -4px, -4px;
  }
  62.5% {
    background-position-x: -4px, -4px,   0,    0,     6px,  6px,
                           12px, 12px,  -4px, -4px,  -4px, -4px;
  }
  75% {
    background-position-x:  0,    0,     6px,  6px,  12px, 12px,
                           -4px, -4px,  -4px, -4px,  -4px, -4px;
  }
  87.5%{
    background-position-x:  6px,  6px,  12px, 12px,  -4px, -4px,
                           -4px, -4px,  -4px, -4px,  -4px, -4px;
  }
  100% {
    background-position-x: 12px, 12px,  -4px, -4px,  -4px, -4px,
                           -4px, -4px,  -4px, -4px,  -4px, -4px;
  }
}

Because every stripe is made of two background images we have to change twelve background positions (two for every stripe) on every step.

And finally we can add the animation property to our element:

animation: wait .80s steps(1, start) infinite;

Here is a live demo on Codepen:

Again, the animation you see embedded here may be stopped, to see it in action visit the Pen.

Thanks for reading. I hope you enjoyed it. Thank you!

New Poll: Version Control Usage

New poll up in the sidebar. The question is about version control and asking you to pick the situation that best describes you. I just think it would be interesting to get a sense of what CSS-Tricks readers usage levels are like when it comes to version control.

This will be agnostic in which specific version control technology you use.

Template and Notes from my Deseret Digital Workshop

Last week I was in Salt Lake City to do a workshop for Deseret Digital. Like my last workshop, we used the time to literally build a website from scratch. I think this live coding style is a decent way to do workshops because it is what real life web development is like. Nothing theoretical, all real working code. The following will be basic notes on what we covered and the template we built. While this certainly isn't as good of a learning experience as being there in person is, I figured it's still a useful thing to share with everyone.

(more…)

Dropdown Default Styling

There has always been big differences across how different browsers handle form styling. There probably always will be - because UI design choices aren't described in the specs. Browser makers perhaps view this as one of the ways they can differentiate the user experience a bit. Select (dropdown) menus are one that is particularly weird.

(more…)

Emmet

The next generation of Zen Coding. Essentially it gives you shortcuts you can type that expand into full HTML or CSS. Like nav>a*8 will expand into a <nav> tag with eight links inside it with empty hrefs. Or, try div.module*4>p*2>lorem and press tab. There are also a bunch of editor navigation shortcuts like "move to the next edit point."

Display Form <progress>

Imagine you have a form with 10 required fields on it. That's a bit larger than your average form on the internet and a good bit of work for a user. You might lose some users along the way, which is never a good thing. Perhaps to encourage finishing the form, you let them know how close to completion they are, and display motivational messages along the way.

(more…)

Web Developer Economics: Hardware Costs

This will be the last part of this mini series about Web Developer Economics before we wrap it up and look at the numbers together. We already looked at:

Now we need to consider the hardware itself. I think this one is pretty simple: you need a computer.

I think you need either a laptop or a desktop. Maybe someday in the future the tools will be there to build websites on tablets or other futuristic devices, but I don't think we're there yet. Laptops these days are so powerful that it's hard to imagine going any other way. You can plug in an external monitor to get a desktop experience, or take them with you. Unless you're like a school computer lab or office where nobody works from home ever, it's hard to imagine going with anything other than a laptop.

I know this site is pretty Mac-focused. That's what I like and use. But I promise you: I really don't care what you use. I'm way more concerned that you are writing maintainable CSS that I am about what kind of computer you are using. If you're happy on your PC running Ubutunu (or whatever) and you're making good websites, you're A-OK in my book.

That said, if you're buying a computer right now to be a part of your web design/development life/business and you ask me what I think you should buy, you should buy a ...

MacBook Pro (Retina, 15", $2,199)

As I've written, this is the best computer I've ever owned. It's worked extremely well for me. I feel very productive on it. It runs all the best software for web development (that I know of). This retina display screen looks great, but as a developer allows us to be ahead of the curve in designing for devices of this pixel density (technically you could write code and build graphics to support it without owning one, but you need to have one to care).

Alternatives: Any other laptop or desktop computer that works for you.

Microsoft Natural Ergonomic Keyboard 4000 ($49.95)

I use this and like it when I'm at home and at my desk. I have RSI (repetitive strain injury) problems when I'm away from it (using laptop keyboard only) for too long.

Alternatives: Use built-in laptop keyboard / some other external keyboard

Kensington Expert Mouse Trackball ($99)

Also helps my RSI but also I think is just a very efficient mouse in that you never need to pick it up or do awkward motions with it. I miss the trackpad when I'm in desktop mode though, with its gestures and wicked fast scrolling.

Alternatives: Use built-in trackpad / some other external mouse

Brother HL-2280DW ($199)

This is a very nice and efficient printer. Wireless, laser printer (cheap ink), and does stuff like automatically print both sides of documents to conserve paper.

Alternatives: Go totally paperless / some other printer


None of these accessories are vital to my job but I consider them business expenses. I bet most of us have a few accessories like this. They might not be these, but you have some, so we'll include these in the final calculations to keep it even.

Office space might be considered a "hardware" expense of sorts. I'm not going to consider that here because it's optional. I don't have an office. If you work somewhere that does, that's factored into the cost of running a business there either by you or the owners of that business.

Service Cost
MacBook Pro $2,199
External Keyboard $49.99
External Mouse $99.99
Printer $199.99
Total $2,548.97

With these numbers and the ones gathered from other posts, I think a wrapup is in order looking at them all together and see what we see. Look for that soon.

ShopTalk Episode 40

Dave and I talk with Laura Kalbag, a freelance designer from the UK with a fresh perspective on just about everything. We talk about process, selling responsive web design, software choices, and more.

Thanks very much to PeepCode and InControl for sponsoring this week.

CSS-Tricks Chronicle VII

I don't think I mentioned this here yet, so: I redesigned my personal site. It's nothing mindblowing, it's just some simple boxes with words in them. I'm happy to have shed my old site which was full of old junk. I'd be happy to have you read it, but the posts will be personal and rarely about web stuff or tech. I will be bringing comments back on it as soon as I can.

The most interesting fact about it: Other than one declaration of font-family, I used no typographic CSS at all. The user-agent stylesheet in browsers has a reasonable set of defaults for text elements and I just went with it.


I started using Divvy and it's been super helpful. It's just a tiny little menu bar app for Mac that allows you to position windows based on a grid you set up. I'm pretty messy with my open windows, and I'm often fiddling with them to get a useful arrangement. Usually, that's browser-on-the-left and sublime-on-the-right. Divvy allows me to get into that setup in just a few commands. It's the little things, right?


As I've written about, I absolutely love the idea of working in public. It's super cool that Daniel Mall and team will be doing it with the Reading is Fundamental website.


I was on the SassCast with Dale Sande recently.

Speaking of Sass, as I'm rewatching and writing notes for the last of the videos in The Lodge, it occurs to much how much Sass is in all those videos. If you're looking to dig into learning Sass and what it's like on real world projects, you could do worse than watching the videos there.


Speaking of The Lodge, I recently spoke with a member who lived in New Zealand. Apparently the internet is quite slow there, and it would take an incredibly long time to download all the videos. I agreed to send them little USB drives with the videos on them. If anyone else is in that position, let me know and I can do the same for you. I need to charge $150 for it though, as the drives of that size are a bit expensive and requires me doing some work.


I made this kinda neat "stairway" style navigation. It's probably a little obnoxious for general use but it could work in some contexts. I used to blog stuff like this after I built it, tutorial style. I should get back to that.


As I type I'm right in the middle of a big multi-leg trip. I was in New York for the first time for FOWD which went very well. I got to be the keynote on the first day! I loved Zoe Gillenwater's talk about future layout specs. Carl did a great job keynoting the second day. I sadly missed Darcy Clarke's talk but he does have some videos of us hanging out that should never make it to the internet.

I got to visit Vimeo's office while I was there thanks to Joe.


My travels this year are far from over. Next I'm headed to Baton Rouge to visit Richard, who I've been nerdfriends with since long before CSS-Tricks was even a thing.

Then I head to Salt Lake City for a day to give a workshop for Deseret Digital, who backed me on Kickstarter to the level of a personal workshop. Then back home for a few days before flying to Philly to do another one of those. Then Hawaii for the conferences there, then back to Wisconsin again for the holidays.

It has been and will be a lot of fun, but I'm sensing the travel burnout coming and I've purposely been very protective of 2013 - keeping it as absolutely free from commitment as possible. I'm at my best during long periods of simple home living.

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