Cloud Four Blog

Technical notes, War stories and anecdotes

Fixed and inflexible

Even before smartphones came along and dashed any hope for a 960-pixel-wide web, designers and organizations have struggled with the challenge of prioritizing and composing content that scrolls. Our screens act like windows to content of variable size and scale, demanding an awful lot of abstract thinking to design for. Sometimes we’re successful, revising content, designing modern day deliverables and embracing compromise like we know in our hearts we should. Other times, we convince ourselves that we can predict this inherently unpredictable medium, making decisions that age quickly and poorly by prioritizing the window instead of the content.

Most recently, I’ve noticed a sharp uptick in the number of requests I receive to explore fixed-position (aka “sticky”) interface elements. Fixed elements are positioned relative to the viewport instead of the page, allowing them to maintain position even as the document scrolls. Some of the most popular sites on the web employ “sticky” menus, and with good reason… when applied thoughtfully, they can yield substantial usability improvements.

But when fixed positioning is used without care, restraint or precision, it can have disastrous consequences. Here are some of the reasons why.

We can’t predict how much space we have.

Our industry has a nasty habit of quietly embracing display resolution “standards” that are mostly fantasy… design decisions are a lot easier if you assume all devices are 320 pixels wide by 480 pixels tall (and users never turn them sideways). The inconvenient truth is that display resolutions vary wildly. Each additional “sticky” element increases the risk of obscuring the page content mostly (or entirely) for some users… in which case the page might as well not exist at all.

We can’t get those pixels back.

Fixed elements aren’t just “prominent,” they photobomb the interface, robbing focus and attention from what really matters — the content! Before you make something “sticky,” consider reevaluating the element’s importance relative to the entire page (instead of on its own merits).

It makes scrolling tougher.

As evidenced by the years-long debate over “The Fold,” the fear that users won’t know (or lack willingness) to scroll persists to this day. When that fear is real, then fixed positioning is a godsend, ensuring the visibility of content regardless of scroll position.

But those fears don’t mesh with reality very well.

Today’s users are so familiar with scrolling that most mobile browsers will hide the scrollbar entirely. “Sticky” elements complicate matters by reducing or obscuring the scrollable area, forcing the user to swipe more carefully to avoid accidental actions.

Ironically, our desire to alleviate the supposed “difficulty” of scrolling may make scrolling that much more difficult!

It can slow everything down.

Users care about speed. But speed isn’t all about navigation… there’s also the overall speed of the experience. Fixed positioning can result in strange browser-specific quirks or even costly repaints, potentially counteracting any efficiency you might have gained.

It may not actually work.

Mobile websites share a lot of their design vocabulary with native mobile apps, where fixed headers, menus and tab bars are commonplace. This makes it easy to forget that fixed positioning as we know it is relatively new to the web, and often unreliable.

“Sticky” headers, footers and navigation flourished in the 1990s, often implemented using frames. When frames fell out of fashion in the early 2000s, most browsers did not support fixed positioning using CSS. In the absence of frames, position: fixed or consistent, intuitive JavaScript, fixed positioning became just another discarded Web 1.0 trend… at least until CSS support arrived in IE7.

But smartphone browsers have historically not supported position: fixed as predictably as their desktop counterparts. It was entirely absent from mobile Safari prior to iOS5, and largely unusable in Android browsers prior to Honeycomb. To this day, behavior can be inconsistent across platforms. To quote Brad Frost in his excellent post on Fixed Positioning in Mobile Browsers, “‘support’ isn’t exactly binary.”

Since you can’t rely on support for fixed positioning, you’ll need to make sure your experience works without it anyway. Which begs the question…

Why position: fixed at all?

I believe there are plenty of interface elements that benefit from fixed positioning, provided they follow a few best practices:

  • The “sticky” element is clearly more important than everything else on the page.
  • The footprint of the element is modest enough that it does not obscure too much of the page content (even in landscape).
  • Any efficiency gained from the element’s consistent availability is significantly greater than any lost as a result of the element’s inclusion (due to performance, obscuring of page content, etc.).
  • There should only be one “global” (navigation, tab bar, etc.) and one “temporary” (modal, dialog, etc.) fixed-position element on-screen at any one time.
  • Fixed positioning should always be an enhancement. Your interfaces should never rely on it.

