Article Archives

SOLID CSS

Miller Medeiros:

SOLID is an acronym for five basic principles of object-oriented programming and design that when applied together can make systems easier to maintain and to extend over time.

Crashing Mobile Webkit

One of the big heart sinking bummers when the new design launched was that the announcement blog post would cause Safari on some mobile devices to crash. It would crash my iPhone 4S, I heard reports of crashing other Android devices, but it wouldn't crash my iPad 2. Debugging on mobile is already kinda hard but debugging a page that crashes the entire application is extra hard. (more…)

Design v10

It's been just about a year since the v9 design. You know what that means! Redesign time! This is, most definitely, the biggest overhaul yet. Not that you won't recognize it. There is a fresh coat of paint, but all the old stuff is there.

(more…)

Enquire.js – Media Query Callbacks in JavaScript

The following is a guest post Nick Williams. Nick emailed me about a new library he created to assist in working with responsive design. Specifically, he was implementing an idea he found here on CSS-Tricks but wanted to do so more intelligently by only running the script when needed. Thus the birth of this new mini library! There are some kind of similar ones out there, but this one is very small and works with native media queries. I'll let Nick tell you more about it...

Enquire.js is a JavaScript library I created for dealing with media queries in JavaScript.

"Whoa! Back it up! Media queries in JavaScript?! What kind of abomination is this?"

Whilst the premise may seem odd, it really is a handy addition to the responsive toolbox.

The Lowdown

Enquire.js is a lightweight, pure JavaScript library for handling media queries. It is less than 1kb when GZIP'd and minified, and has absolutely no dependencies. Yup, you read that right - no dependencies, not even jQuery! The most you will have to do is provide a matchMedia polyfill if you wish to support browsers without a native implementation.

Use Cases

  • Responsive Design
  • Mobile-first Design
  • Assist older browsers with media queries

Raison D'etre

So how and why did this come about? I think the easiest way to explain is through a simple scenario...

Imagine you've got an established website, currently fixed-width and targeted at large-screened devices. You've heard all the hubbub about this "responsive design" business and wish to get in on some of the action. So you dutifully start designing and planning how your website may work on small-screened devices. You've cut out all the chuff, cleared your floating sidebar and bumped up the size of your form elements. Great!

But what about that pesky menu? It's beefy, it's got multiple levels and relies on CSS hover effects to expose the deeper hierarchy - in other words, it ain't gonna work on a small-screened touch device!

So you do a little digging around on Google and stumble across a clever solution to convert a menu into a dropdown. High fives all round, your menu is now functional on mobile touch-based devices! But you've got this nagging sensation. You're not quite sure what it is, but something's still not quite right. Ah yes, that's it; you're running this code even for large screened devices, even though they have absolutely no need for it! You shed a little tear for the wasted CPU cycles, wishing that there was a way to selectively run this JavaScript.

A New Challenger Appears!

This is where enquire steps in to help out.

For now, we'll run with the converting a menu to a dropdown scenario, making the menu appear when the window is less than 960px. With enquire, it's as simple as this:

enquire.register("max-width: 960px", function() {
  // put Chris' code here to convert your menu to a dropdown
});

All this does is tell enquire to invoke the supplied function only if the given media query matches. And so, you save those precious CPU cycles for large-screened devices. OK, I realise that's a bit silly since mobile devices typically have lesser-powered CPUs compared to larger screened devices, but it works from the other direction also - the much-fabled mobile first approach!

Digging Deeper

At this point it's worth quickly running through the enquire API before we get into some meatier scenarios. The previous example showed the most simple use-case for enquire - supplying a function as the second parameter to be run when a media query matches. This will suffice in most scenarios, however enquire can do a lot more if you've got more demanding requirements. You can pass the register method an object as so:

enquire.register("screen and (max-width: 1000px)", {

  // REQUIRED
  // Triggered when the media query transitions
  // from *unmatched* to *matched*
  match : function() {},
  
  // OPTIONAL   
  // Triggered when the media query transitions 
  // from a *matched* to *unmatched*                        
  unmatch : function() {},    
                                
  // OPTIONAL
  // Triggered once immediately upon registration of handler
  setup : function() {},      
                                
  // OPTIONAL
  // Defaults to false
  // If true, defers execution of the setup function
  // until the first media query is matched (still just once)
  deferSetup : true           
});

This signature gives you full control and allows you to define exactly what you want to happen, and when you want it to happen. This only really becomes useful when you make a call to enquire's listen function (more on this shortly).

Examples

So let's get onto some examples that show the more advanced features in action.

Faux Media Queries In Legacy Browsers

Enquire.js can be used to fake some rudimentary media queries in older browsers. However, please don't use this approach as a replacement to genuine media queries in your CSS, just use it as a monkey patch for older browsers (jQuery used in this example):

$(function() {

  // cache body for speed
  var $body = $("body");

  // DRY up handler creation
  function handlerFactory(className) {
    return {
      match : function() {
        $body.addClass(className);
      },
      unmatch : function() {
        $body.removeClass(className);
      }
    };
  }

  // hook up our "media queries"
  enquire
    .register("screen and (max-width : 320px)", handlerFactory("lt-320"))
    .register("screen and (max-width : 640px)", handlerFactory("lt-640"))
    .listen();

});

Here we're using match and unmatch handlers to add or remove classes to the <body> element, which allows us to target styles at different sized screens. Notice we can chain calls to all of enquire's functions.

Of particular note here is the call to the listen function so that enquire will respond to browser resize and orientation change events (though of course in this example, orientation change events are unlikely in legacy browsers). For optimal performance, listen is throttled to only respond to one event in a given timeframe. By default this is 500ms, but you can specify your own throttle by passing as a parameter to listen:

// 10000 milliseconds = 10 seconds. Why not?!
enquire.listen(10000); 

