Advertisement

How They Did It: Flickr Redesign

by

Fresh on the heels of Yahoo!'s acquisition of Tumblr, Yahoo! has implemented a complete redesign of Flickr.com. This was met with some strong criticism as well as strong praise, a lot of which has been attributed to Yahoo!'s new leader, Marissa Mayer. In this article, we will talk about the design decisions and some of the implementation details in the redesign, and we will open some conversation about Yahoo!'s acquisition of Tumblr.


Built for Photography Enthusiasts

The role of Flickr is often questioned by critics of Yahoo!, as Facebook surpassed it as the most popular online photo uploading service. In this redesign of Flickr, we see an interesting set of priorities reflected, which we will discuss in this section.

flickr-how-they-did-it-hom

These priorities reflect that Flickr is targeting an audience of photography enthusiasts.

The Home Page Image Choices

By looking at a random selection of photos from Facebook, you will most likely see a collection of friends-at-the-beach or "selfie" photos. Even in Facebook's advertisements, we see images that are driven by one factor: capturing socially driven moments.

flickr-how-they-did-it-selfie

Writer Justin Rocket Silverman learns the art of the 'selfie'

However, looking at the Flickr homepage, we don't see a single image that would be primarily considered "social". We instead see a selection of primarily nature or pet images, with a few other posed photos. These images are best understood as highly intentional, taken by photography enthusiasts.

The Home Page Information Choices

The home page of Flickr pushes a few messages and a single call to action. The primary message is Flickr's groundbreaking free terabyte of space for images and videos. They emphasize this in the primary landing message, "Smile. Everyone gets a free terabyte" and further in the second "Biggr" slide below the fold, which allows the user to see how many images of a given resolution they could upload to Flickr.

flickr-how-they-did-it-biggr

The megapixel slider goes from 0 to 16 Megapixels. The third slide explains that users can upload their images at their original resolution, and can expect no loss of quality.

flickr-how-they-did-it-resolution

These messages speak strongly to photography enthusiasts; having enough free space to upload high quality images is of importance to photographers. In contrast, Facebook does not communicate any quality or space implications to uploading images.

Photos are King: Content Citizenship

The new Flickr is hyper-focused on photo-centric experiences. This generally places user accounts as a secondary content element. For instance, when a user signs in, the "home" page shows a feed of images and their associated interactions from other users. The logged-in user's groups can be seen to the right. Clicking on a photo opens a navigable lightbox.

flickr-how-they-did-it-logged-in

Flickr also has created a new slideshow experience. The search bar focuses on user uploads (rather than user "profiles") by default. The next two options are your personal photostream, then your "contacts' photos". Finally, the search type can be changed to groups, and lastly for members.


Flickr Isn't Confused

As a secondary effect of Flickr's hyper-focus on photography and the people who care about it, we can quickly see that Flickr's goal isn't to compete with Facebook. Instead, it is to become the photography cloud service for the average photography enthusiast and the professional career photographer to store and discuss photos.

This is not to diminish the interactions enabled by the new redesign. In fact, interaction and conversation is encouraged more than the previous Flickr, which was primarily focused on showing each individual user their most recently uploaded photos. But Flickr's social interactions revolve entirely around the photos; in fact, on a single user's profile page, there is no "wall". Instead, there is a stream of that user's uploaded photos, which can easily be launched into a slideshow. If you like a particular user, you can "Follow" them (Tumblr, anyone?), which will bring that user's photos and associated comments to your logged-in home feed.

Users can access FlickrMail, but only if they have people added to their Contacts; furthermore, access to FlickrMail is somewhat buried.

flickr-how-they-did-it-mail

Groups can post very simple "discussions", which are like forum posts; however, further communication is relatively limited to comments on photos.

Flickr isn't confused or unfocused; instead, it is clearly focused on creating a place to talk about and store photographs.


Some Dirty Details

As is the custom with the "How they did it" series, we are going to spend some time talking about the technical aspects of the new implementation. This section isn't about the overall strategy or whether or not it's effective; instead, this section is packed with tips and tricks based on Flickr's implementation.


Welcome to the Future

Flickr's design hasn't seen a significant update for about seven years. In that time, there have been large advancements made in computing, including much more widespread access to broadband, a general increase in broadband speeds, and a massive shift to mobility and multi-device accessibility. For this reason, Flickr of 2012 looked quite dated, primarily based on a low-bandwidth thumbnail focus, generally displaying one higher resolution image at a time. Furthermore, the Flickr before the redesign did not take advantage of many of the affordances of newer browser technologies.

flickr-how-they-did-it-large

Flickr of yesteryear

Parallax - Flickr is Doing it Right

We've posted about parallax on Tuts+ plenty of times before. When opening a conversation about parallax techniques, one of the first issues addressed is performance. Too often, parallax is implemented in naive ways, like some variation of the following (or worse).