If any of these considerations completely upend your design aspirations, you may want to rethink your user experience with less rigidity. As John Allsopp so aptly put it fourteen years ago, “The journey begins by letting go of control, and becoming flexible.”

Beyond “Hello, World” with Gulp

(This post is for: web developers who have used, or thought about using, a build tool before, are JS-comfy and maybe have noodled around in node.js but wouldn’t, say, feel up to submitting a talk to a node conference.)

It would be hackneyed to call the last twelve months the “Year of Build and Workflow” for web developers, but there’s an element of reality to the contrivance. In 2013, there was grunt (heck, there still is; it didn’t die or anything) and a whole lot of blog posts about streamlining workflow around SASS and templating and build package management, etc.: topics that were—poof!—suddenly an imperative for general people working on the web. I wrote a thing about workflow for A List Apart earlier this year, a few weary weeks after the whole “Oh, you learned grunt? Sucker! Now you need to learn gulp, because whatever!” revolution happened.

Summarized as this: a whole lot of people (increasingly non-nerdcore) learned to use grunt to wrangle previously-tedious workflow tasks for building web sites. This represented a big jump in things we all needed to know. And then, kind of literally overnight, there was gulp. For me, this felt like a burden as well as an opportunity.

I wasn’t exactly a holdout (as you can see), but I was initially resistant to throw the grunt baby out with the 2013 bathwater simply because a new tool existed. And, like maybe some of you (?), I found the initial sell a bit baffling: “streaming build system?” I didn’t know I wanted that? Awesome syntax? I didn’t really have a gripe with grunt on that front. “Speed?” Maybe? I didn’t exactly have to go brew a cup of coffee while my grunt tasks ran.

Grieving and Surmounting

But smart people I know kept extolling its highlights and I decided to give it a whirl. The familiar stages of dev-new-tool excitement-grief happened:

  1. Find and install new tool that people crow about.
  2. Get satisfying example configuration/program running using new tool.
  3. Extend satisfying example configuration/program in a tiny way and find success in making it do something useless, but cool. HELLS YEAH.
  4. Extend awesome slightly-extended configuration/program in another way to make it do something you actually need it to do. Spend 3 hours/days progressively assuring yourself you are a moron—this should really be so easy! Two possible outcomes: rage quit or eventual, sweat-soaked breakthrough.
  5. Assuming you’ve made it this far, progress with a slight wariness, possibly even progressively assuring yourself that the tool devs or Stack Overflow or Google or a particular plugin or, hell, the entire language you’re working in is the real moron here. Also revel in the fact that extant examples of what you’ve now managed to do exist on the Internet at all—you’ve birthed something truly novel. This is often a necessary step to repair the psyche.
  6. If you are kind, you then help other people avoid step 4 (or, at least, put a reassuring hand on their shoulder).

Gulp: The Good

Here’s some of why you might want to use gulp instead of another alternative:

  • Pretty syntax and intuitive structure: There is nothing wrong with grunt’s syntax, but gulp’s is kinda pretty. Using Streams means you’ll be able to do a lot of chaining, which always feels pleasing to the code-scanning eye. I was never a huge fan of the double-step grunt convention of grunt.loadNpmTasks() and grunt.registerTask(). In gulp you can require() and define gulp.task()—that feels more natural to me. I find I don’t have to look up core API stuff for gulp; with grunt, I never memorized it.
  • Speed: There’s no doubt. gulp feels noticeably fast. That is not exactly a scientific observation, but I stand by it.
  • Streams: If you know node already, gulp’s Streams architecture will make you feel right at home.
  • Gulp has a nice clarity that it is about working with streams of files. As such, there is more symmetry between any two given gulp tasks than most given grunt tasks. gulp.src globs and gulp.dest paths become second nature. Stream in, though, out.
  • Works with lots of things, easily: Like grunt, gulp has plugins (many of them). But the first edict in the guidelines for creating a gulp plugin is: “Your plugin should not do something that can be done easily with an existing node module,” meaning that gulp encourages the use of non-plugin-i-fied node packages wherever possible (versus “[w]rapping every possible thing just for the sake of wrapping it”). The plugin landscape feels correspondingly more serene.