Dogfooding

Let's walk through an example of a real world use of enquire, taken from the enquire.js project page (dogfooding FTW!). Here I wanted to make the page load as quick as possible by only loading the bare minimum amount of JavaScript by default, opting to load anything beyond that asynchronously, only when required. This is so that small-screened devices (and by proxy those more likely to be on a slow connection) get the speediest page load possible, and only large-screened devices have to deal with the extra resources.

In particular, this pattern is used to pull all code required to generate and render the "Jump To" sidebar of the project page. This example is slightly simplified as not to distract from the important concepts:

$(function() {

  $toc = $(".toc");

  enquire.register("screen and (min-width: 1310px)", [{

    deferSetup : true,

    setup : function () {

      // use Modernizr's yepnope to load 
      // additional scripts and manage callbacks
      Modernizr.load([ 
        {
          load: "js/jquery.toc.js",
          callback : function() {
            // code to generate "Jump To" list
            // and append to body
          }
        },  

        // load in the bootstrap plugins.
        // they hook themselves up via their data-API
        "js/vendor/bootstrap-scrollspy.js",
        "js/vendor/bootstrap-affix.js"
      ]);
    },

    match : function() {
      $toc.fadeIn();
    },

    unmatch : function() {
      $toc.hide();
    }

  }]).listen();   

});

Two new options have been introduced here - setup and deferSetup. setup is a function that gets called just once, which is great for getting all your expensive DOM manipulation out of the way up-front. By default, setup is invoked as soon as you register your query handler, regardless of whether the query has matched yet. However, if you supply the deferSetup flag we can postpone setup until the first time a query is matched.

In this case it obviously makes sense, as scripts only be loaded for large-screened devices. The match and unmatch function are then left to simply show and hide the "Jump To" list.

Other Examples

A few more scenarios which enquire would handle effortlessly:

  • Responsive images
    • Use data-* attributes and switch an image's src depending on which media query matches
  • Shuffle content around
    • Sometimes it's not as easy as just stacking items on small screens, you may want content to appear in a completely different order.
    • Again, I'd recommend a declarative approach with data-* attributes so you can pick out source elements and destination elements.

There's More...

Enquire.js still has more to offer! You can register multiple handlers per query, and also multiple queries, meaning you've got ultimate flexibility! To read more about this, please visit the enquire.js project page.

Download, Fork and Contribute!

For downloads and source code, visit the project on github. If you wish to contribute, please do so, I'd love other people's opinions, thoughts and ideas. Fork to your heart's content and make a pull request with any changes. If you encounter any issues, feel free to create an issue on github and I will duly fix the problem :)

Licence

The project is licenced under the MIT licence, so you're free to use it in any way you wish.

CSS :target for Off-Screen Designs

The following is a guest post by Matty Collins. Matty wrote to me to share a little demo he cooked up which recreates the experience of using the Message app on an iPhone. Perhaps more interesting than the recreation of that UI is that the technique is very simple, requires no JavaScript (the "Checkbox Hack", and tackles an often difficult question on small screens: how do we handle navigation? I asked Matty if he'd like to write a guest post and he obliged.

I recently saw a presentation by Ryan Seddon on things you can do with checkboxes. It got me thinking about a similar pseudo selector based on the URL, :target, and how it could be used for hiding and revealing elements for extra space (namely on smaller screens). I set myself the task of recreating the iOS Message app without using JavaScript by taking full advantage of awesome CSS3 selectors and transitions.

Simple Example

The following code examples show how we could hide a login box and navigation, exposing them when needed.

<header id="hd">
  <a href="/" class="logo">Company logo</a>
  <nav>
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">News</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </nav>
  <a href="#login">Log in</a>
  <div id="login">
    <fieldset>
      <label for="username">Username:</label>
      <input type="textbox" id="username">
      <label for="password">Password:</label>
      <input type="password" id="password">
      <input type="submit" value="login"/>
      <a href="/register">Sign up</a>
    </fieldset>
  </div>
</header>
<div id="bd">
  <section>
    <p>
      ... lorem ipsum content ...
    </p>
  </section>
  <a href="#auxNav">Internal navigation</a>
  <nav id="auxNav">
    <ul>
      <li><a href="#">First link</a></li>
      <li><a href="#">Second link</a></li>
      <li><a href="#">Another link</a></li>
    </ul>
  </nav>
</div>
body { 
  position: relative; 
  max-width: 960px; 
  margin: 0 auto; 
}

#login { 
  position: absolute;
  top: -200px;
  right: 0;
  -webkit-transition: top 0.3s ease-in-out;
  -moz-transition:    top 0.3s ease-in-out;
  -ms-transition:     top 0.3s ease-in-out;
  -o-transition:      top 0.3s ease-in-out;
  transition:         top 0.3s ease-in-out;
}

#bd { 
  position: relative;
  overflow: hidden;
}

#auxNav {
  position: relative;
  overflow: hidden;
  height: 60px; 
}

#auxNav ul {
  position: absolute;
  left: -100%;
  -webkit-transition: left 0.3s ease-in-out;
  -moz-transition:    left 0.3s ease-in-out;
  -ms-transition:     left 0.3s ease-in-out;
  -o-transition:      left 0.3s ease-in-out;
  transition:         left 0.3s ease-in-out;
}

/* The Magic Part */
#login:target { 
  top: 0;
}

#auxNav:target ul {
  left: 0;
}

By starting the navigation and login offscreen first, we can then reveal them on :target. Note how the anchor link's href attribute "#auxNav" matches the ID of the nav, "auxNav".

The auxNav shows that we don't need to hide the ID itself, but can hide any decendants of it.

The "App"