Note: this assumes the site is using jQuery..

$(window).on("scroll", function(){
  $(".parallax-item").each(function(){
    $(this).css({
      marginTop : $(window).scrollTop()*.5
    });
  });
});

For an example, check out this Pen!

What's wrong with this approach? First, every scroll event runs the function being called. There is no caching of JavaScript objects, no scroll throttling and as importantly, this doesn't take advantage of CSS3 transforms or hardware acceleration.

Making simple changes can help dramatically increase performance in scroll-event-powered interaction, and Flickr has done just that. Here are the primary JavaScript functions used in the parallax technique. (We've taken the liberty to add some comments for understanding's sake.)

(function () {

            // setting up variables to be used throughout
                var useTransform = true;
                var useParallax = true;
                var ua = navigator.userAgent;
                var winLoc = window.location.toString();

                // useragent matching for progressive enhancements
                var is_webkit = ua.match(/webkit/i);
                var is_firefox = ua.match(/gecko/i);
                var is\_newer\_ie = ua.match(/msie (9|([1-9][0-9]))/i);
                var is\_older\_ie = ua.match(/msie/i) && !is\_newer\_ie;
                var is\_ancient\_ie = ua.match(/msie 6/i);
                var is_mobile = ua.match(/mobile/i);

                // to see the page's performance with 2d transforms (instead of 3d), visit http://www.flickr.com/#transform=2d
                var use2DTransform = (ua.match(/msie 9/i) || winLoc.match(/transform\=2d/i));
                var requestAnimationFrame = null;
                var prefixes, transform;
                var parallaxItems = [];
                var scrollHandler = null;
                var nodes;
                var lastExec = new Date();

                // The next two checks potentially used for debugging, or for specific devices or links.
                // To see the page's performance without transforms (margin-top implementation), visit http://www.flickr.com/#notransform
                if (winLoc.match(/notransform/i)) {
                    useTransform = false;
                }

                // to see the page without parallax, visit http://www.flickr.com/#noparallax
                if (winLoc.match(/noparallax/i)) {
                    useParallax = false;
                }

                // Check user agent variables to decide whether or not to use parallax.
                if (is_mobile || is\_ancient\_ie) {
                    useParallax = false;
                }

                // If the url has "useraf" in it, use request animation frame
                if (winLoc.match(/useraf/i)) {
                    requestAnimationFrame = (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame);
                }

                // setting up transform prefixes
                prefixes = {
                    webkit: 'webkitTransform',
                    firefox: 'MozTransform',
                    ie: 'msTransform',
                    w3c: 'transform'
                };
                if (useTransform) {
                    if (is_webkit) {
                        transform = prefixes.webkit;
                    } else if (is_firefox) {
                        transform = prefixes.firefox;
                    } else if (is\_newer\_ie) {
                        transform = prefixes.ie;
                    }
                }

                // The main function for parallax items
                // takes a containerNode param, which is the relative-positioned
                // parent of the absolutely positioned parallax image.
                function ParallaxItem(containerNode) {
                    // set up some vars for caching values throughout
                    var container, bgElements, offset, bgHeight, containerHeight, maxScrolls, height;

                    // cache a YUI-wrapped instance of the container, similar to $(containerNode) in jQuery
                    container = Y.one(containerNode);
                    // get the elements with a class of "parallax-background" inside the container.
                    // the homepage only has one element per container, but this could scale to have multiple bg items
                    bgElements = container.all('.parallax-background');


                    // function to refresh variables for each parallax item
                    function refreshCoords() {
                        offset = container.getY();
                        containerHeight = container.get('offsetHeight');
                        bgHeights = [];
                        maxScrolls = [];
                        bgElements.each(function (item) {
                            height = item.get('offsetHeight');
                            bgHeights.push(height);
                            // max scroll of each container is the
                            // container's offsetHeight - parallax item's offset height + 2
                            maxScrolls.push(containerHeight - height + 2);
                        });
                    }

                    // the actual parallax moving function
                    function refresh(docScrollY) {
                        var i, j, scroll, transformParam;
                        i = 0;
                        bgElements.each(function (bgElement) {
                            // scroll is set to the max of the element's maxscroll and the
                            // document's scroll position minus the offset of the current container
                            // divided by the container's height multiplied by the max scroll.
                            scroll = -Math.round(((docScrollY - offset) / containerHeight) * maxScrolls[i]);
                            scroll = Math.max(scroll, maxScrolls[i]);
                            var transformParam;
                            if (!use2DTransform) {
                                transformParam = 'translate3d(0px,' + scroll + 'px, 0px)';
                            } else {
                                transformParam = 'translateY(' + scroll + 'px)';
                            } if (transform && transformParam) {
                                bgElement.setStyle(transform, transformParam);
                                bgElement.setStyle(prefixes.w3c, transformParam);
                            } else {
                                bgElement.setStyle('marginTop', scroll + 'px');
                            }
                            i++;
                        });
                    }
                    refreshCoords();
                    return {
                        'refresh': refresh,
                        'refreshCoords': refreshCoords
                    }
                }

                // this runs the parallax mover "refresh" function if there are parallax items,
                // passing in the current scroll position of the document
                function refreshParallaxItems() {
                    var docScrollY = Y.DOM.docScrollY();
                    if (!parallaxItems || !parallaxItems.length) {
                        return false;
                    }
                    for (var i = 0, j = parallaxItems.length; i < j; i++) {
                        parallaxItems[i].refresh(docScrollY);
                    }
                }
                function scrollWatcher() {
                    if (requestAnimationFrame) {
                        requestAnimationFrame(refreshParallaxItems);
                    } else {
                        refreshParallaxItems();
                    }
                }
                function addParallaxItem(containerNode) {
                    parallaxItems.push(new ParallaxItem(containerNode));
                    if (!scrollHandler) {
                        scrollHandler = Y.on('scroll', scrollWatcher);
                    }
                }
                // finally, this actually goes through the parallax items and adds them to memory,
                // which sets up all of the event watching, etc
                if (useParallax) {
                    nodes = Y.all('#flickr-frames .parallax-item');
                    nodes.each(function (item) {
                        addParallaxItem(item);
                    });
                    // Whenever a PhotoListView is rendered,
                    // refresh the coordinates of the parallax pieces
                    Y.on('PhotoListView:render', function () {
                        var now = new Date();
                        if (now - lastExec > 250) {
                            for (var i = 0, j = parallaxItems.length; i < j; i++) {
                                parallaxItems[i].refreshCoords();
                            }
                            lastExec = now;
                        }
                    });
                    // Load in the coordinates of the parallax pieces when the document loads
                    refreshParallaxItems();
                }
            }());

