The Windows 7 Guide: From Newbies to Pros

Get Started

Welcome Back, ().

at

Has your work information changed?

Welcome

Please review the fields below for completeness and accuracy prior to submitting.

Welcome Back, ().

Has your work information changed?

Please Correct the Highlighted Fields Below:

Complete the form below:















Yes No

The Mac Manual

Get Started

Welcome Back, ().

at

Has your work information changed?

Welcome

Please review the fields below for completeness and accuracy prior to submitting.

Welcome Back, ().

Has your work information changed?

Please Correct the Highlighted Fields Below:

Complete the form below:















Yes No

How To Scale React Applications

How To Scale React Applications

We recently released version 3 of React Boilerplate1, one of the most popular React starter kits, after several months of work. The team spoke with hundreds of developers about how they build and scale their web applications, and I want to share some things we learned along the way.

2
The tweet that announced3 the release of version 3 of React Boilerplate

We realized early on in the process that we didn’t want it to be “just another boilerplate.” We wanted to give developers who were starting a company or building a product the best foundation to start from and to scale.

Traditionally, scaling was mostly relevant for server-side systems. As more and more users would use your application, you needed to make sure that you could add more servers to your cluster, that your database could be split across multiple servers, and so on.

Nowadays, due to rich web applications, scaling has become an important topic on the front end, too! The front end of a complex app needs to be able to handle a large number of users, developers and parts. These three categories of scaling (users, developers and parts) need to be accounted for; otherwise, there will be problems down the line.

Containers And Components Link

The first big improvement in clarity for big applications is the differentiation between stateful (“containers”) and stateless (“components”) components. Containers manage data or are connected to the state and generally don’t have styling associated with them. On the other hand, components have styling associated with them and aren’t responsible for any data or state management. I found this confusing at first. Basically, containers are responsible for how things work, and components are responsible for how things look.

Splitting our components like this enables us to cleanly separate reusable components and intermediary layers of data management. As a result, you can confidently go in and edit your components without worrying about your data structures getting messed up, and you can edit your containers without worrying about the styling getting messed up. Reasoning through and working with your application become much easier that way, the clarity being greatly improved!

Structure Link

Traditionally, developers structured their React applications by type. This means they had folders like actions/, components/, containers/, etc.

Imagine a navigation bar container named NavBar. It would have some state associated with it and a toggleNav action that opens and closes it. This is how the files would be structured when grouped by type:

react-app-by-type ├── css ├── actions │ └── NavBarActions.js ├── containers │ └── NavBar.jsx ├── constants │ └── NavBarConstants.js ├── components │ └── App.jsx └── reducers └── NavBarReducer.js

While this works fine for examples, once you have hundreds or potentially thousands of components, development becomes very hard. To add a feature, you would have to search for the correct file in half a dozen different folders with thousands of files. This would quickly become tedious, and confidence in the code base would wane.

After a long discussion in our GitHub issues tracker and trying out a bunch of different structures, we believe we have found a much better solution:

Instead of grouping the files of your application by type, group them by feature! That is, put all files related to one feature (for example, the navigation bar) in the same folder.

Let’s look at what the folder structure would look like for our NavBar example:

react-app-by-feature ├── css ├── containers │ └── NavBar │ ├── NavBar.jsx │ ├── actions.js │ ├── constants.js │ └── reducer.js └── components └── App.jsx

Developers working on this application would need to go into only a single folder to work on something. And they would need to create only a single folder to add a new feature. Renaming is easy with find and replace, and hundreds of developers could work on the same application at once without causing any conflicts!

When I first read about this way of writing React applications, I thought, “Why would I ever do that? The other way works absolutely fine!” I pride myself on keeping an open mind, though, so I tried it on a small project. I was smitten within 15 minutes. My confidence in the code base was immense, and, with the container-component split, working on it was a breeze.

It’s important to note that this doesn’t mean the redux actions and reducers can only be used in that component. They can (and should) be imported and used from other components!

Two questions popped into my head while working like this, though: “How do we handle styling?” and “How do we handle data-fetching?” Let me tackle these separately.

Styling Link

Apart from architectural decisions, working with CSS in a component-based architecture is hard due to two specific properties of the language itself: global names and inheritance.

Unique Class Names Link

Imagine this CSS somewhere in a large application:

.header { /* … */ } .title { background-color: yellow; }

Immediately, you’ll recognize a problem: title is a very generic name. Another developer (or maybe even the same one some time later) might go in and write this code:

.footer { /* … */ } .title { border-color: blue; }

This will create a naming conflict, and suddenly your title will have a blue border and a yellow background everywhere, and you’ll be digging into thousands of files to find the one declaration that has messed everything up!

Thankfully, a few smart developers have come up with a solution to this problem, which they’ve named CSS Modules4. The key to their approach is to co-locate the styles of a component in their folder:

react-app-with-css-modules ├── containers └── components └── Button ├── Button.jsx └── styles.css

The CSS looks exactly the same, except that we don’t have to worry about specific naming conventions, and we can give our code quite generic names:

.button { /* … */ }

We then require (or import) these CSS files into our component and assign our JSX tag a className of styles.button:

/* Button.jsx */ var styles = require('./styles.css'); <div className={styles.button}></div> 

If you now look into the DOM in the browser, you’ll see <div></div>! CSS Modules takes care of “uniquifying” our class names by prepending the application’s name and postpending a short hash of the contents of the class. This means that the chance of overlapping classes is almost nil, and if they overlap, they will have the same contents anyway (because the hash — that is, the contents — has to be the same).

Reset Properties For Each Component Link

In CSS, certain properties inherit across nodes. For example, if the parent node has a line-height set and the child doesn’t have anything specified, it will automatically have the same line-height applied as the parent.

In a component-based architecture, that’s not what we want. Imagine a Header component and a Footer component with these styles:

.header { line-height: 1.5em; /* … */ } .footer { line-height: 1; /* … */ }

Let’s say we render a Button inside these two components, and suddenly our buttons look different in the header and footer of our page! This is true not only for line-height: About a dozen CSS properties will inherit, and tracking down and getting rid of those bugs in your application would be very hard.

In the front-end world, using a reset style sheet to normalize styles across browsers is quite common. Popular options include Reset CSS, Normalize.css and sanitize.css! What if we took that concept and had a reset for every component?

This is called an auto-reset, and it exists as a plugin for PostCSS5! If you add PostCSS Auto Reset6 to your PostCSS plugins, it’ll do this exactly: wrap a local reset around each component, setting all inheritable properties to their default values to override the inheritances.

Data-Fetching Link

The second problem associated with this architecture is data-fetching. Co-locating your actions to your components makes sense for most actions, but data-fetching is inherently a global action that’s not tied to a single component!

Most developers at the moment use Redux Thunk7 to handle data-fetching with Redux. A typical thunked action would look something like this:

/* actions.js */ function fetchData() { return function thunk(dispatch) { // Load something asynchronously. fetch('https://someurl.com/somendpoint', function callback(data) { // Add the data to the store. dispatch(dataLoaded(data)); }); } }

This is a brilliant way to allow data-fetching from the actions, but it has two pain points: Testing those functions is very hard, and, conceptually, having data-fetching in the actions doesn’t quite seem right.

A big benefit of Redux is the pure action creators, which are easily testable. When returning a thunk from an action, suddenly you have to double-call the action, mock the dispatch function, etc.

Recently, a new approach has taken the React world by storm: redux-saga8. redux-saga utilizes Esnext generator functions to make asynchronous code look synchronous, and it makes those asynchronous flows very easy to test. The mental model behind sagas is that they are like a separate thread in your application that handles all asynchronous things, without bothering the rest of the application!

Let me illustrate with an example:

/* sagas.js */ import { call, take, put } from 'redux-saga/effects'; // The asterisk behind the function keyword tells us that this is a generator. function* fetchData() { // The yield keyword means that we'll wait until the (asynchronous) function // after it completes. // In this case, we wait until the FETCH_DATA action happens. yield take(FETCH_DATA); // We then fetch the data from the server, again waiting for it with yield // before continuing. var data = yield call(fetch, 'https://someurl.com/someendpoint'); // When the data has finished loading, we dispatch the dataLoaded action. put(dataLoaded(data)); }

Don’t be scared by the strange-looking code: This is a brilliant way to handle asynchronous flows!

The source code above almost reads like a novel, avoids callback hell and, on top of that, is easy to test. Now, you might ask yourself, why is it easy to test? The reason has to do with our ability to test for the “effects” that redux-saga exports without needing them to complete.

These effects that we import at the top of the file are handlers that enable us to easily interact with our redux code:

  • put() dispatches an action from our saga.
  • take() pauses our saga until an action happens in our app.
  • select() gets a part of the redux state (kind of like mapStateToProps).
  • call() calls the function passed as the first argument with the remaining arguments.

Why are these effects useful? Let’s see what the test for our example would look like:

/* sagas.test.js */ var sagaGenerator = fetchData(); describe('fetchData saga', function() { // Test that our saga starts when an action is dispatched, // without having to simulate that the dispatch actually happened! it('should wait for the FETCH_DATA action', function() { expect(sagaGenerator.next()).to.equal(take(FETCH_DATA)); }); // Test that our saga calls fetch with a specific URL, // without having to mock fetch or use the API or be connected to a network! it('should fetch the data from the server', function() { expect(sagaGenerator.next()).to.equal(call(fetch, 'https://someurl.com/someendpoint')); }); // Test that our saga dispatches an action, // without having to have the main application running! it('should dispatch the dataLoaded action when the data has loaded', function() { expect(sagaGenerator.next()).to.equal(put(dataLoaded())); }); });

Esnext generators don’t go past the yield keyword until generator.next() is called, at which point they run the function, until they encounter the next yield keyword! By using the redux-saga effects, we can thus easily test asynchronous things without needing to mock anything and without relying on the network for our tests.

By the way, we co-locate the test files to the files we are testing, too. Why should they be in a separate folder? That way, all of the files associated with a component are truly in the same folder, even when we’re testing things!

If you think this is where the benefits of redux-saga end, you’d be mistaken! In fact, making data-fetching easy, beautiful and testable might be its smallest benefits!

Using redux-saga as Mortar Link

Our components are now decoupled. They don’t care about any other styling or logic; they are concerned solely with their own business — well, almost.

Imagine a Clock and a Timer component. When a button on the clock is pressed, we want to start the timer; and when the stop button on the timer is pressed, you want to show the time on the clock.

Conventionally, you might have done something like this:

/* Clock.jsx */ import { startTimer } from '../Timer/actions'; class Clock extends React.Component { render() { return ( /* … */ <button onClick={this.props.dispatch(startTimer())} /> /* … */ ); } }
/* Timer.jsx */ import { showTime } from '../Clock/actions'; class Timer extends React.Component { render() { return ( /* … */ <button onClick={this.props.dispatch(showTime(currentTime))} /> /* … */ ); } }

Suddenly, you cannot use those components separately, and reusing them becomes almost impossible!

Instead, we can use redux-saga as the “mortar” between these decoupled components, so to speak. By listening for certain actions, we can react (pun intended) in different ways, depending on the application, which means that our components are now truly reusable.

Let’s fix our components first:

/* Clock.jsx */ import { startButtonClicked } from '../Clock/actions'; class Clock extends React.Component { /* … */ <button onClick={this.props.dispatch(startButtonClicked())} /> /* … */ }
/* Timer.jsx */ import { stopButtonClicked } from '../Timer/actions'; class Timer extends React.Component { /* … */ <button onClick={this.props.dispatch(stopButtonClicked(currentTime))} /> /* … */ }

Notice how each component is concerned only with itself and imports only its own actions!

Now, let’s use a saga to tie those two decoupled components back together:

/* sagas.js */ import { call, take, put, select } from 'redux-saga/effects'; import { showTime } from '../Clock/actions'; import { START_BUTTON_CLICKED } from '../Clock/constants'; import { startTimer } from '../Timer/actions'; import { STOP_BUTTON_CLICKED } from '../Timer/constants'; function* clockAndTimer() { // Wait for the startButtonClicked action of the Clock // to be dispatched. yield take(START_BUTTON_CLICKED); // When that happens, start the timer. put(startTimer()); // Then, wait for the stopButtonClick action of the Timer // to be dispatched. yield take(STOP_BUTTON_CLICKED); // Get the current time of the timer from the global state. var currentTime = select(function (state) { return state.timer.currentTime }); // And show the time on the clock. put(showTime(currentTime)); }

Beautiful.

Summary Link

Here are the key takeaways for you to remember:

  • Differentiate between containers and components.
  • Structure your files by feature.
  • Use CSS modules and PostCSS Auto Reset.
  • Use redux-saga to:
    • have readable and testable asynchronous flows,
    • tie together your decoupled components.

(il, vf, al)

Footnotes Link

  1. 1 https://github.com/mxstbr/react-boilerplate
  2. 2 https://twitter.com/mxstbr/status/732833839140229120
  3. 3 https://twitter.com/mxstbr/status/732833839140229120
  4. 4 https://github.com/css-modules/css-modules
  5. 5 http://postcss.org/
  6. 6 https://github.com/maximkoretskiy/postcss-autoreset
  7. 7 https://github.com/gaearon/redux-thunk
  8. 8 https://github.com/yelouafi/redux-saga
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Breaking Out Of The Box: Design Inspiration (September 2016)

Breaking Out Of The Box: Design Inspiration (September 2016)

Inspiration isn’t tied to a specific timeframe or shows up when you need it. There isn’t a magic formula to rely on. Luckily, this year’s summer vacation was fruitful in providing us with many visual stimuli to get the creative process going. Enjoy!

The Hollywood Reporter Link

This editorial illustration for the Hollywood Reporter has a really nice style. The face expressions are so well done with just a few simple lines. That’s not easy to accomplish!

1
Image credit: Ale Giorgini2. (Large preview3)

Wanderlust Alphabet #A Link

A fantastic series to get the travel bug. Just by looking at this you’ve probably already guessed that the ‘A’ in this case stands for ‘Amsterdam’. Lovely usage of two complimentary colors cleverly applied, especially to add depth into shadows and highlights.

4
Image credit: Jack Daly5. (Large preview6)

Wanderlust Alphabet #B Link

Second installment of the travel bug illustrations I’ll be sure to follow. The letter ‘B’ stands for ‘BarcelonaÄ. Again, look at how depth is created by using a strong color palette and this beautiful clean 2D style. The famous parts of this city are so well done with such simple lines.

7
Image credit: Jack Daly8. (Large preview9)

Giphy Pool Link

James Curran is one of the masters of animated gifs to watch. This one made laugh and is so colorfully pleasant. And look at that jump! Just perfect.


Image credit: James Curran10>

Slack — Work Simplified Link

Great integration of the colors used by Slack11. It shows how crazy work life is. Beautiful illustration style. Just perfect branding material.

12
Image credit: Multiple Owners13. (Large preview14)

Stamps Inspired (1965) Link

Illustration based on original stamps from Bulgaria. Quite beautiful! I love the bright yellow in combination with the darker color, as well as the red and orange tones.

15
Image credit: Fe Ribeiro16. (Large preview17)

Saga Magazine Link

I first noticed the interesting structure/texture that works so well with the chosen colors. Love the circles, and ‘straight’ 90° lines — very geometrical. Feels a bit like a puzzle.

18
Image credit: Jonny Wan19. (Large preview20)

Vans Surf Pro Classic Link

The colors just pop so magnificently off the screen in this surf-related illustration. Very fitting for the subject. Inspiration came from late 80s and 90s surf artwork.

21
Image credit: Ian Jepson22. (Large preview23)

Firenze Duomo Link

Lovely illustration of the Duomo in Florence. Color palette is on point. Tasty texture, too. Simply beautiful to look at and get inspired.

24
Image credit: Bailey Sullivan25. (Large preview26)

In The Woods Link

Well taken shot of one of my favorite moments in the month of May. The smell is just overwhelming of these beautiful bluebells. Magical light and bokeh.

27
Image credit: Kirstin Mckee28. (Large preview29)

Mastercard Campaign Link

Some clever use of white space. The dog is just so awesomely done.

30
Image credit: Stephen Kelleher31. (Large preview32)

City Bike Miami Link

Love the eyes and the illusion of the hair in the wind. Same with the dog ears, so cute. That lovely summer feeling on the bike! Perfectly expressed.

33
Image credit: Pietari Posti34. (Large preview35)

Umami Link

An illustration which takes on curiosity and exploration of different tastes and flavors. It’s a great composition and an inspiring color palette.

36
Image credit: Aleksandar Savić1054337. (Large preview38)

Cinque Terre Link

Great color scheme! Illustration that documents a trip to Italy to see Cinque Terre. It’s a must-see apparently. The geometry combined with how the colors are applied is just so perfect.

39
Image credit: Bailey Sullivan40. (Large preview41)

Protected Trees Link

An illustration for The Telegraph‘s property section on buying a home with protected trees in vicinity. Some inspiring choices of shapes and lines.

42
Image credit: Aleksandar Savić1054337. (Large preview44)

Shop Magazine — Eye Blue Link

If you like interesting collages, you’ll love the work of Jimmy Turell. The colors and the half-tone effects are the items that made me pick this one.

45
Image credit: Jimmy Turell46. (Large preview47)

Year In Ideas (2014) Link

Created for Wired48. Another color combo that works wonderfully well together. I always look at how things are constructed, and I’m quite impressed by this illustration.

49
Image credit: Vesa Sammalisto50. (Large preview51)

The Westfjords Link

Beautiful colors of the sky — almost like fire.

52
Image credit: Conor MacNeill53. (Large preview54)

Saison Link

Wonderful die cut beer label design. I always admire such great lettering work. Be sure to check the rest of Ben Didier’s the portfolio55 as there is some stellar lettering work in there.

56
Image credit: Ben Didier57. (Large preview58)

Wanderlust Alphabet #C Link

The third installment in the Wanderlust alphabet that Jack Daly is creating. This time I believe the ‘C’ stands for ‘Copenhagen’. Interesting palette of colors in this one.

59
Image credit: Jack Daly60. (Large preview61)

No-Li Small Batch Festival Link

Nice logo for the No-Li Brewhouse’s Small Batch Festival. The different styles of typefaces really work well together. Beautiful and elegant!

62
Image credit: Riley Cran63. (Large preview64)

SHOP Magazine Austria Spring/Summer 2016 Link

The cover illustration for the spring edition of SHOP magazine in Austria. It depicts the Museum quarter of Vienna. Lovely combination of geometrical and elegant organic lines. Such perfect soft color tones combined with a few more brighter accents.

65
Image credit: Andrew Lyons66. (Large preview67)

Girl On The Go Link

Such a wonderful scene! Especially the colors used and the inspiring details such as the skirt of the woman and the boots of the guy sitting on the bench on the right.

68
Image credit: Steve Scott69. (Large preview70)

Wanderlust Alphabet #D Link

The fourth installment in the Wanderlust alphabet that Jack Daly is creating. This time the ‘D’ stands for ‘Dublin’. Just look at how shadows and highlights are applied — such perfect contrast.

71
Image credit: Jack Daly72. (Large preview73)

An Afternoon At Miticocha Link

Well worth a two-hour round-trip hike I would say if you get to see a scenery like this. This place has a beautiful view of Ninachanca, Jirishanca, and Jirishanca Chico. Pure wanderlust!

74
Image credit: Zolashine75. (Large preview76)

Ponderosa 2016 Link

Not just because there’s a bicycle in it 😉 Most of all picked because it has a wonderful composition with fine details.

77
Image credit: Mads Berg78. (Large preview79)

Music Girls Link

A wonderful fusion between contemporary and retro. Some inspiring texture work going on in there as well. The wooden floor and the little details on the faces — look at those eyes!

80
Image credit: Loris Lora81. (Large preview82)

Facebook Events — Naomi Link

Part of a set of illustrations created for Facebook’s event cover images. Totally loving these colors! Lovely simplistic style, too.

83
Image credit: Naomi Wilkinson84. (Large preview85)

Hiding Behind Mom Link

A great example of what is possible with a few pencil strokes. The socks on the girl are adorable.

86
Image credit: Simona Ciraolo87. (Large preview88)

Look Around Link

An illustration to get the travel bug going. Great style and subtle usage of textures. For a touristic guide of the Garda Lake.

89
Image credit: Federica Bordoni90. (Large preview91)

Summertime Link

“Let the waves hit your feet and the sand be your seat!” Exactly. I love compositions where there is much to discover. Great mix of colors.

92
Image credit: Putri Febriana93. (Large preview94)

Summer Bike Ride Link

Love how the diagonal line adds to the whole composition. Subtle use of shadows and transparency. Such perfect curved lines, especially hair and hat are done so perfectly in every way. Looking at this makes me want to go outside and ride.

95
Image credit: Tjeerd Broere96. (Large preview97)

Wanderlust Alphabet #E Link

The fifth installment in the Wanderlust alphabet that Jack Daly is creating. This time the ‘E’ stands for ‘Edinburgh’. The color treatment is great again. So many good details.

98
Image credit: Jack Daly99. (Large preview100)

American Illustration 33 Link

Super clean and the character really gets your attention. Love how the stockings are done. So simple, yet so elegant.

101
Image credit: Federica Bordoni102. (Large preview103)

Procesni Mehanize Link

Illustrating the never-ending cycle. I always love to analyze the many elements that make a fantastic illustration. You can learn a lot from it.

104
Image credit: Aleksandar Savić1054337. (Large preview106)

Blossom Link

One of the hardest things to get right is shooting directly into sunlight. This one nails it beautifully. Summer vibes!

107
Image credit: Anders Jildén108. (Large preview109)

Focus Magazine Illustration Link

Adorable cuteness and great usage of some basic shapes. Look at that cute mustache of the guy on the left. The color palette is absolutely perfect.

110
Image credit: Loulou and Tummie111. (Large preview112)

The Joy Of New Roads Link

Getting out on your bicycle and discovering new roads and amazing sceneries is a joy hard to describe in words. Lovely light in this photo.

113
Image credit: David Marcu114. (Large preview115)

City Guide Berlin-London-Paris Link

Inspiring arrangement of all the different items in this composition. Beautiful 2D style with lovely subtle textures and patterns to finish things off. The colors also draw you in.

116
Image credit: Maite Franchi117. (Large preview118)

Velorama — Lightyear Link

Love the combination of line art and typography. Looks so elegant! The bike is so well drawn. It shines! Look at the frame, the handlebars and the saddle.

119
Image credit: Silence TV120. (Large preview121)

Els Amos Ocults Del Totxo Link

The Brickmasters in the Shadows. Great editorial illustration. The duplication of the gentleman withthe hat is the eye-catcher. The chosen colors make the whole scene complete.

122
Image credit: Raúl Soria123. (Large preview124)

Bison Link

Right on target! Love what is done with the lines here.

125
Image credit: Matt Carlson126. (Large preview127)

No Man’s Sky Link

Pretty fly! It looks highly complicated but is quite simplistic at the same time. The color scheming is on point, too. The subtle background gradient is so perfect.

128
Image credit: Justin Mezzell129. (Large preview130)

FiveThirtyEight Election Link

This looks fantastic! The many layers of typography are so inspiring.

131
Image credit: Bethany Heck132. (Large preview133)

The Secret To Sleep Link

Lovely muted color palette for starters and some subtle textures work in combination with double shading makes this interesting. I really love the imagination and fantasy.

134
Image credit: Owen Davey135. (Large preview136)

On Geoengineering Link

Created for an editorial piece about geoengineering. Love how it all has been translated to the screen.

137
Image credit: Raúl Soria138. (Large preview139)

Bicycle Adventure Meeting (BAM) Link

In my opinion, a bit of humor always adds something special to any illustration. This one is about the Bicycle Adventure Meeting, a place where lonely, adventurous bike travelers join together. The lovely bright colors give this illustration a happy feeling.

140
Image credit: Fabio Consoli141. (Large preview142)

Brooklyn Bridge Link

Well captured! The tranquility of the water is what does it for me. Just the right shutter speed I’m assuming to get the effect.

143
Image credit: Alexander Rotker144. (Large preview145)

SHOP Magazine — Czech Republic Link

Charming textured style and an inspiring color palette.

146
Image credit: Maïté Franchi147. (Large preview148)

Bicycling Magazine Link

Editorial illustration for an article on the importance of teamwork when learning road biking. I like how the three guys are nicely aligned and how the legs are drawn. As an illustrator, you have the freedom to break with reality in order to achieve beautiful compositions.

149
Image credit: Douglas Jones150. (Large preview151)

(yk, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2016/09/hollywood-reporter-ale-big-opt.jpg
  2. 2 https://www.behance.net/gallery/41166307/Editorial-Illustration-vol-1
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2016/09/hollywood-reporter-ale-big-opt.jpg
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2016/09/wanderlust-series-A-big-opt.jpg
  5. 5 https://dribbble.com/shots/2872483-Wanderlust-Alphabet
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/09/wanderlust-series-A-big-opt.jpg
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/09/wanderlust-series-B-big-opt.jpg
  8. 8 https://dribbble.com/shots/2874109-Wanderlust-Alphabet
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/09/wanderlust-series-B-big-opt.jpg
  10. 10 https://dribbble.com/shots/2836393-LA-Gifathon-Day-13
  11. 11 https://slack.com/
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2016/09/work-simplified-slack-big-opt.jpg
  13. 13 https://www.behance.net/gallery/40894619/Slack-Work-Simplified
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/09/work-simplified-slack-big-opt.jpg
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/09/stamps-inspired-bulgaria-big-opt.jpg
  16. 16 https://dribbble.com/shots/2876067-STAMPS-INSPIRED
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/09/stamps-inspired-bulgaria-big-opt.jpg
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/09/saga-magazine-big-opt.jpg
  19. 19 https://www.behance.net/gallery/41111981/Selected-Editorial-Work-01
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/09/saga-magazine-big-opt.jpg
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Vans-Surf-Pro-Classic-big-opt.jpg
  22. 22 https://www.behance.net/gallery/41053301/Vans-Surf-Pro-Classic
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Vans-Surf-Pro-Classic-big-opt.jpg
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/09/firenze-duomo-big-opt.jpg
  25. 25 https://dribbble.com/shots/2635802-Firenze
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/09/firenze-duomo-big-opt.jpg
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/09/in-the-woods-big-opt.jpg
  28. 28 https://www.flickr.com/photos/kirstinmckee/27120293751/
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/09/in-the-woods-big-opt.jpg
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Mastercard-campaign-big-opt.jpg
  31. 31 http://www.stephenkelleher.com/Mastercard-1
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Mastercard-campaign-big-opt.jpg
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2016/09/city-bike-miami-big-opt.jpg
  34. 34 http://agentpekka.com/artist/pietari-posti/citi-bike-miami-4/
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2016/09/city-bike-miami-big-opt.jpg
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Umami-big-opt.jpg
  37. 37 https://www.behance.net/gallery/41466863/Various-illustrations-2016
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Umami-big-opt.jpg
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Cinque-Terre-big-opt.jpg
  40. 40 https://dribbble.com/shots/2872019-Cinque-Terre
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Cinque-Terre-big-opt.jpg
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Protected-trees-big-opt.jpg
  43. 43 https://www.behance.net/gallery/41466863/Various-illustrations-2016
  44. 44 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Protected-trees-big-opt.jpg
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2016/09/eye-blue-big-opt.jpg
  46. 46 http://www.jimmyturrell.com/2011/09/19/various-collages/
  47. 47 https://www.smashingmagazine.com/wp-content/uploads/2016/09/eye-blue-big-opt.jpg
  48. 48 http://www.wired.com/
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2016/09/year-in-ideas-2014-big-opt.jpg
  50. 50 http://www.vesa-s.com/Wired-1
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2016/09/year-in-ideas-2014-big-opt.jpg
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/09/The-Westfjords-big-opt.jpg
  53. 53 https://www.flickr.com/photos/thefella/9155895849/
  54. 54 https://www.smashingmagazine.com/wp-content/uploads/2016/09/The-Westfjords-big-opt.jpg
  55. 55 https://dribbble.com/prettyuglydesign
  56. 56 https://www.smashingmagazine.com/wp-content/uploads/2016/09/saison-big-opt.jpg
  57. 57 https://dribbble.com/shots/2139224-Saison
  58. 58 https://www.smashingmagazine.com/wp-content/uploads/2016/09/saison-big-opt.jpg
  59. 59 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Wanderlust-Alphabet-C-big-opt.jpg
  60. 60 https://dribbble.com/shots/2881262-Travel-Letters-C-Dribbble
  61. 61 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Wanderlust-Alphabet-C-big-opt.jpg
  62. 62 https://www.smashingmagazine.com/wp-content/uploads/2016/09/no-li-small-batch-big-opt.jpg
  63. 63 http://www.2016.rileycran.com/#/no-li-small-batch-festival/
  64. 64 https://www.smashingmagazine.com/wp-content/uploads/2016/09/no-li-small-batch-big-opt.jpg
  65. 65 https://www.smashingmagazine.com/wp-content/uploads/2016/09/shop-magazine-austria-big-opt.jpg
  66. 66 http://www.lyonsa.com/SHOP-magazine-Austria
  67. 67 https://www.smashingmagazine.com/wp-content/uploads/2016/09/shop-magazine-austria-big-opt.jpg
  68. 68 https://www.smashingmagazine.com/wp-content/uploads/2016/09/girl-on-the-go-big-opt.jpg
  69. 69 https://www.behance.net/gallery/41530311/Editorial-projects-june-july-2016
  70. 70 https://www.smashingmagazine.com/wp-content/uploads/2016/09/girl-on-the-go-big-opt.jpg
  71. 71 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Wanderlust-Alphabet-D-big-opt.jpg
  72. 72 https://dribbble.com/shots/2885564-Wanderlust-Alphabet-D
  73. 73 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Wanderlust-Alphabet-D-big-opt.jpg
  74. 74 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Miticocha-big-opt.jpg
  75. 75 https://www.flickr.com/photos/zolashine/27570839274/
  76. 76 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Miticocha-big-opt.jpg
  77. 77 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Ponderosa-2016-big-opt.jpg
  78. 78 https://www.behance.net/gallery/41404221/Ponderosa-2016
  79. 79 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Ponderosa-2016-big-opt.jpg
  80. 80 https://www.smashingmagazine.com/wp-content/uploads/2016/09/music-girls-big-opt.jpg
  81. 81 http://www.lorislora.com/First-Aid-Kit
  82. 82 https://www.smashingmagazine.com/wp-content/uploads/2016/09/music-girls-big-opt.jpg
  83. 83 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Facebook-Events-Naomi-big-opt.jpg
  84. 84 http://naomiwilkinson.co.uk/Facebook-Events
  85. 85 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Facebook-Events-Naomi-big-opt.jpg
  86. 86 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Hiding-behind-mom-big-opt.jpg
  87. 87 http://simonaciraolo.com/illustration/
  88. 88 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Hiding-behind-mom-big-opt.jpg
  89. 89 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Garda-Lake-tourist-guide-big-opt.jpg
  90. 90 https://www.behance.net/gallery/11760603/Look-Around
  91. 91 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Garda-Lake-tourist-guide-big-opt.jpg
  92. 92 https://www.smashingmagazine.com/wp-content/uploads/2016/09/summertime-putri-big-opt.jpg
  93. 93 https://www.behance.net/gallery/24118509/Summertime
  94. 94 https://www.smashingmagazine.com/wp-content/uploads/2016/09/summertime-putri-big-opt.jpg
  95. 95 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Summer-bike-ride-tjeerd-big-opt.jpg
  96. 96 https://dribbble.com/shots/2909923-Summer
  97. 97 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Summer-bike-ride-tjeerd-big-opt.jpg
  98. 98 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Wanderlust-Alphabet-E-big-opt.jpg
  99. 99 https://dribbble.com/shots/2893203-Wanderlust-Alphabet-E
  100. 100 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Wanderlust-Alphabet-E-big-opt.jpg
  101. 101 https://www.smashingmagazine.com/wp-content/uploads/2016/09/American-Illustration-33-big-opt.jpg
  102. 102 https://www.behance.net/gallery/16752439/American-Illustration-33
  103. 103 https://www.smashingmagazine.com/wp-content/uploads/2016/09/American-Illustration-33-big-opt.jpg
  104. 104 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Procesni-Mehanize-big-opt.jpg
  105. 105 https://www.behance.net/gallery/41466863/Various-illustrations-2016
  106. 106 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Procesni-Mehanize-big-opt.jpg
  107. 107 https://www.smashingmagazine.com/wp-content/uploads/2016/09/blossom-big-opt.jpg
  108. 108 https://unsplash.com/photos/O85h02qZ24w
  109. 109 https://www.smashingmagazine.com/wp-content/uploads/2016/09/blossom-big-opt.jpg
  110. 110 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Focus-Magazine-Illustration-big-opt.jpg
  111. 111 https://www.behance.net/gallery/41407903/Focus-Magazine-illustrations
  112. 112 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Focus-Magazine-Illustration-big-opt.jpg
  113. 113 https://www.smashingmagazine.com/wp-content/uploads/2016/09/The-joy-of-new-roads-big-opt.jpg
  114. 114 https://unsplash.com/new?photo=VfUN94cUy4o
  115. 115 https://www.smashingmagazine.com/wp-content/uploads/2016/09/The-joy-of-new-roads-big-opt.jpg
  116. 116 https://www.smashingmagazine.com/wp-content/uploads/2016/09/city-guide-paris-london-berlin-big-opt.jpg
  117. 117 http://www.maitefranchi.com/index.html
  118. 118 https://www.smashingmagazine.com/wp-content/uploads/2016/09/city-guide-paris-london-berlin-big-opt.jpg
  119. 119 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Velorama-Lightyear-big-opt.jpg
  120. 120 http://silencetv.com/work.html
  121. 121 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Velorama-Lightyear-big-opt.jpg
  122. 122 https://www.smashingmagazine.com/wp-content/uploads/2016/09/the-Brickmasters-big-opt.jpg
  123. 123 http://www.raulsoria.de/#/els-amos-ocults-del-totxo/
  124. 124 https://www.smashingmagazine.com/wp-content/uploads/2016/09/the-Brickmasters-big-opt.jpg
  125. 125 https://www.smashingmagazine.com/wp-content/uploads/2016/09/bison-big-opt.jpg
  126. 126 https://dribbble.com/shots/2899113-Bison
  127. 127 https://www.smashingmagazine.com/wp-content/uploads/2016/09/bison-big-opt.jpg
  128. 128 https://www.smashingmagazine.com/wp-content/uploads/2016/09/No-Mans-Sky-big-opt.jpg
  129. 129 https://dribbble.com/shots/2894892-No-Man-s-Sky
  130. 130 https://www.smashingmagazine.com/wp-content/uploads/2016/09/No-Mans-Sky-big-opt.jpg
  131. 131 https://www.smashingmagazine.com/wp-content/uploads/2016/09/FiveThirtyEight-Election-big-opt.jpg
  132. 132 https://dribbble.com/shots/2905222-FiveThirtyEight-Election
  133. 133 https://www.smashingmagazine.com/wp-content/uploads/2016/09/FiveThirtyEight-Election-big-opt.jpg
  134. 134 https://www.smashingmagazine.com/wp-content/uploads/2016/09/The-Secret-To-Sleep-big-opt.jpg
  135. 135 https://dribbble.com/shots/2924242-The-Secret-To-Sleep
  136. 136 https://www.smashingmagazine.com/wp-content/uploads/2016/09/The-Secret-To-Sleep-big-opt.jpg
  137. 137 https://www.smashingmagazine.com/wp-content/uploads/2016/09/geoengineering-big-opt.jpg
  138. 138 http://www.raulsoria.de/#/om-de-opwarming-te-stoppen-moeten-we-het-klimaat-leren-manipuleren/
  139. 139 https://www.smashingmagazine.com/wp-content/uploads/2016/09/geoengineering-big-opt.jpg
  140. 140 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Bicycle-Adventure-Meeting-big-opt.jpg
  141. 141 http://www.fabioconsoli.com/bam-bike-adventure-meeting/
  142. 142 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Bicycle-Adventure-Meeting-big-opt.jpg
  143. 143 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Brooklyn-Bridge-big-opt.jpg
  144. 144 https://unsplash.com/?photo=-sQ4FsomXEs
  145. 145 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Brooklyn-Bridge-big-opt.jpg
  146. 146 https://www.smashingmagazine.com/wp-content/uploads/2016/09/shop-magazine-czech-republic-big-opt.jpg
  147. 147 https://www.behance.net/gallery/31551067/Mait-Franchi-SHOP-magazine-Czech-Republic
  148. 148 https://www.smashingmagazine.com/wp-content/uploads/2016/09/shop-magazine-czech-republic-big-opt.jpg
  149. 149 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Bicycling-Magazine-douglas-big-opt.jpg
  150. 150 http://www.douglasjones.com/134442/1336565/gallery/bicycling-magazine
  151. 151 https://www.smashingmagazine.com/wp-content/uploads/2016/09/Bicycling-Magazine-douglas-big-opt.jpg
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Redesigning SGS’ Seven-Level Navigation System: A Case Study

Redesigning SGS’ Seven-Level Navigation System: A Case Study

SGS (formerly Société Générale de Surveillance) is a global service organization and provider of inspection, verification, testing and certification services across 14 industries. SGS’ website (along with 60 localized websites) primarily promotes the organization’s core services, as well as provides access to a multitude of useful services, supplementary content and tools. Our goal was to transform sgs.com1 from being desktop-only to being responsive.

This presented a unique set of challenges, especially around the legacy navigation system, which in areas was up to seven levels deep (divided into two parts) and which consisted of some 12,000 individual navigable items.

Our natural reaction upon seeing and using SGS’ navigation system for the first time was that surely the information architecture (IA) had to be simplified because of the sheer volume of navigable links and content. However, considering the navigation had already been optimized for search engines and the IA prior to this project and considering that SGS offers a wide selection of services across many industries (reflected in the volume of content), it was evident that refactoring the IA would not be a part of the solution.

2
Previous navigation solution on sgs.com (View large version3)

Simply put, the navigation tree’s structure had to remain intact. Even so, that didn’t prevent us from making some minor adjustments to the IA. For instance, “News, Media & Resources” and “SGS Offices & Labs” were moved to the top level, for greater visibility. With the former, it was important to more clearly reflect that SGS regularly publishes news and hosts events. With the latter, it was vital that it, along with the contact page, were easily reachable from anywhere in the website’s structure. Therefore, the key question was how could such a behemoth of a navigation system be made to easily transition between different viewports while still being usable?

Establishing Project Policies Link

A healthy client-designer relationship4 is essential to the success of every project. Setting clear expectations as well as providing effective guidance ensures not only that key stakeholders remain focused throughout, but also that trust develops between all parties as the project progresses. This was definitely the case with this project; the collaboration between all parties and the mutual appreciation of each other’s roles and expertise were truly remarkable.

However, to ensure that all parties remained focused, we established at the kick-off meeting a number of important guidelines and requirements within which we could also exercise creativity (some of which we insisted on, others insisted on by the client):

  • Content parity

    Content should be accessible on every device and platform and under no circumstances should be hidden on mobile.
  • Performance

    The website should perform at least 20% faster than competing websites. This was particularly useful when deciding how much information should go on each page.
  • Accessibility

    The website must adhere to WCAG 2.0 level-AA accessibility guidelines. We succeeded in achieving this target, aside from a borderline color-contrast issue, due to the company’s branding.
  • Usability

    The in-house team had to extensively validate concepts and conduct in-person and remote usability testing.
  • Uninterrupted business

    The redesign shouldn’t disrupt the company’s business at all. Clearly, the task was not to optimize the company’s services, but rather to optimize the website, taking into account established business processes. For instance, we had the freedom to optimize web forms, but the structure of the data in the CRM had to remain intact.

The Three Major Challenges Link

With key guidelines established and knowing the navigation’s redesign wouldn’t require a significant overhaul of the IA, we subdivided the redesign into three key yet interdependent sets of activities:

  • Layout placement

    This was handled mostly by the in-house team, with us suggesting improvements and making sure any decisions wouldn’t have radical implications for other aspects of the new responsive design.
  • Interaction and usability

    These were worked on collaboratively with SGS’ design team. Ideas were exchanged via email and in on-site workshops and were regularly validated against users, stakeholders and the overall business requirements.
  • Performance

    This was dealt with solely by us, because it was more of a technical challenge and didn’t require any strategic decision-making other than for us to make the new responsive website fast.

Layout Placement Link

Navigation is a fundamental element of page layout, regardless of the size or complexity of the website. While an off-screen pattern might seem appealing when you’re dealing with such a large-scale navigation system, remember that there can be issues5 when the navigation is not visible to the user.

SGS’ design team had initially tested a variety of concepts, because they had to not just evaluate the navigation interaction, but also create the right balance with the rest of the page and avoid clutter.

A few early, later discarded, concepts of the navigation placed in the layout6
A few early (later discarded) concepts of the navigation placed in the layout (View large version7)

Deciding on the Concept Link

Given the complexity of the website, it was vital that the navigation always remain visible and inform the user where they are within the tree structure. Rather than divide the navigation into two parts in the UI, we wanted the new navigation system to be seamless (from the top level right through to the bottom levels). Therefore, it had to enable the user to easily browse up and down the navigation tree, as well as sideways across the main sections.

To test and validate all of these combinations, we developed a prototype for each of the eight initial navigation concepts. The prototypes confirmed what the in-house team already suspected: The most viable option in terms of usability, maintenance, cross-screen experience, visual clutter and appeal was for the navigation to be placed in the sidebar on large screens and to appear as a dropdown menu on small screens. Essentially, the navigation module would be functionally and visually self-contained, regardless of screen size.

The new navigation module would be visually and interactively identical across different viewpoints, enabling us to approach the design and development mobile-first.8
The new navigation module would be visually and interactively identical across different viewpoints, enabling us to approach the design and development mobile-first. (View large version9)

While we will focus on specific interaction decisions in a minute, it’s worth pointing out that interactive prototypes don’t necessarily have to be discarded once a prototyped concept has been tested and validated.

Prototyping Smart Link

We always develop prototypes directly in HTML, CSS and JavaScript using semantic, accessible and robust markup, because we are then often able to reuse the initial prototypes later in the design process. This meant that our initial prototype for the new navigation system became the cornerstone for the eventual full website prototype, which included all of the page templates and modules.

In delivering the full prototype, we also ensured the style guide was generated automatically for the SGS team. By getting SGS’ design team to think in terms of designing and developing modules, rather than complete pages, the generated style guide would require little ongoing maintenance. The style guide itself refers to all of the distinctive modules used, with each module containing a precise description, code example and automatically generated link to the page template where it is used. Our technology of choice for automating tasks and features is PHP, but automation can be achieved using any server-side language, as long as the output is semantic HTML. (We developed a specific file-system framework for our prototypes, but that’s a topic for another occasion.) Later on in this article, we will explain how server-side scripting helped us to maintain and test multiple versions of the navigation.

Even though starting with semantic, accessible and robust HTML is vital, the principle of “content-first, navigation-second” is just as important because it helps you to account for any possible future exceptions. There was one exception to the “content-first, navigation-second” rule in this project: the home page. We discovered, based on analytics, that the navigation was viewed as the most important element on the home page, which meant it had to come before any core content on the page.

Interaction And Usability Link

Once the decision was made to design and develop a self-contained, screen-size-agnostic navigation module, it was time to focus on navigation interactions. Considering that we had adopted a mobile-first approach to designing the navigation, the navigation module itself not only would naturally function as expected in small viewports, but would easily scale to work in large viewports, too.

Three Interactive Versions Link

Due to the size of the navigation and the potential number of nested levels, we had to eliminate some of the more common mobile navigation patterns10 as options — for instance, select dropdowns and the priority+ pattern. We focused on prototyping three interactive versions of the navigation: a slider, an accordion, and an accordion and slider. Each has its pros and cons, which naturally influenced our decision.

Accordion

The accordion is probably the most common pattern on mobile. It discloses progressively, revealing more detailed information as the user progresses through the topic or action. It also ensures the user does not get overwhelmed, which is why we wanted to use it as a baseline solution.

Here are the accordion’s pros:

  • Users are familiar with it.
  • Users can expand the entire navigation tree to preview multiple options (seven levels of navigation can be a little overwhelming, after all).
  • It works without JavaScript, using the :target pseudo-class11.
  • Developing it is easy.

And the accordion’s cons:

  • The expanded ancestors of a deep-level category would push the current scope too far away from the top of the screen, thus requiring a lot of scrolling.
  • Seven levels of navigation requires seven degrees of the chosen visual cue, whether it be seven shades of a basic color (gray), seven levels of typographic hierarchy or seven levels of indentation.

Slider

This was initially our favorite solution, but it misses one important element: allowing truly sideways browsing across the main sections. It wouldn’t be such a problem if the user always starts browsing from the home page, because they would become increasingly familiar with the main sections. However, for users who land on a page deep in the navigation tree, it definitely would have been a usability problem. For instance, users who land on the third, fourth or fifth level would have to traverse up the tree in order to reach the contact page. Traversing seven levels is no fun, no matter how motivated the user might be.

Slider pros:

  • The hierarchy is clear.
  • The animation is slick.
  • It follows mobile conventions.
  • It is relatively easy to develop.

Slider cons:

  • Browsing sideways is not possible.
  • The animation is not performant.

Hybrid (accordion and slider)

We really wanted to maintain the attractiveness of the slider, while still allowing sideways browsing. Therefore, we developed of a hybrid solution combining the best elements of the two navigation patterns. Incidentally, it was also the solution we settled on.

The hybrid approach brought the best of both worlds.12
The hybrid approach brought the best of both worlds (View large version13)

Hybrid pros:

  • Sideways browsing is possible.
  • The animation is slick.
  • The hierarchy is clear.

Hybrid cons:

  • It requires some initial learning.
  • It is complex to develop, with many moving parts to consider.
  • It has some performance issues.

As mentioned, the user should be able to browse up and down the navigation tree, always aware of where they have come from and where the navigation will take them next. However, that’s just the baseline interaction — we had to address quite a few additional issues in order to develop a usable navigation system.

Eight Distinctive Types of Links Link

Apart from current and ancestor navigation items being distinct in design (which is now, thankfully, a well-established practice), we further improved the navigation and general usability by helping the user to understand where they are and what they’re exploring. Helping the user to understand the current page and its parents, as well as any relevant children relationships, was far from enough. Other important actions were required:

  • being able to go directly to the parent page;
  • being able to preview both parent and children levels, all while staying at the original URL;
  • quickly understanding their current browsing position, while being able to explore the navigation.
  • quickly understanding their current position on the page.

Note: We used breadcrumbs to ensure that the current page position is always clear to the user. Because we wanted to avoid skipping levels altogether, the information in the breadcrumbs and the navigation had to match one to one, even with pseudo-levels (i.e. levels that don’t have an actual page).

The user requirements above resulted in five types of semantically different navigation items, with additional helper links that would allow the user to traverse up and down the tree without having to leave the current page. You can imagine the complexity and interdependencies that come with so many moving parts.

Each of the eight distinctive types of links in the navigation required their own unique combinations of class names, visual identity as well as interactive set of rules14
Each of the eight distinctive types of links in the navigation required its own unique class name, visual identity and interactive set of rules. (View large version15)

Animation Details Link

All elements in the navigation are animated using CSS, with each animation having two distinct parts:

  • horizontally animated levels,
  • vertically animated wrappers.

First, the different tree levels in the slider are toggled by changing the class of the master wrapper. For example, the closed navigation wrapper has a class of .depth-0. When a top-level item is expanded, the class changes to .depth-1. When a second-level item from within that top-level item is selected, the class changes to .depth-2, and so on. This results in a fairly simple set of CSS rules that get applied to a single element — the topmost-ordered list in a slider:

.depth-1 .l-0.nav-open > ol { left: 0; } .depth-2 .l-0.nav-open > ol { left: -100%; } .depth-3 .l-0.nav-open > ol { left: -200%; } 

In the example above, .l-0 corresponds to a zero-level list item, and .nav-open is toggled whenever the accordion is set to open. This means that the ordered list of a direct child in an open accordion list item is absolutely offset to the negative-left position.

Secondly, considering that each level contains a variable number of list items, the transition between any two adjacent levels has to be smooth.

16
Showcasing the default and improved transition

To achieve this, we made sure there is always sufficient vertical room for the horizontal animation to run smoothly. The height is calculated and applied on the fly by retrieving the vertical offset of the element about to enter the screen. This means we had to account for a total of four possible scenarios, but really only needed to resolve two, each with a slightly different order of execution:

  • Short list item to a longer list item

    The horizontal and vertical animation start at the same time.
  • Long list item to a shorter list item

    After the navigation stops sliding horizontally, the vertical animation starts.

Both animations are initiated at the same time, but the second animation gets initiated after a 300-millisecond delay, which is exactly the duration of the first animation (specified in CSS using the transition-duration property). The reason for this is suboptimal animation performance on less-capable devices when multiple layers overlap before disappearing “behind the curtain.” The simplified code looks like this:

if (newHeight < oldHeight) { heightTimeout = 300; } else { heightTimeout = 0; } setTimeout(function() { $('.l-0.nav-open').css('height', newHeight); }, heightTimeout); 

Further Improvements Link

Already faced with a complex set of interdependencies, we realized upon testing the navigation that there was room for improvement.

First, because web fonts sometimes load a little later than the rest of the page, some strings of text in the navigation that are meant to be on one line would expand to a second line before the web font had fully loaded. For instance, the top-level section link “News, Media and Resources” falls onto two rows when rendered in the fallback font.

The navigation rendered in the fallback font17
The navigation rendered in the fallback font (View large version18)

Because everything had to be really compact (since we had to use absolute positioning for the sliding animation), the only solution was to reset the height of the affected element after the web font had loaded. This was done using Web Font Loader19, developed by Bram Stein20 for Adobe Typekit21 and Google Fonts22.

WebFont.load({ custom: { families: ['FONT_NAME_1', 'FONT_NAME_2'] }, active: function() { // recalculate things here }, timeout: 5000 }); 

Note: Did you notice how we used a 5-second timeout? In our testing, we found this to be the sweet spot that made it work on our baseline “good 2G” (450 KB per second) connection!

Secondly, because we decided to conditionally load the navigation nodes in order to improve initial loading performance (more on that in the next section), we wanted the user to be kept aware of how many navigation items are available, in case there is a delay in loading a branch of the navigation tree. We did this by repeating a placeholder background image that resembles a string of text23.

Placeholders are loaded that visually resemble the list of links.24
Placeholders are loaded that visually resemble the list of links. (View large version25)

Finally, we appended the placeholder code in the DOM with JavaScript before requesting the navigation branch. This keeps the DOM as clean as possible.

 element.append('<ol><li></li></ol>'); $.get('NAVIGATION_BRANCH_URL', function(data){ // replace the loader with the branch element.find('ol').replaceWith(data); }); 

Performance Link

If you recall, one of our key targets in the project was for the website to perform at least 20% better than competitors’ websites. Not only did we achieve this target, but in doing so we helped SGS to significantly reduce overall page weight and loading times. Take a look at the following before-and-after statistics:

HTTP requests File size: total File size: HTML
Original SGS home page 40 1,500 KB 72 KB
Original SGS industry page 60 2,200 KB 50 KB
New responsive home page 17 960 KB 42 KB
New responsive industry page 20 680 KB 40 KB

Did You Know That 12,000 Links Equals 3 MB of HTML? Link

That’s correct! When we rendered the full navigation tree for the first time in our prototype, it amounted to 3 MB of bare HTML. No header, no footer and no content — just the navigation tree consisting of 12,000 individual links.

Prior to the redesign, every page contained the core navigation tree, and each industry page also included an industry-specific navigation tree, implemented as a separate module. However, the desktop-optimized design made the core or industry-specific navigation not only difficult to use on small viewports, but difficult to maintain, too. That’s why one of the key goals of the redesign was to consolidate the tree into a single and easy-to-maintain module.

Exploring Options to Improve Performance Link

To thoroughly test each of the three interactive versions of the navigation, as well as evaluate their performance, a flexible testing environment was essential. This would enable us to make changes quickly, as well as to maintain concurrent versions so that we could easily compare them against each other.

Considering the size of the complete navigation tree (up to seven levels deep and 12,000 navigable links), being able to test parts of the navigation tree as well as the full tree itself was important. SGS’ in-house developers were able to export the full navigation tree as a CSV file from their content management system, which allowed us to create an easily configurable PHP function to output either the full tree or part of it, depending on what we needed to test.

Our PHP function also simplified the HTML maintenance of the navigation tree’s structure, because the aforementioned link markup and class names could be easily changed in a single place. Using a server-side language to avoid having to repeat code might sound obvious, but creating this type of environment was not just a welcome addition, but was actually mission critical, because it was the prerequisite to agile experimentation and testing.

Conditionally Loading Links Link

We mentioned that we had to conditionally load the navigation nodes to improve initial loading performance. The question that then needed answering was, How much of the navigation tree should be loaded initially and how much should be loaded later, and when? After testing and comparing the weights and sizes of the different navigation tree branches, as well as studying user behavior on the existing live website, a few interesting conclusions emerged.

First, visitors who were interested in only one type of industry rarely visited other industries. Once browsing their selected industry category, each visitor would typically go on to explore just a couple of other pages.

Secondly (and as we had initially thought), the industry-specific branches caused the majority of performance overhead. When we removed the industry branches altogether, the HTML was reduced to 70 KB, which is a lot better than 3 MB! Still, it meant that each of the 14 industry branches weighed between 300 and 500 KB. When we fragmented each service branch further, we found that each subsequent level would weigh around 24 KB on average.

While we were aware that the HTML could be further reduced by optimizing the class names and adding DOM nodes via JavaScript (more on that in a minute), we still had to determine whether it was best to initiate a single HTTP request at around 300 to 500 KB or to initiate an HTTP request of around 24 KB at each level. Initially, it seemed that sending a 24 KB request each time the user progressed further down the navigation tree would be more beneficial. However, this would have resulted in multiple HTTP requests being sent over the network, which was far from ideal, considering that network latency is often one of the biggest bottlenecks for website performance. It also didn’t make sense to predict the loading of any industry branches either, except when the user showed intent by hovering over an industry link.

Due to the complexity of the navigation and the quantity of links, the following arrangement offered by far the best compromise:

  • Load the first three levels by default in HTML.
  • Load the industry navigation with JavaScript when intent is shown, detected using the mouseover event.
  • Cache loaded branches to speed up loading on consecutive page loads.

The logic for deeper pages was somewhat different, because the navigation needs to be accessible without JavaScript enabled. Therefore, if a user (or even a search engine bot) lands on a deep page, the following would happen:

  1. Render the first three levels and the current page’s ancestor branch and page siblings in HTML, thereby allowing the user to easily access the parent, ancestor and sibling pages, while also being able to access other parts of the website following the same logic.
  2. Load the current branch with JavaScript, and replace the initially loaded current page’s ancestor branch.

Optimizing HTML Link

If you truly want to optimize your HTML, all non-essential items have to be offloaded to CSS and JavaScript. We rigorously pruned everything except the ordered list, its list items and their respective links. All non-essential links (i.e. navigation aids) were also removed from the HTML and are reinserted back in the DOM using JavaScript (because they are ineffective without JavaScript anyway). These non-essential links enable the user to do a couple of things:

  • open the next level (internally, we called these “expanders”);
  • go up a level (we named these “backers” — showing a lack of imagination).

While the resulting DOM was still immense, the navigation aids no longer needed to be transferred individually over the network.

Finally, the last piece of optimization we undertook was to reduce the number of classes, as well as to shorten the length of class names; for example, .very-long-class-name became .v-l-c-n. While the latter yielded the biggest gains, such optimization is difficult to justify because it usually doesn’t significantly trim the size of the HTML file, and, more importantly, it reduces the clarity of the code, thus possibly making maintenance more difficult. However, shaving off even a single byte from each of the 12,000 list items made it a worthwhile exercise and an acceptable trade-off.

The result? A whooping 40 KB or so of initial HTML (8 to 9 KB when compressed and transferred over the network), and 200 to 300 KB of HTML for each industry (15 to 25 KB when compressed and transferred).

Conclusion: Marginal Gains Matter Link

We like to use an analogy from the sports world: Improving every tiny thing by 1% dramatically improves performance26. This applies to what we did in the SGS project and its intricate navigation. By focusing on the finer details, improving each detail by a tiny bit, we significantly reduced the complexity of the navigation and improved loading times, while keeping the navigation appealing and engaging for users. What could have been a nightmare and a tough nut to crack turned into a technically and interactively relevant solution, flexible enough to accommodate further improvement.

Most of all, the design process of continually prototyping, investigating options and refining the best solutions proved to be extremely effective — so much so that it has provided a strong case for the in-house team to apply the same fundamental principles when developing other products in the organization, not to mention that it will help the team to continue refining and optimizing the new navigation system. No web project is ever truly complete; there are always a few more things on the to-do list. That’s perfectly fine, as long as we keep on testing, refining and providing the best experience for users.

(vf, il, yk, al)

Footnotes Link

  1. 1 http://www.sgs.com/
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-previous-navigation-solution-opt.jpg
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-previous-navigation-solution-opt.jpg
  4. 4 https://www.smashingmagazine.com/2016/06/client-experience-design/
  5. 5 http://thenextweb.com/dd/2014/04/08/ux-designers-side-drawer-navigation-costing-half-user-engagement/#gref
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-early-concepts-opt.jpg
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-early-concepts-opt.jpg
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-current-navigation-in-layout-opt.jpg
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-current-navigation-in-layout-opt.jpg
  10. 10 http://bradfrost.com/blog/web/complex-navigation-patterns-for-responsive-design/
  11. 11 http://www.creativebloq.com/css3/build-smart-mobile-navigation-without-hacks-6122800
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-accordion-slider-opt.jpg
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-accordion-slider-opt.jpg
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-eight-types-of-links.gif
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-eight-types-of-links.gif
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-transition-default.gif
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-string-second-row-opt.jpg
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-string-second-row-opt.jpg
  19. 19 https://github.com/typekit/webfontloader
  20. 20 https://github.com/bramstein
  21. 21 https://www.typekit.com
  22. 22 https://fonts.google.com
  23. 23 https://material.google.com/patterns/empty-states.html
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-loading-placeholder-opt.jpg
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/08/sgs-loading-placeholder-opt.jpg
  26. 26 http://jamesclear.com/marginal-gains
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

The Building Blocks Of Progressive Web Apps

The Building Blocks Of Progressive Web Apps

The common wisdom for most companies that set out to build an app is to build a native Android or iOS app, as well as a supporting website. Although there are some good reasons for that, not enough people know about the major advantages of web apps. Web apps can replace all of the functions of native apps and websites at once. They are coming more and more to the fore these days, but still not enough people are familiar with them or adopting them.

Further Reading on SmashingMag: Link

Here, you will be able to find some do’s and dont’s on how to make a progressive web app, as well as resources for further research. I’ll also go into the various components and support issues surrounding web apps. Although not every browser is friendly to them, there are still some compelling reasons to learn more about this technology.

What Makes A Web App Progressive? Link

A progressive web app is an umbrella term for certain technologies that go together to produce an app-like experience on the web. For simplicity’s sake, I’ll refer to them simply as web apps from now on.

An ideal web app is a web page that has the best aspects of both the web and native apps. It should be fast and quick to interact with, fit the device’s viewport, remain usable offline and be able to have an icon on the home screen.

At the same time, it must not sacrifice the things that make the web great, such as the ability to link deep into the app and to use URLs to enable sharing of content. Like the web, it should work well across platforms and not focus solely on mobile. It should behave just as well on a desktop computer as in other form factors, lest we risk having another era of unresponsive m.example.com websites.

Progressive web apps are not new. Mobile browsers have had the ability to bookmark a website to your phone’s home screen since 2011 (2013 on Chrome Android), with meta tags in the head determining the appearance of the installed web page. The Financial Times has been using a web app4 for digital content delivery on mobile devices since 2012.

Moving to a web app enabled the Financial Times to use the same app to ship across platforms in a single distribution channel. Back when I was working for the Financial Times, with a single build we were able to support the following:

  • iOS,
  • Android (4.4+) Chrome,
  • older Android (via a wrapper),
  • Windows 8,
  • BlackBerry,
  • Firefox OS.

That truly achieves “build once, deploy anywhere.”

“But It’s Not In An App Store” Link

There are some good reasons why supplementing a native app with a website is still standard practice for most major companies. Among them are concerns about browser support and the fact that most users are acclimated to using native apps. I will address these issues in more detail later. Not least of these concerns is how the app will get exposure if it is not in an app store.

5
As popularity decreases, exposure in the store decreases exponentially. (Image: Charles Perry6) (View large version7)

I would argue that being in an app store has no major advantage because it has been shown that if you are not in the top 0.1% of apps in the app store, you are not getting significant benefit from being there.

Users tend to find your apps by first finding your website. If your website is a web app, then they are already at their destination.

One of the strengths of a web app is that it enables you to improve engagement by reducing the number of clicks required to re-engage the user between landing on your website and engaging with your app.

By having the user “install” your web app by adding it to their home screen, they can continue engaging with your website. When they close down the web browser, the phone will show them where the web app is installed, bringing you back to their awareness.


Video of a web app being added to the home screen. When the browser is minimized, the icon is animated as it gets added. When the web app is loaded up again, the URL bar is hidden.

Background And Current Climate Link

Modern web apps are based on a new technology called service workers. Service workers are programmable proxies that sit between the user’s tab and the wider Internet. They intercept and rewrite or fabricate network requests to allow very granular caching and offline support.

Since the origins of the web app in 2011, which enabled websites to be bookmarked to the home screen, a number of developments have taken place to lay more groundwork for the creation of progressive web apps.

Chrome 38 introduced the web app manifest, which is a JSON file that describes the configuration of your web app. This allowed us to remove the configuration from the head.

In Chrome 40 (December 2014), service workers started to roll out across Firefox and Chrome. Apple has so far chosen not to implement this feature in Safari as of the time of writing but has it “under consideration8.” The service worker’s function is to simplify the process of bringing an app offline; it also lays the foundation for future app-like features, such as push notifications and background sync.

Apps that were built based on the new service workers and the web app manifest became known as progressive web apps.

A progressive web app is not the same as the spec. In fact, it started out as a definition of what a web app should be in the era of service workers, given the new technology being built into browsers. Specifically, Chrome uses this definition to trigger an install prompt in the browser when a number of conditions are met. The conditions are that the web app:

  • has a service worker (requires HTTPS);
  • has a web app manifest file (with at least minimal configuration and with display: "standalone");
  • has had two distinct visits.

In this case, “progressive” means that the more features the browser supports, the more app-like the experience can be.

The prompt to install the web app is currently shown under varying conditions across Opera, Chrome and the Samsung browser.

Apple has indicated interest in progressive web apps for iOS, but at the time of writing it still relies on meta tags for web app configuration and the application cache (AppCache) for offline use.

At What Point Does A Website Become A Web App? Link

We know what a website looks like and what an app looks like, but at what point does a website become a web app? There is no definitive metric as to what makes something a web app rather than a website.

Here we will go into some more detail about the characteristics of a web app.

A Progressive Web App Should Exhibit Certain App-Like Properties… Link

  • Responsive

    Perfectly filling the screen, these websites are primarily aimed at phones and tablets and must respond to the plethora of screen sizes. They should also just work as desktop websites. Responsive design has been a major part of website building for many years now. Smashing Magazine has some great articles9 on it.
  • Offline-first

    The app must be capable of starting offline and still display useful information.
  • Touch-capable

    The interface should be designed for touch, with gesture interaction. User interaction must feel responsive and snappy, with no delay between a touch and a response.
  • App meta data

    The app should provide meta data to tell the browser how it should look when installed, so that you get a nice high-resolution icon on the home screen and a splash screen on some platforms.
  • Push notifications

    The app is able to receive notifications when the app is not running (if applicable).

… But Should Maintain Certain Web-Like Properties Link

  • Progressive

    The app’s ability to be installed is a progressive enhancement. It is vital that the app still work as a normal website, especially on platforms that do not yet support installation or service workers.
  • HTTPS on the open web

    The app should not be locked to any browser or app store. It should be able to be deep linked to and should provide methods for sharing the current URL.

Taking Your Website Offline Link

Taking your website offline brings some major advantages.

First, it will still work when the user is on a flaky network connection.

In addition, the time from opening the app to using the app is greatly reduced if the app does not rely on the network. This gives the user a great experience. A carefully optimized web app can start faster than a native one if the browser has been used recently.

There are two methods to getting a website to work offline:

  • Old and busted method

    Support for starting your website offline has been around for years in the form of AppCache. AppCache has some serious flaws, though, and has even been deprecated from the specification10. It is difficult to work with and, if misconfigured, could permanently break your website. Still, it is the only way to do offline on iOS, at least until Apple makes a move to support service workers.
  • New hotness

    Also effective are service workers, which are currently supported in Chrome, Firefox and Opera and coming very soon to Edge. Apple’s WebKit team has it marked “under consideration.”

Service workers are like other web workers in that they run in a separate thread, but they are not tied to any specific tab. They are assigned a URL scope when they are created, and they can intercept and rewrite any requests in this scope. If your service worker sits at http://example.com/my-site/sw.js, it will be able to intercept any requests made to /my-site/ or lower but cannot be made to intercept requests to the root http://example.com/.

Because they are not tied to any tab, they can be brought to life in the background to handle push notifications or background sync. Not least, it is impossible to permanently break your website with them because they will automatically update when a new service worker script is detected.

A good guideline is that, if you are building a new website from scratch, start off with a service worker. However, if your website already works offline with AppCache, then you can use the tool sw-appcache-behavior11 to generate a service worker from this, because we may soon reach the point when some browsers will only accept service workers and some will only accept AppCache.

Because AppCache is being deprecated, I will not discuss it further in this article.

Setting Up A Service Worker Link

(Also, see “Setting Up a Service Worker12” for more detailed instructions.)

Because a service worker is a special type of shared web worker, it runs in a separate thread to your main page. This means that it is shared by all web pages on the same path as the service worker. For example, a service worker located at /my-page/sw.js would be able to affect /my-page/index.html and my-page/images/header.jpg, but not /index.html.

Service workers are able to intercept and rewrite or spoof all network requests made on the page, including those made to data:// URLs!

This power enables it to provide cached responses to get pages to work when there is no data connection. Still, it is flexible enough to allow for many possible use cases.

It is only allowed in secure contexts13 (i.e. HTTPS) because it is so powerful. This prevents third parties from permanently overriding your website using an injected service worker from an infected or malicious Wi-Fi access point.

Setting up HTTPS nowadays might seem daunting and expensive, but actually it has never been easier or cheaper. Let’s Encrypt14 provides free SSL certificates and scripts for you to automatically configure your server. In case you host on GitHub, GitHub Pages are automatically served over HTTPS. Tumblr pages can be configured to run on HTTPS, too. CloudFlare can proxy requests to upgrade to HTTPS.

Offlining usually involves picking certain caching methods for different parts of your website to allow them to be served faster or when there is no Internet connection. I will discuss various caching methods below.

I use Service Worker Toolbox2915 to abstract away complex caching logic. This library can be set to handle the routing by providing four preconfigured routes, which can be configured in a clean fashion. It can be imported into your service worker.

Use Case 1: Precaching Link

Precaching pulls down requests before your website works out that they are needed. This can greatly decrease first paint time because your website doesn’t need to parse /site.css before it starts downloading your website’s logo, /images/logo.png.

toolbox.precache(['/index.html', '/site.css', '/images/logo.png']); 

Use Case 2: Offline Link

Allowing users to revisit your website when they are offline in the simplest case means falling back to the cache if the device is offline. Setting a timeout here is important because a flaky network, misconfigured router or captive portal could leave the user waiting indefinitely.

toolbox.router.default = toolbox.networkFirst; toolbox.options.networkTimeoutSeconds = 5; 

In reality, we can actually be a little smarter because the majority of your assets will not change over time. We probably just want to get the content as soon as possible, whether from the cache or the network. The following line tells Service Worker Toolbox that all requests to the images’ paths should come from the cache if they are available there.

toolbox.router.all('/images/*', toolbox.fastest); 

In this case, when the user is authenticating, it is important that we not just return a cached response; we should state that requests made to /auth/ should be network-only.

toolbox.router.post('/auth/*', toolbox.networkOnly); 

Here are some good practices for offlining:

  • Initial static assets should be precached. This downloads them and caches them when the service worker is installed. This means that they do not need to be loaded from the server when they are eventually required.
  • By default, requests should ideally be freshly sourced from the network but fall back to the cache so that they are available offline.
  • A relatively short network timeout means that requests will be able to return cached data on a network connection that says it has a data connection but no responses are being returned.
  • Infrequently updated assets, such as images, should be dispatched from the cache first, then the browser would also try to update them. If toolbox.cacheOnly is used, then it could also save the user’s data.

Note: The browser cache and the Cache API are different animals. The Cache API has been bypassed in the case of network-first or network-only. The request might still hit the browser’s cache because the caching headers in the request say it is still valid. This could result in the problem of the user receiving a mixture of cached and fresh data. Jake Archibald has some good suggestions for avoiding this issue16.

Debugging Your Service Worker Link

If you are in Chrome or Opera, go to chrome://serviceworker-internals. This will allow you to inspect and pause and uninstall your service worker script.

In recent versions of Chrome and Opera, you can get detailed views and debugging tools through the “Application” tab in the inspector.

The Application tab in Chrome Developer Tools17
The “Application” tab in Chrome Developer Tools (View large version18)

Interaction And Animation Performance Link

People have come to expect that the web does not have the smoothly animated interfaces that native apps do. However, the same standard is not acceptable for web apps. Web apps must animate smoothly, lest our users feel we are delivering a degraded, second-class experience. We have three goals to make it feel fast:

  • When the user does something, the app must also do something within 100 milliseconds; otherwise, the user will notice a lag. This counts for taps, clicks, drags and scrolls.
  • Each frame must render at a consistent 60 frames per second (16 milliseconds per frame). Even a few slow frames will be obvious.
  • It must be fast on a three-year-old budget phone running on a poor network, not only your shiny development machine.
  • It must start quickly. Long have we been focused on maintaining user engagement by getting our websites to be visible and usable in under 1 to 2 seconds. When it comes to web apps, start-up time is as important as ever. If all of an app’s content is cached and the browser is still in the device’s memory, a web app can start faster than a native app. One mistake made by native app and website developers alike is requiring networked content in order for the product to work.
  • The web app must be small to download and update: 10 MB from an app store don’t feel like much, but 10 uncached MB downloaded every time is very much impossible to manage for a lot of mobile users.

Off the bat, the most essential item is this, in the head of the document:

<meta name="viewport" content="width=device-width"> 

This line ensures that there is no 300-millisecond tap delay on phone browsers that are Chromium-based or Firefox, but it still allows the user to zoom in by pinching (great for accessibility).

Since iOS 8 came out, clicks are fast by default but might seem slow if the tap is fast, according to certain heuristics19. If this is an issue for you, I recommend using FastClick20 to remove the delay.

There is also the issue of animation performance. You’ll probably want a lot of pretty elements animating in and out, elements that can be dragged by the user, and other lovely interactions.

Web performance can be discussed in great detail and is a subject close to my heart, but I won’t go into much detail here. I will touch on what I do to ensure that my interactions and animations are crisp and smooth.

Dig around or ask around your friends or family for an old smartphone. I usually borrow my partner’s Nexus 4.

Plug the phone into your computer, and go to chrome://inspect/#devices. This will open an inspection window, which you can use to inspect the web pages running on the phone. You can use profiling and view the timeline to find sources of poor performance and then optimize them based on a real baseline device.

Animating certain CSS properties is one of the biggest causes of jittery animation, known as jank. CSS Triggers21 is a great resource for determining which properties can be safely animated without causing the browser to repaint or re-lay out the whole page.

If writing performant animations is a daunting task for you, many libraries out there will handle the job. A favorite of mine is GreenSock22, which can handle touch interactions very well, such as dragging items, and which can do very fancy animation and tweening.

Push Notifications Link

Push notifications are a great way to re-engage with users. By prompting the user, you bring your app to the forefront of their mind. They could finish off an unfinished transaction or receive alerts about relevant new content.

Make sure your push notifications are relevant to the user for events happening at that moment. Don’t waste their time on things that can be done later. What you are notifying them about should require their action (replying to someone or going to an event). Also, don’t push a notification if your web app is visible or in focus.

When interacted with, a notification should take the user to a page that works offline. Notifications can hang around unread; they might be interacted with when the user has no network connection. The user will get frustrated if your push notification refuses to work after they have tried to interact with it.

The very best experience for push notifications frees the user from having to open your web app at all! “You have a new message” is useless and as annoying as a clickbait headline. Display the message and the sender.

Action buttons in the notification can provide interaction prompts that do not necessarily open the browser (“Like this post,” “Reply with yes,” “Reply with no,” “Remind me later”). These serve the user on their terms, keeps them engaged and minimizes their investment of time.

If you spam the user with regular or irrelevant notifications, they might disable notifications for your app in the browser. After that, it will be almost impossible to re-engage them, and you won’t be able to easily prompt them for permission again!

To avoid this, make the route to your app’s “disable notification” button clear and easy. Once you have addressed any issues frustrating users, you can try to re-engage.

The Push Notification API requires a service worker. Because it is possible to receive push notifications when no browser tab is open, the service worker will handle the notification request in a background thread. It can perform async operations, such as making a fetch request to your API before displaying the notification to the user.

To create a push notification, make a request to an endpoint provided by the browser manufacturer. For Chromium-based browsers (Opera, Samsung and Chrome), this would is Firebase Cloud Messaging. These browsers also behave a little off-spec as well.

One can find the details of this by requesting push-notification permission:

serviceWorkerRegistration .pushManager .subscribe({ // Required parameter as receiving updates // but not displaying a message is not supported everywhere. userVisibleOnly: true }) .then(function(subscription) { return sendSubscriptionToServer(subscription); }) 

The subscription is an object that looks like this:

{ "endpoint": "http://example.com/some/uuid" } 

In the example above, the uuid uniquely identifies the browser currently being used.

Note: Chromium-based browsers behave a little differently. You’ll need a Firebase app ID, which needs to be entered in your web app’s manifest file (for example, "gcm_sender_id": "90157766285").

Also, the endpoint will not work in the format it is given. Your server needs to mangle it slightly to get it to work23. It needs to be a POST request, with your API key in the head and the uuid in the body.

When sending a push notification, it is possible to send data in the body of the push notification itself. This is complex and involves encrypting the contents in the API request. The web-push24 package for Node.js can handle this, but I don’t prefer it.

It is possible to perform async requests once the notification has been received, so I prefer to send a minimal notification, known as a “tickle,” to the client, and then the service worker will make a fetch request to my API to pull any recent updates.

Note: The service worker can be closed by the browser at any point. The event.waitUntil function in the push event tells the service worker not to close until the event is finished.

self.addEventListener('push', function(event) { event.waitUntil( // Makes API request, returns Promise getMessageDetails() .then(function (details) { self.registration.showNotification( details.title, { body: details.message, icon: '/my-app-logo-192x192.png' }) }) ); }); 

You can listen for a click or press interaction on the notification events, too. Use these to decide how to respond. You could open a new browser tab, focus an existing tab or make an API request. You can also choose whether to close the notification or keep it open. Use this functionality with actions on the notification to build great functionality into the notification itself. This will make for a great experience, because the user will not be required to open your app each time.

Don’t Ignore The Strengths Of The Web Link

The final and most important point is that, in our rush for an app-like experience, we should not forget to stay web-like in one very important aspect: URLs.

Installed web apps often hide the browser shell. There is no address bar for the user to share the current URL, and the user can’t save the current page for later.

URLs have a unique web advantage: You can get people to use your app by clicking, rather than by describing how to navigate it. All the same, it is very easy to forget to expose this to users. You could write the best app in the world, but if no one can share it, you will have done yourself a major disservice.

It comes down to this: Provide ways to share your app via either sharing buttons or a button to expose the URL.

What About Browsers That Do Not Support Progressive Web Apps? Link

Check out Is ServiceWorker ready?25 for the current status of support for service workers across browsers.

You may have noticed throughout all of this that I have mentioned Chrome, Firefox and Edge but left out Safari. Apple introduced web apps to the world and has shown interest in progressive web apps, but it still does not support service workers or the web app manifest. What can you do?

It is possible to make an offline website for Safari with AppCache, but doing so is both difficult and fraught with weird edge cases that can break the page or keep it permanently out of date after first load.

Instead, build a great web app experience. Your work will not have been wasted because the experience will still be great in Safari, which is a very good browser. When service workers do come to Safari, you will be ready to take advantage of them.

Finally, we can look forward to a lot of exciting developments in the world of web apps, with increasing support for the technologies behind them and new features coming to the web platform, such as the Web Bluetooth API for interacting with hardware, WebVR for virtual reality, and WebGL 2 for high-speed gaming. Now is a great time to explore the possibilities of web apps and to take part in shaping the future of the web.

Links Link

Other Writing on Progressive Web Apps Link

Links Referred to in Article Link

(vf, yk, il, al)

Editor’s Note:We kindly thank Christian Heilmann32 for his kind technical and editorial support — this article wouldn’t be possible without him.

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2016/08/a-beginners-guide-to-progressive-web-apps/
  2. 2 https://www.smashingmagazine.com/2016/02/building-first-class-app-leverages-website-case-study/
  3. 3 https://www.smashingmagazine.com/2015/04/creating-web-app-in-foundation-for-apps/
  4. 4 https://app.ft.com/
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2016/08/graph-from-dazeend-opt.png
  6. 6 http://dazeend.org/2015/01/the-shape-of-the-app-store/
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/08/graph-from-dazeend-opt.png
  8. 8 https://webkit.org/status/
  9. 9 https://www.smashingmagazine.com/responsive-web-design-guidelines-tutorials/
  10. 10 https://github.com/w3c/html/issues/40
  11. 11 https://github.com/GoogleChrome/sw-helpers
  12. 12 https://www.smashingmagazine.com/2016/02/making-a-service-worker/
  13. 13 https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts
  14. 14 https://letsencrypt.org/
  15. 15 https://github.com/GoogleChrome/sw-toolbox
  16. 16 https://jakearchibald.com/2016/caching-best-practices/
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/09/application-tab-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/09/application-tab-opt.png
  19. 19 http://developer.telerik.com/featured/300-ms-click-delay-ios-8/
  20. 20 https://github.com/ftlabs/fastclick
  21. 21 https://csstriggers.com/
  22. 22 https://greensock.com/
  23. 23 https://developers.google.com/web/fundamentals/getting-started/push-notifications/step-07?hl=en
  24. 24 https://www.npmjs.com/package/web-push
  25. 25 https://jakearchibald.github.io/isserviceworkerready/
  26. 26 https://ada.is/blog/2016/06/01/yet-another-progressive-webapp-post/
  27. 27 http://dazeend.org/2015/01/the-shape-of-the-app-store/
  28. 28 https://github.com/GoogleChrome/sw-helpers
  29. 29 https://github.com/GoogleChrome/sw-toolbox
  30. 30 http://developer.telerik.com/featured/300-ms-click-delay-ios-8/
  31. 31 https://jakearchibald.com/2016/caching-best-practices/
  32. 32 https://twitter.com/codepo8
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Freebie: Flat Line UX And E-Commerce Icon Sets (83 Icons, AI, EPS, PNG, SVG)

Freebie: Flat Line UX And E-Commerce Icon Sets (83 Icons, AI, EPS, PNG, SVG)

How often do you have to explain the purpose of a study, objectives, goals or measurements within your company? Maybe you need to prepare a presentation or a brief overview of what next steps should be taken, or maybe you simply need to build a shiny, new pattern library?

Whatever project you may be working on, today’s icon sets will come in handy. All of the vector icons were tirelessly crafted by the design team at Ecommerce Website Design121, and come in various formats that can be used for personal as well as commercial purposes.

This exclusive icon pack is licensed under under a Creative Commons Attribution 3.0 Unported2 license. You may modify the size, color or shape of the icons. No attribution is required, however, reselling of bundles or individual pictograms is not cool. Please provide credits to the creators and link to the article in which this freebie was released if you would like to spread the word in blog posts or anywhere else.

Flat Line User Experience Icon Set (45 Icons) Link

This consistent and beautifully diverse icon set offers a retro discreet feel, fading hues of army green, yellow, orange, red and grey, mixing into sharply defined images.

3
A preview of the Flat Line UX icon set. (Large preview4)
A close-up of two icons included in the flat line UX icon set.5
A close-up of two icons included in the flat line UX icon set. (Large preview6)

E-Commerce Linear Icon Set (38 Icons) Link

These e-commerce linear icons come in green, blue and red, displaying an array of signs, shops, clothes, even barcodes and currencies that clarify and lead the shopper. As you want to help, not to confuse your guests and potential clients, these icons are like Santa’s little helpers, taking some of the stress off your hands and wrapping big expectations into small, but mighty editable buttons.

A preview of the E-commerce linear icon set.7
A preview of the E-commerce linear icon set. (Large preview8)
A close-up of two icons included in the e-commerce linear icon set.9
A close-up of two icons included in the e-commerce linear icon set. (Large preview10)

Download The Icon Pack For Free Link

Insights From The Designer Link

“The 45 Flat Line User Experience Icon Set came from a need for UX (User Experience) icons as opposed to the abundance of User Interface icon sets. The retro color scheme and shapes are an escape from the standard ones. The icons are created in 2px line/stroke design filled with colors and details in line style as shapes. The stroke/line are fully editable in the .eps and .ai file.

With online shopping galloping in retail stats like a purebred stallion towards the finish line at the Royal Ascot, no wonder that e-commerce is in high demand. Together with SEO and social media icons, e-commerce icons are some of the most requested sets. As they always come in handy, these 38 E-Commerce Linear Icons are ready to take their job seriously and show up in all the right places. The designer of the collection literally keeps all her ideas and inspiration for colors, designs, shapes, in a special folder. This system helps her quickly answer to the customer’s preferences. Although there are many free e-commerce icons out there, design-wise they aren’t too adventurous. It was the regular RGB colors that inspired the designer to create the color scheme. These are clean, elegant linear e-comm icons with a retro touch – in 2px stroke design on fresh color backgrounds. The stroke/line are fully editable in the .eps and .ai file.”

A big thank you to the team at Ecommerce Website Design121 — we sincerely appreciate your time and efforts. Keep up the brilliant work!

(il, vf)

Footnotes Link

  1. 1 https://ecomm.design/
  2. 2 http://creativecommons.org/licenses/by/3.0/
  3. 3 https://www.smashingmagazine.com/wp-content//uploads/2016/08/flat-line-user-experience-icons-large-preview-opt.png
  4. 4 https://www.smashingmagazine.com/wp-content//uploads/2016/08/flat-line-user-experience-icons-large-preview-opt.png
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2016/08/ux-linear-closeup-large-preview-opt.png
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/08/ux-linear-closeup-large-preview-opt.png
  7. 7 https://www.smashingmagazine.com/wp-content//uploads/2016/08/e-commerce-linear-icons-large-preview-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content//uploads/2016/08/e-commerce-linear-icons-large-preview-opt.png
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/08/e-commerce-icons-closeup-large-opt.png
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2016/08/e-commerce-icons-closeup-large-opt.png
  11. 11 http://provide.smashingmagazine.com/Freebies/smashing-freebie-ux-and-ecommerce-icon-sets.zip
  12. 12 https://ecomm.design/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Web Development Reading List #152: On Not Shipping, Pure JS Functions, And SameSite Cookies

Web Development Reading List #152: On Not Shipping, Pure JS Functions, And SameSite Cookies

This week’s reading list consists of a lot of little, smart details that you can use on websites. From tweaking the user’s reading experience during page load to pure JavaScript functions and verifying the integrity of external assets. And finally, we see some articles on thinking differently about established working habits — be it working on AI without data or the virtue of not shipping a feature.

Please note that I’ll be on vacation for the next four weeks, so please don’t expect any new Web Development Reading List before October, 7th. Enjoy September, your work, your life!

General Link

  • Jason Zimdars explains why not shipping a feature can be a virtue1. An article about hidden costs and why shipping does not equal success.
  • While many think Apple isn’t in the Artificial Intelligence game, this exclusive look gives some insights2 into why Apple handles things differently. An interesting read that reveals how Apple tries to do Artificial Intelligence with less user data and without tracking you — contrary to the industry’s big players.
3
Not shipping can be a virtue4. Jason Zimdars shares how one of the most important features he ever designed for Basecamp didn’t make it into the product. (Image credit: Jason Zimdars5)

Concept & Design Link

  • The Web Methodology Project6 is a fresh guide to building web projects, and even though it’s still a work in progress, it already looks very useful. So keep an eye on it.

Tools & Workflows Link

  • Google’s Closure Compiler is one of the best tools out there to compile JavaScript, but so far has only been available as a Java platform tool. Now, the team released a JavaScript version of Closure Compiler7 designed to run in Node.js environments. Available on GitHub8 or npm9.

Security Link

Accessibility Link

Illustration of a person being left behind as travellers speed away in a futuristic ship14
Don’t leave your users behind. Mischa Andrews shares thoughts on how we can make the web more accessible15. (Original artwork by Adam Van Winden16)

JavaScript Link

CSS/Sass Link

  • Michael Scharnagl shares some neat techniques to reduce content shifting during page load19 to ensure a smooth reading experience for users. By setting intrinsic ratios for media, font-size-adjust, or new techniques such as scroll anchoring, you can improve the situation enormously.

Work & Life Link

And with that, I’ll close for this week. If you like what I write each week, please support me with a donation21 or share this resource with other people. You can learn more about the costs of the project here22. It’s available via email, RSS and online.

— Anselm

Footnotes Link

  1. 1 https://m.signalvnoise.com/not-shipping-is-a-virtue-b880badb623c
  2. 2 https://backchannel.com/an-exclusive-look-at-how-ai-and-machine-learning-work-at-apple-8dbfb131932b
  3. 3 https://m.signalvnoise.com/not-shipping-is-a-virtue-b880badb623c
  4. 4 https://m.signalvnoise.com/not-shipping-is-a-virtue-b880badb623c
  5. 5 https://m.signalvnoise.com/not-shipping-is-a-virtue-b880badb623c
  6. 6 http://webmethodologyproject.com/guide/
  7. 7 https://developers.googleblog.com/2016/08/closure-compiler-in-javascript.html
  8. 8 https://github.com/google/closure-compiler-js
  9. 9 https://www.npmjs.com/package/google-closure-compiler-js
  10. 10 https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/
  11. 11 https://www.troyhunt.com/protecting-your-embedded-content-with-subresource-integrity-sri/
  12. 12 https://www.igvita.com/2016/08/26/stop-cross-site-timing-attacks-with-samesite-cookies/
  13. 13 https://medium.com/@MischaAndrews/the-inaccessible-web-how-we-got-into-this-mess-7cd3460b8e32
  14. 14 https://medium.com/@MischaAndrews/the-inaccessible-web-how-we-got-into-this-mess-7cd3460b8e32
  15. 15 https://medium.com/@MischaAndrews/the-inaccessible-web-how-we-got-into-this-mess-7cd3460b8e32
  16. 16 http://adamvanwinden.tumblr.com/
  17. 17 http://staltz.com/is-your-javascript-function-actually-pure.html
  18. 18 http://staltz.com/react-could-love-web-components.html
  19. 19 https://www.smashingmagazine.com/2016/08/ways-to-reduce-content-shifting-on-page-load/
  20. 20 https://m.signalvnoise.com/its-urgent-really-8050dfe3b921
  21. 21 https://wdrl.info/donate
  22. 22 https://wdrl.info/costs/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Responsive Images In WordPress With Art Direction

Responsive Images In WordPress With Art Direction

Support for responsive images1 was added to WordPress core in version 4.4 to address the use case for viewport-based image selection2, where the browser requests the image size that best fits the layout for its particular viewport.

Images that are inserted within the text of a post automatically get the responsive treatment, while images that are handled by the theme or plugins — like featured images and image galleries — can be coded by developers using the new responsive image functions and filters. With a few additions, WordPress websites can accommodate another responsive image use case known as art direction3. Art direction gives us the ability to design with images whose crop or composition changes at certain breakpoints.

In this article, I’ll show you how to set up a WordPress website for art direction by going through three progressive examples:

In the art direction example, we’ll be adding some PHP, a polyfill and a cropping plugin to the website.

WordPress’ Automatic Support For Responsive Images Within Posts

Support for responsive images is all about options: We provide a well-described array of image files to the browser, and the browser applies its knowledge of the width and pixel density of the viewport to request the file with the most appropriate resolution. The workhorse here is the srcset attribute, which can be used with img and source tags. Similar to, but more informative than, its older cousin, the src attribute, srcset is essentially a “set of sources” — that is, a list of image files available for downloading. For detailed background on the srcset attribute, I recommend Eric Portis’ article on responsive images7.

Since version 4.4, WordPress automatically adds a srcset attribute to any image that is run through the_content filter. In other words, when WordPress is creating the HTML for your web page, it scans the post or page’s text for img tags and adds a srcset attribute to any tags that don’t already contain one. You won’t see the srcset in the post editor (unless you explicitly add one, although you should generally let WordPress take care of it), but it will be present in the page’s HTML source.

To offer multiple image sizes in the srcset, WordPress leverages its standard behavior of automatically creating several smaller versions of your image files when you upload them to the “Media Library.” You can find these sizes listed on the “Media Settings” screen (under the “Settings” menu in the WordPress administration interface), along with their default values; not listed is the new “medium_large” image size8 (768 pixels wide, with no height limit), the size of which can be changed by a theme or plugin but not through the administration interface.

9
The default maximum sizes shown on WordPress’ “Media Settings” screen are 1024 × 1024 pixels for the “large” size, 300 × 300 pixels for the “medium” size, and 150 × 150 pixels for the “thumbnail” size. The 768 pixel “medium_large” size cannot be changed here. (View large version10)

By default, the autogenerated “medium,” “medium_large” and “large” image sizes are soft-cropped — that is, they maintain the same aspect ratio as the original file. (I refer to these as “scaled” versions.) In these cases, the width given on the “Media Settings” screen is the constraining parameter. In contrast, the “thumbnail” size is hard-cropped to a 150 pixel square, so it most likely has a different aspect ratio than its bigger brothers. WordPress relies on aspect ratio to determine which image sizes should be included in a srcset, and we’ll be seeing this play out in each of our examples.

Let’s say that you upload a 1400 × 952-pixel image to the WordPress media library and keep the image sizes at their default values. Behind the scenes, WordPress creates the following versions of the original image:

Image generation in WordPress based on a 1400 × 952-pixel image
Size Width (px) Height (px) Cropping Aspect ratio (w/h)
full (original) 1400 952 soft 1.47
large 1024 696 soft 1.47
medium_large 768 522 soft 1.47
medium 300 204 soft 1.47
thumbnail 150 150 hard 1

If you then insert the “large” (1024 pixels wide) version into a post and view the HTML source for the published web page, you’d see something like this:

<img src="sample-1024x696.jpg" width="1024" height="696" srcset="sample-300x204.jpg 300w, sample-768x522.jpg 768w, sample-1024x696.jpg 1024w" sizes="(max-width: 1024px) 100vw, 1024px" alt="A meaningful sample image"> 

WordPress has generated a srcset for us using the “medium,” “medium_large” and “large” sizes because these images all share the same aspect ratio. The “thumbnail” version wasn’t included, which makes sense because we want those images to look the same in every viewport.

Two other bits of information are also included in the HTML above. First, the w descriptors within the srcset tell the browser the actual pixel widths of the files; without these, the browser would need download the images to find out their dimensions. Secondly, WordPress’ default value for the sizes attribute tells the browser how wide the image is intended to be in this particular layout. Here, for viewports narrower than 1024 pixels, the image should fill and scale with the size of the viewport; otherwise, the image should be displayed at its default width of 1024 pixels and not any wider. With these final pieces to the puzzle, the browser can now make an intelligent image request, whether it be to display a high-resolution file on a “Retina” display or a low-resolution file on a small phone.

A Variable-Width Banner Image In A Page Template

Now that we understand how WordPress leverages the standard image sizes to build a srcset, it’s time to get acquainted with WordPress core’s new responsive image functions11 by applying viewport-based image selection to a theme. For this example, we’ll look at a full-width banner image that appears on a static front page.

Let’s assume that we have an existing website using the current version of WordPress and that support for post thumbnails is enabled12 in our theme. (Support for post thumbnails allows us to add featured images to posts and pages.) Let’s also assume that the banner image is pulled from the featured image for the front page. If our front page template uses WordPress’ the_post_thumbnail() template tag to generate the HTML for the banner, then we are all set: This function already outputs an img tag that includes srcset and sizes attributes. That’s one reason why it is good to use WordPress template functions when they are available!

Maybe, though, our page template builds the HTML for the banner image piece by piece, as you might need to do if your banner is actually part of a third-party carousel. To make this image responsive, we ask WordPress explicitly for srcset and sizes attributes, using the wp_get_attachment_image_srcset() and wp_get_attachment_image_sizes() functions, respectively:

<?php if ( has_post_thumbnail() ) : ?> $id = get_post_thumbnail_id(); $src = wp_get_attachment_image_src( $id, 'full' ); $srcset = wp_get_attachment_image_srcset( $id, 'full' ); $sizes = wp_get_attachment_image_sizes( $id, 'full' ); $alt = get_post_meta( $id, '_wp_attachment_image_alt', true); <img src="<?php echo esc_attr( $src );?>" srcset="<?php echo esc_attr( $srcset ); ?>" sizes="<?php echo esc_attr( $sizes );?>" alt="<?php echo esc_attr( $alt );?>" /> <?php endif; ?>

Here, we’ve based srcset and sizes on the original image size by passing the full keyword to our functions. If that image is 1280 × 384 pixels, and if we keep the standard image sizes at their default values, then the HTML output would look like this:

<img src="banner.jpg" srcset="banner.jpg 1280w, banner-300x90.jpg 300w, banner-768x231.jpg 768w, banner-1024x308.jpg 1024w" sizes="(max-width: 1280px) 100vw, 1280px" alt="Front page banner alt text"> 

In this case, as in the last, the value that WordPress gives us for the sizes attribute is acceptable for our hypothetical layout. In general, WordPress’ default value for sizes works fine for full-width images, but for any other layout, you are going to need to write the value yourself. Some layouts are more complicated than others: The sizes attribute for a responsive image grid (see Eric Portis’ example13) is pretty straightforward, but layouts that change at different breakpoints, such as pages with a sidebar column, require more thought. For the latter case, Tim Evko uses the Twenty Sixteen theme as an example of applying the wp_calculate_image_sizes filter14 to make the sizes value match the layout’s CSS breakpoints.

An Art-Directed Hero Image In A Page Template

Let’s momentarily revisit the HTML in the banner example and take note of the size of the smallest image in srcset: It’s only 90 pixels tall and probably difficult to discern. The aspect ratio is fixed by the original image, so, realistically, we’ll be looking at a 96-pixel stripe across a 320-pixel phone.

Themes currently get around the “banner stripe” problem by displaying the banner image as the CSS background of a flexible div and adjusting its height and background-size in media queries. This solution is responsive in terms of appearance, however, it is not a true responsive image solution. Enter art direction, the ability to provide different image sources at different viewport widths directly in HTML. With this technique, we can avoid the banner stripe problem by resetting the proportions of an image below a breakpoint to give the smallest resizes better dimensions; we can also use art direction to emphasize a particular area of an image at different sizes or orientations.

In our art direction example, we will use the 1400 × 952-pixel image from our first example to create a responsive hero image. On large viewports, the hero image will look like this (albeit much larger):

Large hero image example15
Full-sized hero image, 1400 × 952 pixels (Image: Josh Felise16) (View large version17)

But for smaller viewports, we will crop the image within WordPress so that it looks like this:

Cropped hero image example18
Cropped hero image with a 5:3 aspect ratio

This approach gives us two images for the price of one — a full-sized and a cropped — each with its own srcset.

Setting up our WordPress environment for art direction takes four steps. As in the previous example, the hero image will be the featured image for the website’s home page, and we’ll be editing the front-page template. I assume that you are making changes to an existing theme and, thus, have created a child theme19 to work in.

1. Include the PictureFill Script Link

We are going to code our hero image by wrapping it in HTML5’s picture element20. The picture element allows us to provide multiple sources for an image, along with media queries to determine when a source will be used. As of this writing, picture is supported globally by 62% of browsers21, so we will need to rely on the Picturefill polyfill22 to implement this element in non-supporting browsers. The Picturefill project is maintained by the Filament Group, and the Picturefill JavaScript file can be downloaded from GitHub23.

To include the PictureFill script in the head of our pages, we’ll place the script file in our child theme directory and add the following code to our child theme’s functions.php file:

// adds Picturefill to 'js' subdirectory inside child theme function theme_add_javascripts() { wp_enqueue_script( 'picturefill-js', get_stylesheet_directory_uri() . '/js/picturefill.min.js', '', '', false ); } add_action( 'wp_enqueue_scripts', 'theme_add_javascripts' ); 

2. Plan the Breakpoint and Configure the Image Sizes Link

To plan our srcsets, we need to decide on three things:

  • the breakpoint at which we will switch from the cropped to the full-sized hero image,
  • the aspect ratio of the cropped hero.
  • one or more scaled-down sizes for the cropped image in small viewports.

Let’s deal with each in turn:

The breakpoint

For our example, let’s say that the couple in the rearview mirror become hard to recognize in images narrower than 768 pixels; perhaps some overlaid text that we are using with this image no longer fits beneath the mirror at this point as well. We’ll set our breakpoint at 768 pixels, which means that we’ll also be able to keep the “medium_large” and “large” image sizes at their default values.

The aspect ratio

This simple implementation of art direction in WordPress doesn’t require us to upload multiple featured images or to type in a value for the breakpoint. Still, we need a way to keep the srcset for the full-sized image from overlapping with the srcset of the cropped image, and for this we will rely on the fact that the wp_get_attachment_image_srcset() function only selects image files with the same aspect ratio as the size we pass to it. We’ll pick a 5:3 (1.67) aspect ratio for the cropped hero image, which differs from the 1.47 aspect ratio of the original.

The image sizes

Based on our breakpoint and aspect ratio, the size of the cropped hero image will be 767 × 460 pixels. The cropped hero won’t be completely responsive, however, unless we define additional image sizes to crop along with it. Applying a performance budget approach24 to our hypothetical theme, we’ll create custom sizes that are 560 and 360 pixels wide, giving us a roughly 20 KB difference in file size between the three cropped versions. (Because the file size of a compressed image depends its color variation and level of detail, I established this size relationship empirically with WordPress’ default 90% JPEG compression.) The custom image sizes will be created by adding the following code to our child theme’s functions.php file:

// cropped hero add_image_size( 'mytheme-hero-cropped', 767, 460, true ); // scaled-down cropped hero 1 add_image_size( 'mytheme-hero-cropped-smaller', 560, 336, true ); // scaled-down cropped hero 2 add_image_size( 'mytheme-hero-cropped-smallest', 360, 216, true ); 

The fourth parameter in the add_image_size function specifies whether the image version can be hard-cropped, which we set to be true; many cropping plugins (which we’ll look at in step 3) will not let us hard-crop an image unless this is set.

Overall, we’ll have the following image versions available to work with:

The standard and custom image sizes generated for the hero image in our example
Size Width (px) Height (px) Aspect ratio (w/h)
Full-sized hero:
full (original) 1400 952 1.47
large 1024 696 1.47
medium_large 768 522 1.47
medium (not needed) 300 204 1.47
Cropped hero:
mytheme-hero-cropped 767 460 1.67
mytheme-hero-cropped-smaller 560 336 1.67
mytheme-hero-cropped-smallest 360 216 1.67
Thumbnail:
thumbnail (not needed) 150 150 1

3. Install a Third-Party Image-Cropping Plugin and Crop the Images Link

WordPress’ built-in image editor does allow us to hard-crop an image, but the change is applied to all image sizes (or just to the “thumbnail”), whereas we need to crop only three. For greater control, we’ll install a third-party cropping plugin from the WordPress directory.

While any cropping plugin should work with our art direction scheme, the ideal plugin would be able to crop multiple versions of an image at the same time, provided that they all had the same aspect ratio. I came across two plugins that are able to do this: Crop-Thumbnails25 and Post Thumbnail Editor26. Testing both of these plugins with our custom image sizes, I found that the Crop-Thumbnails plugin (version 0.10.8) recognized only two of the three sizes as having the 5:3 aspect ratio, meaning that I would need to go through the cropping process two times. (The “mytheme-hero-cropped” size was left out because of a rounding issue: An exact 5:3 aspect ratio would require the width to be 460.2 pixels, instead of 460.) The Post Thumbnail Editor plugin (version 2.4.8) allowed me to crop all three sizes at once.

4. Code the Hero Image Using the <picture> Element Link

Now that our images are ready, we can add the code for the hero image to a copy of the front-page template in our child theme. HTML5’s picture element can hold an img tag and one or more source tags. For our example, the single source element will contain the media query and srcset for the full-sized image, and the img tag will contain the srcset for the cropped image; the cropped image will serve as the default image when the breakpoint condition is not met.

<?php if ( has_post_thumbnail() ) : ?> $id = get_post_thumbnail_id(); $alt = get_post_meta( $id, '_wp_attachment_image_alt', true); /* get the width of the largest cropped image to calculate the breakpoint */ $hero_cropped_info = wp_get_attachment_image_src( $id, 'mytheme-hero-cropped' ); $breakpoint = absint( $hero_cropped_info[1] ) + 1; // pass the full image size to these functions $hero_full_srcset = wp_get_attachment_image_srcset( $id, 'full' ); $hero_full_sizes = wp_get_attachment_image_sizes( $id, 'full' ); // pass the cropped image size to these functions $hero_cropped_srcset = wp_get_attachment_image_srcset( $id, 'mytheme-hero-cropped' ); $hero_cropped_sizes = wp_get_attachment_image_sizes( $id, 'mytheme-hero-cropped' ); <picture> <source media="(min-width: <?php echo $breakpoint; ?>px)" srcset="<?php echo esc_attr( $hero_full_srcset ); ?>" sizes="<?php echo esc_attr( $hero_full_sizes ); ?>" /> <img srcset="<?php echo esc_attr( $hero_cropped_srcset ); ?>" alt="<?php echo esc_attr( $alt );?>" sizes="<?php echo esc_attr( $hero_cropped_sizes ); ?>" /> </picture> <?php endif; ?> 

There are two additional points of interest in this code. First, notice that we are not hardcoding the breakpoint width, even though we know that it should be 768 pixels in this case. Because we calculate the breakpoint using the width of the largest cropped image, we can now change the image sizes in future without needing to go back to edit the template. Secondly, in contrast to the banner image example, the img tag here does not get a src attribute. This is an artifact of using a polyfill to support the picture element: A non-supporting browser would preload the file given in the src attribute, resulting in a double download for this image.

The HTML that we get is shown below:

<picture> <source media="(min-width: 768px)" srcset="hero.jpg 1400w, hero-300x204.jpg 300w, hero-768x522.jpg 768w, hero-1024x696.jpg 1024w" sizes="(max-width: 1400px) 100vw, 1400px"> <img srcset="hero-767x460.jpg 767w, hero-560x336.jpg 560w, hero-360x216.jpg 360w" alt="Front page hero alt text" sizes="(max-width: 767px) 100vw, 767px"> </picture> 

We could finish here, but we could make one refinement to our HTML output. Notice that the 300-pixel-wide “medium” image has been included in the srcset for the full-sized image. This image file will never be used, so we can add a wp_calculate_image_srcset filter to remove it from the srcset. The following code, which goes in the child theme’s functions.php file, looks only at the potential srcset (the $sources array) for the full-sized hero image; it loops through the images and removes those with widths narrower than the breakpoint.

add_filter( 'wp_calculate_image_srcset', 'mytheme_remove_images_below_breakpoint', 10, 5 ); function mytheme_remove_images_below_breakpoint( $sources, $size_array, $image_src, $image_meta, $attachment_id ) { if ( is_front_page() && has_post_thumbnail() ) { // check if we're filtering the featured image if ( $attachment_id === get_post_thumbnail_id() ) { // get cutoff as width of the largest cropped image size // (in HTML, breakpoint = cutoff + 1 ) $cutoff = $image_meta['sizes']['mytheme-hero-cropped']['width']; // check if our version is the full-sized version by // comparing its width to the cutoff if ( $cutoff  $value ) { // if image width is at or below cutoff, // we don't need it if ( $cutoff >= $key ) { unset( $sources[ $key ] ); } } } } } return $sources; } 

Final Thoughts Link

We have just set up a WordPress theme to support art direction in a simple manner. This method relies on WordPress’ standard administration interface as much as possible, and it requires only a single image to be uploaded. Simplicity comes at a cost, however, and this method has its limitations: The sizes for the cropped hero images are hardcoded in the theme, only one breakpoint is assumed, and the aspect ratios of the full-sized and cropped heros must be different.

Programmatically, it is entirely possible to give a website’s content creator complete control over all aspects of art direction, because the wp_calculate_image_srcset filter can process images by width, size keyword or any other bit of meta data that a theme or plugin wants to save. Multiple images could even be selected from the media library and incorporated in the art-directed version. The challenge lies in making the administration interface — the theme customizer or the plugin settings page — simple to use for content creators who may want no options, a few options or the kitchen sink.

Finally, we can’t end an article on responsive images in 2016 without mentioning browser support. While we do have a very effective polyfill for the picture element, if a browser that does not natively support the srcset attribute has JavaScript turned off (or encounters a JavaScript error), a visitor will only see our hero image’s alt text. Global support for the picture element did increase earlier this year when new versions of Safari for Mac and iOS were released, but we are still waiting for the picture element to come to UC Browser and for older browsers — namely, Internet Explorer 11 — to die out.

(vf, al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2015/12/responsive-images-in-wordpress-core/
  2. 2 https://usecases.responsiveimages.org/#viewport-based-selection
  3. 3 https://usecases.responsiveimages.org/#art-direction
  4. 4 #wordpress-automatic-support-for-responsive-images-within-posts
  5. 5 #a-variable-width-banner-image-in-a-page-template
  6. 6 #an-art-directed-hero-image-in-a-page-template
  7. 7 https://www.smashingmagazine.com/2014/05/responsive-images-done-right-guide-picture-srcset/
  8. 8 https://make.wordpress.org/core/2015/11/10/responsive-images-in-wordpress-4-4/
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/08/media-settings-large-opt.jpg
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2016/08/media-settings-large-opt.jpg
  11. 11 https://make.wordpress.org/core/2015/11/10/responsive-images-in-wordpress-4-4/
  12. 12 https://codex.wordpress.org/Post_Thumbnails#Enabling_Support_for_Post_Thumbnails
  13. 13 https://www.smashingmagazine.com/2014/05/responsive-images-done-right-guide-picture-srcset/#the-fluid-and-variable-sized-image-use-cases
  14. 14 https://www.smashingmagazine.com/2015/12/responsive-images-in-wordpress-core/
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/08/car-large-opt.jpg
  16. 16 http://unsplash.com/
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/08/car-large-opt.jpg
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/08/car-small-opt.jpg
  19. 19 https://codex.wordpress.org/Child_Themes
  20. 20 https://responsiveimages.org
  21. 21 http://caniuse.com/#feat=picture
  22. 22 http://scottjehl.github.io/picturefill/
  23. 23 https://github.com/scottjehl/picturefill
  24. 24 http://blog.cloudfour.com/sensible-jumps-in-responsive-image-file-sizes/
  25. 25 https://wordpress.org/plugins/crop-thumbnails/
  26. 26 https://wordpress.org/plugins/post-thumbnail-editor/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Desktop Wallpaper Calendars: September 2016

Desktop Wallpaper Calendars: September 2016

We all love a good wallpaper to polish up our desktops. So to provide you with fresh artwork on a regular basis, we embarked on our desktop wallpapers mission1 eight years ago. Each month we challenge you, the design community, to get your creative juices flowing and produce some inspirational and unique desktop wallpapers.

And, well, also this time designers and artists from across the globe challenged their artistic abilities and contributed their designs for September. The result is a collection of desktop wallpapers that are a little more distinctive than the usual crowd. All of them come in versions with and without a calendar and are free to download. A big thank-you to everyone who shared their artwork! Now, which one will make it to your desktop?

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • You can feature your work in our magazine2 by taking part in our Desktop Wallpaper Calendars series. We are regularly looking for creative designers and artists to be featured on Smashing Magazine. Are you one of them?

Flower Soul

“The earth has music for those who listen. Take a break and relax and while you drive out the stress, catch a glimpse of the beautiful nature around you. Can you hear the rhythm of the breeze blowing, the flowers singing, and the butterflies fluttering to cheer you up? We dedicate flowers which symbolize happiness and love to one and all.” — Designed by Krishnankutty3 from India.

4

Office

“Clean, minimalistic office for a productive day.” — Designed by Antun Hiršman46 from Croatia.

Office47

Penguin Family

“Penguins are sociable, independent and able to survive harsh winters. They work as a team to care for their offspring and I love that!” — Designed by Glynnis Owen67 from Australia.

Penguin Family68

Autumn In The Woods

“Autumn can be best described with the colorful woods where all colors mix and where you can see the great creations of nature.” — Designed by S7 Design92 from Serbia.

Autumn In The Woods93

Autumn Leaves

“Summer is coming to an end in the northern hemisphere, and that means Autumn is on the way!” — Designed by James Mitchell137 from the United Kingdom.

Autumn Leaves138

Do You Remember?

“My wife tells me ‘You have a song for everything!’ and this month was no exception. Earth, Wind, and Fire’s happy, danceable tune was the first thing to come to mind. For me, the catchy beat and memorable lyrics are such a contrast to the month that heralds the first day of Autumn, ushering in a ‘temporary death’ yet with a certain, not-too-distant re-quickening. It’s the 22nd this year, so we took liberties with that excerpt. Ironically, co-writer Allee Willis claims no significance to the date, stating, in an interview with npr.org, ‘It just sang better.’” — Designed by Brian Frolo158 from Cleveland, Ohio, USA.

Do You Remember?159

Tropical Procrastination

Designed by PJ Brown177 from the United States.

Tropical Procrastination178

The September Sun

“September marks the arrival of autumn and is one of the most beautiful months of the year. Autumn — this is a great time for inspiration and creation. The arrival of autumn hits us in the heart, and as the trees turn yellow we begin to notice how quickly time passes by. In September, the sun shines gently, but hedgehogs are preparing for hibernation.” — Designed by Anastasia220 from Russia.

The September Sun221

Viva Mexico

“This month is Mexico’s independence day and I decided to illustrate in my wallpaper one of the things Mexico’s best known for: the Lucha Libre.” — Designed by Maria Keller249 from Mexico.

Viva Mexico250

Hello Spring

“September is the start of spring in Australia so this bright wallpaper could brighten your day and help you feel energized!” — Designed by Tazi Design302 from Australia.

Hello Spring303

Live In The Moment

“The dragonfly flies for a short time and enjoys it to the fullest. Be like the dragonfly, love your life and live in the moment!” — Designed by Denise Johnson327 from Chicago.

Live In The Moment328

Festivities And Ganesh Puja

“The month of September starts with the arrival of festivals, mainly Ganesh Puja.” — Designed by Sayali Sandeep Harde342 from India.

Festivities And Ganesh Puja343

Underwater Love

Designed by Sabrina Stern371 from Costa Rica.

Underwater Love372

Join In Next Month! Link

Please note that we respect and carefully consider the ideas and motivation behind each and every artist’s work. This is why we give all artists the full freedom to explore their creativity and express emotions and experience throughout their works. This is also why the themes of the wallpapers weren’t anyhow influenced by us, but rather designed from scratch by the artists themselves.

A big thank you to all designers for their participation. Join in next month394!

What’s Your Favorite? Link

What’s your favorite theme or wallpaper for this month? Please let us know in the comment section below.

(cm)

Footnotes Link

  1. 1 http://www.smashingmagazine.com/tag/wallpapers/
  2. 2 https://www.smashingmagazine.com/desktop-wallpaper-calendars-join-in/
  3. 3 http://acodez.in/
  4. 4 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/sept-16-flower-soul-full.png
  5. 5 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/sept-16-flower-soul-preview.png
  6. 6 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-320×480.png
  7. 7 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-640×480.png
  8. 8 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-800×480.png
  9. 9 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-800×600.png
  10. 10 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1024×768.png
  11. 11 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1024×1024.png
  12. 12 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1152×864.png
  13. 13 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1280×720.png
  14. 14 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1280×960.png
  15. 15 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1280×1024.png
  16. 16 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1366×768.png
  17. 17 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1400×1050.png
  18. 18 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1440×900.png
  19. 19 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1600×1200.png
  20. 20 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1680×1050.png
  21. 21 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1680×1200.png
  22. 22 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1920×1080.png
  23. 23 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1920×1200.png
  24. 24 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-1920×1440.png
  25. 25 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/cal/sept-16-flower-soul-cal-2560×1440.png
  26. 26 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-320×480.png
  27. 27 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-640×480.png
  28. 28 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-800×480.png
  29. 29 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-800×600.png
  30. 30 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1024×768.png
  31. 31 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1024×1024.png
  32. 32 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1152×864.png
  33. 33 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1280×720.png
  34. 34 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1280×960.png
  35. 35 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1280×1024.png
  36. 36 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1366×768.png
  37. 37 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1400×1050.png
  38. 38 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1440×900.png
  39. 39 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1600×1200.png
  40. 40 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1680×1050.png
  41. 41 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1680×1200.png
  42. 42 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1920×1080.png
  43. 43 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1920×1200.png
  44. 44 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-1920×1440.png
  45. 45 http://files.smashingmagazine.com/wallpapers/sept-16/flower-soul/nocal/sept-16-flower-soul-nocal-2560×1440.png
  46. 46 http://hirsdesign.com/
  47. 47 http://files.smashingmagazine.com/wallpapers/sept-16/office/sept-16-office-full.jpg
  48. 48 http://files.smashingmagazine.com/wallpapers/sept-16/office/sept-16-office-preview.jpg
  49. 49 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-320×480.jpg
  50. 50 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-800×600.jpg
  51. 51 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-1280×720.jpg
  52. 52 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-1280×1024.jpg
  53. 53 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-1440×900.jpg
  54. 54 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-1680×1050.jpg
  55. 55 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-1920×1080.jpg
  56. 56 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-1920×1440.jpg
  57. 57 http://files.smashingmagazine.com/wallpapers/sept-16/office/cal/sept-16-office-cal-2560×1440.jpg
  58. 58 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-320×480.jpg
  59. 59 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-800×600.jpg
  60. 60 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-1280×720.jpg
  61. 61 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-1280×1024.jpg
  62. 62 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-1440×900.jpg
  63. 63 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-1680×1050.jpg
  64. 64 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-1920×1080.jpg
  65. 65 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-1920×1440.jpg
  66. 66 http://files.smashingmagazine.com/wallpapers/sept-16/office/nocal/sept-16-office-nocal-2560×1440.jpg
  67. 67 http://www.echo3.com.au
  68. 68 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/sept-16-penguin-family-full.png
  69. 69 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/sept-16-penguin-family-preview.png
  70. 70 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-320×480.png
  71. 71 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-640×480.png
  72. 72 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-800×600.png
  73. 73 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-1024×768.png
  74. 74 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-1152×864.png
  75. 75 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-1280×720.png
  76. 76 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-1280×960.png
  77. 77 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-1600×1200.png
  78. 78 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-1920×1080.png
  79. 79 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-1920×1440.png
  80. 80 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/cal/sept-16-penguin-family-cal-2560×1440.png
  81. 81 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-320×480.png
  82. 82 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-640×480.png
  83. 83 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-800×600.png
  84. 84 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-1024×768.png
  85. 85 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-1152×864.png
  86. 86 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-1280×720.png
  87. 87 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-1280×960.png
  88. 88 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-1600×1200.png
  89. 89 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-1920×1080.png
  90. 90 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-1920×1440.png
  91. 91 http://files.smashingmagazine.com/wallpapers/sept-16/penguin-family/nocal/sept-16-penguin-family-nocal-2560×1440.png
  92. 92 http://www.s7designcreative.com
  93. 93 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/sept-16-autumn-in-the-woods-full.png
  94. 94 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/sept-16-autumn-in-the-woods-preview.png
  95. 95 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-320×480.png
  96. 96 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-640×480.png
  97. 97 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-800×480.png
  98. 98 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-800×600.png
  99. 99 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1024×768.png
  100. 100 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1024×1024.png
  101. 101 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1152×864.png
  102. 102 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1280×720.png
  103. 103 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1280×800.png
  104. 104 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1280×960.png
  105. 105 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1280×1024.png
  106. 106 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1366×768.png
  107. 107 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1400×1050.png
  108. 108 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1440×900.png
  109. 109 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1600×1200.png
  110. 110 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1680×1050.png
  111. 111 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1680×1200.png
  112. 112 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1920×1080.png
  113. 113 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1920×1200.png
  114. 114 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-1920×1440.png
  115. 115 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/cal/sept-16-autumn-in-the-woods-cal-2560×1440.png
  116. 116 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-320×480.png
  117. 117 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-640×480.png
  118. 118 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-800×480.png
  119. 119 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-800×600.png
  120. 120 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1024×768.png
  121. 121 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1024×1024.png
  122. 122 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1152×864.png
  123. 123 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1280×720.png
  124. 124 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1280×800.png
  125. 125 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1280×960.png
  126. 126 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1280×1024.png
  127. 127 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1366×768.png
  128. 128 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1400×1050.png
  129. 129 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1440×900.png
  130. 130 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1600×1200.png
  131. 131 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1680×1050.png
  132. 132 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1680×1200.png
  133. 133 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1920×1080.png
  134. 134 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1920×1200.png
  135. 135 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-1920×1440.png
  136. 136 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-in-the-woods/nocal/sept-16-autumn-in-the-woods-nocal-2560×1440.png
  137. 137 https://www.behance.net/jamesmitchell23
  138. 138 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/sept-16-autumn-leaves-full.png
  139. 139 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/sept-16-autumn-leaves-preview.png
  140. 140 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-1280×720.png
  141. 141 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-1280×800.png
  142. 142 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-1366×768.png
  143. 143 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-1440×900.png
  144. 144 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-1680×1050.png
  145. 145 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-1920×1080.png
  146. 146 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-1920×1200.png
  147. 147 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-2560×1440.png
  148. 148 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/cal/sept-16-autumn-leaves-cal-2880×1800.png
  149. 149 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-1280×720.png
  150. 150 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-1280×800.png
  151. 151 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-1366×768.png
  152. 152 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-1440×900.png
  153. 153 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-1680×1050.png
  154. 154 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-1920×1080.png
  155. 155 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-1920×1200.png
  156. 156 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-2560×1440.png
  157. 157 http://files.smashingmagazine.com/wallpapers/sept-16/autumn-leaves/nocal/sept-16-autumn-leaves-nocal-2880×1800.png
  158. 158 http://www.codesign.cc
  159. 159 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/sept-16-do-you-remember-full.jpg
  160. 160 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/sept-16-do-you-remember-preview.jpg
  161. 161 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/cal/sept-16-do-you-remember-cal-1024×768.jpg
  162. 162 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/cal/sept-16-do-you-remember-cal-1280×800.jpg
  163. 163 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/cal/sept-16-do-you-remember-cal-1280×1024.jpg
  164. 164 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/cal/sept-16-do-you-remember-cal-1400×1050.jpg
  165. 165 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/cal/sept-16-do-you-remember-cal-1440×900.jpg
  166. 166 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/cal/sept-16-do-you-remember-cal-1600×1200.jpg
  167. 167 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/cal/sept-16-do-you-remember-cal-1920×1080.jpg
  168. 168 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/cal/sept-16-do-you-remember-cal-2560×1440.jpg
  169. 169 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/nocal/sept-16-do-you-remember-nocal-1024×768.jpg
  170. 170 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/nocal/sept-16-do-you-remember-nocal-1280×800.jpg
  171. 171 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/nocal/sept-16-do-you-remember-nocal-1280×1024.jpg
  172. 172 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/nocal/sept-16-do-you-remember-nocal-1400×1050.jpg
  173. 173 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/nocal/sept-16-do-you-remember-nocal-1440×900.jpg
  174. 174 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/nocal/sept-16-do-you-remember-nocal-1600×1200.jpg
  175. 175 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/nocal/sept-16-do-you-remember-nocal-1920×1080.jpg
  176. 176 http://files.smashingmagazine.com/wallpapers/sept-16/do-you-remember/nocal/sept-16-do-you-remember-nocal-2560×1440.jpg
  177. 177 http://peggiejeanie.com
  178. 178 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/sept-16-tropical-procrastination-full.jpg
  179. 179 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/sept-16-tropical-procrastination-preview.jpg
  180. 180 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-320×480.jpg
  181. 181 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-640×480.jpg
  182. 182 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-800×480.jpg
  183. 183 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-800×600.jpg
  184. 184 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1024×1024.jpg
  185. 185 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1152×864.jpg
  186. 186 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1280×720.jpg
  187. 187 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1280×800.jpg
  188. 188 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1280×960.jpg
  189. 189 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1280×1024.jpg
  190. 190 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1366×768.jpg
  191. 191 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1400×1050.jpg
  192. 192 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1440×900.jpg
  193. 193 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1600×1200.jpg
  194. 194 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1680×1050.jpg
  195. 195 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1680×1200.jpg
  196. 196 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1920×1080.jpg
  197. 197 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1920×1200.jpg
  198. 198 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-1920×1440.jpg
  199. 199 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/cal/sept-16-tropical-procrastination-cal-2560×1440.jpg
  200. 200 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-320×480.jpg
  201. 201 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-640×480.jpg
  202. 202 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-800×480.jpg
  203. 203 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-800×600.jpg
  204. 204 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1024×1024.jpg
  205. 205 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1152×864.jpg
  206. 206 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1280×720.jpg
  207. 207 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1280×800.jpg
  208. 208 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1280×960.jpg
  209. 209 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1280×1024.jpg
  210. 210 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1366×768.jpg
  211. 211 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1400×1050.jpg
  212. 212 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1440×900.jpg
  213. 213 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1600×1200.jpg
  214. 214 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1680×1050.jpg
  215. 215 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1680×1200.jpg
  216. 216 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1920×1080.jpg
  217. 217 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1920×1200.jpg
  218. 218 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-1920×1440.jpg
  219. 219 http://files.smashingmagazine.com/wallpapers/sept-16/tropical-procrastination/nocal/sept-16-tropical-procrastination-nocal-2560×1440.jpg
  220. 220 http://anastas.design
  221. 221 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/sept-16-the-september-sun-full.png
  222. 222 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/sept-16-the-september-sun-preview.png
  223. 223 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-800×600.png
  224. 224 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1024×768.png
  225. 225 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1152×864.png
  226. 226 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1280×720.png
  227. 227 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1280×800.png
  228. 228 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1280×960.png
  229. 229 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1400×1050.png
  230. 230 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1440×900.png
  231. 231 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1600×1200.png
  232. 232 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1680×1050.png
  233. 233 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1920×1080.png
  234. 234 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-1920×1440.png
  235. 235 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/cal/sept-16-the-september-sun-cal-2560×1440.png
  236. 236 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-800×600.png
  237. 237 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1024×768.png
  238. 238 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1152×864.png
  239. 239 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1280×720.png
  240. 240 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1280×800.png
  241. 241 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1280×960.png
  242. 242 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1400×1050.png
  243. 243 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1440×900.png
  244. 244 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1600×1200.png
  245. 245 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1680×1050.png
  246. 246 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1920×1080.png
  247. 247 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-1920×1440.png
  248. 248 http://files.smashingmagazine.com/wallpapers/sept-16/the-september-sun/nocal/sept-16-the-september-sun-nocal-2560×1440.png
  249. 249 http://www.mariakellerac.com
  250. 250 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/sept-16-viva-mexico-full.png
  251. 251 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/sept-16-viva-mexico-preview.png
  252. 252 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-320×480.png
  253. 253 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-640×480.png
  254. 254 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-640×1136.png
  255. 255 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-750×1334.png
  256. 256 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-800×480.png
  257. 257 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-800×600.png
  258. 258 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1024×768.png
  259. 259 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1024×1024.png
  260. 260 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1152×864.png
  261. 261 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1242×2208.png
  262. 262 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1280×720.png
  263. 263 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1280×800.png
  264. 264 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1280×960.png
  265. 265 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1280×1024.png
  266. 266 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1366×768.png
  267. 267 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1400×1050.png
  268. 268 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1440×900.png
  269. 269 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1600×1200.png
  270. 270 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1680×1050.png
  271. 271 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1680×1200.png
  272. 272 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1920×1080.png
  273. 273 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1920×1200.png
  274. 274 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-1920×1440.png
  275. 275 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-2560×1440.png
  276. 276 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/cal/sept-16-viva-mexico-cal-2880×1800.png
  277. 277 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-320×480.png
  278. 278 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-640×480.png
  279. 279 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-640×1136.png
  280. 280 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-750×1334.png
  281. 281 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-800×480.png
  282. 282 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-800×600.png
  283. 283 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1024×768.png
  284. 284 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1024×1024.png
  285. 285 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1152×864.png
  286. 286 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1242×2208.png
  287. 287 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1280×720.png
  288. 288 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1280×800.png
  289. 289 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1280×960.png
  290. 290 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1280×1024.png
  291. 291 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1366×768.png
  292. 292 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1400×1050.png
  293. 293 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1440×900.png
  294. 294 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1600×1200.png
  295. 295 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1680×1050.png
  296. 296 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1680×1200.png
  297. 297 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1920×1080.png
  298. 298 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1920×1200.png
  299. 299 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-1920×1440.png
  300. 300 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-2560×1440.png
  301. 301 http://files.smashingmagazine.com/wallpapers/sept-16/viva-mexico/nocal/sept-16-viva-mexico-nocal-2880×1800.png
  302. 302 http://www.tazi.com.au
  303. 303 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/sept-16-hello-spring-full.png
  304. 304 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/sept-16-hello-spring-preview.png
  305. 305 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-320×480.png
  306. 306 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-640×480.png
  307. 307 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-800×600.png
  308. 308 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-1024×768.png
  309. 309 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-1152×864.png
  310. 310 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-1280×720.png
  311. 311 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-1280×960.png
  312. 312 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-1600×1200.png
  313. 313 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-1920×1080.png
  314. 314 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-1920×1440.png
  315. 315 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/cal/sept-16-hello-spring-cal-2560×1440.png
  316. 316 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-320×480.png
  317. 317 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-640×480.png
  318. 318 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-800×600.png
  319. 319 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-1024×768.png
  320. 320 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-1152×864.png
  321. 321 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-1280×720.png
  322. 322 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-1280×960.png
  323. 323 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-1600×1200.png
  324. 324 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-1920×1080.png
  325. 325 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-1920×1440.png
  326. 326 http://files.smashingmagazine.com/wallpapers/sept-16/hello-spring/nocal/sept-16-hello-spring-nocal-2560×1440.png
  327. 327 http://ladybirddee.net/
  328. 328 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/sept-16-live-in-the-moment-full.jpg
  329. 329 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/sept-16-live-in-the-moment-preview.jpg
  330. 330 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/cal/sept-16-live-in-the-moment-cal-1024×768.jpg
  331. 331 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/cal/sept-16-live-in-the-moment-cal-1280×800.jpg
  332. 332 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/cal/sept-16-live-in-the-moment-cal-1280×1024.jpg
  333. 333 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/cal/sept-16-live-in-the-moment-cal-1440×900.jpg
  334. 334 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/cal/sept-16-live-in-the-moment-cal-1600×1200.jpg
  335. 335 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/cal/sept-16-live-in-the-moment-cal-1920×1200.jpg
  336. 336 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/nocal/sept-16-live-in-the-moment-nocal-1024×768.jpg
  337. 337 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/nocal/sept-16-live-in-the-moment-nocal-1280×800.jpg
  338. 338 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/nocal/sept-16-live-in-the-moment-nocal-1280×1024.jpg
  339. 339 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/nocal/sept-16-live-in-the-moment-nocal-1440×900.jpg
  340. 340 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/nocal/sept-16-live-in-the-moment-nocal-1600×1200.jpg
  341. 341 http://files.smashingmagazine.com/wallpapers/sept-16/live-in-the-moment/nocal/sept-16-live-in-the-moment-nocal-1920×1200.jpg
  342. 342 https://www.behance.net/sayali_harde
  343. 343 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/sept-16-festivities-and-ganesh-puja-full.jpg
  344. 344 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/sept-16-festivities-and-ganesh-puja-preview.jpg
  345. 345 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-320×480.jpg
  346. 346 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-800×480.jpg
  347. 347 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-800×600.jpg
  348. 348 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1280×720.jpg
  349. 349 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1280×800.jpg
  350. 350 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1280×1024.jpg
  351. 351 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1440×900.jpg
  352. 352 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1600×1050.jpg
  353. 353 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1600×1200.jpg
  354. 354 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1920×1080.jpg
  355. 355 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1920×1200.jpg
  356. 356 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-1920×1440.jpg
  357. 357 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/cal/sept-16-festivities-and-ganesh-puja-cal-2560×1440.jpg
  358. 358 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-320×480.jpg
  359. 359 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-800×480.jpg
  360. 360 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-800×600.jpg
  361. 361 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1280×720.jpg
  362. 362 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1280×800.jpg
  363. 363 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1280×1024.jpg
  364. 364 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1440×900.jpg
  365. 365 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1600×1050.jpg
  366. 366 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1600×1200.jpg
  367. 367 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1920×1080.jpg
  368. 368 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1920×1200.jpg
  369. 369 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-1920×1440.jpg
  370. 370 http://files.smashingmagazine.com/wallpapers/sept-16/festivities-and-ganesh-puja/nocal/sept-16-festivities-and-ganesh-puja-nocal-2560×1440.jpg
  371. 371 http://sasternportfolio.tumblr.com
  372. 372 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/sept-16-underwater-love-full.jpg
  373. 373 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/sept-16-underwater-love-preview.jpg
  374. 374 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-320×480.jpg
  375. 375 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-640×480.jpg
  376. 376 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-800×600.jpg
  377. 377 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-1024×768.jpg
  378. 378 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-1280×1024.jpg
  379. 379 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-1440×900.jpg
  380. 380 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-1600×1200.jpg
  381. 381 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-1920×1080.jpg
  382. 382 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-1920×1440.jpg
  383. 383 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/cal/sept-16-underwater-love-cal-2560×1440.jpg
  384. 384 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-320×480.jpg
  385. 385 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-640×480.jpg
  386. 386 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-800×600.jpg
  387. 387 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-1024×768.jpg
  388. 388 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-1280×1024.jpg
  389. 389 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-1440×900.jpg
  390. 390 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-1600×1200.jpg
  391. 391 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-1920×1080.jpg
  392. 392 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-1920×1440.jpg
  393. 393 http://files.smashingmagazine.com/wallpapers/sept-16/underwater-love/nocal/sept-16-underwater-love-nocal-2560×1440.jpg
  394. 394 https://www.smashingmagazine.com/desktop-wallpaper-calendars-join-in/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

How We Use Prototyping, And How It Made Us More Efficient

Sponsored ArticleHow We Use Prototyping, And How It Made Us More Efficient

Prototyping is essential to help your team create the best product possible. It’s a chance to experiment with ideas and turn them into something tangible that you can test and build upon. When you fail with your prototype, you land softly — there’s always the chance to iterate and improve.

The team behind Adobe’s new prototyping tool Experience Design1 (Adobe XD) uses prototyping as a method to test new features before they make it into the program. Being a product manager on the Adobe XD team, I’ll share some insights into how the team uses prototyping to build and improve Adobe XD, and make prototyping more efficient for designers.

Further Reading on SmashingMag: Link

So Why Do We Build Prototypes? Link

Prototypes are about communication and hypothesis testing. They give teams a way to experiment something that’s tangible, shortening the psychological distance between the user and the solution.

“A prototype is worth a thousand meetings.” — an IDEO saying.

We build prototypes to learn, solve conflicting ideas, start conversations, and manage the building process. It helps teams to build empathy, to collaborate, to explore options (and barriers) that only become visible when you build something, to test and to be inspired.

The Power of Prototypes is a great clip from HBO’s “From the Earth to the Moon” miniseries. It shows the value of prototyping during the design phase, making people “see” things better.

There’s research to support the theories that you can “build to think” or “write longhand to remember”, which means that if you use your hands, more neurons are utilized to process the task in your brain, making you “think better” or “remember more”.

The biggest benefit always goes back to risk. The sooner we “fail” and the faster we learn, the greater the chances are for success.

5
Failing earlier saves you time and money.

It’s cheaper to fail early in order to validate things that work and things that don’t. That’s why we build prototypes for every major product feature. We test with pre-release users and key customers very early on and definitely before we get to implementation. And yes, we do “fail” a lot, which is great! It’s great because we learn a ton in the process and minimize the risk of failure in the long run. In the end, we tackle real customer needs, with empathy, in an innovative way.

Can Prototyping Be Fun And Engaging? Link

Absolutely! One of the fun prototyping exercises I use to warm design teams up is called “Dark Horse”. From your Design Thinking brainstorm6, pick the craziest idea, the one that’s almost impossible to become a reality; and as a team, build a prototype for it.

7
A team collaborating as they build a prototype for the “Dark Horse” exercise. Large view.8
9
The same team “exploding” a building to solve the design challenge during the “Dark Horse” prototyping exercise. Large view.10

Warning: crazy and funny things WILL happen!

11
Large view.12

You can guarantee oxytocin will be released; team members will bond and connect more.

Building Adobe XD Link

Not too long ago, a small group of very talented designers, engineers, and product managers got together, to prototype what a new solution for designers trying to communicate their message could be. After many different brainstorming sessions, instead of starting from scratch, they used bits of existing prototypes to string together a foundation to explore and experiment with new tools and approaches in a design tool.

This initial prototype grew and new tools were created, validated, fine-tuned and validated again to become Project Comet. In 2016, with a much larger team that includes designers, engineers, product managers, program manager and interns, we came together and met with leading agencies and up and coming designers to focus on solving the UX challenges of today and tomorrow.

As soon as the first prototype was validated, then changed and validated again, we started developing Adobe XD as a native application. First for Mac OS and later for Windows. Additionally, we’re working on a companion app for iOS and Android, for designers to preview their designs in real-time.

Design With Data Prototype Link

In October 2015, at Adobe MAX13, Anirudh Sasikumar14, an engineer working on Adobe XD, demoed a prototype where designers could use the tool to feed designs with real data coming from different sources, such as the Finder and Web, for text and imagery. His Medium post15 covers the features in details.

16
Images flowing from a website to feed a design in Adobe XD with a single click.

I spoke with Anirudh recently, asking how he came up with it and how the prototype helped him validate the approach.

According to him, it’s very common for developers to bind systems to data. Something that’s not true for designers, always needing to use fake data to simulate how the design would behave in the real world.

Anirudh explained the catalyst for designing with real data was the Repeat Grid tool. As soon as we finished building it, it was natural to start thinking about bringing more data in. The design community had already expressed interest in “Designing with data” and numerous workarounds in achieving the same using plugins/extensions.

Thanks to a delay on Caltrain, he started coding the functionality. Having some of the use cases in mind, implementation was easy. By the end of the trip, he had a working version of it. Not polished, but enough to show promise and to be validated.

The magic of prototyping is being able to see all the possibilities and edge cases around it. It’s not in your head anymore, it’s there, closer to reality. You can see so much more!

You can also see walls, problems that never surface before you actually build it. For instance, connecting with Google Sheets was tricky.

17
Google Docs populating repeated grids with a single click, to test different languages.

Phase 1 is complete and available for Mac OS, where designers can drag text files from Finder, to feed a Repeat Grid. The next phase will focus on sample data and bringing content from the Web.

If you want the feature in Adobe XD, feel free to upvote here18.

Deciding Whether To Include Layers Or Not Link

Let me start with the same question we asked hundreds of designers:

Do you need layers?

Initially, we started with the assumption that people didn’t need layers, especially the way layers were presented for so many years in Photoshop or Illustrator. It was a big challenge, because a big number of experienced designers took years to build those mental models.

At Adobe XD, in order to deliver innovation, we challenge existing mental models frequently.

Based on that initial research, Talin Wadsworth19, the lead designer for XD, came up with the concept of local layers. To validate the concept, we worked together to set the context and test the prototype with prerelease users and key customers.

20
The “local layers” prototype we tested with key customers and prerelease users. Large view.21

After a long research and validation process using a prototype to drive conversations, and after multiple adjustments, we confirmed that our customers need layers for exporting and to organize complex designs.

We have started the work to implement this new mental model.

Soon, designers from all over the world will tell us if we got it right. Fingers crossed!

In Conclusion Link

Since day one, we build and test prototypes of every major feature before we implement them. A prototype is an extremely powerful tool to help teams “see” more, experience more, “fail” more, learn more and, in the end, pivot faster to where the secret for success is.

A quote from the book Zero to One sums up the benefit of prototyping well:

“It’s like the world is full of secrets for disruptive success, just waiting for someone to find them”.

Who is going to create the next Uber, or the next Facebook, or even the next Pokemon Go app? Building and testing prototypes can help you get there, faster!

As a suggestion, please remember that Adobe XD can support you and your team when building prototypes for websites or mobile applications. Have you tried it? It’s free: http://xd.adobe.com22. What are you waiting for? Start building prototypes now!

Footnotes Link

  1. 1 http://adobe.ly/2aAMlOx
  2. 2 https://www.smashingmagazine.com/2016/07/how-to-create-icons-adobe-xd/
  3. 3 https://www.smashingmagazine.com/2016/07/quick-ux-prototyping-with-adobe-xd-shortcuts-pdf-cheatsheet/#comments
  4. 4 https://www.smashingmagazine.com/2016/08/experience-design-essentials-animated-microinteractions-in-mobile-apps/
  5. 5 https://www.smashingmagazine.com/wp-content//uploads/2016/07/05-prototypes.jpg
  6. 6 http://blogs.adobe.com/creativecloud/design-thinking-a-manual-for-innovation/?segment=uxuidesign
  7. 7 https://www.smashingmagazine.com/wp-content//uploads/2016/07/dark-horse-1-opt.jpg
  8. 8 https://www.smashingmagazine.com/wp-content//uploads/2016/07/dark-horse-1-opt.jpg
  9. 9 https://www.smashingmagazine.com/wp-content//uploads/2016/07/dark-horse-2-opt.png
  10. 10 https://www.smashingmagazine.com/wp-content//uploads/2016/07/dark-horse-2-opt.png
  11. 11 https://www.smashingmagazine.com/wp-content//uploads/2016/07/dark-horse-3-opt.png
  12. 12 https://www.smashingmagazine.com/wp-content//uploads/2016/07/dark-horse-3-opt.png
  13. 13 https://max.adobe.com/
  14. 14 https://twitter.com/anirudhs
  15. 15 https://medium.com/@anirudhs/project-comet-designing-with-real-data-959beccb5c1a#.mosq7k4ur
  16. 16 https://www.smashingmagazine.com/wp-content//uploads/2016/07/desing-withdata-images-from-web.gif
  17. 17 https://www.smashingmagazine.com/wp-content//uploads/2016/07/desing-withdata-googledocs.gif
  18. 18 https://adobexd.uservoice.com/forums/353007-adobe-xd-feature-requests/suggestions/12924696-design-with-data
  19. 19 https://twitter.com/MrTalin
  20. 20 https://www.smashingmagazine.com/wp-content//uploads/2016/07/layers.gif
  21. 21 https://www.smashingmagazine.com/wp-content//uploads/2016/07/layers.gif
  22. 22 http://adobe.ly/2aAMlOx

↑ Back to topTweet itShare on Facebook

Advertisement

Pixel-Perfect Specifications Without The Headaches

Pixel-Perfect Specifications Without The Headaches

Designers, developers and managers often work with compressed timeframes and multiple projects simultaneously. A team must be able to respond quickly to feedback on their product from clients, project managers and developers. Each minor revision in the UI or UX needs to be reflected in the documentation, so that designers and developers always have the latest information.

A style guide ensures that your project doesn’t encounter serious problems when you implement the initial design. Making sure that all specifications are accurate to their designs is critical, because an inaccurate specification means that developers will have to either rely on guesswork when building the app or go to the design source to get answers to their questions. Transferring all of this information manually to the developers can be a headache and usually takes significant time, depending on the extensiveness of the designs.

In this article, we’ll review the process of creating a style guide, the process of handing off a design, and collaboration across the whole team. We’ll also walk through an example workflow, demonstrating how developers and designers can improve cross-team communication and drastically reduce iteration time.

A Project’s Team Link

A project consists of designers, developers and project managers, and each area has its own particular needs.

Designers Link

When a designer prepares a design, they hand it over to the developer. What they usually do is export some PNGs and prepare a specification with all of their annotations. Specifications can be stressful in a big project, and the design of an interface layout can change quite often. Thus, a traditional style guide will pretty much get outdated almost immediately.

Preparing specifications is tedious — we know that. Manually doing it is time-consuming, and every designer does it a little differently. Most designers spend more time making specifications than actually designing. And they often have to manually export all of their assets for developers. I can tell you that every designer is tired of that.

If you want to save the designer’s time, just tell them to forget about that and focus on the actual design process instead. Every minute a designer spends revising documentation is a minute lost that they could be spending really nailing the visuals, experience and interactions.

Developers Link

Inspecting specifications is painful. Developers will usually ask the designers for every little detail contained in the design or, worse, are forced to do it themselves in Photoshop or Sketch. In most cases, they need to manually convert all sizes of the assets according to the platform’s requirements (for example, converting pixels to density-independent pixels, scale-independent pixels, points, etc.). They often don’t have enough detailed information about the visual design and have to guess, resulting in visual inconsistencies.

Even when the developer has successfully implemented the design, there is still the possibility that the designer will make a change, at which point the developer would have to manually inspect the design again and figure out what exactly has changed. Not flexible at all!

Managers Link

Project managers are always trying to find ways to improve collaboration between designers and developers, because everyone on the team should be on the same page for every design change. If you’re working with a remote team, you’re probably going to need some online space to collaborate and meet, a single channel of communication. Modern communication tools such as Slack make that possible, but the project managers still need to track progress and provide feedback on what has changed and where. They are well familiar with messy email attachments and feedback coming from multiple places.

They also need to figure out the current state of the product very quickly. They need to stay on top of the design process by reviewing changes, comparing versions visually side by side, and discussing them in real time in one place.

Syncing Designers And Developers With Less Hassle Link

Creating design specifications involves identifying colors, x and y values, fonts, text weights, distances, positions and a number of other characteristics of the assets. Each asset carries certain characteristics that need to be recorded.

You need a tool to bridge the gap between the design and coding stages of development, a tool that simplifies and speeds up the specification and development process, a tool that provides a single entry point for all design-related stuff, so that you (the designer, developer or manager) don’t have to think about where to find the latest version of the design. This will result in products getting built and shipped faster.

Thankfully, tools exist out there to help with this. Each of them takes in Photoshop or Sketch documents and produces a specification for developers, including code snippets and image assets. These tools also track changes between versions of the design.

How They Work Link

This is where Avocode1, Sympli2, and Zeplin3 enter the scene. These are collaboration tools for UI designers and front-end developers. They are built for the process of going from Photoshop or Sketch to code. You can upload designs and turn them into specifications and guidelines that are tailored to the platform you are working on. Using these tools, you can:

  • inspect designs from Photoshop or Sketch without using the original app, and quickly get measurements appropriate to the platform you’re working on;
  • get instant access to image assets, colors, fonts and even dimensions;
  • export resource files for any kind of element, whether text, button or something else;
  • add notes and notify team members about design changes instantly.

Last but not least, designers and developers will essentially work in a shared workspace, where elements such as sizes, distances, fonts and icons move seamlessly back and forth, without requiring a large design file annotated with what the designer needs.

However, as I’ve said, these tools are for inspecting, not editing or interactive prototyping. This is important. These are not image editors, and they don’t allow you to create designs or prototypes. You still need to create and edit your files in Photoshop or Sketch and then open the files for inspection in one of these tools.

Avocode Link

Avocode is one of these tools that bridge the gap between web designers and developers. The process of creating a website starts with designing in Photoshop or Sketch; however, when the designer is finished and the front-end developer has to implement the design, the design file is broken down into images, colors, sizes, CSS, etc.

4
(View large version)5

First Steps Link

Before doing anything in Avocode, you need to create an account6. A free two-week trial of the application is available on the website.

7
(View large version)8

Avocode contains two parts: a web-based manager and a desktop application. It works based on projects, and you need to create a project to get started. A sample web project (a landing page) is provided to help first-time users understand what features are available.

9
(View large version)10

Upload Design Link

After creating a project, you need to upload your design. You can use Dropbox or manually drag and drop files from your local system.

11
(View large version)12
13
(View large version)14

User Interface Overview Link

After creating a project and uploading your designs, you need to install the desktop application to inspect them. The web app only has previewing and commenting features and doesn’t allow you to inspect a design in detail.

15
(View large version)16

So, let’s dig into the details of the desktop app! Avocode feels like a powerful and professional application. The UI looks very similar to Photoshop — same color scheme and typefaces. The dark Photoshop-like interface makes Avocode look and feel really slick. If you’re an intermediate Photoshop or Illustrator user, the learning curve is close to none.

The main tab you’ll be focusing on and working with most of the time is “Project Designs.” It shows each of your projects in the form of a thumbnail, title and activity indicator.

17
(View large version)18

If you double-click on a thumbnail, you’ll immediately see a screen with a full list of groups and layers, exactly like Photoshop. On the bottom is a set of Avocode tools. The first one we will use is the Select tool. With it, you can select individual layers, or multiple layers, and see its properties on the right side. You will notice that the inspector’s content changes based on which item is selected.

19

Below, the layer for the call-to-action button is selected. When you select an item in your PSD, the sidebar shows the CSS for that item. As a bonus, Avocode also gives you the option to copy LESS or Sass code:

20
(View large version)21

You can select an image and see its dimensions. The image-exporting options in Avocode are really nice, too. You can set up different rules that allow you to export all of your images in any number of configurations, including JPG, PNG and SVG formats, as well as with the right proportions (“1x” means the original size).

22
(View large version)23

The info panel has all of the important information about the design. You can even get a public link to share the design with anyone. What’s best is that this panel lists all of the fonts used, with links to Typekit and Google Web Fonts so that you can easily use them in your project.


Using Avocode, you can visually compare revisions of designs easily.

Tools Link

The Measure tool is useful. Select a layer and then hover over other layers to see their positions relative to the first layer. Below is a selected layer with a “Get started now” button, and its relative position to the top, left and right.

24
(View large version)25

The next one is a color picker, which basically takes a color and copies its hex value to your clipboard. You can add this color as a variable to your design. With this tool, you can quickly create a color scheme for your design.

26
(View large version)27

The final tool is Slice, which makes it possible to export a selected part of the design as an image or style scheme.

28
(View large version)29

The good thing is that each tool has a hotkey combination, which is handy for users who use the keyboard to quickly switch between options.

Another cool feature of Avocode is the use of guides. However, a first-time user might wonder whether this option is available because the feature is hidden behind a little button in the bottom-right area of the screen. Avocode supports both user-created guides as well as designed guides that have already been made in Photoshop or Sketch. So, if your Photoshop document has guides, they will show up in Avocode.

30
(View large version)31

Using Avocode, you can visually compare revisions of designs easily. You can access this feature in the “design detail” of your project in the web app:


Visually compare revisions of designs easily.

Collaboration Link

Avocode lets you leave notes in a specific area in the design, allowing you to discuss design changes with anyone in one place instantly.

Simply click or drag anywhere in the design to highlight the area you want to talk about, then write your message, and hit the submit button. Everyone will instantly get a notification:


Discuss any part of the design in the app.

Cost Link

Avocode charges $10 per month per user for the business plan, which has integration with Slack and permissions management. If your team consists of one to three people and you don’t need permissions management, you can choose the “Garage” plan, which costs $7 per month per user.

Pros Link

  • Multi-platform support (Mac, Windows, Linux)
  • A great Photoshop-like UI and a deep and thoughtful toolset

Cons Link

  • Currently only supports the web
  • No free plan (after the trial, you have to subscribe with a regular paid plan)
  • Unlike Sympli or Zeplin, doesn’t support detail inspection in the web app (the desktop app is required)

Sympli Link

Sympli isn’t just a design handoff or collaboration tool — it’s a complete collaboration platform that covers the entire product design team, including design handoff features for designers coming from Photoshop (Adobe XD coming soon) and Sketch, as well as automated implementation features and tools for developers in its Android Studio and Xcode plugins. Recently launched this spring, it’s a great tool that has done a lot to speed up the design and development process.

32
(View large version)33

One of the biggest reasons to use Sympli is its integration with Xcode and Android Studio, making it a tool for the whole team because it goes beyond design handoff to help developers with automated implementation.

34
(View large version)35

First Steps Link

When users visit the Sympli website36, they are immediately oriented with the “How it works” section, which tells the user what they need to know to get started and familiarizes them with the product. First, sign up and create a new project. Select the project type (Sympli supports web, Android and iOS projects) and the resolution (@1x, @2x or @3x). After that, you will be able to upload you designs.

37
(View large version)38

Upload Design Link

Sympli works as a plugin in Photoshop or Sketch; however, like in Zeplin, you can’t directly upload native design files. Sympli is cloud-based, so it works across platforms. And for those security-conscious companies that prefer not to use the cloud, Sympli offers enterprise options for on-premise setup.

Compared with Avocode and Zeplin, Sympli has an interesting option for exporting assets.

39
(View large version)40

Sympli for Sketch is a native plugin, which has some additional benefits, such as the ability to export hidden assets (in case you have multiple states of the same control on the artboard) and validation of asset names to conform with the destination platform’s requirements. This means Sympli not only will generate assets with all of the required formats and sizes in platform-specific units for the marked layers or groups, but will also validate all specified names, handle asset name duplicates, export hidden assets and even help you to stay within the asset-naming requirements for Android or iOS.

41
(View large version)42

Developers can also apply naming-convention rules for their assets, so that renaming rules get applied every time a designer sends assets.

Collaboration in Sympli starts before the design handoff. Several designers can work on a project at the same time and can export screens to the same project. Once the designs are uploaded, the project owner invites people using a shareable link or sends it directly to the team members’ inboxes. If you are updating an existing project that has already been shared, the team will be notified about the updates.

43
(View large version)44

User Interface Overview Link

Sympli doesn’t have a separate desktop application; the powerful web app has all of the required functionality. Mockups are accessible via IDE extensions (Xcode or Android Studio). You can always access the latest version of the design mockups, and designers can send links to particular screens, rather than files, so that recipients don’t have to dig up those screens themselves.

45
(View large version)46

Sympli automatically stores all colors and fonts in a project’s “Summary” section. It finds multiple instances of the same color or font used in multiple layers, groups them in an expandable list of styles, and generates the names for them automatically. It also allows users to rename colors and sync the changes.

47
(View large version)48

Sympli not only specs the fonts used, but also shares font files through its Brandbooks feature. Designers can attach font files to a project to be made available to developers right away, along with collections of company-named colors. Font files can be attached to multiple projects.

49
(View large version)50

All colors and fonts are presented in platform-specific notation, so that you don’t have to change them manually. Also, Sympli provides access to assets in bitmap or vector format; the developers chooses which, and both formats are generated on the fly, automatically.

51
(View large version)52

You can visually compare revisions of designs easily. To access this feature, open the design detail in Sympli and click the “Version” link. However, a new mechanism for comparing versions is coming soon, which will highlight changes and show versions side by side.

53
(View large version)54

Tools Link

The first tool we will look at is Layers. With it, you can select individual layers or multiple layers and review properties on the right side. You will notice that the inspector’s content changes based on which item is selected.

55
(View large version)56

One of the best features of Sympli is the Ruler, a very useful measurement tool. Click on any element in the layout and track its relative position to the other elements. The measurements are presented in platform-specific units (depending on the destination: points for iOS, density-independent pixels for Android, and pixels for web projects).

57
(View large version)58

Collaboration Link

Sympli has a commenting tool, named Spots, that facilitates collaboration and helps to clarify points of confusion late in the design process.

59
(View large version)60

Sympli seamlessly integrates with Slack. Whenever someone leaves a note or updates the design, a notification is posted to the Slack channel.

Bonus: Happy Developers Link

As mentioned, a big difference with Sympli is its extensions for the Android Studio and Xcode development environments. Sympli integrates fully with both IDEs, allowing you to bring designs and mockups from Photoshop and Sketch right into the environment where developers are working.

61
(View large version)62

The IDE extensions provide several cool features, such as smart asset synchronization, which is a visual dialog that makes it possible to merge assets, showing you what is currently in the project and what you’ll have after the assets are synchronized. You can include or exclude individual assets.

63
(View large version)64

A mind-blowing feature is the visual implementation of designs as storyboards. Basically, developers can drag and drop designs from mockups into interface-builder views, and the views will be styled in exactly the same way as the mockups, including both configuration and runtime properties:


Design mockups are displayed as storyboards.

You can even drag and drop styles from a design mockup right into a storyboard.

While Sympli automates code and tasks, it doesn’t introduce any third-party dependencies into a project, nor does it introduce any changes in the technical process. So, developers aren’t forced to use any frameworks or introduce any libraries into their projects.

Cost Link

Sympli charges based on the number of projects. The free plan covers one active project. The “Pro” plan is most common, with a price of $25 per month, which allows eight active projects to be run simultaneously. Each paid plan includes an unlimited number of collaborators and archived projects, along with great tech support.

Pros Link

  • No desktop app (the rich web application has everything)
  • Supports web and mobile app design (iOS and Android)
  • The Xcode and Android Studio extensions take designs smoothly to development, giving developers some cool automation tools.
  • Powerful collaboration features, such as Brandbooks (reusable style guides), company management features, and versioning

Cons Link

  • UI is too minimal (it could definitely use a human touch and more personality).

Zeplin Link

Zeplin is the last collaboration tool for UI designers and front-end developers we’ll be looking at. When a designer exports Photoshop or Sketch files to Zeplin (by selecting the artboard and pressing Command + E), all of the styles are communicated to the developers. In other words, the specification sheet is automated, similar to Sympli.

First Steps Link

When you enter the Zeplin website65, you’ll immediately notice delightful details, such as the fun cartoon zeppelin logo. Little details like these provide visual stimulation and delight.

66

Onboarding consists of a basic tutorial video, which users see upon signing up. The video has enough information to get you started.

67
(View large version)68

As with Avocode, users have to install a desktop application. Then they are asked what type of project they would like to create. Unlike Avocode, Zeplin supports not only web projects, but also Android and iOS. Let’s choose iOS.

69
(View large version)70

Now it’s time to upload some designs. Zeplin has a powerful and delightful empty state, telling you what to do next.

71
(View large version)72

Upload Design Link

Zeplin doesn’t allow you to directly upload designs, and it works only as a plugin within Photoshop or Sketch, again similar to Sympli. Normally when you launch Zeplin, the plugin should be installed automatically, so uploading designs is only a couple of clicks away. In Photoshop and Sketch, you can export a whole design or individual objects.

73
(View large version)74

To see your assets in Zeplin, mark the layers as “exportable.” Again, the empty state will guide you step by step:

75
(View large version)76

Once the designs have been uploaded, the project owner can invite people using a shareable link or send the link directly to the team members’ inboxes.

77
(View large version)78

If you want some feedback on your designs or style guide, you can also use the sharing icon, next to the “Scene” menu item. You’ll see a dialog like the one below, which clearly explains how it works and even links to sample data.

79
(View large version)80

User Interface Link

Productivity apps tend to be dry and lack any sort of personality. But Zeplin has managed to make the boring process of coordinating feedback somehow enjoyable. As soon as you upload your designs, they are turned into specifications and guidelines tailored to the platform you are working on (in our case, iOS).

Unlike Avocode and Sympli, Zeplin doesn’t have a special set of tools for working with a design. It’s more of a viewing app, with asset-exporting capabilities and team-collaboration features. Developers can select a layer and see its size and all other necessary information (in the case of a text field, you would see the font’s name, size and color).

81
(View large version)82

As you can see, all measurements are displayed in points (which iOS developers require). Also, all projects in Zeplin have a color palette, allowing you to name the selected colors.

83
(View large version)84

If you’ve made image assets exportable in Sketch, you’ll see them in “Assets” in Zeplin:

85
(View large version)86

The colors and fonts used in a project are displayed in the “Styleguide” tab. You can rename these colors and export them if you plan to use them in your project. In general, this makes designing for iOS and Android Studio way more pleasant!

87
(View large version)88

Developers can see, copy or download the CSS for web projects, the XML resources for Android projects, and the UIFont and UILabel extensions for iOS, both for the color variables and text styles, in the “Styleguide” section. Below are two examples:

89
For a web project (View large version)90
91
For an iOS app (View large version)92

Collaboration Link

Because its available as a standalone app as well as a web app, you can access Zeplin pretty much anywhere. Every screen in Zeplin has a link, which you can find in the right panel of the screen. So, if a team member has not installed the desktop app, they will still be able to see the project in the web application.

93
(View large version)94

Last but not least, the tool’s annotation features allow team members to comment on parts of the app and use the result as a road map. This also helps to clear up any confusing parts of the specification process and preserves a record of the notes taken for anyone to review.

95
(View large version)96

This streamlined process makes life so much easier for everyone involved.

Cost Link

Zeplin’s price is based on the number of projects. A free plan is available for single projects. The most common plan is “Growing business,” with a price of $25 per month to run eight active projects simultaneously. All plans include unlimited team members.

Pros Link

  • The UI is minimalist, intuitive, friendly and just playful enough to make you grin.
  • Supports web and mobile app design (iOS and Android)

Cons Link

  • No measurement tool
  • No versioning (or visual comparison) for designs
  • You still need to export assets from Zeplin and then manually copy and paste or import the design specifications and styles to an IDE such as Xcode or Android Studio.
Comparing the tools at a high level.97
Comparing the tools at a high level. (Large preview98)

Tips On Selecting The Right Tool Link

Selecting the right product is always difficult, especially when you have several good options (as we do). All of the tools we’ve looked at are amazing, and I believe you’d enjoy using any. That being said, here are some tips to help you select the most suitable one:

  • Avocode is great for web development projects. If you are in mobile app development, then go with either Sympli or Zeplin.
  • Consider Sympli if you focus on web or mobile app development and would like full integration with Xcode and Android Studio to generate layouts (even from imported assets) for your initial designs. Sympli is great for large teams because of the corporate plans, version control and other features. There is also a lot of public information about updates and upcoming features, so you’ll be able to know what’s coming up in Sympli.
  • You might be better off with Zeplin if your mobile app development projects are relatively small and you don’t frequently change a design, require detailed visual comparison between versions, or need color and font collections that can be used in other projects. Zeplin has a user-friendly and intuitive UI, which is important for team collaboration, especially first-time users.

Conclusion Link

All three tools focus on the pain points that designers and developers experience when working together. The tools cater to those two very different types of users with different functionality. But each balances those needs beautifully and helps teams iterate quickly by providing living, breathing, interactive specifications.

Say no to clunky, difficult-to-understand, flat specifications that take forever to generate. We now have tools to easily and accurately translate the vision for an app into the measurements needed to code it. This interactive approach to specifications allows teams to spend more time on what’s important: creating beautiful and functional designs and giving users the best possible experience.

(il, al)

Footnotes Link

  1. 1 https://avocode.com/
  2. 2 https://sympli.io/
  3. 3 https://zeplin.io/
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image29-opt.png
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image29-opt.png
  6. 6 https://avocode.com/
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image15-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image15-opt.png
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image13-opt.png
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image13-opt.png
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image22-opt.png
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image22-opt.png
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image20-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image20-opt.png
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image08-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image08-opt.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image39-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image39-opt.png
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image26-371-opt.jpg
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image32-opt.png
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image32-opt.png
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image25-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image25-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image44-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image44-opt.png
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image50-opt.png
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image50-opt.png
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image02-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image02-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image21-opt.png
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image21-opt.png
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image19-opt.png
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image19-opt.png
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image45-opt.jpg
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image45-opt.jpg
  36. 36 https://sympli.io/
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image12-opt.png
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image12-opt.png
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image48.gif
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image48.gif
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image11-opt.jpg
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image11-opt.jpg
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image03-opt.jpg
  44. 44 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image03-opt.jpg
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image01-opt.png
  46. 46 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image01-opt.png
  47. 47 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image04-opt.jpg
  48. 48 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image04-opt.jpg
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image43-opt.png
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image43-opt.png
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image38-opt.jpg
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image38-opt.jpg
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image33-opt.png
  54. 54 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image33-opt.png
  55. 55 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image16-opt.png
  56. 56 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image16-opt.png
  57. 57 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image27-opt.png
  58. 58 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image27-opt.png
  59. 59 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image06-opt.png
  60. 60 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image06-opt.png
  61. 61 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image41-opt.png
  62. 62 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image41-opt.png
  63. 63 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image31-opt.png
  64. 64 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image31-opt.png
  65. 65 https://zeplin.io/
  66. 66 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image07-228-opt.png
  67. 67 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image09-opt.png
  68. 68 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image09-opt.png
  69. 69 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image24-opt.png
  70. 70 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image24-opt.png
  71. 71 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image18-opt.png
  72. 72 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image18-opt.png
  73. 73 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image10-opt.png
  74. 74 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image10-opt.png
  75. 75 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image34-opt.jpg
  76. 76 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image34-opt.jpg
  77. 77 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image17-opt.jpg
  78. 78 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image17-opt.jpg
  79. 79 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image30-opt.png
  80. 80 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image30-opt.png
  81. 81 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image14-opt.png
  82. 82 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image14-opt.png
  83. 83 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image00-opt.png
  84. 84 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image00-opt.png
  85. 85 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image47-opt.png
  86. 86 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image47-opt.png
  87. 87 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image28-opt.png
  88. 88 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image28-opt.png
  89. 89 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image37-opt.png
  90. 90 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image37-opt.png
  91. 91 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image42-opt.png
  92. 92 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image42-opt.png
  93. 93 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image23-opt.png
  94. 94 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image23-opt.png
  95. 95 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image35-opt.jpg
  96. 96 https://www.smashingmagazine.com/wp-content/uploads/2016/08/image35-opt.jpg
  97. 97 https://www.smashingmagazine.com/wp-content/uploads/2016/08/comparing-tools-large-opt.jpg
  98. 98 https://www.smashingmagazine.com/wp-content/uploads/2016/08/comparing-tools-large-opt.jpg
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Ways To Reduce Content Shifting On Page Load

Ways To Reduce Content Shifting On Page Load

Have you ever opened a website, started reading and, after some time had passed and all assets had finished loading, you found that you’ve lost your scroll position? I undergo this every day, especially when surfing on my mobile device on a slow connection — a frustrating and distracting experience.

Every time the browser has to recalculate the positions and geometries of elements in the document, a reflow happens. This happens when new DOM elements are added to the page, images load or dimensions of elements change. In this article, we will share techniques to minimize this content shifting.

Media Link

When a website loads, it takes some time until the images are loaded and the browser is able to calculate the space needed. The following GIF, recorded with the throttling set to 3G, demonstrates the effect.

One way to avoid this is to set a fixed width and height for all images, but this isn’t practical for responsive websites because we want images and videos to adapt to the available space.

Intrinsic Ratio Link

With intrinsic ratios1, also referred to as the padding-bottom hack, we can define the sizes that our media will occupy.

2
Formula for intrinsic ratio

The formula for getting the value for padding-bottom is this:

(height of the asset / width of the asset) * 100(%) 

If we have an image with a width of 1600 pixels and a height of 900 pixels, then the value would be this:

 (900 / 1600) * 100(%) = 56.25% 

Here is a Sass mixin we can use to define the aspect ratios of our images, videos, iframes, objects and embedded content.

@mixin aspect-ratio($width, $height) { position: relative; padding-bottom: ($height / $width) * 100%; img, video, iframe, object, embed { position: absolute; top: 0; left: 0; right: 0; bottom: 0; } } 
.ratio-sixteen-nine { @include aspect-ratio(1600, 900); } 
<figure> <img src="waterfall.jpg" alt="Waterfall in Iceland"> </figure> 

To make the experience even better, we can style the placeholder by adding a background to the wrapper.

figure { background: #ddd url(camera-icon.svg) no-repeat center center; } 

For images, we can use an icon to indicate to users that an image will appear. By implementing aspect-ratio placeholders, the user can decide whether to wait for the image or continue reading, all without losing their current scroll position.

Placeholder picture3
(View large version4)

Widgets Link

In addition to media content, your website might be using widgets or third-party content that is added via JavaScript and that would also shift content if not handled carefully.

Advertisements Link

Although a lot of websites are responsive these days, most ads still have a fixed size. For a responsive website, we can use placeholders in our HTML, in which we load the predefined ads if they match the specified screen size.

/* On small screens show 320x250 banner */ @media all and (max-width: 500px) { .ad-container-s { width: 320px; height: 250px; } } /* On medium screens show 728x90 banner */ @media all and (min-width: 800px) { .ad-container-m { width: 728px; height: 90px; } } 

In our example, we have one medium rectangle (300 × 250) and one leaderboard (728 × 90). On small screens, we would show the rectangle, while on bigger screens we would show the leaderboard. By setting fixed dimensions for the placeholder, the loading of the ads won’t trigger a content shift.

Advertisement5
(View large version6)

Many people will never see the ads, but only the empty placeholder, because they will be using an ad blocker, or the advertisement won’t show up for other reasons. Therefore, you should style the placeholder to indicate that there is normally an ad. If you are already using an ad-blocker detection script, you can replace the placeholder with a message or a promotion of your products7.

Users might even rethink the use of an ad blocker on your website if the ads have one less disadvantage — that distracting jump effect.

Dynamic Content Link

For other widgets, we might not know their exact sizes beforehand, but we can define the minimum heights the widgets will require.

.widget { min-height: 400px; } 

By using min-height, we will reserve enough space for most cases and avoid a big jump if the widget needs more space.

Finding the right size for min-height takes some time, but users will be thankful that their reading experience has not been abruptly interrupted.

Web Fonts Link

Fonts have different x-heights. Therefore, our fallback font and web font will take up a different amount of space.

Currently, one best practice8 for loading web fonts is to use the Font Face Observer9 script to detect when a font has loaded so that it can be applied in the CSS afterwards.

In this example, we are applying the webfont-loaded class to the html element once the web font is ready to use.

var font = new FontFaceObserver('Lato'); font.load().then(function () { document.documentElement.className += " webfont-loaded"; }); 

In the CSS, we apply the web font once it has successfully loaded.

p {font-family: sans-serif;} .webfont-loaded p {font-family: 'Lato', sans-serif;} 

When the web font finally finishes loading, we will notice a quick jump. To minimize this, we can modify the x-height of the fallback font to match the web font as closely as possible, thus reducing the jump.

font-size-adjust Link

The font-size-adjust property10 allows you to specify the optimal aspect ratio for when a fallback font is used. For most fonts, the ratio is between 0.3 and 0.7.

To find the right aspect ratio for your web font, I recommend setting up your browser to show two paragraphs side by side, one with the web font and the other with the fallback font, and then adjust the property with your browser’s developer tools.

p { font-size-adjust: 0.5; } 

Because font-size-adjust is currently supported only11 in Firefox and Chrome (behind a flag), we can use a combination of letter-spacing and line-height to adjust the size of the fallback font in other browsers.

p { font-family: sans-serif; font-size: 18px; letter-spacing: 1px; line-height: 0.95; } /* Older browsers */ p { letter-spacing: 1px; line-height: 0.95; } /* If browser supports font-size-adjust, use this */ @supports (font-size-adjust: none) { p { letter-spacing: 0; line-height: 1; font-size-adjust: 0.59; } } /* Once the web font has loaded, apply this */ .webfont-loaded p { font-family: 'Lato', sans-serif; letter-spacing: 0; line-height: 1; } 

Here, we are defining letter-spacing and line-height as a fallback first, and we are using @supports12 to feature-detect and then apply font-size-adjust if it is supported.

We won’t get a perfect solution for all fonts, but it will minimize the distraction when the typeface changes.

Layout Link

Until now, we have covered media, widgets and fonts, but the content could also shift when the CSS for the main layout gets applied.

Flexbox vs. Grid Link

Flexbox can cause horizontal shifting13, as shown by Jake Archibald.

With flexbox, the content controls how the layout is displayed, whereas with grid layouts, the layout is displayed according to the grid definition. Therefore, using grid for the main layout is better.

You probably won’t see the content shift if you’re developing on a fast machine with a great Internet connection, but users who are surfing on a slow connection will.

.wrapper { display: flex; } .sidebar { flex: 1 1 30%; } .content { flex: 1 1 70%; } /* Use grid instead of flexbox if supported */ @supports (display: grid) { .wrapper { display: grid; grid-template-columns: 30% 70%; } .sidebar { grid-column: 1; } .content { grid-column: 2; } } 

Support14 for CSS grid layouts isn’t very good at the moment, but it will increase in the next month when Safari 10 ships, and Firefox and Blink-based browsers will probably enable it by default. To be future-proof, we should use flexbox as our foundation and enhance the experience with a grid layout if it is supported.

Little Big Details Link

Changing CSS properties based on user interaction can often cause horizontal shifting. This can be avoided by using alternative CSS properties.

text-shadow for Bold Text Link

When changing the font weight of text, the size of the element will change and a content shift will occur.

a:hover, a:focus { font-weight: bold; } @supports (text-shadow: none) { a:hover, a:focus { font-weight: normal; text-shadow: 1px 0 0 currentColor; } } 

Redrawing text-shadow can be computationally more intensive than changing font-weight, but it is the only way to prevent the jump effect when changing to a heavier weight of text.

Once again, we are using feature-detection to apply text-shadow, instead of font-weight, upon interaction from the user. Because @supports is supported by fewer browsers than text-shadow, we could also consider using Modernizr15 to detect the feature and apply the improvement in all supported browsers.

Small details will often make a good experience great. Your users will appreciate every content shift that is avoided.

Scroll Anchoring Link

Now that you’ve learned about ways to avoid content jumps, you might be wondering why browsers can’t prevent content jumps more efficiently.

The Chrome team recently introduced scroll anchoring16, which does exactly that.

Scroll anchoring is a proposed intervention17 that adjusts the scroll position to reduce visible content jumps.

At the moment, scroll anchoring is only available behind an experimental flag in Chrome, but other browser vendors have shown interest and will hopefully implement it in future.

Conclusion Link

As you can see, there are many solutions for avoiding the jump effect on page load. Yes, implementing all of these techniques would take some time, but it is totally worth it — until scroll anchoring is supported in more browsers.

If you take the time to avoid jumps by using the techniques mentioned above — defining placeholders, reserving space and preparing for fallbacks — then users will have a less annoying experience and will be able to enjoy your content without interruption.

How do you minimize content shifting on your websites? Have you discovered any particular tricks or techniques to prevent the jump effect?

(il, al)

Front page image credits: Rayi Christian W.18

Footnotes Link

  1. 1 http://alistapart.com/article/creating-intrinsic-ratios-for-video
  2. 2 http://provide.smashingmagazine.com/padding-bottom-formula.svg
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2016/08/placeholder-picture-large-opt.png
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2016/08/placeholder-picture-large-opt.png
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2016/08/advertisement-large-opt.png
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/08/advertisement-large-opt.png
  7. 7 https://www.smashingmagazine.com/2016/03/never-ending-story-ad-blockers/#prominently-highlight-your-products
  8. 8 https://www.zachleat.com/web/comprehensive-webfonts/
  9. 9 https://github.com/bramstein/fontfaceobserver
  10. 10 https://www.w3.org/TR/css-fonts-3/#font-size-adjust-prop
  11. 11 http://caniuse.com/#feat=font-size-adjust
  12. 12 https://drafts.csswg.org/css-conditional-3/#at-supports
  13. 13 https://jakearchibald.com/2014/dont-use-flexbox-for-page-layout/
  14. 14 http://caniuse.com/#feat=css-grid
  15. 15 https://modernizr.com/
  16. 16 https://developers.google.com/web/updates/2016/04/scroll-anchoring
  17. 17 https://github.com/WICG/interventions/blob/master/scroll-anchoring/explainer.md
  18. 18 http://tumblr.unsplash.com/post/89277673479/download-by-rayi-christian-w
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Web Development Reading List #151: Microinteraction UX, Feature Policy, And Passport.js

Web Development Reading List #151: Microinteraction UX, Feature Policy, And Passport.js

In the last few years, I’ve seen a lot of code. As a freelancer working on multiple big projects with a lot of people, you’ll inevitably see all varieties of code styles. But I also realized how much writing JavaScript changed over the past years.

Having learned JavaScript before ES6 was there, a great mentor (Hans Christian Reinl1) taught me the most important lesson: Always write clean, understandable code. Avoid ternary operators, declare variables in one place, make functions as simple as possible. Basically things that so many JavaScript style guides also advise. But with the growing adoption of ES6/ES2015, I also saw an increase of code where most of these principles (except for keeping functions small) are ignored.

I think it has something to do with the increased flexibility of ES6. A lot of developers probably think since arrow functions — which are shorter than a normal function — can be used, they should also write everything else in the shortest, smartest way. However, in my opinion and experience, this leads to a less maintainable codebase, one that’s hard to read for people who don’t work on it on a daily basis. Be smarter! By applying simplicity and not cleverness to your code.

News Link

  • Carbide Alpha2 is a new kind of programming environment which requires no installation/setup, has auto-import for npm and GitHub, and does some other crazy stuff. Just have a look at all the amazing features that are listed on the website.

Concept & Design Link

5
Spokeo declared death to complexity and simplified their advanced search6. (Image credit: Ali Torbati7)

Security Link

  • Both the W3C and WICG (Web Incubator CG) share ideas on two new headers: Clear-Site-Data8 and Feature-Policy9. They both improve the security and privacy of users. While the first one can clean locally-stored objects, the latter declares features the browser is allowed to use within the origin, such as geolocation, cookies, and WebRTC. As a site-owner, you can use this to prevent a third-party from tracking your users.
  • NIST’s new password rules10 say that text messages shouldn’t be used for two-factor authentication anymore. A huge progress that will hopefully lead to less crappy 2FA in the future.
  • I recently shared an attack abusing target="_blank"11 on pages where users can add custom URLs. To make clear how bad the attack is, Ben Halpern now shows how he made it work on Instagram12 (they fixed it pretty fast). So remember to use rel="noopener" for any URL that you didn’t hard-code into the source.
New password rules13
The United States National Institute for Standards and Technology (NIST) formulated new guidelines for password policies14 to be used in the US government. (Image credit: Naked Security15)

Web Performance Link

JavaScript Link

  • The JavaScript library Grade.js17 produces complementary gradients generated from the top two dominant colors of an image.
  • Brecht Billiet explains why you don’t always need a third-party component and illustrates this with an example of building a modal in Angular 218.
  • Passport.js19 is an authentication middleware for Node.js, supporting authentication via username and password, Facebook, Twitter, and many more.

Work & Life Link

  • When dealing with clients, it’s important to ask the right questions20. It’s your job to find out what the end user needs and to guide the client to what they want.

Going Beyond… Link

  • We’ve been breaking global temperature records since ten months. And July was the hottest July on record21.
  • You can now contribute to OpenStreetView22 with your phone. The aim of creating an open-source alternative to Google’s Streetview functionality is really promising and has already some locations covered23. This is especially interesting in situations where people need fast updates — like in the case of the earthquake that stroke Italy this week and in which contributors updated all the maps in OpenStreetMap within a few hours.
  • Xaddress24 is an interesting idea of a universal address for every human on the world. It’s great to see the challenges of such systems and how we could solve them.
  • This interview with Steven Pinker25, psychology professor at Harvard University, explains why we think 2016 is the worst year ever. And next year will be the same. It’s a psychological issue since the news share only things that happened but not things that didn’t happen. If we look at the overall statistics of threats worldwide, we live in a safer and better world than ever before.

And with that, I’ll close for this week. If you like what I write each week, please support me with a donation26 or share this resource with other people. You can learn more about the costs of the project here27. It’s available via email, RSS and online.

— Anselm

Footnotes Link

  1. 1 https://drublic.de/
  2. 2 https://alpha.trycarbide.com/
  3. 3 https://medium.com/@alitorbati/death-to-complexity-how-we-simplified-advanced-search-a9ab2940acf0
  4. 4 https://www.smashingmagazine.com/2016/08/experience-design-essentials-animated-microinteractions-in-mobile-apps/
  5. 5 https://medium.com/@alitorbati/death-to-complexity-how-we-simplified-advanced-search-a9ab2940acf0
  6. 6 https://medium.com/@alitorbati/death-to-complexity-how-we-simplified-advanced-search-a9ab2940acf0
  7. 7 https://medium.com/@alitorbati/death-to-complexity-how-we-simplified-advanced-search-a9ab2940acf0
  8. 8 https://www.w3.org/TR/clear-site-data/
  9. 9 https://wicg.github.io/feature-policy/
  10. 10 https://nakedsecurity.sophos.com/2016/08/18/nists-new-password-rules-what-you-need-to-know/
  11. 11 https://wdrl.info/archive/129/977fcb771e018ba5f347e68a1ab515878c5bebb2
  12. 12 https://dev.to/ben/the-targetblank-vulnerability-by-example
  13. 13 https://nakedsecurity.sophos.com/2016/08/18/nists-new-password-rules-what-you-need-to-know/
  14. 14 https://nakedsecurity.sophos.com/2016/08/18/nists-new-password-rules-what-you-need-to-know/
  15. 15 https://nakedsecurity.sophos.com/2016/08/18/nists-new-password-rules-what-you-need-to-know/
  16. 16 https://css-tricks.com/use-webpagetest-api/
  17. 17 http://benhowdle.im/grade/
  18. 18 http://blog.brecht.io/Modals-in-angular2/
  19. 19 http://www.passportjs.org/
  20. 20 http://alistapart.com/article/why-arent-you-asking-questions
  21. 21 http://www.slate.com/blogs/bad_astronomy/2016/08/16/july_2016_was_the_hottest_july_on_record.html
  22. 22 https://www.openstreetmap.org/user/mvexel/diary/39274
  23. 23 http://openstreetview.org/map/@36.77409249464195,-122.83126831054686,8z
  24. 24 http://xaddress.org/
  25. 25 http://www.vox.com/2016/8/16/12486586/2016-worst-year-ever-violence-trump-terrorism
  26. 26 https://wdrl.info/donate
  27. 27 https://wdrl.info/costs/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Upgrading CSS Animation With Motion Curves

Upgrading CSS Animation With Motion Curves

There is UI animation, and then there is good UI animation. Good animation makes you go “Wow!” — it’s smooth, beautiful and, most of all, natural, not blocky, rigid or robotic. If you frequent Dribbble or UpLabs1, you’ll know what I am talking about.

Further Reading on Smashing: Link

With so many amazing designers creating such beautiful animations, any developer would naturally want to recreate them in their own projects. Now, CSS does provide some presets for transition-timing-function6, such as ease-in, ease-out and ease-in-out, which add some level of smoothness and realism, but they are very generic, aren’t they? How boring would it be if every animation on the web followed the same three timing functions?

One of the properties of transition-timing-function is cubic-bezier(n1, n2, n3, n4), in which you can pass four numbers to create your very own timing function. Towards the end of this article, you’ll know exactly what these four numbers represent — still, believe me, coming up with four numbers to capture the transition you are imagining in your head is nowhere close to being easy. But thanks to cubic-bezier8 and Ceasar9, you don’t have to. These tools bring motion curves to the web.


(Credit: m-2-h10)

Motion curves are primarily used by animators (for example, in Adobe After Effects11) to create advanced, realistic animations. With cubic-bezier and Ceasar, you can simply manipulate the shape of a curve, and those four numbers (n1, n2, n3, n4) will be filled in for you, which is absolutely great! Still, to use and make the most out of motion curves, you need to understand how they work, and that’s what we’re going to do in this article. Let’s begin.

Understanding Motion Curves Link

A motion curve is nothing but a plot between any animatable property12 and time. A motion curve defines how the speed of an animation running under its influence varies over time.

13
A motion curve is a plot between an animatable property and time. (View large version14)

Let’s take distance (translateX)15 as an example of an animatable property. (The explanation holds true for any other animatable property.)

Calculating speed at time t1 on a distance-time plot.16
Calculating speed at time t1 on the distance-time plot. (View large version17)

If you’ve had any experience with physics and basic calculus, you’ll know that deciphering speed from a distance-time graph is very simple. The first derivative of distance as a function of time, with respect to time, is speed, which means that an object following a distance-time curve would have greater speed in places where the curve is steep and lower in places where the curve is flatter. If you know how that works, great! You’re all set and can skip to the next section.

Now, I am aware that design and development is a diverse field, and not everyone has the same background. Perhaps the two paragraphs above were all jargon to you. Don’t fret. We’ll keep going and make sense of the jargon.

Consider the red box below. Let’s get a little callow here and call the red box “Boxy”; it’ll be easier to refer to it that way. All right, so Boxy is going to move from one edge of the screen to the other in a linear fashion, and we are going to analyze its motion.

One of the presets of transition-timing-function is linear. To make Boxy move, all we do is add the following class.

 .moveForward { transform: translateX(1000px); } 

To control the animation, we would set the transition property for Boxy as follows:

#boxy { width: 200px; height: 200px; background: red; transition-property: transform; transition-duration: 1s; transition-timing-function: linear; }

That’s a very verbose way to specify transition. In reality, you will almost always find transition written in its shorthand form:

#boxy { width: 200px; height: 200px; background: red; transition: transform 1s linear; }

Let’s see it go.

Boxy undergoing linear motion18
Box undergoing linear motion.

Robotic, isn’t it? You could say that this motion feels robotic because it’s linear, which is a perfectly plausible answer. But could you explain why? We can see that setting linear results in robotic motion, but what exactly is happening behind the scene? That’s what we’ll figure out first; we’re going to get to the innards and understand why this motion feels robotic, blocky and not natural.

Let’s start by graphing Boxy’s motion to see if we can gain some insight. Our graph will have two axes, the first being distance, and the second time. Boxy covers a total distance of 1000 pixels (distance) in 1 second (time). Now, don’t get scared by all the math below — it’s very simple.

Here is our very simple graph, with the axes as mentioned.

Empty graph with axes19
Empty graph with axes (View large version20)

Right now, it’s empty. Let’s fill it up with some data.

To start off with, we know that at 0 seconds, when the animation has not yet started, Boxy is in its initial position (0 pixels). And after 1 second has passed, Boxy has travelled a total of 1000 pixels, landing at the opposite edge of the display.

Boxy's initial and final positions21
Boxy’s initial and final positions (View large version22)

Let’s plot this data on the graph.

Graph with Boxy's initial and final positions plotted23
Graph with Boxy’s initial and final positions plotted (View large version24)

So far so good. But two data points are not enough — we need more. The following figure shows the positions of Boxy at different points of time (all thanks to my high-speed camera).

Boxy's positions at different points of time25
Boxy’s positions at different points of time (View large version26)

Let’s add this data to our graph.

Graph with different positions plotted27
Graph with different positions plotted (View large version28)

You could, of course, have many more data points for different times (for example, 0.375 seconds, 0.6 seconds, etc.) but what we have is enough to complete our graph. By joining all of the points, we have completed the graph. High five!

Final graph29
Final graph (View large version30)

Cool, but what does this tell us? Remember that we started our investigation with the goal of understanding why Boxy’s linear motion feels unnatural and robotic? At a glance, this graph we’ve just constructed doesn’t tell us anything about that. We need to go deeper.

Keep the graph in mind and let’s talk for a minute about speed. I know you know what speed is — I’d just like to put it in mathematical terms. As it goes, the formula for speed is this:

Mathematical formula for speed31
Mathematical formula for speed (View large version32)

Therefore, if a car covers a distance of 100 kilometers in 1 hour, we say its speed is 100 kilometers per hour.

Representing speed33
Representing speed (View large version34)

If the car doubles its speed, it will start covering double the distance (200 kilometers) in the same interval (1 hour), or, in other words, it will cover the original distance of 100 kilometers in half the time (0.5 hours). Make sense?

Similarly, if the car halved its speed (that is, slowed down by half), it would start covering a distance of 50 kilometers in the same interval (1 hour), or, in other words, it would cover the original distance of 100 kilometers in twice the time (2 hours).

Great! With that out of the way, let’s pick up where we left off. We were trying to figure out how the graph between distance and time can help us understand why Boxy’s linear motion feels robotic.

Hey, wait a second! We have a graph between distance and time, and speed can be calculated from distance and time, can’t it? Let’s try to calculate Boxy’s speed at different time intervals.

Calculating speed at different intervals35
Calculating speed at different intervals (View large version36)

Here, I’ve chosen three different time intervals: one near the start, one in the middle and one at the end near the final position. As is evident, at all three intervals, Boxy has exactly the same speed (s1 = s2 = s3) of 1000 pixels per second; that is, no matter what interval you choose in the graph above, you will find Boxy moving at 1000 pixels per second. Isn’t that odd? Things in real life don’t move at a constant speed; they start out slowly, gradually increase their speed, move for a while, and then slow down again before stopping, but Boxy abruptly starts with a speed of 1000 pixels per second, moving with the same speed and abruptly stopping at exactly the same speed. This is why Boxy’s movement feels robotic and unnatural. We are going to have to change our graph to fix this. But before diving in, we’ll need to know how changes to the speed will affect the graph drawn between distance and time. Ready? This is going to be fun.

Let’s double Boxy’s speed and see how the appearance of the graph changes in response. Boxy’s original speed, as we calculated above, is 1000 pixels per second. Because we have doubled the speed, Boxy will now be able to cover the distance of 1000 pixels in half the time — that is, in 0.5 seconds. Let’s put that on a graph.

Graph showing double speed37
Graph showing double speed (View large version38)

What if we tripled the speed? Boxy now covers 1000 pixels in one third of the time (a third of a second).

Graph showing triple speed39
Graph showing triple speed (View large version40)

Hmm, notice something? Notice how, when the graph changes, the angle that the line makes with the time axis increases as the speed increases.

All right, let’s go ahead and halve Boxy’s speed. Halving its speed means that Boxy will be able to cover only 500 pixels (half the original distance) in 1 second. Let’s put this on a graph.

Graph showing half speed41
Graph showing half speed (View large version42)

Let’s slow down Boxy a little more, making the speed one third of the original. Boxy will be able to cover one third of the original distance in 1 second.

Graph showing a third of the speed43
Graph showing a third of the speed (View large version44)

See a pattern? The line gets steeper and steeper as we increase Boxy’s speed, and starts to flatten out as we slow Boxy down.

Line gets steeper as speed increases and flattens out as speed decreases45
Line gets steeper as speed increases and flattens out as speed decreases. (View large version46)

This makes sense because, for a steeper line, a little progress in time produces a much higher change in distance, implying greater speed.

A small change in time produces a relatively large change in distance, making for a steeper graph.47
A small change in time produces a relatively large change in distance, making for a steeper graph. (View large version48)
A small change in time produces a relatively large change in distance, making for a steeper graph.49
A small change in time produces a relatively large change in distance, making for a steeper graph. (View large version50)

On the other hand, for a line that is less steep, a large change in time produces only a little change in distance, meaning a lower speed.

Change in time verus change in distance in a graph that is less steep51
Change in time versus change in distance in a graph that is less steep (View large version52)
Change in time versus change in distance in a graph that is less steep53
Change in time versus change in distance in a graph that is less steep (View large version54)

With all of the changes we have made, Boxy is still moving in a linear fashion, just at different speeds. However, with our newly gained knowledge of how changes to distance versus time can affect speed, we can experiment and draw a graph that makes Boxy move in a way that looks natural and realistic.

Let’s take it step by step. First, things in real life start out slow and slowly increase in speed. So, let’s do that.

In all of the iterations of the graph shown below, you will notice that the points at opposite corners remain fixed. This is because we are not changing the duration for which the animation runs, nor are we changing the distance that Boxy travels.

Constructing a custom motion curve55
Constructing a custom motion curve (View large version56)

If Boxy is to follow the graph above, it will move at a slower speed for 0.25 seconds, because the line is less steep starting from 0 to 0.25 seconds, and then it will abruptly switch to a higher speed after 0.25 seconds (the reason being that the line in the graph gets steeper after 0.25 seconds). We will need to smoothen this transition, though; we don’t want any corners — it’s called a motion curve, after all. Let’s convert that corner to a curve.

Constructing a custom motion curve57
Constructing a custom motion curve (View large version58)

Notice the smooth transition that Boxy undergoes from being at rest to gradually increasing in speed.

Boxy following the motion curve above59
Box following the motion curve above (View large version60)

Good! Next, objects in real life progressively slow down before stopping. Let’s change the graph to make that happen. Again, we’ll pick up a point in time after which we would like Boxy to start slowing down. How about around 0.6 seconds? I have smoothened out the transition’s corner to a curve here already.

Final custom motion curve61
Final custom motion curve (View large version62)

Look at Boxy go! A lot more natural, isn’t it?

Boxy following the custom motion curve63
Boxy following the custom motion curve (View large version64)

The curve we drew in place of the corner is actually a collection of many small line segments; and, as you already know, the steeper the line on the graph, the higher the speed, and the flatter the line, the slower the speed. Notice how in the left part of the image, the line segments that make up the curve get steeper and steeper, resulting in a gradual increase in speed, and progressively flatten out on the right side, resulting in the speed progressively decreasing?

A curve is nothing but a collection of many line segments.65
A curve is nothing but a collection of many line segments. (View large version66)

With all of this knowledge, making sense of motion curves becomes much easier. Let’s look at a few examples.

67
(View Large version)68
Example 169
Example 1 (View large version70)
71
(View Large version)72
Example 273
Example 2 (View large version74)
75
(View Large version)76
Example 377
Example 3 (View large version78)

Using Motion Curves In UI Animation Link

The next time you have to animate a UI element, you will have the power of motion curves at your disposal. Whether it’s a slide-out bar, a modal window or a dropdown menu, adding the right amount of animation and making it look smooth and natural will increase the quality of your user interface greatly. It will make the user interface just feel good. Take the slide-out menu below:

See the Pen nJial80 by Nash Vail (@nashvail9681) on CodePen9782.

Clicking on the hamburger menu brings in the menu from left, but the animation feels blocky. Line 51 of the CSS shows that the animation has transition-timing-function set to linear. We can improve this. Let’s head on over to cubic-bezier9183 and create a custom timing function.

If you’re reading this, it’s safe to assume that you’re a designer or a developer or both and, hence, no stranger to cubic bezier curves; there’s a good chance you’ve encountered them at least once. Bezier curves are a marvel. They are used primarily in computer graphics to draw shapes and are used in tools such as Sketch84 and Adobe Illustrator85 to draw vector graphics. The reason why cubic bezier curves are so popular is that they are so easy to use: Just modify the positions of the four different points, and create the kind of curve you need.

Because we always know the initial and final states of the animated object, we can fix two of the points. That leaves just two points whose positions we have to modify. The two fixed points are called anchor points, and the remaning two are control points.

Parts of a bezier curve86
Parts of a bezier curve (View large version87)

As you remember, cubic-bezier accepts four numbers (n1, n2, n3, n4) when you create a custom transition-timing-function. These four numbers represent nothing but the positions of the two control points: n1, n2 represents the x and y coordinates of the first control point, and n3, n4 represents the coordinates of the second control point. Because changing the position of the control points will change the shape of the curve and, hence, our animation overall, the result is the same when any or all of n1, n2, n3, n4 is modified. For example, the figure below represents cubic-bezier(.14, .78, .89, .35):

A cubic bezier curve representing (.14, .78, .89, .35).88
A cubic bezier curve representing (.14, .78, .89, .35) (View large version89)

The math behind these seemingly simple curves90 is fascinating.

All right, all right, let’s get back to where we were going with cubic-bezier9183: creating a custom transition-timing-function. I want the kind of animation in which the menu slides in very quickly and then gracefully slows down and ends:

Adjusting the cubic bezier curve92
Adjusting the cubic bezier curve (View large version93)

This looks good. The animation will start out fast and then slow down, rather than move at a constant speed throughout. I am simply going to copy cubic-bezier(.05, .69, .14, 1) from the top of the page and replace linear with it.

See the Pen nJial95 by Nash Vail (@nashvail9681) on CodePen9782.

See the difference? The second iteration feels much more natural and appealing. Imagine if every animation in your UI followed a natural timing function. How great would that be?

As we’ve seen, motion curves aren’t tricky at all. They are very easy to understand and use. With them, you can take your UI to the next level.

I hope you’ve learned how motion curves work. If you were going through a lot of trial and error to get motion curves to work the way you want, or if you were not using them at all, you should now be comfortable bending them to your will and creating beautiful animations. Because, after all, animation matters.

(al)

Footnotes Link

  1. 1 http://www.uplabs.com
  2. 2 https://www.smashingmagazine.com/2015/12/animating-clipped-elements-svg/
  3. 3 https://www.smashingmagazine.com/2015/06/practical-techniques-on-designing-animation/
  4. 4 https://www.smashingmagazine.com/2015/09/creating-cel-animations-with-svg/
  5. 5 https://www.smashingmagazine.com/2014/11/the-state-of-animation-2014/
  6. 6 https://developer.mozilla.org/en/docs/Web/CSS/transition-timing-function
  7. 7 https://dribbble.com/LukasStranak
  8. 8 http://cubic-bezier.com
  9. 9 https://matthewlein.com/ceaser/
  10. 10 https://dribbble.com/m-2-h
  11. 11 http://www.adobe.com/products/aftereffects.html
  12. 12 https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig26_large-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig26_large-opt.png
  15. 15 https://css-tricks.com/almanac/properties/t/transform/#article-header-id-3
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig27_large-opt.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig27_large-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/08/TNndMJe.gif
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig1_large-opt.png
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig1_large-opt.png
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig2_large-opt.png
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig2_large-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig3_large-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig3_large-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig4_large-opt.png
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig4_large-opt.png
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig5_large-opt.png
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig5_large-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig6_large-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig6_large-opt.png
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig7_large-opt.png
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig7_large-opt.png
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig8_large-opt.png
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig8_large-opt.png
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig9_large-opt.png
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig9_large-opt.png
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig10_large-opt.png
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig10_large-opt.png
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig11_large-opt.png
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig11_large-opt.png
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig12_large-opt.png
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig12_large-opt.png
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig13_large-opt.png
  44. 44 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig13_large-opt.png
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig14_large-opt.png
  46. 46 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig14_large-opt.png
  47. 47 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig15_large-opt.png
  48. 48 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig15_large-opt.png
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig16_large-opt.png
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig16_large-opt.png
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig17_large-opt.png
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig17_large-opt.png
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig18_large-opt.png
  54. 54 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig18_large-opt.png
  55. 55 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig19_large-opt.png
  56. 56 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig19_large-opt.png
  57. 57 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig20_large-opt.png
  58. 58 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig20_large-opt.png
  59. 59 https://www.smashingmagazine.com/wp-content/uploads/2016/08/xs6l6oW.gif
  60. 60 https://www.smashingmagazine.com/wp-content/uploads/2016/08/xs6l6oW.gif
  61. 61 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig21_large-opt.png
  62. 62 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig21_large-opt.png
  63. 63 https://www.smashingmagazine.com/wp-content/uploads/2016/08/iI5mrff.gif
  64. 64 https://www.smashingmagazine.com/wp-content/uploads/2016/08/iI5mrff.gif
  65. 65 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig22_large-opt.png
  66. 66 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig22_large-opt.png
  67. 67 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig23_large-opt.png
  68. 68 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig23_large-opt.png
  69. 69 https://www.smashingmagazine.com/wp-content/uploads/2016/08/Ij44EBG.gif
  70. 70 https://www.smashingmagazine.com/wp-content/uploads/2016/08/Ij44EBG.gif
  71. 71 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig24_large-opt.png
  72. 72 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig24_large-opt.png
  73. 73 https://www.smashingmagazine.com/wp-content/uploads/2016/08/F4Ve4Xl.gif
  74. 74 https://www.smashingmagazine.com/wp-content/uploads/2016/08/F4Ve4Xl.gif
  75. 75 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig25_large-opt.png
  76. 76 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig25_large-opt.png
  77. 77 https://www.smashingmagazine.com/wp-content/uploads/2016/08/a0YYL8I.gif
  78. 78 https://www.smashingmagazine.com/wp-content/uploads/2016/08/a0YYL8I.gif
  79. 79 http://codepen.io/nashvail
  80. 80 ‘http://codepen.io/nashvail/pen/qNYmLG/’
  81. 81 ‘http://codepen.io/nashvail’
  82. 82 ‘http://codepen.io’
  83. 83 http://cubic-bezier.com
  84. 84 https://www.sketchapp.com/
  85. 85 http://www.adobe.com/in/products/illustrator.html
  86. 86 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig28_large-opt.png
  87. 87 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig28_large-opt.png
  88. 88 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig29_large-opt.png
  89. 89 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig29_large-opt.png
  90. 90 https://medium.freecodecamp.com/nerding-out-with-bezier-curves-6e3c0bc48e2f#.113c4usq9
  91. 91 http://cubic-bezier.com
  92. 92 https://www.smashingmagazine.com/wp-content/uploads/2016/08/bezierDemo.gif
  93. 93 https://www.smashingmagazine.com/wp-content/uploads/2016/08/bezierDemo.gif
  94. 94 http://codepen.io/nashvail
  95. 95 ‘http://codepen.io/nashvail/pen/rLvymO/’
  96. 96 ‘http://codepen.io/nashvail’
  97. 97 ‘http://codepen.io’
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Sucuri vs CloudFlare (Pros and Cons) – Which One is Better?

Due to an increased emphasis on website security in today’s digital landscape, one of the most common requests we’ve gotten from readers is to do a pros and cons analysis of Sucuri vs CloudFlare to explain which one is better. Sucuri and CloudFlare are online services that offer website firewall, CDN, and DDoS protection services. In this article, we will compare Sucuri vs Cloudflare with pros and cons to find out which one is better.

Even the most secure websites on the internet are vulnerable to distributed denial of service attacks (DDoS), hacking attempts, and malware injection.

As a WordPress site owner you can use some security best practices like password protecting admin directory, limiting login attempts, adding two factor authentication, etc.

However these tips only work on software level which leaves your website mostly open to other types of attacks. These attacks can cause financial damage, data loss, poor search rankings and bad user experience.

Sucuri and CloudFlare offer a website application firewall (WAF).

This means that all your website’s traffic goes through their server scanners. If a request looks malicious, then the firewall would block it before it even reaches your website.

On the surface, these two services look nearly identical, but there are some key differences.

In this comparison, we’ll focus on:

  • Features
  • Pricing
  • Malware Removal Service

By the end, you’ll know exactly which platform is best for you.

Ready? Let’s compare Sucuri vs Cloudflare.

Features

In this section, we will look at the features offered by Sucuri and CloudFlare.

It’s important to note that both services offer different plans that come with different set of features.

As a user, make sure you’re not a victim of their marketing site because not all plans come with all the features.

CloudFlare Features

CloudFlare is best known for their free CDN service. They specialize in mitigating DDOS attacks using their Website Application Firewall product. CloudFlare keep your site available to users during an attack or under heavy traffic when your server is not responsive.

Their website firewall blocks suspicious traffic before it even reaches your website. The firewall also extends to form submissions which protects your website from comment spam and registration spam.

CloudFlare website firewall

CloudFlare also offers free and custom SSL certificates with all their plans. Free and pro plans only allow you to use CloudFlare issued certificate. For custom certificate you will need to upgrade to their Business or Enterprise plan.

While CloudFlare offer a free option that includes CDN, most other features including their Website Application Firewall require a paid plan.

CloudFlare doesn’t offer server scanning service to detect malware. It also doesn’t offer a malware removal guarantee if you were to be hacked on their watch.

Sucuri Features

Sucuri is one of the most reputable website security and monitoring service. They offer comprehensive website monitoring, scanning for malware, DDoS protection, and malware removal services.

Sucuri offers CloudProxy, a website firewall and load balancing service. It blocks suspicious traffic from reaching your website by effectively blocking DDoS attacks, code injection, bad bots, and other website threats. See our case study of how Sucuri helped us block 450,000 attacks in 3 months.

Sucuri offers integration with the free Let’s Encrypt SSL for their basic plan. You can also use custom SSL certificates with their professional and business plans.

Sucuri CloudProxy

Sucuri scans your website regularly for file changes, code injection, and malware. They clean up hacked sites, with support for all popular CMS software like WordPress, Joomla, Drupal, etc.

Winner: Sucuri is a clear winner because they offer a better combination of tools and services (Website Firewall + Load Balancing + Malware Cleanup / Hack Repair).

Pricing

Pricing is an important factor for many small businesses.

Here, we will compare the different pricing plans offered by CloudFlare and Sucuri, so you know exactly what you’re getting for your money.

FREE is not always better

CloudFlare Pricing Plans

CloudFlare offers a free CDN service for all. They don’t charge you for the bandwidth which means you will be able to use their free CDN regardless of your traffic volume.

However, this free plan does not come with the website application firewall. Your website may benefit from CDN, but it will not be properly protected against DDoS attacks, spam, bad traffic, etc.

For their web application firewall, you need the Pro plan which costs $20 / month (this is what you need for improved security).

This pro plan does not include advanced DDoS mitigation and custom SSL. For those features, you will need their Business plan which costs $200 per month.

Sucuri Pricing Plans

Unlike CloudFlare, Sucuri doesn’t offer a free plan. Their website security stack plan starts at $199.99 for an year, which is cheaper than CloudFlare’s pro plan.

This basic plan includes full website monitoring, website application firewall, DDoS protection, malware removal, and free LetsEncrypt SSL certificate.

Instead of excluding features from lower level plans, Sucuri uses priority as an incentive for their higher paying plans.

For example, malware removal estimated time for basic plan is 12 hours, 6 hours for professional plan, and 4 hours for business plan. However, the actual cleanup timings are way faster than that for all customers.

They offer 24/7 support as part of all plans. Their business plan subscribers can also use the Live Chat support.

Winner:Sucuri is an obvious choice for small businesses when it comes to pricing. CloudFlare Pro costs $240 / year vs Sucuri cost $199 / year and offer more features. To unlock same features, you’d have move up to CloudFlare’s $2400 / year plan. Sucuri’s most expensive plan is at $499 / year.

Malware Removal Service

Apart from denial of service attacks, malware and code injections are the most common threats faced by WordPress site owners.

Let’s see how both services protect your website against those common threats.

Website security and malware removal

CloudFlare – Security and Malware Removal

CloudFlare free version is basically a content delivery network which helps make your website fast.

The website security firewall comes with their paid plan. It includes CloudFlare’s ready to use custom rules set. These rules protect your site from common code injection hacks, XSS JavaScript exploits, and form submissions.

However, they do not offer file change detection, malware scanning, blacklist monitoring, and many other security features. You can add third-party apps for malware scanning, but these services will cost you additional fees.

Sucuri – Security and Malware Removal

Sucuri is a security focused company. They specialize in monitoring websites and protecting them against malware and other attacks.

Sucuri’s website application firewall protects you against DDOS, SQL injections, XSS JavaScript injections, comment and contact form spam.

However, if something crosses all those security barriers and somehow reaches your website, then Sucuri offers to clean up your website (for free).

If you already have a website affected with malware, then Sucuri will clean that up as well.

Winner:Sucuri – For combining website application firewall with monitoring, malware protection, and clean up services.

Conclusion

CloudFlare and Sucuri both offer protection against DDoS attacks on your website. CloudFlare does a little better in the content delivery network area.

Sucuri fares better in the overall features, better security monitoring, and lower prices. If you are using a CMS like WordPress, then Sucuri is what you need.

We hope this article helped you compare pros and cons of Sucuri vs CloudFlare. You may also want to see our list of 7 best WordPress backup plugins.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

Diverse Test-Automation Frameworks For React Native Apps

Diverse Test-Automation Frameworks For React Native Apps

The bar is set high for today’s mobile apps. First, apps must meet the standard of quality that app markets expect. Secondly, mobile app users are very demanding. Plenty of alternatives are available to download, so users will not tolerate a buggy app. Because mobile apps have become such a crucial part of people’s lives, users won’t be shy about sharing their love or hate for an app — and that feedback gets in front of millions of users in seconds.

Further Reading on Smashing: Link

Mobile is more important than ever6. But getting an app just right, getting it to work across all possible devices, with different OS versions, display resolutions, chipsets and other hardware characteristics, and making the user experience smooth across all possible configurations, is a challenging task.

7
The increase in mobile platforms and device fragmentation. (View large version8)

A ton of great technologies, tools, frameworks and open-source components are available for building native mobile apps. What value does React Native9 bring to the scene, and how can we make sure that apps built with it are well received by their target audiences?

In this article, we’ll look at what’s available for testing React Native apps10. First, I’ll explain some key features of React Native, before looking at how to implement these tests. Secondly, I’ll categorize testing methods and frameworks on three levels (unit, integration, functional), providing examples for each. Finally, I’ll provide simple examples of how to implement tests using the most popular open-source test-automation frameworks for functional app testing.

The Basic Architecture Of React Native Apps

It all got started with React11 more than three years ago, when Facebook introduced its framework to web developers. It was bound to be popular, not just because it was authored and developed by Facebook, but because of the capabilities it provided to web developers — and especially how it changed the way we build apps.

The concept of this type of “learn once, write anywhere” framework wasn’t new, though; we had already seen JavaScript libraries do similar things (Sencha12, PhoneGap13 and Appcelerator14, among others), but something was better about React that had an impact on developers’ habits and how they break down an application’s UI into discrete components.

React Native does not use the DOM for rendering. Instead, it renders with native UI views, which means you are using the native components provided by the operating system. This sort of product-creation flow, where you replace the DOM API with a more declarative API, gives developers a more cohesive and simplified level of abstraction15.

React Native development flow on Android and iOS16
React Native development flow on Android and iOS. (Image: Testdroid676351422917) (View large version18)

The key thing about React Native is that it brings the React programming model19 to mobile apps, development and testing. It doesn’t actually work directly as a cross-platform tool or framework, but it accelerates the trend of building mobile apps on this new platform. And that’s one of the cornerstones of what makes React Native so powerful, easy to learn and easy to write on this new platform.

The major difference, as well as advantage, of native mobile versus the web is that, instead of running a JavaScript-based implementation in a browser and exposing HTML elements, we are now relying on the embedded JavaScriptCore in apps20, which get platform-specific UI elements.

Test Automation On Different Levels: Unit, Integration, Component And Functional

All mobile software is built using composition. On Android and iOS21, this means that small software components are arranged together to form larger, higher-level components with greater functionality, until the goals and requirements of the application have been met. A good testing practice is to run tests that cover functionality at all levels of the composition.

In this article, I’ll cover test methods and automation frameworks at three levels. The primary focus is on the highest level, functional testing, but React Native apps can be tested — and testing can be automated — on at least the following levels:

  • Unit testing

    This could be even as basic as testing JavaScript objects and methods on the component level.
  • Component testing

    Each component can be tested either visually or functionally. ReactTestUtils2322 provides a simple framework for testing React components.
  • Integration testing

    Integration testing comes next and is a phase when a group of different units are typically tested as an entity.
  • Functional testing

    Functional testing is a type of black-box testing that focuses on user requirements and interactions, and it covers all underlying software, all user interaction and the application as an entity.

In addition to ReactTestUtils2322, React Native provides useful unit-testing methods24, but none of them thoroughly cover the application’s actual logic. Therefore, mobile apps built on React Native benefit more from functional UI testing. A variety of functional test-automation frameworks25 are available, and we’ll look at few of the most popular ones in this article.

While unit testing can be done at the component level, functional test automation provides better capabilities for testing the larger entities in a React Native app. With React Native, component logic unit testing can be done in isolation, using traditional JavaScript libraries and forcing React Native to return regular components instead of native ones. With functional test-automation frameworks, UI components are part of the app and are easy to test as a whole.

I’ll separate these frameworks into cross-platform frameworks26 and platform-specific frameworks4027, as illustrated in the picture below.

Different test-automation options for React Native apps28
Different test-automation options for React Native apps. (Image: Testdroid676351422917) (View large version30)

The best part of React Native apps is that they are fully native for both major mobile platforms (Android and iOS). This means we get more frameworks, tools and native methods for testing purposes. We’ll look at functional test-automation frameworks in the section below titled “Using Functional Test-Automation Frameworks With React Native Apps31.”

Let’s start with unit-testing capabilities32, using a JavaScript test to illustrate.

Unit Testing With Jest and Jasmine Link

By default, React Native provides Jest33 tests for unit testing, and this works for both Android and iOS. Currently, test coverage isn’t perfect, but according to Facebook, more unit-testing capabilities will be introduced in React Native, and users can already build their own.

Jest uses the Jasmine behavior-driven framework34 as the basis for testing JavaScript code. Every test case starts from a describe() function call, similar to how JUnit uses the TestCase class. The describe() function takes two parameters: the description and title of the test case, and the function to be executed. The it() function includes all of the test steps and (similar to JUnit) provides a series of expect() functions.

Here is an example of a Jasmine test script for a player application.

describe("Player", function() { var player; var song; beforeEach(function() { player = new Player(); song = new Song(); }); it("should be able to play a song", function() { player.play(song); expect(player.currentlyPlayingSong).toEqual(song); //demonstrates use of custom matcher expect(player).toBePlaying(song); }); describe("when song has been paused", function() { beforeEach(function() { player.play(song); player.pause(); }); it("should indicate the song is paused", function() { expect(player.isPlaying).toBeFalsy(); // demonstrates use of 'not' with a custom matcher expect(player).not.toBePlaying(song); }); it("should be possible to resume", function() { player.resume(); expect(player.isPlaying).toBeTruthy(); expect(player.currentlyPlayingSong).toEqual(song); }); }); // demonstrates use of spies to intercept and test method calls it("tells the current song whether the user has made it a favorite", function() { spyOn(song, 'persistFavoriteStatus'); player.play(song); player.makeFavorite(); expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true); }); //demonstrates use of expected exceptions describe("#resume", function() { it("should throw an exception if song is already playing", function() { player.play(song); expect(function() { player.resume(); }).toThrow("song is already playing"); }); }); });

This basic example shows how Jasmine can be used to test the functionality of an app, but it keeps the focus on method-level testing. In addition, React Native provides some basic capabilities for testing integrated components. This works for both native and JavaScript components and enables communication between them via a bridge.

Integration Testing Link

At the moment, integration tests highlighted in the React Native community are available only for iOS and are very limited in their ability to test components. The communication goes through the bridge and requires both native and JavaScript components. For this functionality, two components are available to implement customized integration tests, RCTestRunner35 and RCTestModule36.

A basic Objective-C example for building a test skeleton of an iOS app would start like this:

@implementation ExampleTests { RCTTestRunner *_runner; } - (void)setUp { [super setUp]; _runner = RCTInitRunnerForApp(@"IntegrationTestHarnessTest", nil); } - void()testExampleTests { [_runner runTest:_cmd module:@"ExampleTests"] } @end

However, there are other ways to run integration testing and to extend it to Android and iOS. A good alternative for running both unit and integration tests is Mocha37, which provides a feature-rich JavaScript test framework that runs on Node.js38. Mocha also provides behavior-driven development (BDD), test-driven development (TDD) and QUnit interfaces for testing.

For functional UI testing, I’ll be covering the most prominent and most used test-automation frameworks, including Appium, Calabash, XCTest and a few others.

Using Functional Test-Automation Frameworks With React Native Apps

To streamline the app development process and to maximize testing coverage, we have numerous open-source test-automation frameworks to choose from.

The best choice — if your app will run on several OS platforms — is a framework that supports multiple platforms39 and provides a robust foundation for test automation. In mobile, the term “cross-platform” refers to a framework that provides the same API, tools and capabilities for both Android and iOS.

In addition, a range of great platform-specific frameworks4027 are available. Naturally, each framework has been built for a particular platform and, in most cases, is easier to adopt for that platform. In addition to Appium and Calabash, I’ll cover four platform-specific frameworks in this article: Robotium and Espresso for Android, and XCTest and EarlGrey for iOS.

Different test-automation frameworks for functional UI testing41
Different test-automation frameworks for functional UI testing. (Image: Testdroid676351422917) (View large version43)

When it comes to test automation, bear in mind that apps built with React Native are fully native on both iOS and Android; hence, functional test-automation frameworks will work fine with them.

The example I’ll use with each framework is an implementation of a very basic radio button UI.

<Radio onSelect={this.onSelect.bind(this)} defaultSelect={this.state.optionSelected - 1}> <Option color="black" selectedColor="#000000"> <Item title="First option" description="First radio button"/> </Option> <Option color="black" selectedColor="#000000"> <Item title="Second option" description="Second radio button"/> </Option> <Option color="black" selectedColor="#000000"> <Item title="Third option" description="Third radio button"/> </Option> </Radio> 

The test snippet included in each framework section below shows how the test script deals with each UI element and how clicks and other user inputs are handled. The purpose of the examples is not to provide step-by-step instructions, but rather to compare examples and show what is available for test automation today and what programming languages can be used for testing.

Cross-Platform Frameworks

As stated, React Native is not actually a cross-platform framework, but adoption of it across other platforms is easy. In the next two sections, we’ll go through two popular cross-platform test-automation frameworks for mobile testing and mobile test automation.

Appium Link

Appium44 is an open-source test-automation framework, with an inspection tool that works well for native, hybrid and mobile web apps. It uses JSONWireProtocol45 internally to interact with iOS and Android apps, using Selenium WebDriver46. Because of this, Appium works extremely well for the mobile web as well, and the use cases are very similar if Selenium is used for web testing.

In fact, Appium has been a rising star in mobile test automation47 in the last year. Originally, it was built to provide cross-platform support for both major platforms, Android and iOS.

Being cross-platform means that the framework and its scripts work exactly the same on both platforms. In addition, Appium provides fantastic programming language support48 — developers can write tests using their favorite language (for example, Java, Ruby, Python, C#), tools and environment. It’s also easy to get started, to create and maintain reusable tests, and to execute those tests on real physical devices.

When it comes React Native-powered apps, JavaScript isn’t necessarily required; tests can be written in any language. For example, Appium scripts can look like this:

driver.findElement(By.id("com.example.app:id/radio0")).click(); driver.findElement(By.id("com.example.app:id/radio1")).click(); driver.findElement(By.id("com.example.app:id/radio2")).click(); driver.findElement(By.id("com.example.app:id/editText1")).click(); driver.findElement(By.id("com.example.app:id/editText1")).sendKeys("Simple Test"); driver.findElement(By.name("Answer")).click(); // or alternatively like this: driver.findElement(By.id("com.example.app:id/button1")).click();

So, how do these WebDriver functions access apps running on devices? Basically, Appium starts a test script on the device or emulator, which then creates a server and listens for commands from the main Appium server. It is the same as the Selenium server, which gets HTTP requests from Selenium client libraries49. The difference between Android and iOS is illustrated in the picture below:

How Appium works on Android and iOS50
How Appium works on Android and iOS. (Image: Testdroid676351422917) (View large version52)

With iOS, Selenium WebDriver gets a command from the Appium script (for example, click()) and sends it in the form of JSON via an HTTP request to the Appium server53. Appium knows the automation context and sends this command to the Instruments command server, which waits for the Instruments command client to pick it up and execute it with bootstrap.js in the iOS Instruments environment. Once the command is executed, the Instruments command client sends the message back to the Appium server, which logs everything related to the command in its console. This cycle keeps going until the test script has finished.

On Android, things work almost the same way, except that the frameworks used are Selendroid and UiAutomator54. In short, Appium translates WebDriver commands to UiAutomator (API level 17 or higher) or Selendroid (API level 16 or lower) commands. On a physical device, bootstrap.jar launches a TCP server that gets commands from a TCP client. The process is similar on iOS.

If you are interested in getting started with Appium, plenty of material is available, including step-by-step instructions55 and Appium tutorials56.

Calabash Link

Another great cross-platform testing framework is Calabash57, which enables anyone to write tests for mobile applications. The main difference is that Calabash tests are written in Cucumber58. The idea behind using this sort of language for tests is awesome: The test itself is like a specification, and all tests are simple and easy to read yet executable by the automation system.

Compared to Appium, Calabash provides an easier way to create cross-platform tests for Android and iOS. This is due to the straightforward vocabulary and specification-oriented language, which makes Calabash tests identical on both platforms. The actual tests are written in Gherkin59 and run in Cucumber.

Because of these capabilities, the differences between Calabash working on Android60 and on iOS61 applications are minor. Again, there is no implication for React Native apps because all components and user interfaces are fully native to these platforms.

Calabash on Android and iOS62
Calabash on Android and iOS. (Image: Testdroid676351422917) (View large version64)

The basic testing and test-creation flow, however, remains the same. Calabash (and Gherkin) tests comprise features, scenarios and steps. The recommended approach is to complete the highest-level descriptions first: features, followed by scenarios and then the actual steps. A good rule of thumb is to create Calabash features65 first.

Calabash features, scenarios and steps66
Calabash features, scenarios and steps. (Image: Testdroid676351422917) (View large version68)

The example below shows how our application and its UI components (radio buttons, text field and button) would be implemented in Calabash:

Feature: Answer the question feature Scenario: As a valid user, I want to answer app question, I wait for text "What is the best way to test application on a hundred devices?" Then I press radio button 0 Then I press radio button 1 Then I press radio button 2 Then I enter text "Simple Test" into field with id "editText1" Then I press view with id "Button1"

Steps usually begin with one of the keywords given, then, when, and or but. However, they don’t have to; they can use * instead.

Calabash is also widely used by non-developers, and it can be used for product specifications and documentation due to its easy-to-understand language and logic. Eventually, the features and scenarios are wrapped in Ruby code.

Setting up Calabash69 and starting to work with it are easy. If you have Bundler70 and Ruby (or rbenv) installed, just hit these few lines in your console, and a Calabash environment will soon be set up:

$ gem install calabash-android $ gem install calabash-cucumber

This will take care of installing Calabash-Android and Calabash-iOS, and your journey with test automation can begin.

Platform-Specific Frameworks

When it comes to automating tests on Android and iOS apps, there are certain advantages to using platform-specific frameworks over cross-platform ones. For instance, some frameworks are built closely to SDKs and IDEs71, which are readily available while an application is under development. Let’s look at a few examples of these types of frameworks for Android and iOS.

Robotium and ExtSolo (Android) Link

Robotium72 was one of the first testing frameworks to work for native and hybrid Android apps. The UI tests created with Robotium enable functional, system and user-acceptance tests for Android apps, spanning and handling multiple Android activities. In fact, Robotium provides support for very early versions of Android, starting from API level 8.

Recently, Robotium was extended with the ExtSolo library73, which provides various useful features for app testing:

  • automatic scaling of x and y clicks for any display resolution;
  • multi-path drags;
  • automatic screenshot capture at moment of test failure;
  • mock locations (GPS coordinates);
  • change of Android device language;
  • control of Wi-Fi connection;

With Java code, tests are easy to build using any Java SDK and IDE. The primary function used in this example is findViewById, which finds a view that is identified by the id attribute. The UI element could be also identified by a name, class or some other attribute. Our code example with an id attribute would look like this:

solo.clickOnView(solo.findViewById("com.example.app:id/radio0")); solo.clickOnView(solo.findViewById("com.example.app:id/radio1")); solo.clickOnView(solo.findViewById("com.example.app:id/radio2")); solo.enterText((EditText) solo.findViewById("com.example.app:id/editText1"), "Simple Test"); solo.clickOnView(solo.findViewById("com.example.app:id/button1"));

Robotium here is trying to locate UI elements based on the id, description and other characteristics. Unfortunately, this isn’t always the best approach and does not necessarily work well with webview components. However, with the help of the ExtSolo library, users can define clicks and other interactions on UI elements that scale with the resolution. Also, hardcoding coordinates is possible, and these scale when the display resolution changes.

If you are using Robotium, then getting started with Robotium ExtSolo is easy and effortless. Just clone the repository for yourself and build the library:

$ git clone https://github.com/bitbar/robotium-extensions $ ant clean instrument

After this, place the recently built .jar file in the libs folder in your Android Studio project, and make sure your project is linked to it. All of these great additional features and services are now in your workspace.

Espresso (Android) Link

The Espresso74 testing framework provides APIs for writing UI tests to simulate user interactions for an Android app. The Espresso API75 is lightweight and provides three main components: viewMatchers, viewActions and viewAssertions.

The beauty of Espresso is that it provides automatic synchronization of test methods and UI elements that are being tested. For example, if the test script wants to press a button but the button isn’t visible on the screen yet, it will wait until this button can be pressed (i.e. it is visible and a click can happen). This makes test execution very fast because no test scripts need to include any sleep or wait commands. Also, developers do not need additional logic to handle timing-related issues.

// R class ID identifier for radio buttons onView(withId(R.id.radio0)).perform(click()); onView(withId(R.id.radio1)).perform(click()); onView(withId(R.id.radio2)).perform(click()); onView(withId(R.id.EditText1)).perform(click()); // Instead of R, we use getIdentifier onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.example.app:id/EditText1", null, null))).perform((typeText("Simple Test"))); onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.example.app:id/Button1", null, null))).perform(click());

Espresso has its own pros and cons, and due to the lightweight API, not many additional services or function calls are available to developers. For instance, you must use alternative methods to take screenshots, manage tests, output test results and more.

At Google IO 201676 Google introduced Espresso Test Recorder as an integral part of Android Studio. While the feature is not yet available, it will definitely be worth the wait.

XCTest and KIF (iOS) Link

XCTest77 is tightly coupled with Xcode but is still usable with both real iOS devices and simulators. XCTest allows developers to write tests for components at any level and also provides a framework for UI testing capabilities. XCTest tests are grouped into subclasses of XCTestCase78. Writing any tests with XCTest should be trivial to iOS developers because XCTest is fully compatible with both Objective-C and Swift.

KIF79 (short for “keep it functional”) is an iOS integration test framework that is closely related to and that uses XCTest test targets. KIF tests can be executed directly in XCTestCase or any subclass. KIF allows for easy automation of iOS applications by leveraging the accessibility attributes that the OS makes available to those with visual disabilities.

Let’s see how our UI components would look with Objective-C:

- (void)testClicksOnRadioButtons { [tester tapViewWithAccessibilityLabel:@”Radio1”]; [tester tapViewWithAccessibilityLabel:@”Radio2”]; [tester tapViewWithAccessibilityLabel:@”Radio3”]; [tester enterText:@”Simple Test” intoViewWithAccessibilityLabel:@”editText1”]; [tester tapViewWithAccessibilityLabel:@”Answer”]; }

Alternatively, with Swift, the test would look as simple as this:

testClicksOnRadioButtons() { let app = XCUIApplication() app.radiobutton[0].tap() app.radiobutton[1].tap() app.radiobutton[2].tap() app.staticTexts[“Simple Test”] app.button[0].tap() }

Note that this high-level pseudo-code requires additional code in order to fully function. If you are looking for more information on XCTest and generally on using Xcode testing capabilities, Apple has you covered80.

EarlGrey (iOS) Link

It was just earlier this year when Google open-sourced81 its functional iOS app-testing framework, named EarlGrey. Being used internally by Google, it has worked relatively well with native iOS apps — YouTube, Google Calendar, Google Photos, Google Play Music, to name a few — and has sparked some serious interest. To get started with EarlGrey82, you’ll need the Xcode environment installed and basic knowledge of iOS development.

There are a lot of similarities between EarlGrey and Espresso (yes, both are developed by Google), and their characteristics make both frameworks work and execute tests quickly. Similar to Espresso, EarlGrey tests automatically wait for events (animations, network requests, etc.) before trying to interact with the UI. This makes writing tests easier because developers do not need to worry about sleep or wait commands. In addition, the code itself is easier to maintain because it provides procedural descriptions of the test steps.

EarlGrey also contains matchers that are available from the GREYMatchers83 class. The documentation recommends using UI elements with the accessibility parameters. To identify UI elements, developers can use grey_accessibilityID() or grey_accessibilityLabel().

- (void)testBasicSelectionAndAction { [[EarlGrey selectElementWithMatcher::grey_accessibilityID(@"ClickHere")] performAction:grey_tap()]; // Example of long press with EarlGrey matchers - (void)testLongPress { [[EarlGrey selectElementWithMatcher::grey_accessibilityLabel(@"Box")] performAction:grey_longPressWithDuration(0.5f)]; [[EarlGrey selectElementWithMatcher::grey_accessibilityLabel(@"One Long Press")] assertWithMatcher:grey_sufficientlyVisible()]; // Example of multi-select, visible click on items - (void)testCollectionMatchers { id visibleSendButtonMatcher = grey_allOf(grey_accessibilityID(@"Box"), grey_sufficientlyVisible(), nil); [[EarlGrey selectElementWithMatcher:visibleSendButtonMatcher] performAction:grey_tap()]; }

Similar to XCTest, our radio button implementation isn’t that straightforward, and buttons for XCTest should be defined as iOS-supported UIElements to enable clicks and user interactions.

Conclusion

We’ve covered the basics of React Native applications and how they can be tested using various methods and frameworks. This comes up quite often, but the industry standards for mobile test automation at the functional UI level will work on React Native apps just as they do with any other native apps. The test-automation frameworks we’ve covered here are widely used for native mobile apps, hybrid apps, the mobile web as well as React Native apps.

In summary, determining the programming language that a mobile application is built on is not critical because it won’t have any influence on the test-automation frameworks that it can be tested with. As discussed, plenty of powerful test-automation frameworks are available today, which React Native apps will work with when wrapped as an APK or IPA.

What are you using for React Native app testing? Weigh in with a comment below!

(al, ml)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2016/04/the-beauty-of-react-native-building-your-first-ios-app-with-javascript-part-1/
  2. 2 https://www.smashingmagazine.com/2016/04/consider-react-native-mobile-app/
  3. 3 https://www.smashingmagazine.com/2015/01/basic-test-automation-for-apps-games-and-mobile-web/
  4. 4 https://www.smashingmagazine.com/2016/03/server-side-rendering-react-node-express/
  5. 5 https://www.smashingmagazine.com/2015/05/client-rendered-accessibility/
  6. 6 http://www.smartinsights.com/mobile-marketing/mobile-marketing-analytics/mobile-marketing-statistics/
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/06/01-fragmentation-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/06/01-fragmentation-opt.png
  9. 9 https://facebook.github.io/react-native/docs/
  10. 10 http://testdroid.com/tech/testing-react-native-apps-on-android-and-ios
  11. 11 https://code.facebook.com/projects/176988925806765/react/
  12. 12 https://www.sencha.com/
  13. 13 http://phonegap.com/
  14. 14 http://www.appcelerator.com/
  15. 15 https://www.smashingmagazine.com/2016/04/the-beauty-of-react-native-building-your-first-ios-app-with-javascript-part-1/
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/06/02-react-native-architecture-opt.png
  17. 17 http://testdroid.com
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/06/02-react-native-architecture-opt.png
  19. 19 https://www.smashingmagazine.com/2016/04/consider-react-native-mobile-app/
  20. 20 http://trac.webkit.org/wiki/JavaScriptCore
  21. 21 https://code.facebook.com/posts/1189117404435352/react-native-for-android-how-we-built-the-first-cross-platform-react-native-app/
  22. 22 http://facebook.github.io/react/docs/test-utils.html
  23. 23 http://facebook.github.io/react/docs/test-utils.html
  24. 24 https://facebook.github.io/react-native/docs/testing.html
  25. 25 https://www.smashingmagazine.com/2015/01/basic-test-automation-for-apps-games-and-mobile-web/#different-ways-to-automate-mobile-testing
  26. 26 #cross-platform-frameworks
  27. 27 #platform-specific-frameworks
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/06/03-testing-react-native-opt.png
  29. 29 http://testdroid.com
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/06/03-testing-react-native-opt.png
  31. 31 #test-automation-frameworks
  32. 32 https://facebook.github.io/react-native/docs/testing.html#jest-tests
  33. 33 http://facebook.github.io/jest/
  34. 34 http://jasmine.github.io/
  35. 35 https://github.com/facebook/react-native/blob/master/Libraries/RCTTest/RCTTestRunner.h
  36. 36 https://github.com/facebook/react-native/blob/master/Libraries/RCTTest/RCTTestModule.h
  37. 37 https://mochajs.org/
  38. 38 https://nodejs.org/en/
  39. 39 #cross-platform-frameworks
  40. 40 #platform-specific-frameworks
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/06/04-test-automation-frameworks-opt.png
  42. 42 http://testdroid.com
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/06/04-test-automation-frameworks-opt.png
  44. 44 http://appium.io/
  45. 45 https://code.google.com/p/selenium/wiki/JsonWireProtocol
  46. 46 http://docs.seleniumhq.org/projects/webdriver/
  47. 47 http://testdroid.com/news/37-things-you-should-know-about-appium
  48. 48 http://testdroid.com/news/appium-tip-1-how-to-get-started-setup-and-run-your-first-tests
  49. 49 https://www.smashingmagazine.com/2015/01/basic-test-automation-for-apps-games-and-mobile-web/#appium-executing-tests-on-real-devices-on-a-cloud-service
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2016/06/05-appium-architecture-opt.png
  51. 51 http://testdroid.com
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/06/05-appium-architecture-opt.png
  53. 53 http://testdroid.com/tech/how-to-use-selenium-for-cross-browser-testing-on-mobile-devices
  54. 54 http://testdroid.com/news/appium-tip-16-finding-elements-with-appium-automation-engine
  55. 55 https://blogs.technet.microsoft.com/antino/2014/09/22/how-to-set-up-a-basic-working-appium-test-environment/
  56. 56 http://testdroid.com/news/37-things-you-should-know-about-appium
  57. 57 https://github.com/calabash
  58. 58 https://cucumber.io/
  59. 59 https://github.com/cucumber/cucumber/wiki/Gherkin
  60. 60 https://github.com/calabash/calabash-android
  61. 61 https://github.com/calabash/calabash-ios
  62. 62 https://www.smashingmagazine.com/wp-content/uploads/2016/06/06-calabash-diagram-opt.png
  63. 63 http://testdroid.com
  64. 64 https://www.smashingmagazine.com/wp-content/uploads/2016/06/06-calabash-diagram-opt.png
  65. 65 http://testdroid.com/tech/creating-the-right-calabash-tests
  66. 66 https://www.smashingmagazine.com/wp-content/uploads/2016/06/07-calabash-features-scenarios-steps-opt.png
  67. 67 http://testdroid.com
  68. 68 https://www.smashingmagazine.com/wp-content/uploads/2016/06/07-calabash-features-scenarios-steps-opt.png
  69. 69 http://testdroid.com/tech/how-to-setup-and-get-started-with-calabash
  70. 70 http://bundler.io/
  71. 71 http://android-developers.blogspot.fi/2016/05/android-studio-22-preview-new-ui.html
  72. 72 https://github.com/RobotiumTech/robotium
  73. 73 https://github.com/bitbar/robotium-extensions
  74. 74 https://google.github.io/android-testing-support-library/docs/espresso/index.html
  75. 75 https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/
  76. 76 https://www.youtube.com/watch?v=isihPOY2vS4
  77. 77 https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/testing_with_xcode/
  78. 78 https://developer.apple.com/library/tvos/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/04-writing_tests.html
  79. 79 https://github.com/kif-framework/KIF
  80. 80 https://developer.apple.com/library/tvos/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/03-testing_basics.html
  81. 81 http://google-opensource.blogspot.com/2016/02/earlgrey-ios-functional-ui-testing.html
  82. 82 http://testdroid.com/news/how-to-get-started-with-earlgrey-ios-functional-ui-testing-framework
  83. 83 https://github.com/google/EarlGrey/blob/master/EarlGrey/Matcher/GREYMatchers.m
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

How to Delay Posts From Appearing in WordPress RSS Feed

Recently, one of our readers asked if it’s possible to delay posts from appearing in the WordPress RSS feed? Delaying posts in your RSS feed can save you from accidental publishing and beat content scrapers in SEO. In this article, we will show you how to delay post from appearing in WordPress RSS feed.

Why Delay Feed in WordPress?

Sometimes you may end up with a grammar or spelling mistake in your article. The mistake goes live and is distributed to your RSS feed subscribers. If you have email subscriptions on your WordPress blog, then those subscribers will get it as well.

Spelling mistakes go live to your RSS feed subscribers

By adding a delay between your RSS feed and your live site, you get a little time window to catch an error on a live site and fix it.

RSS feeds are also used by content scraping websites. They use it to monitor your content and copy your posts as soon as they appear live.

If you have a new website with little authority, then a lot of times these content scrapers may end up beating you in the search results.

Content scrapers use RSS feeds to auto-publish your posts

By delaying an article in the feed, you can give search engines enough time to crawl and index your content first.

Having said that, let’s see how to easily delay posts from appearing in WordPress RSS feed.

Delaying Posts in WordPress RSS Feed

This method requires you to add little code into WordPress. If this is your first time adding code manually, then take a look at our beginner’s guide on pasting snippets from web into WordPress.

You need to add the following code to your theme’s functions.php file or in a site-specific plugin.

 function publish_later_on_feed($where) { global $wpdb; if ( is_feed() ) { // timestamp in WP-format $now = gmdate('Y-m-d H:i:s'); // value for wait; + device $wait = '10'; // integer // http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_timestampdiff $device = 'MINUTE'; //MINUTE, HOUR, DAY, WEEK, MONTH, YEAR // add SQL-sytax to default $where $where .= " AND TIMESTAMPDIFF($device, $wpdb->posts.post_date_gmt, '$now') > $wait "; } return $where; } add_filter('posts_where', 'publish_later_on_feed'); 

This code checks to see if a WordPress feed is requested. After that it sets the current time and the time you want to add as delay between post’s original date and the current time.

After that it adds the timestamp difference as the WHERE clause to the original query. The original query will now only return the posts where timestamp difference is greater than the wait time.

In this code we have used 10 minutes as $wait or delay time. Feel free to change that into any number of minutes you want. For example, 60 for 1 hour or 120 for two hours.

We hope this article helped you learn how to easily delay posts from appearing in WordPress RSS feed. You may also want to see our guide on how to show content only to RSS subscribers in WordPress.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

I Contributed To An Open-Source Editor, And So Can You

I Contributed To An Open-Source Editor, And So Can You

A few months ago, Jason Grigsby’s post about autocompletion in forms1 made the rounds. I loved the idea of allowing users to fill in their credit card details by taking a picture of their card. What I didn’t love was learning all of the possible values for autofill by heart2. I’m getting lazy in my old age.

Lately, I’ve gotten spoiled from using an editor that does intelligent autocompletion for me, something that in the past only massive complex IDEs offered. Opening my editor of choice, I created an input element and added an autocomplete attribute, only to find that the code completion offered me the state of on or off. Disappointing.

What I wanted was the following:

All possible values for autocomplete offered by this editor

The great thing about our development environments these days is that we build the tools we use in the technologies that we use them to write. Yes, this sounds confusing — we’ve reached code Inception. Node.js3 allows us to run JavaScript on the back end, and with Electron4 we can create installable applications for all platforms using HTML, CSS and JavaScript.

Atom5 was the first editor to use this technology and to allow for contributions by being open source, closely followed by Microsoft’s Visual Studio Code6.

Almost all of the other editors in use allow us to write extensions, plugins or snippet collections in various formats. I deliberately didn’t want to write a plugin or extension, but rather wanted to add this functionality to the core of the editor. Plugins, extensions and snippets have their merits; for example, they are easy to update. The problem is that they need to be found and installed per user. I considered autocompletion too important and wanted to hack the editor itself instead.

Both Atom and Visual Studio Code are available on GitHub and come with instructions on how to extend them. The challenge is that this can feel daunting. I’m here today to show you that it isn’t as tough as you might think. Visual Studio Code is my current editor, and it features amazing autocompletion. That’s what I wanted to tackle.

Extensible and customizable tools are nothing new. Most of what we use can be extended in one way or another, whether in the form of add-ons, plugins or specialist languages. The first editor I used in anger was Allaire and Macromedia’s HomeSite7, which had funky languages like VTML8, WIZML9 and JScript, the Windows version of JavaScript at the time. I wrote a lot of extensions and toolbars for that editor, which very much boosted the productivity of my company back then.

Thankfully, these days, companies understand that offering specialist languages is time wasted, when the web stack has grown to become much more interesting to build applications with.

If you download Visual Studio Code now, you will see that my autocomplete feature is a part of it. And here is how I did that.

1. Complain Link

My first step was to go to Visual Studio Code’s GitHub repository10 and file an issue11 requesting this feature for the editor. This could also be your final step if you don’t want to do it yourself. Someone else who is looking for something to do for the project might find your complaint and tackle it for you. In my case, I wanted to find out more.

2. Fork The Code Link

Instead of just filing an issue, I went to the GitHub repository and forked the code. I used my personal account for this. You don’t need to be affiliated with Microsoft or get added to a special group. The repository is public and open. Everybody is welcome. There is even a code of conduct for contributions12, which means that people should be playing nice. I downloaded the code to my hard drive and followed the instructions on how to build the editor locally.

3. Get The Development Workflow In Place Link

Visual Studio Code is written in Node.js and TypeScript. The development flow starts with a script provided by the team, which gives me a development version of Visual Studio Code running next to the one I am using. A script running on the command line ensures that my changes are captured and that every time I save my code, the development version of the editor restarts and I can test the changes. All of this is nicely documented, from building and running the code from source13 to setting up the development workflow14. And it is independent of platform — you get instructions for Windows, Linux and Mac OS X.

You can see what this looks like on my computer in the following screenshot. The large-view editor (1) is the one I use to code the other; the one on the right (3) is the development edition; and on the bottom (2) is the script creating the new version of the development edition. Writing an editor in an editor does feel odd, but you get used to it.

Figure 215
(View large version16)

Don’t get discouraged if all of this doesn’t work for you on the first go. I hit a few snags and had to turn to Google and StackOverflow for solutions. The Node.js community was very helpful.

4. Write The Functionality Link

Next, I was ready to go all in and use TypeScript to write some clever code. I understood that this is where a lot of people throw in the towel, considering it too tough to continue.

My biggest issue was that I had no idea where to begin with this functionality. So, I did what we all do: I did a full text search for autocomplete in the whole project. Using this highly scientific approach, I found an htmlTags.ts file17 full of tag definitions and arrays of attribute values. I looked up the input element and found this:

input: new HTMLTagSpecification( nls.localize('tags.input', 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.'), ['accept', 'alt', 'autocomplete:o', 'autofocus:v', 'checked:v', 'dirname', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'height', 'inputmode:im', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple:v', 'name', 'pattern', 'placeholder', 'readonly:v', 'required:v', 'size', 'src', 'step', 'type:t', 'value', 'width']), 

That autocomplete:o looked interesting, so I checked where o is defined. Here’s what I found:

var valueSets: IValueSets = { … o: ['on', 'off'], … } 

That looked like what was happening when I added an autocomplete attribute. To change that, I went to the standard definition of possible autocomplete values18 and copied them.

I created a new value set named inputautocomplete and pasted in the values:

var valueSets: IValueSets = { … inputautocomplete: ['additional-name', 'address-level1', 'address-level2', 'address-level3', 'address-level4', 'address-line1', 'address-line2', 'address-line3', 'bday', 'bday-year', 'bday-day', 'bday-month', 'billing', 'cc-additional-name', 'cc-csc', 'cc-exp', 'cc-exp-month', 'cc-exp-year', 'cc-family-name', 'cc-given-name', 'cc-name', 'cc-number', 'cc-type', 'country', 'country-name', 'current-password', 'email', 'family-name', 'fax', 'given-name', 'home', 'honorific-prefix', 'honorific-suffix', 'impp', 'language', 'mobile', 'name', 'new-password', 'nickname', 'organization', 'organization-title', 'pager', 'photo', 'postal-code', 'sex', 'shipping', 'street-address', 't].sort()el-area-code', 'tel', 'tel-country-code', 'tel-extension', 'tel-local', 'tel-local-prefix', 'tel-local-suffix', 'tel-national', 'transaction-amount', 'transaction-currency', 'url', 'username', 'work'], … } 

I then went to all of the definitions of elements that support autocomplete and replaced the o with my own inputautocomplete:

input: new HTMLTagSpecification( nls.localize('tags.input', 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.'), ['accept', 'alt', 'autocomplete:inputautocomplete' … ]), 

I saved my changes; the script rebuilt the editor; I tried the development version of the editor; and autocomplete worked the way I wanted it to.

5. Send A Pull Request Link

That was that. I committed my changes to Git (inside Visual Studio Code19), went to GitHub and added a pull request. A few days later, I got a comment saying that my pull request went through and that what I did would be part of the next build.

6. Be Baffled Link

Frankly, I didn’t think this was amazing enough to warrant a change to the core of the editor. I just wanted to play around. Many of you might think the same about the work you do. And that’s the thing: We’re wrong. Contributing to open-source projects doesn’t require you to be an amazing developer. Nor does it require you to be famous or part of the in-crowd. Sometimes all you need to do is look at something, analyze it and find a way to improve it.

It is up to us to make the tools we use better. If you see a way to contribute to an open-source project, don’t be shy. You might be the one who comes up with an idea so obvious and so simple that others have overlooked it. You might be the one who makes something more usable or nicer to look at. We all have skills to contribute. Let’s do more of that.

(al)

Footnotes Link

  1. 1 https://cloudfour.com/thinks/autofill-what-web-devs-should-know-but-dont/
  2. 2 https://html.spec.whatwg.org/multipage/forms.html#autofill
  3. 3 https://nodejs.org/en/
  4. 4 http://electron.atom.io/
  5. 5 https://atom.io/
  6. 6 http://code.visualstudio.com/
  7. 7 https://en.wikipedia.org/wiki/Macromedia_HomeSite
  8. 8 https://en.wikipedia.org/wiki/VTML
  9. 9 http://www.ulitzer.com/node/41695
  10. 10 https://github.com/Microsoft/vscode/
  11. 11 https://github.com/Microsoft/vscode/issues/7142
  12. 12 https://opensource.microsoft.com/codeofconduct/
  13. 13 https://github.com/Microsoft/vscode/wiki/How-to-Contribute#build-and-run-from-source
  14. 14 https://github.com/Microsoft/vscode/wiki/How-to-Contribute#development-workflow
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/08/editor-large-preview-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/08/editor-large-preview-opt.png
  17. 17 https://github.com/Microsoft/vscode/blob/master/src/vs/languages/html/common/htmlTags.ts
  18. 18 https://html.spec.whatwg.org/multipage/forms.html#autofill
  19. 19 https://code.visualstudio.com/docs/editor/versioncontrol
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

How to Change the Author of a Post in WordPress

Do you want to change the author of a post in WordPress? Sometimes you may need to display a different author, then the person who added the post in WordPress. You do not need to copy and paste the entire WordPress post with a different user account. In this article, we will show you how to easily change the author of a post in WordPress with just a few clicks.

Before You Change The Author of a Post in WordPress

If you just want to show your own name on a post written by some other user on your WordPress site, then you are ready to follow the instructions in this article.

On the other hand, if you want to show a different user as author, then first you need to make sure that this user exists on your WordPress site. See our guide on how to add new users and authors in WordPress for detailed instructions.

You can see and manage all users on your WordPress site by visiting the Users page when logged in with your WordPress administrator account.

Managing users in WordPress

If you just want to change the way your name is displayed, then check out our guide on how to add or change your full name in WordPress.

Having said that, let’s see how to quickly and easily change the author of a post in WordPress.

Changing Author of a WordPress Post

First you need to edit the post or page where you want to change the author name. On the post edit screen, you need to click on the Screen Options menu at the top right corner of the screen.

Screen Options button

This will show a flydown menu on the screen with a bunch of options. You need to check the box next to ‘Author’ option.

Enable author box on posts screen

After that, you need to scroll down on the post edit screen just below the post editor. You will see the Author box there.

Simply click on the drop down menu and select a different author.

Select an author for the post

Don’t forget to click on the Save Draft or Update button to save your changes.

Save your changes by clicking on update or save draft button

That’s all, you have successfully changed the author of a post in WordPress.

Quickly Change Author for Multiple Posts in WordPress

Changing author by editing a post is easy. However, if you have to do this for multiple posts, then it would take quite a lot of time to do that.

There is an easier way to quickly change author for multiple WordPress posts at once. To bulk update authors, click on the Posts menu from your WordPress admin bar. This will list all the posts on your WordPress site.

By default, WordPress shows 20 posts per page. If you want to display more posts, then you need to click on the Screen Options and change the number of posts you want to display.

Show more posts in admin area

Now you need to select the posts where you want to change the author. After selecting posts, select ‘Edit’ from ‘Bulk Actions’ dropdown menu and then click the ‘Apply Button’.

Bulk edit posts in WordPress

WordPress will now show you Bulk Edit metabox. You need to select the new author by clicking on the dropdown menu next to Author option.

Bulk edit author for multiple posts in WordPress

Don’t forget to click on the ‘Update’ button to store your changes.

That’s all, you have successfully changed the author for multiple WordPress posts without editing them individually.

We hope this article helped you learn how to change the author of a post in WordPress. You may also want to see our comparison of the best WordPress backup plugins.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.