Each message ("screen") has an ID and is positioned off screen. When the anchor link is clicked, the hash link in the URL changes, the :target selector matches, and the appropriate screen shows.

I used the :checked selector to toggle the editing of a message. Each message in the list is an anchor to its full detail version. The tiny bit of code :target { left: 0; } is all that was needed to bring them into view.

A hidden "delete" button slides in when the edit button is selected. The button text is changed via content in the :before pseudo element, rather than creating another element to swap states. The "delete" message button simply hides the next message in the list when it is checked.

Each message was then shown upon the :target selector matching, sliding in from the left (there were difficulties with transitioning from the right). A more complex chaining of checkboxes was used to slide in checkboxes for each thread in the message (while slightly altering its dimensions) and exposing another checkbox at the bottom to confirm the deletion. Using the same method as before, the message was hidden via :checked + div { display: none; }

View demo

(Demo works on mobile but it's more of a desktop experience - making it fit a mobile screen would be trivially easy.)

Advantages

  • No JavaScript!
  • Only an anchor link, ID and a simple pseudo selector is needed to achieve this
  • Isn't completely reliant on markup order. Each object just needs an ID, or ID in the selector. Eg: #hd:target nav
  • Falls back to anchor when unsupported
  • Auto scrolls to element so fixed position isn't required

Disadvantages / Issues

  • Only seems to transition in and out when positioned off the left hand side, others only transition after leaving :target
  • Only one element can feature on the screen
  • Using a right offset completely confused Chrome, would falsely show the last ID as targeted

Conclusion

I'm always interested in what we can create with only markup and CSS. While this is a hack and may not be ideal for production use, at the very least it shows we don't have to compromise design or interactivity if the device/user is lacking JavaScript and can fall back to simply scrolling the desired element into view.

Related Links

Play Sound on Hover – Web Audio API Edition

I got an email from a Notary Sojac who saw my tutorial on playing a sound on hover. In that tutorial we had to resort to some fairly hackish behavior to get the sound to react nicely to our events. Notary Sojac had an update to make the existing code work better, but more importantly, was looking into the Web Audio API for doing stuff like this. I didn't even know that was a thing. Turns out it's not controlling HTML5 audio elements, it's deeper level access than that.

The following is a guest post by Notary Sojac explaining all that.

We're all impressed with the capabilities of HTML5 canvas. The idea of creating a standardized and logical way of performing 2d drawing operations opened the door to an amazing new world where one programmer could learn one language and develop amazing products that could be deployed to all relevant platforms! Think about how critical this is for a moment. Now think about who would want an amazing graphics application that has a buggy, glitchy sound system that only makes sounds moments after you clicked and sometimes forgets to make sounds all together? That's the kind of product you get (especially in mobile platforms) if you go the HTML5 <audio> element route. It's better in desktop browsers, but unfortunately will never be perfected due to reasons beyond the scope of this article. But as of now, for the desktop, there is still hope. And there is hope in the future for mobile applications as well. That hope is named...

Web Audio API

The web audio API is designed for high precision and low level access. You can literally write bits of data to the samples. I'm not 100% sure what a sample is, but I think it has to do with air pressure against a microphone (aka, the microphone's driver position) at a single moment in time. That's pretty low level if you ask me. In Google Chrome, all audio functions are handled by a separate thread to ensure non-wonkyness.

On August 21st, Mozilla began making public the fact that they're dropping their original, pioneering "Audio Data API" and are beginning to implement Google's "Web Audio API" in their browser. But that means, at the time of this writing, you'll need to use a fallback for Firefox.

You can hear a great deal of good information from this Google I/O talk by Chris Wilson:

How To Use It

Unfortunately you need to use a lot more JavaScript with the Web Audio API than you do with plain old HTML5 audio elements, but often times the precision of the Web Audio API is imperative.

First we need to load the sound, which can be done with a function like this:

// you'll put the PCM audio in here
var audioBuffer = null;  
var context = new webkitAudioContext();

function loadDogSound(url, variableToBufferSound) {
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.responseType = 'arraybuffer';

  // Decode asynchronously
  request.onload = function() {
    context.decodeAudioData(request.response, function(buffer) {
      variableToBufferSoundIn = buffer;
    }, onError);
  }
  request.send();
}

Then we play the buffer, with a function like this:

function playSound(buffer) {

  // creates a sound source
  var source = context.createBufferSource();

  // tell the source which sound to play
  source.buffer = buffer;          

  // connect the source to the context's destination (the speakers)           
  source.connect(context.destination);       
  
  // play the source now
  source.noteOn(0);                          
}

That's a heck of a lot more code than we need as designers, just trying to play simple mouseover sound effects. Luckily, I snapped together a little JavaScript framework for using the Web Audio API.

With this new API, all one needs to do is:

  1. Create an AudioContext
  2. Load a sound into that AudioContext
  3. Play the sound

All of these steps are one liners! Fallbacks to good old HTML5 are included!

<script src="javascripts/webAudioApiForDesigners.js"></script>

<script>
// 1
var context = initializeNewWebAudioContext();

// 2
context.loadSound('audio/beep.ogg', 'beep');

$("#nav-one a")
  .mouseenter(function() {
    // 3
   context.playSound('beep');
  });
</script>

View Demo

List of reasons why HTML5 audio elements may be a bad choice

  • Wonky latency problems where sounds are heard at wrong times
  • Unexplainable popping sounds when playing multiple sound files at once
  • Limit to number of HTML5 audio elements that can play simultaneously

Reasons why HTML5 might be more suitable to your project

  • Very simple and straightforward to use
  • Can play background music just fine
  • Eventually (wild guess: no sooner than within the next 3 years) the bugs will be ironed out of these sorts of html DOM elements

More Information

HTML5 Rocks has a solid introduction.