Avoiding Step 4: Tips for Getting along with Gulp

  • Make sure your gulp tasks finish correctly. If not, it will wreak havoc with dependencies and other tasks. Be sure to read the section of the docs about valid things to return from gulp tasks and how to handle async tasks. Trust me on this one.
  • In fact, read the entire API documentation. If this sounds like a tall order, take note that it is shorter than this blog post. The core API for gulp is outstanding in its simplicity.
  • Get an understanding of Streams, a core node construct, because this is the way that gulp works. Take a few minutes/a while and read a primer on Streams. It’s a bit to get your head around, but if you’re doing any heavy lifting with gulp (or other node, for that matter), you’ll be glad you learned.
  • Watch out for plugin quality. The plugin landscape may be straightforward, but it’s young, and there are some stinkers. I lost some serious time to a couple.
  • Dig hard for real-world (read: complex) examples. This situation has gotten better in the past few months. Dan Tello’s excellent post on Gulp + Browserify: The Everything Post is a must-read-right-now. When I first encountered his repo full of organized gulp tasks, it changed my everything. I ended up extending my fork to handle dependencies effectively, but his gulp-starter repo has since been updated to do that, also, so, win! There is more documentation and examples out there now than there was a few months ago. But documentation about gulp things can sometimes presuppose that you know more about various concepts than—gasp—perhaps you do. Don’t fret. That jargon sounds weird to other people, too. Read slowly and give yourself some time!
  • Watch out for plugins getting between you and what you’re doing. Like any build tool with plugins, gulp puts a layer between you and (in gulp and grunt’s case) node. Sometimes it’s hard to debug whether you’re doing it wrong, or whether the plugin between you and the wrapped node package is doing something wrong (or at least making things real complicated). If you don’t understand the syntax of a plugin or what it’s doing, consider that a red flag and slow down until you do. Or: see if you can accomplish what you’re doing with a node module instead.
  • Complexity explodes as you add more tools to the mix. We are using browserify for our application code, but it got outrageously onerous for managing vendor code, much of which was not modular in any sensical way (this was serious step-four territory). We ended up throttling down and using something a bit simpler. Don’t be afraid to over-simplify if it gets the job done. I find you can usually kick up complexity later, when needed, but that the opposite—dialing it down—is not so easy.

We do some really cool things at present with gulp. We use it to parse YAML front-matter out of templates (which get piped through underscore and have partials inserted and come out as static HTML files) to create an auto-index of project assets, adding automated screenshots (thanks, phantom.js!) at different widths to show responsive layout. This of course along with SASS and auto-prefixer and browserify and concatenation and and and…whew. Because each task in the works is totally modular, this ends up not feeling rickety and spaghetti, believe it or not—and that alone is worth the price of admission.

Go out and build! Let me know how it goes!

My thanks to Cloud Fourian Erik Jung for leading us out of step 4 hell vis-a-vis the whole vendor JS thing I mentioned above.


Fantastic intro to new srcset and sizes

I normally don’t write a post simply to link to another article, but if you’ve enjoyed the things I’ve written about responsive images, you really should read what Eric Portis wrote about Srcset and Sizes.

Eric describes the logic behind srcset and sizes, how they are part of the new picture proposed standard, and how to use them.

Easy. Peas.

What’s New in hideShowPassword 2

Last June, we released our hideShowPassword plugin for improving the experience of password-entry (particularly on mobile devices). As of this writing, it’s our most-starred and most-forked project on GitHub.

We’ve released a handful of incremental and bug-fix updates since then, but today we’re shipping a full-fledged Version 2 with several noteworthy improvements.