Check out the comments we've added to get a fuller understanding of what's happening here. This may seem a bit daunting, especially if you aren't familiar with Yahoo!'s YUI node JS utilities. Instead of getting caught up on all of the details of this code, let's look at a few specific important pieces that matter.

First we see the extensive use of variable caching. This includes setting up max heights, offsets, etc in a refresh. Next, we see use of progressive enhancement to define when to use 3D, 2D, or no transforms. This greatly improves performance for newer browsers. Furthermore, 3D transforms are supported in all current major browsers (except Opera and Opera Mini), which means a significant performance improvement by way of hardware acceleration, which kicks in when using 3D transforms on a given element. (Check out this article for more information). This helps the homepage realize much higher framerates - usually at or above 60fps.

It's interesting to note that the Flickr dev team left some seemingly unused pieces in the source code, like url-based functionality switches that enable or disable things like parallax and transforms. Perhaps this is used for certain device redirects; this may have been a debugging technique the dev team forgot to take out. It also could be a callout to devs to play around with the application and see the performance benefits of using these different techniques. Whatever it is, it's a blast to play around with once you find it, and has virtually no performance impact.

One more note about the parallax implementation: Flickr has completely avoided using background-size for the image containers, and has avoided "full-screen" sizing as well, opting instead for generally min-height parallax container elements. Why? Performance of background-size:cover is terrible, causing low framerates and generally a degraded user experience. Instead, Flickr has chosen to load larger background images; 2048x850, to be exact. This covers the width of almost any screen, and provides enough height to do an effective parallax implementation. Browser repaints are reduced significantly as well.

CSS3 Powered Call-to-action

In a throttled scroll-watching function, the final call-to-action at the bottom of the Flickr homepage transitions in as the user scrolls over a wall of horizontally justified photos from users. The animation is powered by CSS3 transitions, including a 12px webkit blur filter, opacity, and scaling. The call to action includes large typography (10em or 144px to be exact), and a fittingly large CSS3-styled button.

flickr-how-they-did-it-signup

Here is the CSS for the button.

/* Webdesigntuts+ note: browser-specific prefixes removed */
display: inline-block;
padding: 0px 2em 5px 2em;
font-size: 2em;
line-height: 1.75em;
font-weight: 400;
text-decoration: none;
background: #ff0084;
color: #fff;
box-shadow: 0px 2px 8px rgba(0,0,0,0.5);
border-radius: 5px;
background-image: linear-gradient(bottom, rgb(215,0,104) 35%, rgb(243,0,111) 84%);
background-clip: padding-box;

Fairly straightforward, but effective. The internal site once a user has signed up has similarly large elements, like the upload form.

Other Polish and Best Practices

Small enhancements throughout the homepage also work to improve user experience. For instance, the megapixel slider utilizes an inline data uri for the handle, while the slider trough solely uses css gradients and other definitions. No http requests are required for any part of the slider, other than its associated JavaScript.