CSS-Tricks Chronicle II

  • A bit randomly, I've had some great guest post submissions all at once. I published one from Arley McBlain earlier this week and I have two more I need to publish. Probably one tomorrow and one on Monday. This is great because it's been hard to write much in the midst of the big redesign.
  • Speaking of the redesign, it's feeling very close to competition. The last big thing is building the private access area ("The Lodge"). This is the area where Kickstarter backers get access to to watch the screencasts. And yep, you'll be able to buy access as well if you missed the Kickstarter. That was always the deal. Kickstarter folks just got it less expensively, amongst other rewards.
  • All the merchandise from the Kickstarter has been ordered. Should be shipping out within a few weeks. Some of it was exclusive to the Kickstarter but some of it will be for sale at some point. I'm thinking of offering always-open merchandise ordering on CodePen, CSS-Tricks, and ShopTalk for the merch. I figure if someone wants a shirt, no sense in making them wait.
  • The next conference I'll be at is the Breaking Development conference in Dallas, Texas, September 24-26. I'll be doing a workshop and a talk both centered around "A Modern Web Designer's Workflow". It will be brand new material from me. I have an outline of what I want to cover, but really need to dig into it and get some materials made.
  • I was happy today that the Photoshop 13.0.1 update was released which fixed this awful bug where path outlines kept turning back on when you explicitly turned them off.
  • CodePen is now an officially registered California corporation. We're doing it all right like grown ups.
  • I wanted to add datalist support to the external JS input box on CodePen to list a bunch of URL's from cdnjs.com. I did, and it works great in Firefox (see) but not great in WebKit browsers where string matching only happens on start of string not anywhere in the options, making it useless. I forked Chosen (then later select2) thinking I could alter it to make it work with input/datalist as well but I fear the code is just too complex. I might do a simpler hand rolled solution.
  • I just did my talk "Let's Do Simple Stuff to Make Websites Faster" at the RWD Summit. I fleshed it out a bunch since the last time I gave it at WordCamp San Francisco (which you can watch here). I also recorded myself doing it again for a screencast here on CSS-Tricks.
  • Fabrice Weinberg has been working on an jQuery implementation of ::nth-everything

Responsive Web Above The Fold

The following post is by Arley McBlain. Arley has written a few other great articles for CSS-Tricks in the past so I'm pleased to have him back for another!

This post's title isn't just a weak attempt at SEO stuffing, it's also a blind-folded scissor kick into a beehive convention! Few topics in web production can bring a nerd's blood to a rolling boil as quickly as "The Fold" and "Responsive Web Design", so it's high time we combine the two and bring this server to its knees under the sheer weight of trolls sharing how they really feel about me as a person.

Before the Webbys have to invent the "Best Use of Naivety" award I'd like to point out that for years I've been in the "The Fold is Dead" camp. Nothing used to please me more than comparing a website to the source of the scrolling metaphor; papyrus scrolls (bonus points when I could work a font joke in). "Sure, and when scribes wanted to avoid scrolling they probably wrote letters on fortune cookie paper, amiright?!" (clients probably love sarcasm). However, recently I've been forced to admit that maybe I should be a bit more accommodating of the Fold's proponents, rather than simply beating them over the head with my sack of used mouse scroll wheels.

Recently Google (incidentally a company whose clean "above the fold" website is merely a gateway to lots of scrolling search results) added a new feature to their Google Analytics suite that allows you to see what size of browsers users are visiting your site with. This allowed me to stop pretending that the data from the user's monitor resolution actually meant something relevant, and to begin to learn more about the way users are surfing my site.

View Browser Size analtyics in Standard Reporting > Content > In-Page Analytics, and click the "Browser Size" button. (view full size)

Google Analytics is a useful tool, and can do more than just shatter your faith in humanity's ability to upgrade their web browser. This tool can literally tell you how your site is being used. You can easily see who is scrolling and clicking those big shiny buttons you painstakingly designed, even after they've been pushed well out of sight by multiple instances of the "Ask Jeeves" toolbar. It will literally show you a percentage of who is scrolling and clicking individual links!

This new analytics tool made me start thinking about the fold afresh. I used to think of the fold as a weakness or handicap of Luddite users, but for the first time I saw that the fold has a huge bearing on the way that I (a savvy webmaster) surf the web as well. I had to admit to myself that I bounce a lot (Google Analytics probably has me pegged with the attention span of a goldfish). I'll often making the decision to leave a website within a second of arriving if I don't immediately see what I came for, or if I think the site looks like it was built by rodents. Judging books and websites by the cover doesn't usually hurt until a lack of results has me return to that same page to look harder, only to find the content in question sitting smug just below the fold.

Getting Started

The new browser size analytics feature has been around just long enough now that you can see some real data on how your current site design fares with impatient people like me! You'll see that many users aren't using their browsers full screen. While this has always been true of Mac users (most bitterly say they prefer their windows smaller after not being able to figure out what that UI "+" button does), it turns out that many PC users probably don't either (probably trying to look cool to the aforementioned Mac people).

I'm guessing the results of the reports will motivate you to do one of two things: personally confront each user on their questionable computer habits in dimly lit remote areas, or make you want to fine tune your design. The latter is where some handy vertical responsive web design comes in (for the former I recommend a sack full of used mouse scroll wheels).

Vertical Responsive Web Design

For the last couple years we've all been resizing our monitor widths like giddy accordion players to better understand RWD. The magic behind those is the now-common Media Query:

@media screen and (min-width: 768px) {  
  marquee { font-size: 43em; }
}

To get started with vertical RWD is a simple matter of addressing heights. Cinchy.

@media screen and (min-height: 768px) {  
  blink { color: pink; }
}

I wanted to make a couple practical vertically responsive demos to tantalize and delight!

Example #1: A Cuddlier, Squishier Fold