Simpler Usage

The plugin’s “inner toggle” feature tended to steal the show, yet its syntax was verbose:

$(selector).hideShowPassword(true, { innerToggle: true });

We now support a simpler, shorthand syntax for enabling the inner toggle:

$(selector).hideShowPassword(true, true);
 
// enable toggle but hide till input focus:
$(selector).hideShowPassword(true, 'focus');
 
// using shorthand method:
$(selector).showPassword('focus');

Improved Accessibility

My personal favorite feature is the improved accessibility of the inner toggle button. Some changes we made based on real-world feedback:

  • The toggle button element is now a <button> by default (it was previously a <div>).

  • Several accessibility attributes have been added to better communicate the purpose and state of the button to assistive devices.

  • The toggle should now be keyboard-accessible, with space and enter key events attached where necessary.

We understand every project’s different, and you may need to tweak some of these new properties. Luckily, Version 2 also includes…

Overhauled Options

Just about anything we could make an option, we have. There are so many new options, we had to re-organize the options object to accommodate them all. See the full list here.

Built For jQuery and Zepto

Version 1 of hideShowPassword supported Zepto, but we’ve decided to simplify the plugin’s dependencies by only supporting jQuery from here on out. This makes sense to us for a few reasons:

  • Zepto’s data module was required, necessitating a custom build of Zepto to work at all.

  • The plugin’s inner toggle features could be unpredictable given Zepto’s simpler width and height calculation methods.

  • Zepto does not support AMD, and likely never will. We introduced AMD support to hideShowPassword in our first minor update based on developer feedback.

  • While Zepto’s modest file size remains an attractive feature, its performance once loaded may not be so competitive.

Get It Now!

All the aforementioned improvements (plus more fixes and tweaks) are available right now on GitHub (which is also a great place to report issues or request features). Check out the live demo if you remain unconvinced.

If you use the plugin in a project, please drop us a line and let us know. We’d love to hear about it!

SimpleSlideView: Controlling Flow With JavaScript

In July we released SimpleSlideView, a jQuery and Zepto plugin for simple, responsive sliding views (here’s a demo). In the last few months, I’ve noticed an uptick in developers emailing to ask a variation of this question:

How do I change or stop a view transition based on user input?

It’s a great question, and one that may not be immediately apparent from the demo alone.

When using SimpleSlideView, there are two ways to navigate between views. The simplest way is with HTML, which is great for predictable, non-dynamic interactions or prototyping:

<button data-pushview="#result">See Result</button>

The straightforwardness of this technique is a double-edged sword. It’s easy to use, but it’s also kind of static. What if we want to change the destination? Or prevent the transition altogether? For that, we’ll want to use JavaScript instead.

We can remove the data-pushview attribute from the button, but we’ll need some way to select it via JS, so let’s give it an ID:

<button id="result-btn">See Result</button>

And here’s the scripty part:

// Save the simpleSlideView instance to a variable
var slideView = $('#container').simpleSlideView();
// Add a click event handler to the button
$('#result-btn').click(function(){
  // On click, push the view with an ID of 'result'
  slideView.pushView('#result');
});

Right now this probably feels like a step backward. It’s more verbose. But we’ve gained the freedom to define the sliding-view behavior any way we like.

Suppose you only want to transition when certain criteria are met:

if (isValid) {
  slideView.pushView('#thanks');
} else {
  alert('Oops! Something seems off.');
}

Or maybe you’d like the next view to depend on the value of something else:

if (age < 21) {
  slideView.pushView('#soda');
} else {
  slideView.pushView('#beer');
}

Here’s a working example that uses Moment.js and your browser to determine the weekday of a date you provide. The result is populated before the view transitions, and only if Moment.isValid() returns true:

See the Pen Weekday (SimpleSlideView Demo) by Tyler Sticka (@tylersticka) on CodePen.

For more info on what you can do with SimpleSlideView and JavaScript, refer to the documentation on GitHub. If you’re using SimpleSlideView in your own projects, we’d love to hear about it!