Very slight text shadows are used on the headers to lift them off of their associated background images a bit. Semi-transparent (RGBa) background colors are being used for the top navigation bar as well as the image wall titles. Flickr is also using Mustache templates for the image wall. All of these elements allude to the fact that Flickr is getting a push towards maintaining a much more leading-edge front-end design.

Criticism

Here are a few thoughts about things that could be better with the new Flickr, or that you may consider in your development practices.

Responsive Implementation

Right now, the mobile strategy adopted by Flickr relies on two main points: native applications and a mobile specific site. The mobile specific site is much less attractive than the desktop version. Considering the simple fact that mobile is growing faster than ever, this redesign could and should be reconsidered as an opportunity to adopt responsive strategies. The desktop version of the site is less than ideal at anything lower than 960px. This throws out many smaller tablets and almost any phone.

Minified, Less, More Specific JavaScript

Best practices tell us that marketing-driven, call-to-action homepages and splash pages are not the best place to load application content. However, Some of the scripts loaded on Flickr.com's new homepage are used throughout the rest of the application. It would be benefical to, instead, create a single, smaller JavaScript file that relies less on the YUI library, and more on simple event listeners, selectors, and AJAX functions.

That JavaScript file needs to be minified as well; however, it may be the case that it isn't minified for the sake of developers who want to peek at the source. (See the developer callout at the end of this article.)

UA Sniffing is Unreliable

User-agent sniffing is bad news unless you thoroughly check every string with every device (less practical than is useful). Unfortunately, using a simple string like "mobile" as Flickr is doing here isn't enough to definitively say whether or not we're on a mobile device. Sure, this may cover a significant percentage of devices, let's say even 99%, but when that's 99% of 200 million people, youre leaving 2,000,000 devices out.

It's also unlikely that using something that enhances performance drastically, like transforms, should be limited by simple UA sniffing. Instead, using a feature detection suite like Modernizr would be more beneficial and more definitive of the user's browser abilities. Seeing as Modernizr is backed by some of the folks at Google, it's not surprising we don't see it included on Flickr, but the underlying concept is simple, and the tests are easily replicable.

OpenGraph Tags

OpenGraph tags are essential to sharing a site on Facebook. Sharing a site on Facebook is a basic function of the web for many users. Unfortunately, if a site doesn't specifically implement OpenGraph meta tags, the shared link item looks fairly bare on a Facebook news feed.

If Flickr is indeed competing with Facebook, this may be a gamble that it will help them turn people against Facebook, or disassociate Flickr from Facebook entirely. Or, it could just be an oversight. Either way, it makes me (and likely some other users) avoid sharing Flickr.com with my Facebook friends.

Copywriting Considerations

Okay, we get that Flickr (and Tumblr) don't like er's. But, there comes a point where removing letters from words gets annoying and cheesy, and even difficult to read. Flickr is edging on that line. Using things like "Biggr", "Spectaculr", and "Wherevr" arguably don't improve the branding or user experience. Flickr is the name of the service; "bigger" describes a new feature of that service. Otherwise, why not also change "follower" to "followr", or "developer" to "developr"? Because it doesn't make sense and sounds alienatingly strange. Consider Apple's incredibly effective advertising copywriting; "iPad" does not translate into copy like "Take your iMac with you, iAnywhere".


Bonus: A Callout to Developers

An interesting piece Yahoo! included in the source for Flickr is a callout to front-end devs, with news that Flickr is hiring. This cool ascii logo can be found in the head tag.

<head>



   ad88 88 88            88                  
  d8"   88 ""            88                  
  88    88               88                  
d88888d 88 88  ,adPPYba, 88   ,d8  8b,dPPYba,
  88    88 88 a8"     "" 88 ,a8"   88P'   "Y8
  88    88 88 8b         8888[     88        
  88    88 88 "8a,   ,aa 88`"Yba,  88        
  88    88 88  `"Ybbd8"' 88   `Y8a 88
You're reading. We're hiring.
http://flickr.com/jobs/

What Will Happen to Tumblr?

Known for its younger audience with a propensity to be more brash than, say, Blogger users, but less brash than Redditors, Tumblr sits in a unique position having been acquired by a giant like Yahoo!.

flickr-how-they-did-it-tumblr-yahoo

Will Yahoo! kill the free-form nature of Tumblr's content creation? Will Flickr and Tumblr become integrated, so that users can publish Flickr photos automatically to Tumblr? Or will Tumblr transparently continue to exist, with simply a new terms of service that allows Yahoo! to collect and use data from Tumblr's 109 million blogs and 51.2 billion posts? It could be an incredible source of data to Yahoo!, who seem to be in acquisition mode, acquiring PlayerScale days after acquiring Tumblr.


What do You Think?

Let us know what you think of the new Flickr, and what you think about the future of Tumblr under Yahoo!'s direction, in the comments!

Advertisement