The most obvious use of vertical RWD would be to keep your all-important calls to action above the fold. To make this example extra fun I've chosen to do this on an existing horizontally responsive layout courtesy of Twitter Bootstrap. Being responsive on two axes is good fun, and is a great opportunity to make some messy code, if you're into that kind of thing.

When you vertically resize this demo site on desktop I've decided that I want to keep all four of the buttons in view as much as possible (hopefully the average site will just have one key CTA). For mobile sizes I only will require the blue CTA button to stay visible. For this demo I've decided not to worry about screens shorter than 320px. Realistically that should cover the extremely small desktop users and mobile users alike. We should be comfortable to talk about the users with smaller viewports in the tone that we usually reserve for IE6 users.

With this Twitter Bootstrap layout there are four horizontal break points - all but the last one (when the lower 3 columns get stacked) I am able to keep my buttons in view. This is all done by a few media queries which you can find in a <style> block at the bottom of the document's source code.

All in all, it was pretty cinchy to retro fit this layout to work in this way (he said with confidence despite deliberately picking a layout lacking media above the fold), especially by piggy-backing on existing horizontal break points.

Of course we also need to address the ugly elephant that basically lives in this room like an ever-unwelcome squatter: what shall we do about the old versions of Internet Explorer? There's a lovely little JavaScript library called CSS3MediaQueries.js that does the trick fairly well. I've included it in this demo in conditional IE tags. While it doesn't resize as fluidly as a modern browser, on the page load the user will see the responded version of the layout. Beauty.

Twitter Bootstrap demo:

View Demo

Example #2: WordPress Dashboard Navigation Tweak

This example is much simpler: one tiny media query with a simple bit of CSS that completely changes the ordinarily relative positioned left navigation that all WordPress admins are familiar with:

@media screen and (min-height: 500px) {  
  #adminmenuwrap { position: fixed; } 
}

Now, regardless of the navigation being in the collapsed or n00b mode (I jest), it will stay visible when you're scrolling through taller pages - provided your vertical resolution is taller than 500px. If your browser is shorter than that it goes back to being a relative positioned element that will scroll with the rest of the site. I've chosen 500px which is enough for the standard menu, as well as a few extra menu items from plugins or themes.

This vertical oriented RWD positioning treatment can work very well for navigation, widgets, pictures of cats, page tools, and even the lovely ads, like the ones from the charming sponsors of this website!

For this proof of concept I've made a localized HTML version of the WordPress dashboard (all of the links are broken it's a demonstration of the scrolling effect only):

WordPress Dashboard Demo (media query only):

View Demo

The 500px used in my example only works when you know the maximum height needed for the element. However, if the height of that object is unknowable or changes (an accordion navigation with multiple levels for example) you may want to consider a bit of jQuery that will compare the height of the object to the height of your window.

I have done this in the following variation of our demo by calling jQuery and using this script:

var setResponsive = function () {

  // Is the window taller than the #adminmenuwrap by 50px or more?
  if ($(window).height() > $("#adminmenuwrap").height() + 50) {

     // ...if so, make the #adminmenuwrap fixed
     $('#adminmenuwrap').css('position', 'fixed'); 
    
  } else {
       
     //...otherwise, leave it relative        
     $('#adminmenuwrap').css('position', 'relative'); 

  }

}

$(window).resize(setResponsive);
setResponsive();

WordPress Dashboard Demo (with jQuery):

View Demo

A Tall Order

So there you go.

A slight disclaimer: throughout this post I've been using the phrase "vertical responsive web design" - please understand that I'm just specifying the orientation of the responsivity, not coining a phrase. Whether the response is vertical or horizontal the term "responsive web design" captures it all.

I think there's a lot more we can be doing with vertical responsive web design in relation to our best practices, our content, and our users. The advent of this snappy new Google Analytics tool makes this a great time to start. In the past these wily short-browsered users may have been unpredictable and frustrating enough to drive Berners-Lee to kick a kitten, but now we can learn from their behavior, and predict the common ways they'll view important content.

Good news my friends, the fold is now undead.

Retina MacBook, Three Weeks In

I rationalized buying a new Retina MacBook Pro a few weeks ago by telling myself 1) it's my responsibility to stay on top of new things that affect the web 2) I want to make sure the redesign looks good on retina displays 3) my current laptop had very little RAM and a small hard drive. I was always running out of space. And finally 4) I needed the extra horsepower for exporting/converting all the video I'd be doing.

But if we're being totally honest: 5) I like new nerdy toys.

Here's some thoughts after three weeks of use.

(more…)

CSS-Tricks Chronicle I

I'm going to start a new style of blog post around here called CSS-Tricks Chronicle. It's going to be a (probably) weekly roundup of all the relevant happenings around the site and stuff I'm doing. Kind of a throwback to the spirit of blogging. It will give me a good home to link up interesting stuff that I didn't otherwise have a good home for. (more…)

The innovations of Internet Explorer

While IE is the butt of half the web developer jokes ever written, it has been responsible for its fair share of web innovation over the years. Nicholas C. Zakas shares some of that, starting as far back as IE 3.

ShopTalk Episode 30 & New Design

This week Dave and I were joined by JavaScript avenger Rebecca Murphey where we talk a little #hotdrama followup, the future of JavaScript, GitHub etiquette, charging while learning, and more. And OH HEY there is a brand new design for ShopTalkShow.com by our own Dave and his Paravel brother Reagan Ray! Go look around. Thanks to Squarespace (use code SHOPTALK for 10% off) and the Responsive Web Design Summit (use code SHOPTALK for 20% off) for sponsoring.

Exclude Compressed CSS from Sublime Text 2 Projects

If you're using Sublime Text 2, you might have switch to it because it's Find in Project is super fast and nice. And if you're using Sublime Text 2, that means you're working locally on files, meaning there is a good chance you're using CSS preprocessors. If you're using CSS preprocessors, you probably compile CSS into a compressed style (non-relevant whitespace stripped) because that's best, speed wise, for live websites.

Now let's say you use Find in Project to find a class definition (e.g. ".sidebar-poll") that you need to edit. You'll probably find the .scss file or .less file or whatever, but you'll also find it in the compressed CSS, which is this giant one-line file and totally borks up your Find Results page.

Yeah, I don't really need to see that.

We can't blame Sublime Text 2 because 1) It's finding what you told it to find and 2) They provide a way to fix this if you don't want to see those Find results. To fix this:

1. Save your project

Open your project (drag folder of project onto Sublime Text 2 icon in dock). Then save it from the Project menu.


This is nice anyway, since you get a file (YOUR-PROJECT.sublime-project) that you can double-click to open it back to the state you left it in at any time.

2. Edit Project

Go to Project > Edit Project.

3. Add Exclude Pattern

Change the JSON to include the folder_exclude_patterns of the folder where you keep your compressed CSS (just the name of the folder will work fine):

{
  "folders":
  [
    {
      "path": "/Users/chriscoyier/GitHub/whatever/",
      "folder_exclude_patterns": ["css"]
    }
  ]
}

Now that folder won't show up in the sidebar of your project. Huzzah! To remove files from search results, a setting like:

"binary_file_patterns": ["*.css", "*.log, *.min.js"],

Note

This is for excluding folders on a per-project basis. If you always want to exclude a particular folder, you can change this exact same setting in Sublime Text 2 > Preferences > Settings - Default (or User).

256 Classes Beats an ID

According to the spec, one ID should be infinitely more specific than a class. But as it turns out, if you add 256 classes to a single element (same or different) it will override the ID. Dumb little edge case that probably will never be fixed, but interesting. Ryan Seddon digs in a little more.

Don’t Overthink It Grids

The vast majority of websites out there use a grid. They may not explicitly have a grid system in place, but if they have a "main content area" floated to the left a "sidebar" floated to the right, it's a simple grid.

If a more complex layout presents itself, people often reach for a grid framework. They assume grids are these super difficult things best left to super CSS nerds. That idea is perpetuated by the fact that a lot of the grid systems they reach for are very complicated.

Here's how I build grids. It's not hard or complicated. Even making them flexible is no big deal.

(more…)

Smashing Mag CSS Q&A 3

The third installment of my recent question and answer series. This one includes code for dealing with retina version of sprites, fiddling with flexbox, and some of my favorite CSS tricks lately.

ShopTalk Episode 29

This week Dave and I were joined by Tab Atkins and we talk about Tab's job as a spec writer working at Google, Flexbox, the future of float clearing, using encoded characters, smooth animations, and more!

Thanks to the Responsive Web Design Summit for sponsoring. RWDSummit is an online conference and you can save 20% by using coupon code SHOPTALK.

Made to Measure

Allen Tan:

So if static templates are too limiting, but per-piece art direction is too costly, how else can we make scalable, sustainable digital publications that are beautiful and accessible? To find a middle path, we can take a cue from the art of the tailor.

I totally agree that the future of good design on digital publishing is somewhere in that middle ground. Art direction "lite", perhaps. And maybe with a bit of automation.

CSS Style Guides

As we wrap up our recent poll on ordering CSS properties, it brings up the larger issue of CSS style guides. Ordering properties is just one choice you have to make that makes up a complete styling strategy. Naming is a part of it. Sectioning is a part of it. Commenting, indentation, overall file structure... it all makes up a complete CSS style guide.

Let's round up some existing ones.

(more…)

Multiple Pseudos Work by Adobe

Things are moving along in the pseudo elements world again which is exciting. Alan Stearns put together this mock spec that defines usage like ::before(n) and ::nth-pseudo().

Meny

Hakim El Hattab is at it again with a simple, beautiful, three-dimensional way to handle "hidden left side navigation" that's getting so popular on small screens.

CSS Pie Timer

Editor's Note: Hugo Giraudel made a cool demo for a "pie timer" on CodePen. It's definitely not an intuitive or simple thing to do in CSS. Then he sent me a write up on how he did it and I'll be darned if it doesn't make a real nice CSS-Tricks article. Thanks Hugo!

What are we making?

You may have seen some of these loaders, mostly on Flash websites. It's basically a piece of pie getting bigger and bigger to become a whole circle.

At a first I thought it's gonna be easy peasy, just have a circle, make it spin, hide some part of it behind a mask and I'm done. Well, it turned out it's way more difficult. In fact, CSS is not prepared for such a task, even with preprocessors like SASS & Compass. We always struggle when it comes to making shapes, and even more when we have to style or animate those. Most of the time, we manage to work around it and get something working, at the price of maintainability or semantics.

Why do this?

I think the most common use case would be timers. But these concepts could be used to make pie charts with pure CSS as well. If you're es

Even if there are several awesome tools outthere to manage pie charts (mostly with JavaScript), we could probably easily figure out how to do pie charts with CSS only, and even animate those with such a trick.
There is a tutorial about making CSS pie charts with the clip property on Atomic Noggin Enterprise website : http://atomicnoggin.ca/blog/2010/02/20/pure-css3-pie-charts/

Well, this is a workaround with bad semantics! But the maintainability isn't so bad, so here we go.

The HTML

We need 3 different elements:

  • a spinner: this is the half-circle which will rotate during the whole thing
  • a mask: this is the element which will hide the spinner during the first 50% of the animation
  • a filler: this is the element which will complete the circle during the last 50% of the animation

And we need all these elements to be in the same parent to allow absolute positionning :

<div class="wrapper">
  <div class="spinner pie"></div>
  <div class="filler pie"></div>
  <div class="mask"></div>
</div>

Since the spinner and the filler are two half of the same circle, we use a shared class (.pie) to style them.

The CSS

To keep the code in this article clean and understandable, we won't add any vendor prefixes.

The parent element sets up the size and absolute positioning context for the timer:

.wrapper {
  width: 250px;
  height: 250px;
  position: relative;
  background: white;
}

It is important to make sure the width and height are equal to make a circle and ensure the whole thing works.

The "spinner" and the "filler" share this CSS:

.pie {
  width: 50%;
  height: 100%;
  position: absolute;
  background: #08C;
  border: 10px solid rgba(0,0,0,0.4);
}

Their width equals 50% of the parent width since they are both part of the same circle, and their height is the same as the parent height. We also give them some color and a border to identify them properly.

The "spinner"

.spinner {
  border-radius: 125px 0 0 125px;
  z-index: 200;
  border-right: none;
  animation: rota 10s linear infinite;
}

We have to make the thing look like a half-circle with border-radius on the top left corner and the bottom left corner. Plus, we give it a positive high z-index in order to put it on top of the filler but behind the mask.

Then we add the animation at 10 seconds long. We'll talk more about animations later.

The "filler"

.filler {
  border-radius: 0 125px 125px 0;
  z-index: 100;
  border-left: none;
  animation: fill 10s steps(1, end) infinite;
  left: 50%;
  opacity: 0;
}

For the spinner, we set border-radius and z-index, remove the border-left, and make the animation 10 seconds long. For this element, the animation-timing-function is not set to linear but to steps(1, end). This means the animation will not progressivly go from 0% to 100% but will do it instantly.

Since the filler won't be visible during the first part of the animation, we set its opacity to 0, and its position to 50% of the parent width.

The "mask"

.mask {
  width: 50%;
  height: 100%;
  position: absolute;
  z-index: 300;
  opacity: 1;
  background: inherit;
  animation: mask 10s steps(1, end) infinite;
}

The mask is present since the beginning of the animation, so its opacity is set to 1 and its background is inherited from the parent background-color (to make it invisible). In order to cover the spinner, it has the same dimension has it, and its z-index is set to 300.

The keyframes

@keyframes rota {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@keyframes fill {
  0%        { opacity: 0; }
  50%, 100% { opacity: 1; }
}

@keyframes mask {
  0%        { opacity: 1; }
  50%, 100% { opacity: 0; }
}

The first animation (rota) is for the spinner. It progressively rotates from 0 to 360 deg in 10 seconds.

The second animation (fill) is for the filler. It immediatly goes from 0 to 1 opacity after 5 seconds.

The last animation (mask) is for the mask. It immediatly goes from 1 to 0 opacity after 5 seconds.

So the animation looks like this:

  • T0 - the spinner is on the left, hidden by the mask. The filler is hidden.
  • T1 - the spinner starts rotating clockwise, and slowly appears from behind the mask.
  • T2 - the spinner has gone 360/10*2 = 72° and keeps rotating.
  • T3 - the spinner has gone 360/10*3 = 108° and keeps rotating.
  • T4 - the spinner has gone 360/10*4 = 144° and keeps rotating.
  • T5 - the spinner has gone 360/10*5 = 180° and keeps rotating. At this very moment, the filler instantly goes at 100% opacity while the mask goes disappears.
  • T6 - the spinner has gone 360/10*6 = 216° and keeps rotating.
  • T7 - the spinner has gone 360/10*7 = 252° and keeps rotating.
  • T8 - the spinner has gone 360/10*8 = 288° and keeps rotating.
  • T9 - the spinner has gone 360/10*9 = 324° and keeps rotating.
  • T10 - the spinner has gone 360°, getting back to its starting point. Then we restart the animation. The mask goes at 100% opacity while the filler goes disappears.

Bonus

Here's some additional tricks which can be pretty cool, depending on what you want.

Pause on hover

.wrapper:hover .filler,
.wrapper:hover .spinner,
.wrapper:hover .mask {
  animation-play-state: paused;
}

With this snippet of code, you can hover the whole animation by hovering the parent element.

Inside content

Thanks to z-index, we can easily add some content inside the spinner and make it rotate the same way. Try adding the following snippet to your code :

.spinner:after {
  content: "";
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  top: 10px;
  right: 10px;
  background: #fff;
  border: 1px solid rgba(0,0,0,0.4);
  box-shadow: inset 0 0 3px rgba(0,0,0,0.2);
}

Pre-processors or CSS variables

Currently, this isn't very easy to maintain. But if we use variables (which preprocessors or the upcoming native CSS variable) we can make it easier. For example, you could add a variable to manage duration time, instead of having to change it on the 3 animation declarations.
If you want to ease the maintainability without dealing with pre-processors, I guess you could create a class which only handle the animation duration, and add this class to the 3 children elements. It would look like something like that :

.animation-duration {
  animation-duration: 10s;
}
<div class="wrapper">
  <div class="spinner pie animation-duration"></div>
  <div class="filler pie animation-duration"></div>
  <div class="mask animation-duration"></div>
</div>

Downsides

Sadly, there are some things this technique can't do:

  • Doesn't support gradients (looks awful)
  • Doesn't support box-shadows (looks dirty)
  • Isn't completly responsive. If you change the parent element's dimension, everything goes right except the border-radius. You still have to change border-radius values manually because we can't set 50% border-radius unless we're dealing with a perfect square.
  • Isn't semantic (4 elements for a single animation). Upcoming multiple pseudo elements may help this, or web components.

Browser support

Since we are using CSS animations and keyframes, the browser support is pretty low but will improve over time. For now, the only browsers supporting CSS animations are:

  • Internet Explorer 10
  • Firefox 12+
  • Chrome
  • Safari 5+
  • Opera 12+
  • iOS Safari 3+
  • Android 2+ (buggy till v4)

Demo

View Demo on CodePen

Squarespace 6

You all know I don't do very many sponsored blog posts here on CSS-Tricks. But when Squarespace reached out about doing some advertising for their new version 6 I was bummed to tell them there is nothing open (I had just removed an ad zone from the sidebar to clean things up a smidge). So I thought heck, let's do a blog post about it which will give me a chance to say what I want to say about it and also introduce the new Squarespace in a more detailed way. So yes: this is a sponsored post but they are my words (they wouldn't even give me talking points) and it's my choice.

What is Squarespace?

It is a web app for building websites. You don't write any code. You use their super slick interface for designing the site and managing the content.

They have just released "Squarespace 6", a kind of reboot to the app. I think it's much nicer than the previous iterations. In this latest version, the things that it makes sense to do while looking at a live preview of your site, you do while looking at a live preview of your site. The things that make more sense to do while looking at an admin screen of sorts, you do in an admin screen. I feel like previous iterations forced more into the live preview area.

Lovely, simple backend.

I'm a web designer. Why would I use this?

You're a web designer. That means your family asks you to build websites for them. Your friends. Your friends of friends. Your hairdresser wants you to build a site for their cat. You don't have time for that, and honestly, even if you could fit them in and they had the money to pay you what you are worth, what they actually need is a simple, nice looking template where they can post pictures and text and arrange little modules of content. You can set them up in just a few minutes on Squarespace. Then not only do they have a site that works for them, they can manage it themselves instead of bugging you.

This template will work great for your cousin's wife's friend who is like this really great actress and just needs a simple site for herself.

I have a friend, Scott McCormick, who actually is a really great photographer. I built him a simple custom site on WordPress. It turned out nice I think, but in retrospect I really wish we would have set him up on Squarespace. I think it would be a better fit for him. It would give him more control and allow the most important activity, posting new photos, to be easier and more intuitive than it is on his current site.

Plus, he'd get built in statistics which I'm sure he'd be very interested in. I could set up Google Analytics on it but honestly I don't want to be in charge (and the go-to guy) for analytics for every site I have a hand in.

Analytics included.

It's not just for your castoffs, though.

I don't want to sell Squarespace short though. It's not just for people you're too busy to build a site for directly or who you don't have time to deal with. Look at these templates. They are super nice. They might be perfect for yourself or for a paying client of yours. And of course you can alter them to match your style.

I hesitate a bit to mention "coming soon" features, but the Squarespace folks assure me that "Developer Mode" is coming soon to Squarespace 6 and it's going to be some super next-level powerful tools for crafting your Squarespace sites. I haven't seen it, but this is paramount for us web designers. I believe Squarespace 5 had some good developer tools, so if they are re-inventing that for version 6 and do as good a job as the site builder stuff, it's gonna be great.

The Future

I recently hosted a discussion about CSS reusability. The genesis of the post was me looking at a website template and thinking about how many (millions) of times a website almost exactly like that has been hand coded by a web designer. Are we going to do that forever? I hope not. I hope simple content based sites become more of a self-service, commodity kind of thing. I know that's a bit controversial. We'll have to chat about that more specifically some time. I'm definitely not anti-designer, I'm about having designers solve more important problems. Squarespace (and the rise of sites like it) is the start of this revolution.

Deal

If you are interested in going for it, you can sign up for Squarespace and save 10% using the code CSSTRICKS. It's 10% off whatever purchase you make. So if you go monthly, it's just the first month. If you go yearly or bi-yearly, it's like you saved that 10% on each of the 12 or 24 months so the savings are higher.

I thought I'd drop their video in here too:

Prism

A code syntax highlighter by Lea Verou. Small, fast, and designed to work on front end languages. And my favorite, class names that make sense.

A Discussion About CSS Reusability

Look at this website layout:

You've probably coded up something like that, right? How many times? A lot? Did you do it from scratch each time?

I think more discussion about front end code reusability is worth having. Theoretically I would think CSS would be some of the most reusable code we have available, but that doesn't seem to be true in practice.

I have more thoughts, but I'll save them for the comment thread.

ShopTalk Episode 26

Dave and I do a RAPIDFIRE show this week where we try and get through as many listener questions as we can in one show. Thanks very much to Crafting Type (a 5 day workshop on building your own typeface in Canada) and Environments for Humans (next upcoming confererence is the online CSS Summit) for sponsoring.

Seamless iframes Today

I didn't even know there was such a thing as "seamless" iframes. But there is and they are coming (literally an attribute on the iframe element). Essentially they inherit some styles from outside of them, but are otherwise sandboxed. Perfect for something like Disqus eh? Front end engineer Ben Vinegar from Disqus introduces them and shows some smart ways for emulating them now.

Crazy Town Selectors

I recently used this selector as an example in a blog post:

.article #comments ul > li > a.button {
  /* Crazy town */
}

There was a few comments to the effect that this seemed perfectly reasonable. I think if we step through it backwards the craziness comes out more clearly.

(more…)

Sprites and Retina Displays

CSS sprites are often used for small icons. That is exactly what looks bad on retina displays. Maykel Loomans has a way to deal with that that doesn't make our CSS twice as complicated: 1) Make sprite exactly twice as big 2) Swap out background in media query 3) Shrink background-size in half so coordinates are still correct.

Judging CSS / Spotting Bad Code

In a recent Q&A article on Smashing Magazine, a question was asked about how to tell if a developer has written bad CSS. Specifically:

What are the signs that the CSS is sub-optimal, or that the developer hasn’t done a good job? What do you look for in CSS to determine how good or bad it is?

I thought that was an interesting question and I'd expound upon my answer a bit.

(more…)

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