Collective #550

Inspirational Website of the Week: Déplacé Maison A refreshing design with lots of character and perfect details. Our pick this week. Check it out Where to put buttons on forms Button placement can make or break a form. Find out the Read more

Improve Your JavaScript Knowledge By Reading Source Code

dreamt up by webguru in Uncategorized | Comments Off on Improve Your JavaScript Knowledge By Reading Source Code

Improve Your JavaScript Knowledge By Reading Source Code

Improve Your JavaScript Knowledge By Reading Source Code

Carl Mungazi



Do you remember the first time you dug deep into the source code of a library or framework you use frequently? For me, that moment came during my first job as a frontend developer three years ago.

We had just finished rewriting an internal legacy framework we used to create e-learning courses. At the beginning of the rewrite, we had spent time investigating a number of different solutions including Mithril, Inferno, Angular, React, Aurelia, Vue, and Polymer. As I was very much a beginner (I had just switched from journalism to web development), I remember feeling intimidated by the complexity of each framework and not understanding how each one worked.

My understanding grew when I began investigating our chosen framework, Mithril, in greater depth. Since then, my knowledge of JavaScript — and programming in general — has been greatly helped by the hours I have spent digging deep into the guts of the libraries I use daily either at work or in my own projects. In this post, I will share some of the ways you can take your favorite library or framework and use it as an educational tool.

The source code for Mithril’s hyperscript function

My first introduction to reading code was via Mithril’s hyperscript function. (Large preview)

The Benefits Of Reading Source Code

One of the major benefits of reading source code is the number of things you can learn. When I first looked into Mithril’s codebase, I had a vague idea of what the virtual DOM was. When I finished, I came away with the knowledge that the virtual DOM is a technique which involves creating a tree of objects that describe what your user interface should look like. That tree is then turned into DOM elements using DOM APIs such as document.createElement. Updates are performed by creating a new tree describing the future state of the user interface and then comparing it with objects from the old tree.

I had read about all of this in various articles and tutorials, and whilst it was helpful, being able to observe it at work in the context of an application we had shipped was very illuminating for me. It also taught me which questions to ask when comparing different frameworks. Instead of looking at GitHub stars, for example, I now knew to ask questions such as, “How does the way each framework performs updates affect performance and the user experience?”

Another benefit is an increase in your appreciation and understanding of good application architecture. Whilst most open-source projects generally follow the same structure with their repositories, each of them contains differences. Mithril’s structure is pretty flat and if you are familiar with its API, you can make educated guesses about the code in folders such as render, router and request. On the other hand, React’s structure reflects its new architecture. The maintainers have separated the module responsible for UI updates (react-reconciler) from the module responsible for rendering DOM elements (react-dom).

One of the benefits of this is that it is now easier for developers to write their own custom renderers by hooking into the react-reconciler package. Parcel, a module bundler I have been studying recently, also has a packages folder like React. The key module is named parcel-bundler and it contains the code responsible for creating bundles, spinning up the hot module server and the command-line tool.

The section of the JavaScript specification which explains how Object.prototype.toString works

It will not be long before the source code you are reading leads you to the JavaScript specification. (Large preview)

Yet another benefit — which came as a welcome surprise to me — is you become more comfortable reading the official JavaScript specification which defines how the language works. The first time I read the spec was when I was investigating the difference between throw Error and throw new Error (spoiler alert — there is none). I looked into this because I noticed that Mithril used throw Error in the implementation of its m function and I wondered if there was a benefit to using it over throw new Error. Since then, I have also learnt that the logical operators && and || do not necessarily return booleans, found the rules which govern how the == equality operator coerces values and the reason Object.prototype.toString.call({}) returns '[object Object]'.

Techniques For Reading Source Code

There are many ways of approaching source code. I have found the easiest way to start is by selecting a method from your chosen library and documenting what happens when you call it. Do not document every single step but try to identify its overall flow and structure.

I did this recently with ReactDOM.render and consequently learned a lot about React Fiber and some of the reasons behind its implementation. Thankfully, as React is a popular framework, I came across a lot of articles written by other developers on the same issue and this sped up the process.

This deep dive also introduced me to the concepts of co-operative scheduling, the window.requestIdleCallback method and a real world example of linked lists (React handles updates by putting them in a queue which is a linked list of prioritised updates). When doing this, it is advisable to create a very basic application using the library. This makes it easier when debugging because you do not have to deal with the stack traces caused by other libraries.

If I am not doing an in-depth review, I will open up the /node_modules folder in a project I am working on or I will go to the GitHub repository. This usually happens when I come across a bug or interesting feature. When reading code on GitHub, make sure you are reading from the latest version. You can view the code from commits with the latest version tag by clicking the button used to change branches and select “tags”. Libraries and frameworks are forever undergoing changes so you do not want to learn about something which may be dropped in the next version.

Another less involved way of reading source code is what I like to call the ‘cursory glance’ method. Early on when I started reading code, I installed express.js, opened its /node_modules folder and went through its dependencies. If the README did not provide me with a satisfactory explanation, I read the source. Doing this led me to these interesting findings:

  • Express depends on two modules which both merge objects but do so in very different ways. merge-descriptors only adds properties directly found directly on the source object and it also merges non-enumerable properties whilst utils-merge only iterates over an object’s enumerable properties as well as those found in its prototype chain. merge-descriptors uses Object.getOwnPropertyNames() and Object.getOwnPropertyDescriptor() whilst utils-merge uses for..in;
  • The setprototypeof module provides a cross platform way of setting the prototype of an instantiated object;
  • escape-html is a 78-line module for escaping a string of content so it can be interpolated in HTML content.

Whilst the findings are not likely to be useful immediately, having a general understanding of the dependencies used by your library or framework is useful.

When it comes to debugging front-end code, your browser’s debugging tools are your best friend. Among other things, they allow you to stop the program at any time and inspect its state, skip a function’s execution or step into or out of it. Sometimes this will not be immediately possible because the code has been minified. I tend to unminify it and copy the unminified code into the relevant file in the /node_modules folder.

The source code for the ReactDOM.render function

Approach debugging as you would any other application. Form a hypothesis and then test it. (Large preview)

Case Study: Redux’s Connect Function

React-Redux is a library used to manage the state of React applications. When dealing with popular libraries such as these, I start by searching for articles that have been written about its implementation. In doing so for this case study, I came across this article. This is another good thing about reading source code. The research phase usually leads you to informative articles such as this which only improve your own thinking and understanding.

connect is a React-Redux function which connects React components to an application’s Redux store. How? Well, according to the docs, it does the following:

“…returns a new, connected component class that wraps the component you passed in.”

After reading this, I would ask the following questions:

  • Do I know any patterns or concepts in which functions take an input and then return that same input wrapped with additional functionality?
  • If I know of any such patterns, how would I implement this based on the explanation given in the docs?

Usually, the next step would be to create a very basic example app which uses connect. However, on this occasion I opted to use the new React app we are building at Limejump because I wanted to understand connect within the context of an application which will eventually be going into a production environment.

The component I am focusing on looks like this:

class MarketContainer extends Component {
 // code omitted for brevity
}

const mapDispatchToProps = dispatch => {
 return {
   updateSummary: (summary, start, today) => dispatch(updateSummary(summary, start, today))
 }
}

export default connect(null, mapDispatchToProps)(MarketContainer);

It is a container component which wraps four smaller connected components. One of the first things you come across in the file which exports connect method is this comment: connect is a facade over connectAdvanced. Without going far we have our first learning moment: an opportunity to observe the facade design pattern in action. At the end of the file we see that connect exports an invocation of a function called createConnect. Its parameters are a bunch of default values which have been destructured like this:

export function createConnect({
 connectHOC = connectAdvanced,
 mapStateToPropsFactories = defaultMapStateToPropsFactories,
 mapDispatchToPropsFactories = defaultMapDispatchToPropsFactories,
 mergePropsFactories = defaultMergePropsFactories,
 selectorFactory = defaultSelectorFactory
} = {})

Again, we come across another learning moment: exporting invoked functions and destructuring default function arguments. The destructuring part is a learning moment because had the code been written like this:

export function createConnect({
 connectHOC = connectAdvanced,
 mapStateToPropsFactories = defaultMapStateToPropsFactories,
 mapDispatchToPropsFactories = defaultMapDispatchToPropsFactories,
 mergePropsFactories = defaultMergePropsFactories,
 selectorFactory = defaultSelectorFactory
})

It would have resulted in this error Uncaught TypeError: Cannot destructure property 'connectHOC' of 'undefined' or 'null'. This is because the function has no default argument to fall back on.

Note: For more on this, you can read David Walsh’s article. Some learning moments may seem trivial, depending on your knowledge of the language, and so it might be better to focus on things you have not seen before or need to learn more about.

createConnect itself does nothing in its function body. It returns a function called connect, the one I used here:

export default connect(null, mapDispatchToProps)(MarketContainer)

It takes four arguments, all optional, and the first three arguments each go through a match function which helps define their behaviour according to whether the arguments are present and their value type. Now, because the second argument provided to match is one of three functions imported into connect, I have to decide which thread to follow.

There are learning moments with the proxy function used to wrap the first argument to connect if those arguments are functions, the isPlainObject utility used to check for plain objects or the warning module which reveals how you can set your debugger to break on all exceptions. After the match functions, we come to connectHOC, the function which takes our React component and connects it to Redux. It is another function invocation which returns wrapWithConnect, the function which actually handles connecting the component to the store.

Looking at connectHOC’s implementation, I can appreciate why it needs connect to hide its implementation details. It is the heart of React-Redux and contains logic which does not need to be exposed via connect. Even though I will end the deep dive here, had I continued, this would have been the perfect time to consult the reference material I found earlier as it contains an incredibly detailed explanation of the codebase.

Summary

Reading source code is difficult at first but as with anything, it becomes easier with time. The goal is not to understand everything but to come away with a different perspective and new knowledge. The key is to be deliberate about the entire process and intensely curious about everything.

For example, I found the isPlainObject function interesting because it uses this if (typeof obj !== 'object' || obj === null) return false to make sure the given argument is a plain object. When I first read its implementation, I wondered why it did not use Object.prototype.toString.call(opts) !== '[object Object]', which is less code and distinguishes between objects and object sub types such as the Date object. However, reading the next line revealed that in the extremely unlikely event that a developer using connect returns a Date object, for example, this will be handled by the Object.getPrototypeOf(obj) === null check.

Another bit of intrigue in isPlainObject is this code:

while (Object.getPrototypeOf(baseProto) !== null) {
 baseProto = Object.getPrototypeOf(baseProto)
}

Some Google searching led me to this StackOverflow thread and the Redux issue explaining how that code handles cases such as checking against objects which originate from an iFrame.

Useful Links On Reading Source Code

Smashing Editorial
(dm, yk, il)

Source: Smashing Magazine, Improve Your JavaScript Knowledge By Reading Source Code

Collective #531

dreamt up by webguru in Uncategorized | Comments Off on Collective #531


C531_listcss

CSS Lists, Markers, And Counters

In this article, Rachel Andrew starts by looking at lists in CSS, and moves onto some interesting features defined in the CSS Lists specification — markers and counters.

Read it


C531_DIVI

Our Sponsor

Divi: Custom CSS Control

Divi is a revolutionary WordPress theme and visual page builder for WordPress. Developers can easily combine Divi’s visual design controls with their own custom CSS. Divi’s interface is simple yet not limiting.

Try it for free


C531_trombone

Popup Trombone

A really awesome experiment by Matthew Rayfield where you can play a trombone by resizing the browser window.

Check it out







C531_texel

Texel

A proof-of-concept generative design toolkit made by Matt DesLauriers.

Check it out









C531_SEOmyth

SEO Mythbusting

A Google Webmasters video series hosted by Martin Splitt with the aim to clarify common misconceptions around technical SEO.

Watch it






Collective #531 was written by Pedro Botelho and published on Codrops.


Source: Codrops, Collective #531

That Was SmashingConf Toronto 2019

dreamt up by webguru in Uncategorized | Comments Off on That Was SmashingConf Toronto 2019

That Was SmashingConf Toronto 2019

That Was SmashingConf Toronto 2019

Rachel Andrew



We all enjoyed returning to Toronto for the second Smashing conference, and in this post, I am sharing some of the things that took place as well as the resources that were shared over the course of the two conference and two workshop days. Look out for the videos of all the presentations which will be released very soon.

The team worked hard to create a friendly welcoming space for everyone at the conference. We all know how it can be a little overwhelming to walk into a room of a few hundred strangers, knowing that you would love to make friends and have interesting discussions, but finding it hard to get started.

In order to avoid that, we asked everyone to read and follow our Code Of Conduct, try to create a range of spaces and activities where people can meet like-minded people, and also encourage everyone to follow “The Pac-Man Rule” when standing in a group.

Slide showing a graphic of the pacman rule

Pac-man rule for conversations (Large preview)

https://platform.twitter.com/widgets.js

“It’s a genuine friendliness that the Smashing team possesses, and that serves as the foundation for an inclusive, approachable event. It turns out that little things like launching balloons to kick off the event and advocating for the Pac-Man Rule go a long way towards making everyone feel welcome.”

Dan Rose

The Presentations

The first thing you think about when attending a conference is to wonder who is speaking, and what they will be talking about. At SmashingConf Toronto, we had an amazing lineup of speakers, with people you might know quite well plus some new faces. As many of our speakers presented without slides, we don’t have a huge number of slide decks to share. However, the list below links to some of the resources our speakers shared. We will also have videos available very soon!

Stage with people throwing candy into the audience

Vitaly and Phil throw candy to audience members (Photo credit: Marc Thiele)

Day One

The Day One Collaborative Doc created by attendees is full of takeaways from day one of the conference.

https://platform.twitter.com/widgets.js

Speaker Name Talk Title
Brad Frost Let’s Build a Design System
Sarah Drasner Let’s Write a Vue App From Scratch
Phil Hawksworth JAMStack: Silly Name. Serious Stuff.
Chris Gannon Make It Move! Create a Web Animation From Scratch
Kristina Podnar Help! I’m Your Ailing Website. The Digital Policy & Standards Rehab Hour
Steven Hoober Authentic Digital Design By The Numbers

Sarah onstage coding

Sarah Drasner writes a Vue app on stage. (Photo credit: Marc Thiele)

Day Two

Check out the Day Two Collaborative Doc for more resources and thoughts from our attendees and speakers.

Our mystery speaker was Seb Lester, and many of you were thrilled to get to hear his talk.

https://platform.twitter.com/widgets.js

We then enjoyed talks covering a wide range of topics from our day two speakers.

Speaker Name Talk Title
Phil Nash Diving Into Service Workers, Live
Jules Forrest For The Love Of The Grid
Dan Rose Seeing The Pages For The Components
Diana Mounter The Secret Lives of Color Systems
Scott Jehl Move Fast & Don’t Break Things

We found a few blog posts sharing takeaways from these talks. Arshabhi Rai recapped Day 1 and Day 2; and kinopo shared their takeaways in What a lovely SmashingConf.

Workshops

Auditorium style lecture room with people working on laptops

Vitaly shares responsive design knowledge with his workshop group (Photo credit: Marc Thiele)

Our workshops are a big part of each of our Smashing conferences. In Toronto, we had two days of full-day workshops, with some attendees choosing to do a workshop day before and after the conference. Workshops this time round were as follows:

Name Talk Title
Rachel Andrew Next Steps With CSS Layout
Chris Gannon Designing Delightful Animations For The Web
The Deque Team How To Translate Wireframes Into Accessible HTML/CSS
Vitaly Friedman Smart Responsive UX Design Patterns
Scott Jehl Lightning Fast Web Performance
Sarah Drasner Intro To Vue.js
Brad Frost The Design System Process
Vitaly Friedman New Front-end Adventures, 2019 Edition
Cloudinary Hacking Lizard Brain: Improving Visual Experience On The Web

https://platform.twitter.com/widgets.js

Side Activities

A conference isn’t just about the talks and speakers. We want to make spaces where attendees and speakers can learn from each other and share experiences in a more informal setting. To help with that, we ran various other things over the conference. At lunchtime, we had lunch sessions run by Deque on Day 1, and Netlify on Day 2, attendees could grab a plate of lunch and settle down in a more cozy environment to take part in those sessions.

https://platform.twitter.com/widgets.js

We had a great lounge area, with the talks live-streamed for folks who wanted to step out of the movie theater for a while.

People on sofas watching a presentation via a live stream

Our lounge area (Photo credit: Marc Thiele)

Morning Run

If you follow me on Twitter, you’ll know that I’m a keen runner, and it’s always nice to have some company on an early morning run. For a few conferences now, we’ve been organizing pre-conference runs — Toronto was no exception. We had 12 runners on Day 1, and 6 hardy souls on Day 2 joining us despite having attended the party. We only got slightly off-track once, and got a nice view of Toronto to take our photos.

https://platform.twitter.com/widgets.js

Jam Session

https://platform.twitter.com/widgets.js

On the evening before the conference, we had a Jam Session at Shopify hosted by Tiffany Tse (and her lovely assistant Walnut). There was a speaker panel featuring Steven Hoober, Scott Jehl, Kristina Podnar, Brad Frost, Jules Forrest, Phil Hawksworth and myself, plus lightning talks from Tiffany Tse, Kelly Harrop, April Ellsey, Steve Pereira, and Christine Fowler.

Graffiti And Photo Walks

On the day before and last evening of the conference, walks took place to explore graffiti around Toronto and take photos of the city. A great way to meet people and explore the location for those coming from out of town.

People in a street taking photos of graffiti

On the graffiti walk (Photo credit: Scott Whitehead)

Conference Party

There has to be a party, and we always try to do something fun and perhaps a little unusual for our conference parties. This time, we went bowling — courtesy of sponsorship by SpeedCurve.

Focus On The Local Community

Between sessions on stage, we invited organizers of community groups in the Toronto area on stage to share information about their groups. We hope that local attendess found some new meetups to go to. The groups that we featured were:

Name Details
Women Who Code Toronto Twitter: @WomenWhoCode,
Introduced by Stephanie
DevHub Toronto & Vancouver Twitter: @devhubTO
Events, educational programs, collaboration, and co-working
Introduced by Emma
The DevOps Toronto meetup Twitter: @devopsto
Introduced by Steve
Designers & Coffee Twitter: @Doriganic
Meetups, hands-on design challenges and feedback sessions, to casual networking nights.
Introduced by Dorsa
DevTO Twitter: @DevTO
Coding stories, eats and drinks. Join us on the last Monday of every month!
Introduced by Nael.
Serverless Toronto meetup Introduced by Daniel Zivkovic
Toronto Web Performance Group Twitter: @towebperf
Introduced by Henri Helvetica

Want To Join In The Fun?

We packed a lot into those few days! If you were there, we hope that you enjoyed it as much as we did. It was great to meet so many of you.

Audience members throwing balloons

SmashingConf Toronto opened with balloons (Photo credit: Marc Thiele)

If you would like to be part of the SmashingConf fun next year, we already have tickets on sale for SmashingConf San Francisco and you can leave your email to be the first to know when SmashingConf Toronto 2020 goes on sale. The rest of the 2019 events (New York and Freiburg) are already sold out! There are a few workshop-only tickets available for New York 2019, but be quick!

Smashing Editorial
(il)

Source: Smashing Magazine, That Was SmashingConf Toronto 2019

Inspired Design Decisions: Pressing Matters

dreamt up by webguru in Uncategorized | Comments Off on Inspired Design Decisions: Pressing Matters

Inspired Design Decisions: Pressing Matters

Inspired Design Decisions: Pressing Matters

Andrew Clarke



As I’d always been at the top of my class during high school, I headed to art college full of confidence that one day I’d be an accomplished painter. This over-confidence didn’t last long though, because when I arrived, I found myself surrounded by conceptual artists, filmmakers, painters, performance artists, printmakers, and sculptors, who all seemed much more talented than I was.

This was especially true of my friend Ben, a gifted painter who went to his studio late every night to work on several large canvases. Ben’s paintings had incredible depth because he built up hundreds of subtle layers of paint over several months.

I didn’t have any of Ben’s patience. I needed to see results quickly, so my paintings were anything but deep or subtle. Compared to Ben’s, mine looked like paintings by numbers. It didn’t take me long to realise that painting just wasn’t the right medium for me.

Luckily, the course I’d chosen wasn’t structured, and it didn’t have a formal curriculum. This allowed students free movement between disciplines, so I moved from the painting studio to printmaking and spent the next few years happily making prints.

I found the printmaking process incredibly satisfying. I loved making prints from linocuts, and in much the same way that I’m often entirely absorbed by writing code today, I regularly lost myself carving thousands of tiny marks until the floor was covered in sharp shards of lino.

Printmaking and writing code have plenty in common. Both can quickly transform a blank canvas into finished work, without waiting weeks watching paint dry. Both benefit from regular iteration and testing. In fact, there’s very little difference—except inky hands — between running a test print and refreshing a browser window.

Pressing Matters magazine cover

Pressing Matters magazine. (Large preview)

I haven’t cut lino for thirty years, but I still appreciate the art of printmaking. On a recent trip to London, I popped into Magma and picked up a copy of Pressing Matters. It’s an independently published magazine which “hones in on the people, passion and processes behind the art form of printmaking.” Its publishers hope to inspire newcomers to printmaking, but as I thumbed through its pages, I found there is plenty about the design of Pressing Matters which can inspire web designers too.

Andy Clarke
May 2019

Andy Clarke reading Pressing Matters magazine

Pressing Matters has a distinctive, but simple style. (Large preview)

Pressing Matters: The Passion And Process Behind Printmaking

I may not have made any prints for thirty years, but I’m still fascinated by the process of printmaking as much as I appreciate the end results. Picking up a copy of Pressing Matters (pressingmattersmag.com) on a recent trip to my favourite magazine shop and flicking through its pages, I was immediately transported back to art school where my fingers were almost always covered in cuts from lino cutting tools, and I smelled like ink and turpentine.

Pressing Matters has a distinctive, but simple style. It uses a limited palette and often connects the colour of headlines and other typographic elements with colours found in nearby photographs and prints. The result is a design which feels connected.

Pressing Matters magazine spread

© Pressing Matters Magazine. (Large preview)

Pressing Matters’ Creative Director John Coe uses layout patterns which produce a rhythm which flows throughout the magazine. Differently sized modules speed you past pages packed with prints, then the pace slows to allow you to linger on larger artwork reproductions. These layouts frame the magazine’s content perfectly, and while they’re original, they’re also discreet enough not to detract from the subject matter.

What struck me about Pressing Matters initially was how the magazine includes a variety of layout styles but allowed for various types of content, but still maintains a high degree of consistency throughout.

Pressing Matters magazine spread

© Pressing Matters Magazine. (Large preview)

When I looked closer at how its pages were constructed, I discovered a layered compound grid comprised of two and three columns running through the magazine. Using a compound grid makes perfect sense for a magazine devoted to printmaking, which itself often involves multiple layers of ink to form something deeper and richer than can be achieved with a single layer.


You might think that a complex grid could stifle creativity and would result in designs which look stiff, but in Pressing Matters, the compound grid feels fluid and full of energy.

Pressing Matters magazine spread

© Pressing Matters Magazine. (Large preview)

While many of Pressing Matters’ pages rely on symmetrical two or three- column layouts, it’s when the two and three-column grids are combined that the magazine really comes to life.

Not only is this grid adaptable to accommodate various types of content, the variety of possible layout permutations also allow for changes in visual pacing throughout the magazine.

I’ll teach you all about Karl Gerstner and his mobile grid later in this issue, but just like Gerstner’s iconic work for Capital magazine, Pressing Matters uses large facing images to slow reading down.

Whitespace opens up around running copy to allow for easy reading. Text wraps around the fluid shapes in images. Pages packed with prints are arranged masonry-style. Text split across two columns runs alongside images which are arranged on a three-column grid, and these techniques combine to create an engaging and enjoyable reading experience.

Pressing Matters magazine spread

© Pressing Matters Magazine. (Large preview)

Pressing Matters proves that compound grids can have a profound effect on the experience of reading a magazine. The same layout principles which make Pressing Matters so appealing can also be applied to products and websites, despite them being very different media.

These principles are not new and they have guided art direction and design for decades. They matter just as much on the web as they do in the pages of a glossy magazine. Whether your readers are offline or on, grids are fundamental to their understanding of your stories, and you can use them for more than aligning content.

Next time you’re passing your nearest magazine store, pop in and pick up a copy of Pressing Matters. You won’t get inky fingers, but you will get your hands on inspiration for your next project.

Making Sense Of Compound Grids

Grids have a long and varied history in design, from the earliest books, through movements like constructivism and the International Typographic Style, right up to the present-day popularity of grids in frameworks like Bootstrap and material design.

A generation of product and website designers have grown up with grids from Bootstrap, the 960 Grid System before it, and even the Blueprint framework before that. In frameworks like these — and in plenty of work built on them — grids are used mostly for aligning content to columns.

An unimaginative design based on Bootstrap

I guess you’ve seen those “Which one of these two layouts are you designing today?” tweets, lamenting the current state of design on the web. Does Bootstrap create unimaginative designs? No, people do. (Large preview)

When you use grids imaginatively, they do much, much more than align content. A grid brings cohesion to a composition. It helps people understand the stories you’re telling by suggesting hierarchies. Grids inform people what to read first, then next, and how much attention to give it.

They define the position of valuable information or a call to action. A thoughtfully chosen grid leads to a wealth of possibilities and any number of exciting designs.

The use of grids for web design has improved consistency, legibility, and usability, but using grids included with frameworks including Bootstrap has also led to a generation of homogenous layouts and uninspiring designs.

When I teach design classes, I often ask my students to draw what a grid means to them. Nine out of ten sketches twelve symmetrical columns. Symmetrical multi-column grids have become a staple mainly because twelve columns can be easily divided into halves, thirds, quarters, and eighths. Because they’re so easy to learn, grids like the ones included with Bootstrap have become a staple.

In fact, they’re now so ubiquitous that starting a new design without sketching three or four columns can be incredibly difficult as it involves changing your mental model and the way you think about grids. It’s important to know that symmetrical column-based grids are only one of several options. Compound grids are one of those options but despite the enormous flexibility they offer — something incredibly important for today’s multi-device designs — they’re rarely spoken of with product and website design.

Way back in July 2009, Diogo Terror wrote “Lessons From Swiss Style Graphic Design” for Smashing Magazine which mentions Karl Gerstner and includes many fabulous examples of Swiss Style Graphic Design.

Capital Magazine

In the 1940s and ’50s, designers including Josef Müller-Brockmann made using grids to create consistent and creative layouts one of the defining aspects in what became known as the International Typographic Style or Swiss Design.

Capital Magazine covers

Capital Magazine 1962. (Large preview)

Swiss artist and typographer Karl Gerstner was one of the first designers to exploit the creative flexibility of using grids, and it’s the compound grid which Gerstner designed in 1962 for Capital magazine that has become one of his best-known creations.

Capital Magazine spread

Capital Magazine 1962. (Large preview)

The concept behind Capital was to provide “a human view of economics, an economic view of humanity” and so its content and Gerstner’s design had to be accessible, clear, and engaging. Given the potential variety and unpredictability of Capital’s content, Gerstner also needed a grid which would help him to lay out any content consistently and without restrictions.

Karl Gerstner’s mobile grid

Karl Gerstner’s mobile grid; a compound grid he designed for Capital magazine in 1962. Confused? So was I. (Large preview)

Gerstner designed what he called a “mobile grid,” although it’s not the type of mobile you and I are used to. This grid is the one most likely to be found when searching for compound grids, but it’s also the one most likely to baffle on first look.

The compound grid Gerstner designed for Capital looks incredibly complex when seen as it does above, so to explain how he created it — and how you can use it — I’m going to break Gerstner’s grid down into its constituent parts.

Example based on Karl Gerstner’s mobile grid

(Large preview)

There are 58 columns and rows in Gerstner’s mobile grid, but he started with just one. Content in this single module fills the full width of the page.

Example based on Karl Gerstner’s mobile grid

(Large preview)

Then Gerstner divided his single module into two columns and rows. Using two columns in this way results in a reassuring symmetrical design.

Example based on Karl Gerstner’s mobile grid

(Large preview)

That large module can also be sub-divided into three columns and rows. Have you noticed how the gutters between the divisions in Gerstner’s grid are always the same size?

Example based on Karl Gerstner’s mobile grid

(Large preview)

By splitting the large module into four, these columns of content feel formal, and the overall impression is that this design is a serious one.

Example based on Karl Gerstner’s mobile grid

(Large preview)

When the full-page module is divided into five columns and separated into two spacial zones by a flowline, this design feels more technical. With Gerstner’s mobile grid, you can use each set of columns and rows separately. You can also turn them into a compound grid by either overlaying or stacking them.

Example based on Karl Gerstner’s mobile grid

(Large preview)

Dividing the page into six columns and six rows of modules, enables an incredible variety of layout options. The flexibility of a compound grid comes from the interplay of two or more grids and how that affects the position and size of elements. This often makes a compound layout far more interesting than one grid in isolation.

Say Hello To Compound Grids

A compound grid is two or more grids of any type — column, modular, symmetrical, and asymmetrical — on one page. They can occupy separate areas or overlap.

If you’re still unsure about using modular grids as Karl Gerstner did, you can start by making a compound by overlapping two column grids; one with two columns, the other with three.

It’s the interplay of the two grids which makes this compound layout more interesting than a single grid. The flexibility of a compound grid becomes apparent when I make the grid lines visible.

4+6 compound grid

4+6 compound grid. (Large preview)

If you’re watching closely, you should notice how compound grids will take your design in a different direction than twelve symmetrical columns.

By laying a three-column grid over one with two columns, you create four columns where the outer two are twice the width of those on the inside. I like to think of this as a rhythmic pattern; 2|1|1|2.

Rhythmic patterns

By using any number of equally-sized columns or rows, your layouts form a consistent pattern and an even rhythm which does not change across the page. Think of each column as a beat and tap twelve of them on your desk. It doesn’t sound very inspiring, does it?

Example based on 2+3 compound grid

2+3 compound grid. (Large preview)

Compare that with the rhythm from a 2|1|1|2 pattern and you should understand how using compound grids can change both your mental model and the layouts you create. Using this 2|1|1|2 pattern for my first layout. I place the main body of content — including the headline, standfirst paragraph, and running text, into the first column in my two-column grid. I use a single column from my three-column grid to place supporting information about the Jaguar E-Type series, without question the most beautiful car ever made.

A blueprint image of that astounding automobile crosses the remaining space, creating a visual connection between the two areas of content.

Example based on 2+3 compound grid

2+3 compound grid. (Large preview)

For an altogether different design (above) — one which uses both layout and italic type to suggest the movement and speed of the E-Type — I stagger my standfirst paragraph and running text using grid lines from both the two-column and three-column grids.

Changing the compound formation to combine three-column and four-column grids (3+4) creates an altogether different rhythmic pattern of 3|1|2|2|1|3.

Example based on 3+4 compound grid

3+4 compound grid. (Large preview)

With a compound of two grids (above,) you might use widths from one or the other. Or you could combine widths from both to form columns which don’t conform to either. You can use these new widths to inform the sizes of images and text. While the standfirst paragraph starts on the three-column grid, the running text which follows begins on the four-column grid.

Example based on 3+4 compound grid

3+4 compound grid. (Large preview)

That same combination of grids (above) can make a very different impression by combining columns widths from both grids to inform the width of my column of running text. This column matches the width of my large vertical image to balance both sides of this design.

Example based on 4+5 compound grid

4+5 compound grid. (Large preview)

This time, I set the main block of running text across two columns and derived their widths by combining column units of 4 and 3.

As for those very narrow columns, whose width is only 1 unit, they’re perfect for informing the size of typographic elements including this bold drop cap.

Example based on 4+5 compound grid

4+5 compound grid. (Large preview)

Overlaying four columns with five (above) leads to a highly unusual rhythmic pattern of 6|1|4|3|3|4|1|6.

For this alternative design, I use that same pattern in a different way by running my text over three columns. I use the widths from the five-column grid to inform the width of my supporting information and the image of this E-Type’s curvy rear end.

Example based on 4+6 compound grid

4+6 compound grid. (Large preview)

In this version of the design (above,) a large image shows off the iconic shape of E-Type’s body and fills almost all the width of my page.

A solid block of running text sits directly under the Jaguar’s wheels and derives its width from both the four-column and six-column grids.

My next design (below) literally places the E-Type at the centre of the action and text wraps around it on both sides. Remember, it’s not necessary to fill every grid module with content. By limiting the width of my standfirst paragraph and leaving space elsewhere in the layout empty, I create a dynamic diagonal which adds energy and movement to this design.

Example based on 4+6 compound grid

4+6 compound grid. (Large preview)

Of all the possible grid combinations, the combination of four and six-column grids is the one I use most often in my work. It’s flexible enough to handle many different types of content and makes an incredible variety of compositions possible.

Example based on 4+6 compound grid

Left: The pull quote feels disconnected from the story. Right: The edge of this quote aligns to lines in the six-column grid. (Large preview)

While the overall feeling from this final design feels balanced — largely due to a centred block of running text, the pull quote feels disconnected from the story as it occupies only the width from one column in the six-column grid. I can improve this design by aligning the edge of this quote to lines in the six-column grid, so it feels part of the story.

… (Box)

Setting the pace

Six differently paced layout modules

Magazine designs often use differently sized areas to vary the pace. (Large preview)

Rhythm is an essential factor, not just within the page, but also across the pages of an entire product or website. Compound grids are not only flexible enough to accommodate a wide variety of content types, but they also allow you to vary this visual pacing. Magazine designs often use differently sized areas to vary this pace. Repeating smaller modules speeds up the movement, while larger ones slow it down. People naturally spend longer looking at larger spacial zones, and we can use the same technique at particular moments in someone’s journey to slow them down and make them take notice.

Stacking Grids

You can combine column grids with hierarchical and even modular grids. When pages contain two separate subjects or different types of content, stacking grids can be a great way to make that difference more obvious.

At the top of this next page is a story about the Jaguar E-Type. Underneath there’s an altogether different story about the famous Le Mans 24 hour race. To leave someone in little doubt these stories are separate, use a different grid for each. I base the top story on a four-column grid, the bottom on a six.

4+6 column grids, stacked

4+6 column grids, stacked. (Large preview)

Above, I make the difference between these two stories obvious by placing the second against a grey background. I also use paragraph spacing instead of first-line indentations.

4 columns and a modular grid, stacked

4 columns and a modular grid, stacked. (Large preview)

I make the difference between these two stories obvious by placing the first against a grey background. In the second story I also use bolder type and paragraph spacing instead of indenting the first line.

Karl Gerstner

Karl Gerstner (1930–2017) was a Swiss artist and one of the most influential typographers. He began work when he was only 19, studied under Fritz Büler, and then went on to co-found GGK, one of the most successful Swiss creative agencies of the ’70s.

Books about Gerstner’s work have been out of print for decades, and copies often run to hundreds of Pounds so I wouldn’t be surprised if you haven’t seen his designs first-hand. But, you’ll have seen plenty of other peoples’ work which was inspired by it.

Gerstner made unjustified, ragged-right text famous as up until then, columns of type were usually justified. He also developed the idea of using typefaces and typographic design to create connections between words on a page and their meaning. While this concept might seem obvious to us today, this idea seemed revolutionary in the 1960s.

Karl Gerstner’s probably best known for his iconic work on the quarterly Capital Magazine, starting in 1962. In fact, it’s through my research into Capital, and the compound grid Gerstner created for it that I first became aware of him and his work.

dvertisements for Sinar, by Karl Gerstner

Advertisements for Sinar, by Karl Gerstner. (Large preview)

By a strange coincidence, I recently discovered that Gerstner’s agency also created advertisements for Sinar, the Swiss large format camera maker I worked with during the early 1990s. In these advertisements, the shape of the word “Sinar” resembles the results of using the swing and tilt movements on a large format camera.

Developing Compound Grids

When you first see Karl Gerstner’s mobile grid, you might think compound grids are challenging to implement. Whereas developing compound grid would’ve been a complicated process using traditional methods, today’s layout tools, including CSS Grid, now make it simple.

Designing layouts using compound grids requires a shift in your mental model, and developing them is no different. However, CSS Grid line numbers combined with new flexible length units (fr) will make that shift smoother.

Following the order I used earlier, I’ll start with a compound of two-column and three-column grids (2+3) which has a rhythmic pattern of 2|1|1|2.

Example design

(Large preview)

Translating that pattern into values for grid-template-columns couldn’t be easier, but first I need to apply CSS Grid to the body element of my page, then set a gap between columns which is relative to the width of my viewport. As I don’t want these styles applied at smaller screen sizes, I enclose them within a media query:

@media screen and (min-width : 48em) { 
body {
display: grid;
grid-column-gap: 2vw; }
}

Now, I use fr units to specify the pattern for my compound grid. The result is four columns where the width of the outer columns occupy twice the space of the inner two:

body {
grid-template-columns: 2fr 1fr 1fr 2fr; }

Example design

(Large preview)

A combination of three-column and four-column grids (3+4) will result in six columns and a rhythmic pattern of 3|1|2|2|1|3. My flexible length units will be:

body {
grid-template-columns: 3fr 1fr 2fr 2fr 1fr 3fr; }

Example design

(Large preview)

Finally, combining four-column and six-column grids (4+6) creates eight columns, two of them much narrower than the rest. To create a rhythmic pattern of 2|1|1|2|2|1|1|2 my flexible length units will be:

body {
grid-template-columns: 2fr 1fr 1fr 2fr 2fr 1fr 1fr 2fr; }

With these Grid properties applied, all direct descendants of a grid-container become grid-items, which I can place using areas, line numbers, or names.

The design I’m developing requires only the most basic structural elements to implement it, and my markup looks like this:

<body>
<h1>….</h1> 
<p>…</p>
<img> 
<main>…</main> 
<aside>…</aside>
</body>

I use the eight columns from the 4+6 compound grid above. Here are the styles to implement that:

@media screen and (min-width : 48em) {
body {
display: grid;
grid-template-columns: 2fr 1fr 1fr 2fr 2fr 1fr 1fr 2fr; 
grid-column-gap: 2vw;
grid-row-gap: 2vh; align-content: start; } 
}

The elements above are direct descendants of the body. I place them on the grid by using line numbers. First the headline, the paragraph which immediately follows it, and finally my main element. These elements all start on grid line 4 and end on line 8:

h1, h1 + p, main { 
grid-column: 4 / 8; }

The blueprint image of my beautiful Jaguar E-Type should be wider than other elements in this design, so I place it using different line numbers. It starts at line 2 and extends the full width of my page:

img {
grid-column: 2 / -1; }

Now, I place the aside element which contains my supporting information about the three series of E-Type. As I want this element to align to the bottom of my layout, I add the align-self property with a value of end:

aside { 
grid-column: 1 / 3; 
align-self: end; }

Final example design

(Large preview)

Finally, as I want both main and aside elements to appear next to each other on the same row, I give them identical row number values:

main,
aside { grid-row: 4; }

All that’s left is for me to add some small typographic touches to improve my design. I don’t need a presentational class attribute value to style the paragraph, which immediately follows my headline. I can use an adjacent sibling selector instead:

h1 + p { 
font-weight: 700; }

To style the first line of the first paragraph in my main element, I use a combination of descendant, pseudo-element, and pseudo-class selectors:

main p:first-of-type::first-line { 
font-weight: 700; }

Finally, to indent every following paragraph which is does not immediately follow my headline, I use both a :not() negation pseudo-class selector and two adjacent sibling selectors:

p:not(h1 + p) + p { 
text-indent: 2ch; }

NB: Smashing members have access to a beautifully designed PDF of Andy’s Inspired Design Decisions magazine and full code examples from this article.

Smashing Editorial
(ra, yk, il)

Source: Smashing Magazine, Inspired Design Decisions: Pressing Matters

UX Improvements For Keyboard Accessibility

dreamt up by webguru in Uncategorized | Comments Off on UX Improvements For Keyboard Accessibility

UX Improvements For Keyboard Accessibility

UX Improvements For Keyboard Accessibility

Vitaly Friedman



How can we provide an accessible user experience for keyboard-only and assistive technology users without affecting the experience for any other users? We’ve kindly asked Aaron Pearlman, Principal UX Designer at Deque Systems, to share some practical tools and techniques to ensure that we’re all providing an inclusive and accessible experience for our users.

As a part of our Smashing Membership, we run Smashing TV, a series of live webinars, every week. No fluff — just practical, actionable webinars with a live Q&A, run by well-respected practitioners from the industry. Indeed, the Smashing TV schedule looks pretty dense already, and it’s free for Smashing Members, along with recordings — obviously.

We hope you’ll enjoy the webinar as much as we did!

“UX Optimizations For Keyboard-Only And Assistive Technology Users” with Aaron Pearlman (Watch video on YouTube)

Aaron Pearlman: You should be able to see my screen. Okay, right now, let me just… There we go, very good. Well, hello everybody. Like I said, I am Aaron Pearlman, the Principal User Experience Designer for Deque. And I think— Uh, let me move— Zoom tends to put a bit of UI in the way, so I apologize if I look like I’m frantically moving and mouse hopefully it’s not showing up. And so, today we’re going to talk about the types of optimizations that you can make for Keyboard-Only and Assistive Technology users. As I mentioned a moment ago, these type of optimizations, these type of things aren’t going to preclude anyone else from using your… they’re not going to be unutilized by other people as well. They just tend to be things that are going to be more advantageous to users that dominantly use a system with keyboard Only User Assistive Technology.

Aaron Pearlman: For those who aren’t familiar with what that means, what a Keyboard-Only User Assistive Technology is— a keyboard only user would be somebody who just typically uses your keyboard to traverse a system. So they’re going to be using tab and Shift tab a lot and the arrow keys to traverse your system, so focus is quite important to them. You might find this one individual may have motor skill issues, may have vision deficiencies as well, the keyboard-only users, and then assistive technology users also use a keyboard to traverse your system, they may use other assistive technologies as well such as screen meters like VoiceOver or a braille reader or something like that.

Aaron Pearlman: So, that’s kind of what we’re focusing on — our users of that nature because a good portion of individuals who have disabilities tend to fall into this camp. That doesn’t mean everybody. Certainly, there are a myriad of different disabilities and gradiations in between, but for the purpose of this, this is what we’re going focus on today.

Aaron Pearlman: So, a little bit of an overview of what we’re going to cover: we’re going to talk a little bit of design process with plenty of maybe doing a little bit of an exercise type-of-thing that we might go into, maybe not, before we go to the skip links. And then skip links are going to be one of the features that we’re going to cover, ways to optimize your modal, and how to handle focus. So, these are going to be the three big categories that we’re going to cover and then we’ll have time for questions when we’re all done.

Aaron Pearlman: To start, I thought we could do a little bit of UX design process overview. I was in different workshops and stuff, I find that there a myriad of different individuals that are there from lots of different disciplines, not everybody is a user experience designer, so they may not be as familiar with the process that many UX designers employ. So for this, I thought we would just briefly go over it, we’re not going to spend a tremendous amount of time on it, but I find it merits going over just briefly. Also because it’s going to tie into designing accessibly as well. So, most UX design tends to go through a process called discovery, it’s not always called discovery, sometimes it’s called rapid ideation, rapid iteration. A lot of people have different names for it, but the point is that it’s the part of the design process where a lot of the fabrication happens.

Aaron Pearlman: It’s a lot of the time where we have also different ideas and requirements gathering, it’s one where a lot of research and synthesizing that with your organizational goals and filtering that with all of that information, and what comes out of it are typically artifacts that allow us to be able to build the system that we’re going to be making or the features that we’re making. Those tend to be — they’re not always — but they tend to be things like prototypes, sometimes you’ll see mental models that will come out of them as well. But a prototype in some level of fidelity that is a reflection of how your target user is going to achieve their goals. The TLDR is that reiterate design and we test with users and reiterate, test with users, reiterate, test with users, and then in the end, it ends up going to be built.

Aaron Pearlman: You think that’s important, is the considerations for accessibility are that we want to be thinking about and doing accessibility throughout that design process. And different levels of fidelity can merit, thinking about different types of things, it really depends. Won’t go into a lot of that, but just in general, we want to incorporate those heuristics and methods, and we’re going to as designers grow our powers of accessibility over time, just as we grow our powers of being a good user experience designer over time. There’s not an expectation in the beginning that you’re going to go and read WCAG 2.1, then you’re going to read the ARIA spec, and then you’re going to be done and you’re not going make any more mistakes, or you’re not going to miss anything when it comes to your designs and designing accessibly. That’s not necessarily reasonable by any stretch of the imagination.

Aaron Pearlman: Just know that you’re going to be learning over time. Certainly I still mistakes in accessibility, and everything that I work on and it’s just all about getting better. So, [inaudible] because I’m always designing accessibly. So one small plug though it’s relevant to what we’re going to be working on today is called Trane. It’s our fully accessible pattern library at Deque, we use it to build our own products. It’s an HTML, CSS and JavaScript front end framework, it quite similar to Bootstrap, if you’ve ever used anything like that. We also have a react library that’s sister library too as well. Our team develops in react. But we’re going to be looking at a few of the things in here today as examples. But this is open source, it’s available, there will be a link to it at the end of this deck, which I’ll make available to everybody.

Aaron Pearlman: And it’s free for you to use and get on get branches and use it to your heart’s content or contribute to it, we’d love to see a contribution to it as well. So just a small plug, but we will be referring to it as we go through. So for the first thing that we’re going to look at are skip links. And for those who may not be familiar with what a skip link is, skip links are little links that will tend to show up as the very first tab stop in a web application or website. And what they allow you to do is they allow you to bypass parts of the website. Why would you want to do that?

Aaron Pearlman: Well, if you have a website that has really rich menu, that may be a big billboard menu or just has a lot of stuffs to it, if you’re a Keyboard Only or Assistive Technology User, when you get to that site and your VoiceOver begins to read off of it, or even not, even, maybe you are a sighted user, you just use your keyboard only, you’re going to have to tab cycle through all of those different items to get down to the contents or to the workspace that you want to begin whatever your activity that you’re doing there is. And so, what a skip link allows you to do is to bypass typically, typically navigation to get to the workspace area of that application.

Aaron Pearlman: There can be multiple links sometimes and typically only see one, but we have some examples. I’ll show you an example of where you can use multiple skip links as well. So I thought we could look at a couple different types of Skip links or a few different types of skip links, and then we’ll look at another page that doesn’t have a skip link, and maybe talk a little bit about where one might be useful there. The first one we’re going to look at, hopefully you can see my screen. The first one we’re going to look at is this skip link that we use on deque.com and what it is, is what I would call a displacement element in that it displaces the page. So when I tab into here, I can see the skip link is there and it will tell me to skip to content.

Aaron Pearlman: And when I select that, it will send me to the content below, and I call it displacement because it literally inserts and hides itself and inserts itself into there and displaces it. This was the skip link that we chose to use for our content, but it’s one that’s very common. You’ll see it insert itself at the top of a website or web application. The next one we’re going to look at is one at a site that I’m sure that many of you have used or used quite frequently. It’s Amazon, we’ll look at their skip link. When I tab in there, if you look in the upper left corner there, you’ll see it overlaid, this is an overlay style, this is very, very common where it’ll overlay the content, and so it will often skip whatever’s behind it to show you the skip to main content there.

Aaron Pearlman: The pros and cons between displacing versus overlaying are negligible. If you find that your content is something that you never want to obfuscate, then you may want to insert something and just use it, displacement one, vice versa, it doesn’t matter, that’s fine as well. If you’re designing content that reads from right to left, like Arabic content, you may put your skip link in the upper right corner, it may merit that. It really comes down to what’s appropriate. But ultimately, that discretion will be to the designer in their team. So, this is an example of two skip links that were a single skip link, and I thought I would show you one where there are multiple options inside the skip link.

Aaron Pearlman: I’m going to pull up that example, this is from our pattern library. Now for this particular example, I wouldn’t actually design something that had multiple skip links for it because it doesn’t really merit it, but we just did it for the purpose of demonstrating it. So I’m going to tab in and in the upper left corner, we use an overlay that shows you two skip links right here. And these are tab stops inside of here, so if I hit tab again, we’re going to tab into the next one and if I tab away, it’s going to go. If I tab again, it’s going to leave and it’s going to go into the header at the top there. I’m going to shift tab back, shift tab back so that we can see that we can move in and out of here.

Aaron Pearlman: And then I will go ahead and enter one of these just so that you can see it. And what happens at this point when I select it, it sends me into the workspace area and it actually focuses that workspace area. What you’ll see for a lot of web applications is they don’t actually show the focus itself, we wanted to show that in our applications, this isn’t a focus of elements so to speak, but it is something that can take focus. And then from here, we’re going to focus and then we can go to the different items inside of there that are the focus of all elements that are inside of there, the [inaudible 00:12:28] elements. So, those are examples of a few different ways that you can do skip links.

Aaron Pearlman: Like I said, there’s an example inside the pattern library, you’re welcome to use it, we also have a version of it as well, I believe here that has errors. We have a single skip link example as well, and you can just use that as well. So we have a couple of different examples here. But those are examples of common ways that you can use skip links. And they are primarily beneficial to individuals that only use their keyboard to traverse the system when they use a system technology as a result of that.

Aaron Pearlman: But at sometimes, there can be other instances where that a skip link potentially could be beneficial. I’ve seen it can be potentially beneficial. You could imagine an instance where the big workspace of your site maybe it’s a bunch of search results and it does a lazy score where you’ll scroll to the bottom and then it’ll load more results, and scroll to the bottom and it’ll load more results, you scroll to the bottom, and it will load more results.

Aaron Pearlman: Well, how do you get to the footer? And I’ve had this trouble actually before, where I’ve gone to search engines and I was never able to get to the footer. And what would’ve been nice is the skip link that actually let me skip to the footer, because I was looking for information down in the footer. So there’s ways that skip links can be beneficial to that. It’s not the only way that you can solve that problem. Certainly, you can use hard keys or shortcut menus as well. There are lots of different techniques to accomplish these goals, but that’s the one that skip links tend to be very good at [inaudible 00:14:13]. Some things to keep in mind when designing a skip link is that, typically it’s going to be the very first tab stop on your website web application.

Aaron Pearlman: And that’s commonly where it’s found, and so if I’m screaming or a keyboard only user, I can get to it immediately. It’s the very first thing I can do when I enter in. So if it’s something that a web app that I use frequently, I can get right to what I’m trying to do. It should also be visually depicted where it is supposed to be in the information, in the AI basically, so you can put skip links and other parts of your application as well, like I could put one here if I wanted to, find a long scrolling stack site and I wanted to do that, and I wanted to have a skip link within something. I’m fairly sure that you can anchor into different things like that, but it should visually be represented where it should be, inside of the application.

Aaron Pearlman: In general, that’s extremely uncommon. Most skip links are always in the very first tab stops. In general, don’t do that. I think you technically can, but I would say don’t. And then the final thing is it is an interactive element and it’s the past color contrast, so make sure that it does, if you decide to use like an image or something in it, I would, but if you did, it needs to have the proper accessible name along with it as well. In general, most people use texts and links, so it’s going to be marked up as a link. Just make sure that it is passing color contrast so that it [inaudible 00:16:07]. Very good. So that’s kind of all we have for skip links.

Aaron Pearlman: It’s a fairly succinct but very common pattern that you see everywhere and it’s something that you can add fairly, it’s a fairly straight forward to add to your web application, but it can make a big difference for individuals who use their keyboard or system technology. So let me go ahead and close this and let’s move on to modal optimizations. Chose to do this because modals are very, very, very, very common amongst most web apps and they come in a lot of different forums, a lot of different ways that modals are shaped and created.

Aaron Pearlman: But some common things that I see that show up in more of the things that we can correct, until there’s some optimizations that we can do to make it a better experience for keyboard-Only and Assistive Technology users. And in general, I think your modal are much better one. One thing I thought I would show here really quickly is, one important thing that a Modal needs to do is it needs to be able to trap focus inside of it. I wanted to show an example of … it’s right here. I love dribble by the way, so this is not a dig against them. This is probably just a small oversight here. I used them all of the time as a delightful site and has wonderful stuff on it.

Aaron Pearlman: So if I were to hit the sign in, oops, I’m sorry, the sign up. Here’s a modal here and something that can happen sometimes. If you notice carefully, I’m hitting tab, tab, tab, tab, tab. As you can see behind the screen, it’s a little bit difficult to see. You can see focus hasn’t quite been trapped inside the Modal and this can happen sometimes. So if I was a user who’s using Assistive technology or a Keyboard-Only, it would be very difficult for me to get back to this.

Aaron Pearlman: It’s something that happens very, very, very, very commonly, and it certainly can happen when you’re inserting different interesting things into Modal. So something we want to make sure of, and the reason I’m bringing that up, the reason that’s actually very, very important is when a modal is evoked, it needs to sort of announce itself to the individual that evoked it, know what they basically just opened, but they actually opened the correct thing.

Aaron Pearlman: And so, the way that it can announce itself is that, either the body of the modal needs to be focused or potentially the header of the modal can be focused so that we can tell the individual that’s evoking the modal, that it is what’s happening. So if they have voice, they’re using for example, VoiceOver on it, it’ll tell them what they’re looking at. So I thought I’d give a couple examples of ways that the body can be focused and then an example of how model can focus the header instead and then what we can do with that.

Aaron Pearlman: I’m going to open up this really quick here. Very good. And so the modal that they have for this, I think it’s a clothing site right here. And what happened is it focused the body and I can show that best by… I’m going to turn on VoiceOver really quick. I’m going to pull it up.

VoiceOver: VoiceOver on Chrome.] Bonobos, [inaudible 00:20:10]-

Aaron Pearlman: And you won’t be able to hear it-

VoiceOver: Google Chrome, Aaron.pearlman@deque.com-

Aaron Pearlman: But you’ll be able to see it.

VoiceOver: Close the card, your card is empty, group has keyboard focus. You’re currently on the group in opening your card, close the card, your card is empty group. You’re currently on the group inside of web content, VoiceOver off.

Aaron Pearlman: So right there when I focused it, it read out a bit of everything that was going on your card closed and your card is empty because of the buying was focused at that point. And that’s perfectly valid. That’s a perfectly valid way of focusing your modals. It’s not a problem at all. And then from there you can tab cycle through everything that’s inside of it. Another common way of when a modal is evoked is to focus the header.

Aaron Pearlman: And that’s what we do in on the modals that we use for our applications is we focus the header. So I’m going to evoke the modal, and as you can see right here, focus is right here where it says modal with form, focus is right there on the header. We actually, rather than indicating that as like an index, we programmatically focus that. And the reason that we programmatically focus that as I tab cycle through here, it’s now going to the close button, also in the header, then to the first interactive element, which is field to the next field, to the next field, to the next fields, tabbing again to the save, tabbing again to the cancel.

Aaron Pearlman: And from here when I hit tab, if that header was a tab stop, it would go there, but we chose not to do that. Instead, we go to the close and the reason that we do that is just if somebody was using Voice Over as you may have seen some of what was being written and was going into my ears at the same time, it was actually very a bit distracting because it speaks very quickly, it’s a bit chattery. And so one of the optimizations that we wanted to make for the experience here was to make it a little less chattery. So yes, we announce it, it goes, we programmatically focus modal with form when they first get there, so that it lets them know that the modal that they evoked is in fact it’s what they’re currently focused on.

Aaron Pearlman: But we don’t need to announce it again and again and again if they were to cycle through this shifts cycling through this modal. So it’s a small optimization likely would be completely invisible to the majority of your cited mouse only users. But that small optimization, you can imagine if I used modals a lot for filling out forms frequently and I was a user that used Keyboard-Only or Assistive Technology that optimization would add up over time. So, little teeny user experience things that we can do, that can make a significant difference overall in the care that we can put into our designs, so that they’re the most often experience that we can provide.

Aaron Pearlman: Speaking of handling focus, the last one that we are going to go into is focus handling itself. And we saw one example of it, what can happen if focus can get lost in certain types of handling? But rather than being just something that can be a significant issue, the way that you handle focus can change significantly the experience that an individual would have. Really the rule about handling focus, especially with the two instances that we’re going to look at right now, which are, removing and adding elements to your work space or whatever you’re working in is that … It can definitely change how somebody interacts with it. And so we want to make it follow the expected experience that you would have for somebody who is a Mouse-Only user or a sighted user, a Mouse-Only user I should say.

Aaron Pearlman: In this instance we’re going to look at … for here we’re going to look at … Okay, let me drag it over. Hold on one second. I’m going to have to take this out of here temporarily. There we go. So you shouldn’t be able to see an example of a modal that I’ve designed, it’s actually a single modal, we have two kind of images of it and just one is just showing what’s below the fold there rather than making one really, really wrong or I just split it up so you could see what was below in fold. And on the right side, if you look, there’s a trashcan icon that is currently being focused. And so when we click on that trash can icon, assuming that there isn’t a dialogue that says, “Are you sure you want to delete it?”

Aaron Pearlman: Let’s just assume that that’s not the case. The real question then goes, what happens with focus there? Because when that trash can icon is hit or is selected, it is going to remove instructions that are in right here, and it’s also going to remove itself. So where does focus go? So we as designers, we want to choose where focus goes because otherwise the browsers going to choose for focus goes if you’re making a web application inside of a web application and we don’t want the browser to choose where focus goes because it tends to throw things to the body. So in this case, where we really want focus to go is we want focus to go to the next focusible element, not necessarily the … what I would call the analog to that, which will be focusing the next trash can, the trash can for instructions to instead we focus instructions to itself.

Aaron Pearlman: And the reason we would want to do that, is you can imagine if somebody accidentally hit, using their keyboard only they hit return, then they hit return again. It would have just deleted two sets of instructions instead of one. And we would want to, we prevent that for a mouse only user by literally having those things physically far apart. But we want to also be able to prevent that because focus is what they’re using to traverse this. So I thought I’d show another example of what do we do when we’re deleting the last item in entire section here.

Aaron Pearlman: Now we’ve got cooking instructions, the final instruction for instruction one, where does focus goes here? Now for this particular one, it’s going to follow suit with what the previous one was, which is it’s going to go actually up to the next focus but filled again, which is ingredient one for the same reason that we wouldn’t want to throw it to the trashcan again because then if somebody again hit select again or hit return again, we would be … They’d accidentally delete two things that they unintended, didn’t want to.

Aaron Pearlman: For the same reason, we wouldn’t necessarily want to throw that to one of these links here because we would have the opposite problem where they’d be accidentally adding things as well. And we don’t necessarily want it to go to the body, because we go to the body and your Voice Over user, your Assistant Technology user, is just going to start chattering about the modal again or rather than letting you continue to interact and do what you intended to do.

Aaron Pearlman: And then finally, the final example that I have here is what do we do when we’re going to remove the last item in this case, in the modal here, there’s nothing left. Where would I send it? And this is definitely up to the discretion of the designers to where it should go. There’s no, it’s not going to be inaccessible if you choose to send it to the clothes or send to focus maybe to the cancel. It doesn’t necessarily make it inaccessible, it’s just that, it really comes down to what would you expect? What information would you want to convey? What narrative do you want to convey to that user and where we choose to send it as we choose to send it back to the header to let the user know that they’re still on the modal, they’re still there, we haven’t closed it on them, for example there.

Aaron Pearlman: And so that’s actually a programmatic shift because like I said, it’s not terrible voice. It’s not as terrible focusible element like that. So we programmatically shift focus to that in this particular example. So those are some nice examples of what to do maybe with focus when you’re removing items. So I thought you could … I would show an example of what you do when you’re adding an item. So I’ve got example of that real quick here for focus retention.

Aaron Pearlman: And right here, we’re going to hit this add another … you can just focus here, add another ingredient and focus then shifts to the actual ingredient in this case, the field that you added for two reasons, one, because the assumption is by adding that next field that we wanted to interact with it and that would be the expected behavior if I was a Mouse-Only user, I’d be adding that presumably so that I could actually begin to type text into it.

Aaron Pearlman: And then again, we wouldn’t necessarily want to keep focus on another ingredient for the same reason that if they hit return again, we wouldn’t want to add two ingredients instead of one. It should be opposite problem of the previous example. And the final, the final example I wanted to show, because I think it might be worthwhile showing is … actually I have that example, I may pull that up in a little bit. But I can describe it pretty, pretty aptly in that, if you have what do you do when you evoke a modal? For example, you saved something, the modal goes away, where does focus now go and what we tend to do, but the rule of thumb on that is that you want to send it back to whatever element [inaudible 00:31:03] gets.

Aaron Pearlman: So if you imagine if you had a little edit pencil and you select it, opens up the modal, you fill out that modal, you hit save, you’d want to send focus back to that interactive element that tends to be … or we do. There may be instances where you want to send it somewhere else. If it’s a wizard and it goes somewhere else after that, again to the discretion of the designer, to what the narrative that you’re trying to tell us to where to go. But for things that are like the one … instance that I just described, which is very common. You evoke a modal, or you do something with it and it gets dismissed as a result of that and the context doesn’t necessarily change.

Aaron Pearlman: And you don’t want to send that focus back to where it was. And the reason for doing that is so that, a Keyboard-Only or Assistive Technology user can pick back up with where they are. Because remember they’re in that space and that space is somewhat linear as to how they traverse and especially when you’re using town to get through everything. So, I think we’re just about at 40 minutes, we just about at time for all the examples and things that I had. So I’m going to pass it back over to Scott.

Scott: Thanks Aaron. That was pretty awesome, and we do have a lot of questions from the attendee as well as a few from individually who couldn’t make it today because he’s traveling. So Poan who’s a regular attendee of our webinars asks, “When you’re removing items, shouldn’t we have an acknowledgement of the action and move the focus there and then move to the next element?”

Aaron Pearlman: when removing an item, should you have an … are you referring to like a notice like a toast or are you saying should you have a live region that is letting you know what’s happening? If you’re shifting focus to remove an item, like the ones that I just showed in that particular instance the evocation of that delete for example, should be adequate enough to let them know that they in fact deleted.

Aaron Pearlman: It should be gone. Also, if they’re using Voice Over, it’s going to pick that up as well. If you’re interacting with something and it’s making changes somewhere else, for example, like you did something and then it changed some metrics somewhere for example, you’re probably going to want to use a live region that does something politely to let them know that that’s happened. That’s something that’s sort of out of the purview of where you’re working in specifically. I hope that answers your question. It might be diving into something that’s a little bit more technical. I may need to follow up a little bit more with some of it, if we’re going to get into deep technical implementation stuff.

Scott: Perfect.

Aaron Pearlman: My developer, so they don’t steer you arrive but in general that tends to be the case. The example that I showed should be adequate. If you want it to because it’s a delete, you could have an interim part where you throw an alert and say, “Are you sure you want him to delete this?” Which case you’re just reinforcing it further what happening.

Scott: Great. So, yeah, try and keep the questions user experience focused. So from a user experience standpoint, how would you manage focus for notification messages?

Aaron Pearlman: Focus for a notification? I can show you one if you’d like to see.

Scott: Sure.

Aaron Pearlman: We can pick back random because we happen to have toasts, which are notifications. So I’m going to open up toasts here. So this is actually being focused right now. This toast is evoked and it is being focused right now and you can actually, as you can see, you can tab into the clause right here. So, it depends. So, if I finished something and I wanted to notify them that it’s been finished and I toasted it, then I want to focus it so that they can see that it’s been … that I’m communicating that information to them. So you want to shift focus to it.

Scott: Melanie is asking, “Do you have any tips for tips or resources for navigating slideshows?”

Aaron Pearlman: For navigating slideshows?

Scott: [crosstalk 00:36:00]. Very specific.

Aaron Pearlman: Yes. So navigating slideshows. We don’t use them very often, so I’m going to answer this as best as I can. So one slideshows especially ones that are like carousels, they need to have a control so that you can stop them. I think that’s an accessibility need, is that they have to have some control and a mechanism so that they can be stopped. Anything that’s an animation wise can’t animate for more than five seconds at a time and then the animation has to stop.

Aaron Pearlman: That may not be relevant to what you’re doing, but it is moving. And those controls then need to be focusable most carousels have … A lot of fancy new ones. we’ll have menus that can come up when they get hovered over or focused on, just consider that all those controls need to be traversable, and then their very image heavy. A lot of carousels and slideshows need to be, so that you’re going to need to have proper alternative texts on them. Just the things that you would expect.

Aaron Pearlman: Off the top of my head, I don’t know of any fully accessible carousel that I can think of. But let me see if I can find a better example and I will try and pass it along through smashing and have that available if I can find it. It’s a great question because they come up a lot. I ended up tending to solve that problem in a slightly different way because I think they’re tricky, but that doesn’t mean that they can’t be done.

Scott: Rebecca is asking, “Can you give a use case for skip links?” And then similar early related, Patricia’s asking, “Do you know how to solve the issue with skip links in Safari plus the VoiceOver?” [crosstalk 00:38:18]. Again, maybe more technical than user experience related.

Aaron Pearlman: Yes. The second one, I’m not entirely sure what actually is going on that, that there may be an issue there. Again, I can try and see if that’s something that our developers have encountered before and how they’ve gotten around it. So we’ll make a note of that and I’ll try and circle back. But for the first one what’s a use case for Skip links? I want to avoid giant banner menus and I want to get straight to a sale that I heard that there is today and I don’t want to have to do that.

Aaron Pearlman: If I was a sighted a mouse only user, I would just visually ignore it and then go move my mouse over and just click on the sale item. If I’m a keyboard only ora assisted technology user, I would have to tab through all of that menu, potentially bunch of banner items as well before I could finally get to the workspace. that has maybe the sale items. So that would be a great use for a Skip link to get right to the content. Skip to main content is a phrase you see very, very common. Skip to main content.

Scott: Okay. That’s a good, good point. And I think in terms of all the user related questions from the attendees that covers them. We do have some general questions that we like to ask. So, low hanging fruit for people that are trying to build an accessible website. If somebody wants to put together a site in a few hours and make sure it’s accessible, what are some the easy things that just they can check off the list right away.

Aaron Pearlman: Sure. So some things that you can do immediately with any site or application that you’re working on, you can review your font choices for things like color contrast, there are plenty of color, if you put in color contrast, selector, picker or something like that, you’ll get it and you’ll just put it in the Hex value or the RGB value of what your font is and then what the background, whatever element the background color is sitting on and make sure that it’s meeting at 4.5 to one.

Aaron Pearlman: So that’s one that you can do immediately. Check your color Palette, you want to do color contrast where I see that color contrast fails a lot is when people use the endless shades of gray to have various levels of first class, second class, third class elements and things like that. Just make sure that if it’s an interactive element that it’s a passing color contrast.

Aaron Pearlman: Another thing, check your the images that are important, that are non decorative images. Make sure that they have all texts. Just one that you can add immediately. And then check your review, your heading structure, make sure that your h1 tags, h2 tags, h3 tags, h4 tags and so on. They all make sense with the structure of it and make sure that the content is properly paired with those heading tags.

Aaron Pearlman: That’s things that you can do immediately. And then also you can just, this is a small blog but you can download AX, that’s our accessibility engine. It’s totally free. It’s a little extension for chrome and Firefox and just hit the run button and see what you find. It’s a lot of things that you can help alleviate immediately or change immediately. You can also turn on VoiceOver, for example, if you’re on a Mac and start to go through your site and see what it sounds like for somebody who uses just a technology. It’s a great thing that we can do immediately.

Scott: Okay. Janat, has a question here. So what is it about accessibility that interests you and how did you know you’ve been doing design and UX for so long, but you’ve only been doing accessibility for smaller period of time, so that catch your attention?

Aaron Pearlman: It had been something that had been on the purview of some of the design that I had done in a later part of my design career till I got here. In my design career, I’ve always wanted to work on things that I felt in some way tried to make the world a slightly better place and I felt that working. And accessibility was one way to make … Very much believe in the core value of universal design or more importantly adapted design. Design that adapts itself to two different types of individuals to provide what we call GQ like digital equality. We want everyone to be able to use everything as best as we can possibly provide that universal experience that we can have. I don’t know as a person that very much appeals to me. And so it was just a good fit to learn design. That’s really cool.

Aaron Pearlman: Designing accessibly is a one way street. Like once you start to design accessible, you never don’t not design accessible anymore. It’s like UX designers don’t design unless you’re being tongue in cheek, you’re not going to design something to have a really poor user experience. It’s going to be part of your vernacular from that point forward. And once you begin to design accessibly, it never goes away. I can’t like not think about accessibility as I do designing and that’s a really, really cool thing.

Aaron Pearlman: It also affords you to start to think about things that you didn’t think you had access to. Like, did you know that your focus on your page, you can design focus to look differently for different elements on the page? That blew my mind when I found that out and I thought that was so cool that gave me a little bit more control, I knew you could create really cool Hover States, but I didn’t know focus was a state that you had full control over as well.

Scott: Our industry there’s always a new trend that’s just kind of how it goes, that’s the web. Are there any design trends right now that you know that are inhibiting accessibility? And if so, is there any recommendations you can make to avoid that?

Aaron Pearlman: I don’t know if there’s anything that’s super trendy right now when I look at different sites and web applications that couldn’t be designed excessively. I think there are pitfalls that that we’ve been falling into longer than any one trend as existed or at least has existed for some time. I just mentioned one, what I call the endless shades of gray. That’s one. In general, just being mindful of the contrast for your text. It is rampant.

Aaron Pearlman: It is by an order of magnitude, the most accessibility issues, if you were to like run an engine against it, like AX, it’ll be color contrast almost always. So just being really, really, really mindful of that regardless of where your text is on the page. Again, I mentioned it again, just being careful with your images. If you have an image that’s conveying important information to a sited user, that information needs to be conveyed to the user. That is user as well.

Aaron Pearlman: And what I mean by information that’s conveyed is if what’s being conveyed is that the person is doing something that’s, you wouldn’t necessarily describe it as a man standing. It could be that they’re playing baseball. Maybe that’s the important part. So make sure that the, that the, the alternative text matches with the intended information that’s trying to be conveyed, received out a lot too. Even when all texts is there, it just doesn’t accurately describe what is trying to be portrayed.

Aaron Pearlman: And then the other one too is progressive disclosure menus, many times you see on Hover Menus and stuff like that. They don’t do a great job of being evoked on focus as well. And they don’t always do a good job of … So that is a trend I do see. I do see a lot of menus coming up on Hover, when you hover over something you get the secondary menu that was hidden before that now finds itself to the front.

Aaron Pearlman: Also making that be able to Hover or a mechanism that allows you to evoke it and that will properly capture focus inside there so that you can use it. Those are a few things off the top of my head that I can say I would see a lot.

Aaron Pearlman: So as a graphic designer, you obviously work with development teams and a lot of the times when we’re doing wireframes and design of the onset of the project, they’re inherently not inaccessible. It doesn’t really become an issue, it seems until it comes to the development stage and people start taking that design and turning it into code. So how do you work with developers to make sure that the design that is being made from the start is going to be accessible when they’re done with it. Do you do audits throughout the process, at the end of the process? Like what’s the workflow with developers?

Aaron Pearlman: Sure. So the workflow for our development team is going to be, I think somewhat similar to a lot of other organizations. We work in scrum, so we work in sprints and scrum and I’ll go through a discovery process. They’re going to be privy to that, they’re not going to see it when the design is fully finished.

Aaron Pearlman: They’re going to see it throughout the design. I’ll have opportunities to talk with them a little bit about what the intent of the design is. They will probably set in on some of the user research that I’ve done, some of these ability testing that I’ve done. So, hopefully at that point nothing’s really new to them that I’m not going to get any 11th hour that we can’t even do this thing. I still have to deal with all the other things outside of accessibility that every other designer has to deal with, like is this feasible? Is it valuable? Is it all of those things that we have to deal with.

Aaron Pearlman: With regards specifically to accessibility, sometimes I will annotate the designs in a particular way that will indicate where tab focus should go. At the end of the slide deck that I have, there’s a great resource that one of the designers from Adobe put together. I know there’s like a pdf, there may be. There’s like a sketch file as well in there, there may be an XD file as well.

Aaron Pearlman: I don’t think, maybe just sketch. But it shows you like all of these different ways that you can annotate things like, accessible names, tab order and basically are little objects that you can place on your design to indicate some of those things as you go through. It’s a really, really wonderful resource. It’s all included in here as well. That’s a great way of saying, “Here’s part of my prototype and here’s the expected tab, order for it.” So that you have that as part of your artifact as part of the digital documentation or annotation that goes along with it.

Aaron Pearlman: So that’s one thing that we do is I annotate my designs pretty heavily. Everything from the size of how certain things are supposed to be to the Hex codes or RGBA values for what’s supposed to look like and feel like. But then also, there are accessibility annotations that you can add to it too.

Aaron Pearlman: And then just communicating, looking through the builds as they go through, making sure things like if you made any custom focuses that those custom focuses, look great, check the color contrast, make sure that it’s coming through, that the font choices that you’ve had there are some fonts that when their weight is higher and they’re bigger. Their color contrast it doesn’t have to be a 4.5. It can actually be a little bit lower, but you just going to want to just keep an eye on those things. Just as you would keep an eye on the experience stuff as well. You’re going to want to keep an eye on that stuff that you’ve been mindful for and annotated in your designs.

Scott: So we have a couple minutes left here. So I’ll ask one more question. Some people feel accessibility can stifle creativity throughout the design process. Is that something that you’ve come across? How do you think creativity fits into accessible design?

Aaron Pearlman: Sure. That was one of my initial reactions to having to design accessibly, was that somebody basically put the handcuffs on me and says, “There’s a much smaller box you have to be able to work in.” It’s true that designing accessibly means that there can be some more challenges because there’s more rules that you have to follow. But in the end, I found that the experience ends up being better and I haven’t … Once I removed that misnomer and began to do more and more accessible designs that were WCAG 2.0 AA accessible, I noticed that I can pretty much do everything that I wanted to do.

Aaron Pearlman: I would just need to sometimes express or solve problems in a slightly different way than I did before. I think a lot of people when they think about designing accessibly … I’ll give you a very specific example. When they think about designing accessibility they think, “Oh, well, I can’t do all of these fancy visualizations, for example. I’m not going to be able to do all of those things because they’re not going to be accessible, because if an individual can’t see them, I’m not going to be able to do that.”

Aaron Pearlman: I was designing a visualization that was just basic, just sort of line graph and under those, there was a line graph, on the x axis there was I think it was time and on the y axis it was usage or something like that. And there was this nice little gradient that went down from it and there was sort of these light lines that went behind it to delineate the months and time. And when I talked with one of my subject matter experts about making it accessible, it turned out I was sure he was just going to be like, “Nope.” But he said that there was actually just a few things that I needed to do to make this really nice looking graph accessible. One, that line at the top it need to pass color contrast because that’s actually what’s conveying the information of the trend over time.

Aaron Pearlman: The gradiated stuff underneath it’s just decoration and as long as it’s not interrupting the passing of color contrast of that and the y and x axis lines and ended up being okay. Those lines behind it were okay, but I ended up adding tick marks at the bottom there to indicate that. And then when I hovered and focused over, because sometimes you can hover over and it’ll add a dot to part of the line graph, just making sure that the dot itself would pass color. contrast. I did that by doing the sort of donut thing where you put a white dot with another dot or I should say has it like a large stroke on the outside of it as well.

Aaron Pearlman: And then I added a little bit of treatment in there that would bring the those lines that were faded back forward. And it all pass color contrast and ended up being fine. It was really pretty visualizations that passed. Now granted, I’m not getting into all of the accessible name stuff and being able to do that. Many libraries are on that. Put that aside, at least we call a contrast because is where I think a lot of designers struggle with. You can do it.

Aaron Pearlman: It’s just about being really mindful about those types of things, and getting more examples and just trying and trying different things, and having other people that you can pitch those ideas with and bounce them back and forth and checking again, just really do that. I don’t think it really inhibits anything. It just makes you have to think a little bit more clearer about how you’re going to do it and making sure that you’re looking through the lens of how an individual engaged with this if they had low vision, or if they couldn’t see it at all or couldn’t hear if you’re building a media application.

Scott: One more question, but I think we should’ve touched upon it. What stage in your process do you start thinking about accessibility? I’m going to assume throughout the whole process.

Aaron Pearlman: Yeah, it is throughout the whole process. I’ll be a little bit more rather than … I know who I say that and it sounds a little flippant. So, early on when you’re doing things like low fidelity prototyping, you’re going to be thinking about things like some tab order stuff. You’re going to be thinking about maybe headings and structure, things like that. Those are the type of accessibility stuff that you think about. Later on as it gets higher in fidelity, you’re going to be thinking about things more like, colors and your pallets that you’ve chosen, maybe accessible names, alternative text for anything that may merit that, you may be thinking about, if you’re doing any custom focuses, for example, that’s probably where you’re going to start to think about that.

Aaron Pearlman: It doesn’t mean that you couldn’t think about it when you’re doing low fidelity just means in general, when I go through my process those things tend to fall into those categories. You’re thinking about accessibility the whole time, but you’re not always thinking about everything with it as you’re in lower fidelity stuff, and you’re ideating, and you’re just thinking about ideas, and you’re just working through ideas, let that creative stuff go through as you become more attuned to accessibility, it will just sort of intrinsically make its way in and there’ll be less of a conscious thing.

Scott: Yeah. Fair enough. Well, on that note, we’ve run out of time, Aaron. Thank you very much for your time and—

Aaron Pearlman: That was great. I’ve had a wonderful time.

Scott: You’re going to be at the next couple of Smashing conferences, I think.

Aaron Pearlman: I will be at the one in New York. I’ll be at the one in New York.

Scott: Okay. And are you guys doing a workshop there?

Aaron Pearlman: Yes, we’re.

Scott: Okay. Awesome. Well thank you again for your time and just to let see the members that are still watching, we’ve two webinars next week. The first one is the Power of Digital People, with Kristina Podnar. And then we have a number three in our series with Andrew Clarke, Inspired Designs Decisions, number three inspired by Ernest Joural. Thank you very much everybody for attending today. And again, this recording will be available in dispatching membership panel once we’re done editing it and we hope to see you all next week. So thanks again Erin.

That’s A Wrap!

We kindly thank Smashing Members from the very bottom of our hearts for their continuous and kind support — and we can’t wait to host more webinars in the future.

We couldn’t be happier to welcome Aaron to our upcoming SmashingConf New York (October 15-16) — we’d love to see you there as well!

Please do let us know if you find this series of interviews useful, and whom you’d love us to interview, or what topics you’d like us to cover and we’ll get right to it.

Smashing Editorial
(il)

Source: Smashing Magazine, UX Improvements For Keyboard Accessibility

CSS Lists, Markers, And Counters

dreamt up by webguru in Uncategorized | Comments Off on CSS Lists, Markers, And Counters

CSS Lists, Markers, And Counters

CSS Lists, Markers, And Counters

Rachel Andrew



Lists in CSS have particular properties which give us the standard list styling we expect. An unordered list gains a list bullet, of the type disc, and ordered lists are numbered. My interest in exploring lists in more detail came from some work I did to document the ::marker pseudo-element for MDN. This pseudo-element ships in Firefox 68 and is being released today. With the ::marker pseudo element available to us, we can start to do some interesting things with lists, and in this article, I’ll explain more.

Deconstructing A List

You may not have thought much about lists, although we use them frequently in our markup. Many things can be marked up quite logically as a list. While step-by-step instructions or ranked elements may naturally be described by an ordered list <ol>, many things in a design can be described using an unordered list <ul>. A very common usage of the element, for example, is to mark up navigation, as it is a list of destinations on the site. For our exploration, let’s start by finding out exactly what a list is in CSS.

As with many things in CSS, lists have some initial values applied to them. These values make them look like a list. These special values begin with the information that a list item has the display property with a value of list-item. This creates a block-level box, with an additional marker box. The marker box is where the list bullet or number is added.

Lists were defined early on in CSS, and much of the definition of lists as we use them today is from CSS2. The CSS2 specification describes a list item as follows:

“An element with display: list-item generates a principal block box for the element’s content and, depending on the values of list-style-type and
list-style-image, possibly also a marker box as a visual indication that the element is a list item.”

The principal block box is the main box of the element and contains all of the children as a list item can contain other markup. The marker box is then placed in respect to this principal box. The specification goes on to detail the fact that any background color will be only behind this principal box, and not the marker. Also that the marker can be set to one of a range of pre-defined values:

  • disc
  • circle
  • square
  • decimal
  • decimal-leading-zero
  • lower-roman
  • upper-roman
  • lower-greek
  • lower-latin
  • upper-latin
  • armenian
  • georgian
  • lower-alpha
  • upper-alpha
  • none
  • inherit

The Level 3 display specification defines display: list-item along with the other possible values for the display property. It refers back to CSS 2.1 — as do many CSS properties and values which come from CSS2 — but describes the list-item keyword as, “causing the element to generate a ::marker pseudo-element”.

The Level 3 specification also introduces the ability to create an inline list item with the two value syntax being used display: inline list-item. This is as yet unimplemented by browsers.

Creating Marker Boxes On Non-List Items

As with other values of display, it is perfectly valid to give any HTML element a display type of list-item (should you wish to generate a ::marker pseudo-element on the item). This will not cause the element to become a list item semantically, but instead it will only visually display as a list item, and therefore be able to have a ::marker. When we discuss the ::marker pseudo-element below, you will discover some cases where giving other elements display: list-item can be useful.

The CSS Lists Level 3 Specification: ::marker And Counters

The display specification expands and clarifies the definition of lists that we find in CSS2, however, there is also a specification which defines list behavior in detail: the CSS Lists Specification Level 3. As the basic behavior of list items is defined in display, this specification details the marker box generated when something has display: list-item along with the counters which are used by default whenever you create an ordered list. There is some potentially useful functionality accessed via these features.

The ::marker Pseudo-Element

The ::marker pseudo-element allows you to target the list marker — separately from the content of the list item. This was not possible in previous versions of CSS, therefore, if you changed the color or font size of the ul or li, this would also change the color and font size of the markers. In order to do something as seemingly simple as having different color list bullets than text, would involve either wrapping the content of the list item in a span (or using an image for the marker).

ul {
  color: #00b7a8;
}

ul span {
  color #333;
}

With the ::marker pseudo element, the simplest thing you might want to try is having a different bullet to text color, which means that instead of the code in the example above you can use:

ul {
    color: #333;
}

ul ::marker {
    color: #00b7a8;
}

You might also want to use a different size and font-family for the numbering on an ordered list.

ol ::marker {
  font-size: 200%;
  color: #00b7a8;
  font-family: "Comic Sans MS", cursive, sans-serif;
}

You can see all of these in a supporting browser by using my CodePen example:

See the Pen [Colored bullets with and without marker](https://codepen.io/rachelandrew/penVJQyoR) by Rachel Andrew.

See the Pen Colored bullets with and without marker by Rachel Andrew.

You could use the ::marker pseudo-element on non-list items. In the code below, I have set a heading to display: list-item. This gives it a bullet and therefore a ::marker box to target.

I have changed the bullet to use an emoji:

h1 {
  display: list-item;
}

h1::marker {
  content: "🐱";
}

 Heading with a cat emoji to the left of it

In Firefox, you can see the emoji used as a marker.

See the Pen [Heading and marker](https://codepen.io/rachelandrew/pen/wLyyMG) by Rachel Andrew.

See the Pen Heading and marker by Rachel Andrew.

In the above example, I have used generated content in the rules for the marker. Only a small subset of CSS properties is available for use on ::marker. These include font properties and color, however, they also include the content property, for including generated content.

The addition of content as an allowed property for ::marker is recent, however, it is included in the Firefox implementation. The inclusion means that you can do things like include a string of text in a ::marker. It also raises additional possibilities for formatting of markers when you combine the use of counters with ::marker.

Browser Support And Fallbacks

For browsers that do not support the ::marker pseudo-element, the fallback is the regular marker that would have been displayed anyway. Unfortunately, we can’t currently use Feature Queries to detect support for selectors such as this pseudo-element right now, although there has been an issue raised about adding this to the specification. This means that you can’t fork your code to do one thing when you have support and something else if you do not. In most cases, falling back to the regular marker will be a reasonable solution.

Counters

Ordered lists have list numbering — something which is achieved by way of a CSS Counter. The CSS Lists specification therefore also describes these counters. We can access and create counters ourselves which, combined with the ::marker pseudo-element can give us some useful functionality. These counters can also be used in regular (non ::marker) generated content.

If I have a numbered list of steps (and I would like to write out “Step 1”, “Step 2”, and so on), I can do this by using generated content in my marker and appending the list-item counter, this represents the built-in counter:

::marker {
  content: "Step " counter(list-item) ": ";
}

An ordered list with Step 1, Step 2, and so on, before each list item

In Firefox, you will see the counter prefixed with the word “Step”.

See the Pen [Counters and marker](https://codepen.io/rachelandrew/pen/BgRaoz) by Rachel Andrew.

See the Pen Counters and marker by Rachel Andrew.

Nested Counters

If you have nested lists, a common way to number them is to have the top-level item a whole number, (1), then child items as (1.1, 1.2) and their children (1.1.1, 1.1.2), and so on. You can achieve this by using more functionality of counters.

When you nest HTML lists, you will end up with multiple counters of the same name — nested inside each other. The nest of counters can be accessed using the counters() function.

In the code below, I am using counters() to format my list markers as described above. The first argument for counters() is the name of the counter to use. I’m using the built-in list-item counter. The second argument is a string — this is what will be concatenated between output counters (I’m using a .). Finally, I add a : outside of the counter function but inside the value of content so that my counter output will be separated from the content by a colon.

::marker {
  content: counters(list-item,'.') ':';
  color: #00b7a8;
  font-weight: bold;
}

This gives me the output as in the image. If you are using a browser which supports ::marker and counters, then you can see it working in the CodePen example — try changing the string from a . to something else to see how that changes the output.

A set of nested lists

In Firefox, you will see nested list numbering separated by dots.

See the Pen [Nested counters](https://codepen.io/rachelandrew/pen/VJbwxL) by Rachel Andrew.

See the Pen Nested counters by Rachel Andrew.

What’s The Difference Between counter() And counters()?

The counter() function we used in the first example to write out our steps uses the innermost counter only. Therefore, in the situation where you have a set of nested lists, you will write out the counter which related to the level you are currently on.

The counters() function essentially writes out that whole branch and gives you the opportunity to concatenate a string between counters in the branch. So if you have a list item with a counter of 2 (which is part of a list nested inside a list item with a counter of 4), then the branch contains:

  • 4
  • 2

You can output this as 4.2 in the marker by using:

::marker {
  content: counters(list-item,'.');
}

Counters On Other Elements

Counters can be used on things which are not lists — either to output a marker — in which case the element will need to have display: list-item — or to output regular generated content. Counters are used extensively in book production, in order to enable chapter and figure numbering amount other things. There is no reason not to take a similar approach on the web, in particular for longer articles.

The CSS properties defined in the CSS Lists specification which deal with these counters are:

  • counter-set
  • counter-reset
  • counter-increment

To see how these work outside of lists we can look at an example of using counters to number the headings in a document.

The first thing I need to do is to create a counter for headers on the body element — ready for use. I’m using the counter-reset property to do this. The counter-reset and counter-set properties are very similar. The counter-reset property will create a new counter if a counter of the specified name does not already exist, but will also create nested counters as described above if a counter of that name does exist. The counter-set property will only create a new counter if there is no counter of that name. For this, use either property would work just fine, however, counter-set does not have as good browser support as counter-reset, so I am taking the practical route:

body {
  counter-reset: heading-counter;
}

Now that I have a counter, I can then use the counter-increment property on the selector for the headers; this should increment the counter every time the selector matches.

h2 {
  counter-increment: heading-counter;
}

To see the value, I need to output it to the document. I can do this by using Generated Content and adding it before the heading as shown in the following CodePen example:

h2::before {
  content: counter(heading-counter) ": ";
  color: #00b7a8;
  font-weight: bold;
}

See the Pen [Headings and counters](https://codepen.io/rachelandrew/pen/gNGjxq) by Rachel Andrew.

See the Pen Headings and counters by Rachel Andrew.

Alternatively, I could make the h2 element into a list-item and then use ::marker, as demonstrated below. As already detailed, using the ::marker element has limited browser support. In Firefox, you should see the counter used as the marker for the heading, while other browsers will show the default bullet.

h2 {
  display: list-item;
}

h2::marker {
  content: counter(heading-counter)  ": ";
  color: #00b7a8;
  font-weight: bold;
}

See the Pen [Headings, markers, and counters](https://codepen.io/rachelandrew/pen/pXWZay) by Rachel Andrew.

See the Pen Headings, markers, and counters by Rachel Andrew.

Counters On Form Elements

There is also a little bit of interactivity that you can achieve using CSS Counters — something that you might think you need JavaScript to do.

I have a form which has a number of required fields. The required status can be selected in CSS with a :required pseudo-class, and the fact that a field has not been completed can be detected by way of the :invalid pseudo class. This means that we can check for fields which are both required and invalid, and increment a counter. Then output that as generated content.

See the Pen [Counting required form fields](https://codepen.io/rachelandrew/pen/vqpJdM) by Rachel Andrew.

See the Pen Counting required form fields by Rachel Andrew.

How useful this is in reality is debatable — given that we can’t really do anything with that value other than stick it into generated content. There are also concerns with regard to generated content being inaccessible to certain screen readers, therefore any usage that is more than decorative would need to ensure other ways of accessing that information. Read, “Accessibility Support For CSS Generated Content” and the more recent information, “CSS Content Property Screen Reader Compatibility” for more details regarding accessibility and generated content.

However, it demonstrates that counters can achieve more useful things than simply numbering lists. It may be that one day that knowledge does come in handy to solve some problem you are working on.

Find Out More

This article ended up rather a long way from styling lists, despite the fact that everything I have described is found in the CSS Lists specification. You can find more information about the things described in the links below. If you have found an interesting use for CSS Counters, or can think of things you could use ::marker for, add a note in the comments.

Smashing Editorial
(il)

Source: Smashing Magazine, CSS Lists, Markers, And Counters

How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 2)

dreamt up by webguru in Uncategorized | Comments Off on How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 2)

How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 2)

How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 2)

Matt Curtis



As mentioned in part 1, this tutorial is intended for people who know and use the Sketch app and are not afraid of dabbling with code as well. To profit from it the most, you will need to have at least some basic experience writing JavaScript (and, optionally, HTML/CSS).

In the previous part of this tutorial, we learned about the basic files that make up a plugin, and how to create the plugin’s user interface. In this second and final part, we’ll learn how to connect the user interface to the core plugin code and how to implement the plugin’s main features. Last but not least, we’ll also learn how to optimize the code and the way the plugin works.

Building The Plugin’s User Interface: Making Our Web Interface And The Sketch Plugin Code “Talk” To Each Other

The next thing we need to do is to set up communication between our web interface and the Sketch plugin.

We need to be able to send a message from our web interface to the Sketch plugin when the “Apply” button in our web interface is clicked. This message needs to tell us about what settings the user has input — like the number of steps, rotation amount, the number of duplicates to create, and so on.

WKWebView makes this task a little bit easier for us: we can send messages to our Sketch plugin from our web interface’s JavaScript code by using the window.webkit.messageHandlers API.

On our Sketch code’s side, we can use another method, addScriptMessageHandler:name: (or addScriptMessageHandler_name) to register a message handler that will be called whenever it receives a message sent from our plugin web interface.

Let’s start by making sure we can receive messages from our web UI. Head over to our ui.js file’s createWebView function, and add the following:

function createWebView(pageURL){
        const webView = WKWebView.alloc().init();

        //        Set handler for messages from script

        const userContentController = webView.configuration().userContentController();
        
        const ourMessageHandler = ...

        userContentController.addScriptMessageHandler_name(
                ourMessageHandler, "sketchPlugin"
        );

        //        Load page into web view

        webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent());

        return webView;
};

Here we use the web view’s userContentController property to add a message handler we’ve named “sketchPlugin”. This “user content controller” is the bridge that ensures messages get across from our web view.

You might have noticed something odd about the above code: the object we’re adding as the message handler, ourMessageHandler, doesn’t exist yet! Unfortunately, we can’t just use a regular JavaScript object or function as the handler, as this method expects a certain kind of native object.

Luckily for us, we can get around this limitation by using MochaJSDelegate, a mini-library I wrote that makes it possible to create the kind of native object we need using regular ol’ JavaScript. You’ll need to manually download and save it in your plugin bundle under Sketch/MochaJSDelegate.js.

In order to use it, we’ll need to first import it into ui.js. Add the following at the top of the file:

const MochaJSDelegate = require("./MochaJSDelegate");

Now we can use MochaJSDelegate to create the type of message handler addScriptMessageHandler:name: is expecting:

function createWebView(pageURL){
        const webView = WKWebView.alloc().init();

        //        Set handler for messages from script

        const userContentController = webView.configuration().userContentController();

        const scriptMessageHandler = new MochaJSDelegate({
                "userContentController:didReceiveScriptMessage:": (_, wkMessage) => {
                        /* handle message here */
                }
        }).getClassInstance();

        userContentController.addScriptMessageHandler_name(
                scriptMessageHandler, "sketchPlugin"
        );

        //        Load page into web view

        webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent());

        return webView;
};

The code we just added creates the native object we need. It also defines a method on that object named userContentController:didReceiveScriptMessage: — this method is then called with the message we want as the second argument. Since we’re not actually sending any messages yet, we’ll have to come back here at a later time and add some code to actually parse and handle the messages we receive.

Next, we need to add some code to our web interface to send us those messages. Head over to /Resources/web-ui/script.js. You’ll find I’ve already written most of the code that handles retrieving the values of the HTML <inputs /> the user will enter their options into.

What’s still left for us to do is to add the code that actually sends the values over to our Sketch code:

Find the apply function and add the following to the end of it:

//        Send user inputs to sketch plugin

window.webkit.messageHandlers.sketchPlugin.postMessage(JSON.stringify({
        stepCount, startingOptions, stepOptions
}));

Here we use window.webkit.messageHandlers API we mentioned earlier to access the message handler we registered above as sketchPlugin. Then send a message to it with a JSON string containing the user’s inputs.

Let’s make sure everything is set up properly. Head back to /Sketch/ui.js. In order to make sure we’re getting messages as we expect, we’ll modify the method we defined earlier so that it displays a dialog when we get a message:

function createWebView(pageURL){
        // ...

        const scriptMessageHandler = new MochaJSDelegate({
                "userContentController:didReceiveScriptMessage:": (_, wkMessage) => {
                        const UI = require("sketch/ui");
                        
                        UI.alert("Hey, a message!", wkMessage.body());
                }
        }).getClassInstance();

        userContentController.addScriptMessageHandler_name(
                scriptMessageHandler, "sketchPlugin"
        );

        // ...
};

Now run the plugin (you may need to first close any existing Mosaic window you have opened), enter some values, then click “Apply”. You should see an alert like the one below — this means everything is wired up correctly and our message went through successfully! If not, go back over the previous steps and ensure that everything was done as described.

Image showing the dialog you should see after clicking the ‘apply’ button in the plugin’s UI.

The dialog you should see appear once you click Apply. (Large preview)

Now that we’re able to send messages from our interface to our plugin, we can move on to writing the code that actually does something useful with that information: generating our layer mosaics.

Generating The Layer Mosaics

Let’s take stock of what’s necessary in order to make this happen. Simplifying things a bit, what our code needs to do is:

  1. Find the current document.
  2. Find the current document’s selected layer.
  3. Duplicate the selected layer (we’ll call it the template layer) x number of times.
  4. For each duplicate, tweak its position, rotation, opacity, etc., by the specific values (amounts) set by the user.

Now that we’ve got a reasonable plan, let’s continue writing. Sticking with our pattern of modularizing our code, let’s create a new file, mosaic.js in the Sketch/ folder, and add to it the following code:

function mosaic(options){

};

module.export = mosaic;

We’ll use this function as the only export of this module since it makes for a simpler API to use once we import it — we can just call mosaic() with whatever options we get from the web interface.

The first two steps we need to take are getting the current document, and then its selected layer. The Sketch API has a built-in library for document manipulation which we can get access to by importing the sketch/dom module. We only need the Document object right now, so we’ll pull it out explicitly. At the top of the file, add:

const { Document } = require("sketch/dom");

The Document object has a method specifically for accessing the current document we can use, called getSelectedDocument(). Once we have the current document instance, we can access whatever layers the user has selected via the document’s selectedLayers property. In our case, though, we only care about single-layer selections, so we’ll only grab the first layer the user has selected:

function mosaic(options){
        const document = Document.getSelectedDocument();
        const selectedLayer = document.selectedLayers.layers[0];
};

module.export = mosaic;

Note: You might have been expecting selectedLayers itself to be an array, but it’s not. Instead, it’s an instance of the Selection class. There’s a reason for this: the Selection class contains a bunch of useful helper methods for manipulating the selection like clear, map, reduce, and forEach. It exposes the actual layer array via the layer property.

Let’s also add some warning feedback in case the user forgets to open a document or to select something:

const UI = require("sketch/ui");

function mosaic(options){
        const document = Document.getSelectedDocument();

        //        Safety check:

        if(!document){
                UI.alert("Mosaic", "⚠️ Please select/focus a document.");

                return;
        }

        //        Safety check:

        const selectedLayer = document.selectedLayers.layers[0];

        if(!selectedLayer){
                UI.alert("Mosaic", "⚠️ Please select a layer to duplicate.");
                
                return;
        }
};

module.export = mosaic;

Now that we’ve written the code for steps 1 and 2 (finding the current document and selected layer), we need to address steps 3 and 4:

  • Duplicate the template layer x number of times.
  • For each duplicate, tweak its position, rotation, opacity, etc., by the specific values set by the user.

Let’s start by pulling all the relevant information we need out of options: the number of times to duplicate, starting options, and step options. We can once again use destructuring (like we did earlier with Document) to pull those properties out of options:

function mosaic(options) {
        //        ...
        
        //        Destructure options:

        var { stepCount, startingOptions, stepOptions } = options;
}

Next, let’s sanitize our inputs and ensure that step count is always at least 1:

function mosaic(options) {
        //        ...
        
        //        Destructure options:
        
        var { stepCount, startingOptions, stepOptions } = options;
        
        stepCount = Math.max(1, stepCount);
}

Now we need to make sure that the template layer’s opacity, rotation, etc., all match up with the user’s desired starting values. Since applying the user’s options to a layer is going to be something we’ll do a lot of, we’ll move this work into its own method:

function configureLayer(layer, options, shouldAdjustSpacing){
        const { opacity, rotation, direction, spacing } = options;

        layer.style.opacity = opacity / 100;
        layer.transform.rotation = rotation;

        if(shouldAdjustSpacing){
                const directionAsRadians = direction * (Math.PI / 180);
                const vector = {
                        x: Math.cos(directionAsRadians),
                        y: Math.sin(directionAsRadians)
                };

                layer.frame.x += vector.x * spacing;
                layer.frame.y += vector.y * spacing;
        }
};

And because spacing only needs to be applied in-between the duplicates and not the template layer, we’ve added a specific flag, shouldAdjustSpacing, that we can set to true or false depending on whether we’re applying options to a template layer or not. That way we can ensure that rotation and opacity will be applied to the template, but not spacing.

Back in the mosaic method, let’s now ensure that the starting options are applied to the template layer:

function mosaic(options){
        //        ...
        
        //        Configure template layer

        var layer = group.layers[0];
        
        configureLayer(layer, startingOptions, false);
}

Next, we need to create our duplicates. First, let’s create a variable that we can use to track what the options for the current duplicate are:

function mosaic(options){
        //        ...

        var currentOptions; // ...
}

Since we already applied the starting options to the template layer, we need to take those options we just applied and add the relative values of stepOptions in order to get the options to apply to the next layer. Since we’ll also be doing this several more times in our loop, we’ll also move this work into a specific method, stepOptionsBy:

function stepOptionsBy(start, step){
        const newOptions = {};
        
        for(let key in start){
                newOptions[key] = start[key] + step[key];
        }

        return newOptions;
};

After that, we need to write a loop that duplicates the previous layer, applies the current options to it, then offsets (or “steps”) the current options in order to get the options for the next duplicate:

function mosaic(options) {
        //        ...
        
        var currentOptions = stepOptionsBy(startingOptions, stepOptions);

        for(let i = 0; i < (stepCount - 1); i++){
                let duplicateLayer = layer.duplicate();

                configureLayer(duplicateLayer, currentOptions, true);

                currentOptions = stepOptionsBy(currentOptions, stepOptions);
                layer = duplicateLayer;
        }
}

All done — we’ve successfully written the core of what our plugin is supposed to do! Now, we need to wire things up so that when the user actually clicks the “Apply” button our mosaic code is invoked.

Let’s head back to ui.js and adjust our message handling code. What we’ll need to do is parse the JSON string of options we’re getting so that they’re turned into an object we can actually use. Once we have these options, we can then call the mosaic function with them.

First, parsing. We’ll need to update our message handling function to parse the JSON message we get:

function createWebView(pageURL){
        //        ...
        
        const scriptMessageHandler = new MochaJSDelegate({
                "userContentController:didReceiveScriptMessage:": (_, wkMessage) => {
                        const message = JSON.parse(wkMessage.body());
                }
        });
}

Next, we’ll need to pass this over to our mosaic function. However, this isn’t really something our code in ui.js should be doing — it’s supposed to be primarily concerned with what’s necessary to display interface-related things on screen — not creating mosaics itself. To keep these responsibilities separate, we’ll add a second argument to createWebView that takes a function, and we’ll call that function whenever we receive options from the web interface.

Let’s name this argument onApplyMessage:

function createWebView(pageURL, onApplyMessage){
        // ...
        
        const scriptMessageHandler = new MochaJSDelegate({
                "userContentController:didReceiveScriptMessage:": (_, wkMessage) => {
                        const message = JSON.parse(wkMessage.body());
                        
                        onApplyMessage(message);
                }
        });
}

We’ll also need to modify our exported method, loadAndShow, to take this onApplyMessage argument as well and pass it off to createWebView:

function loadAndShow(baseURL, onApplyMessage){
        //        ...
        
        const webView = createWebView(pageURL, onApplyMessage);
}

Finally, head over to main.js. We now need to import our mosaic function, and call it with the options we receive from the plugin’s user interface:

const mosaic = require("./mosaic");

function onRun(context){
        UI.loadAndShow(context.scriptURL, options => {
                mosaic(options);
        });
};

We’re almost done!

However, if we ran our code now and clicked the “Apply” button in the plugin interface, nothing would happen. Why? The reason is due to how Sketch scripts are run: by default, they “live” only until the bottom of your script is reached, after which Sketch destroys it and frees up whatever resources it was using.

This is a problem for us since it means that anything we need to have asynchronously happen (in this case, that’s after the bottom of our code is reached), like receiving messages, cannot, because our script has been destroyed. This means we wouldn’t get any of our messages from the web interface since we’re not around to receive and respond to them!

There’s a way to signal to Sketch that we need our script to stay alive beyond this point, using Fibers. By creating a Fiber, we tell Sketch that something asynchronous is happening and that it needs to keep our script around. Sketch will then only destroy our script when absolutely necessary (like the user closing Sketch, or when the Mosaic plugin needs to be updated):

//        ...

const Async = require("sketch/async");

var fiber;

function onRun(context){
    if(!fiber){
        fiber = Async.createFiber();
        fiber.onCleanup(() => {
            UI.cleanup();
        });
    }
    
    UI.loadAndShow(context.scriptURL, options => {
        mosaic(options);
    });
};

Voilà! Let’s try out our plugin now. With a layer selected in Sketch, enter some settings, then click apply:

Let’s try out our plugin now — with a layer selected in Sketch, enter some settings, then click “Apply.”

Final Improvements

Now that we’ve got the majority of our plugin’s functionality implemented, we can try to “zoom out” a bit and take a look at the big picture.

Improving The User’s Experience

If you’ve played around with the plugin in its current state, you might’ve noticed that one of the biggest points of friction appears when you try to edit a Mosaic. Once you create one, you have to hit undo, adjust the options, then click ‘Apply’ (or press Enter). It also makes it harder to edit a Mosaic after you’ve left your document and returned to it later, since your undo/redo history will have been wiped out, leaving you to manually delete the duplicate layers yourself.

In a more ideal flow, the user could just select a Mosaic group, adjust options and watch the Mosaic update until they get the exact arrangement they’re looking for. To implement this, we have two problems to solve:

  1. First, we’ll need a way to group the duplicates that make up a Mosaic together. Sketch provides the concept of Groups, which we can use to solve this problem.
  2. Second, we’ll need a way to tell the difference between a normal, user-created group and a Mosaic group. Sketch’s API also gives us a way to store information on any given layer, which we can use as a way tag and later identify a group as one of our ‘special’ Mosaic groups.

Let’s revisit the logic we wrote in the previous section to address this. Our original code follows the following steps:

  1. Find the current document.
  2. Find the current document’s selected layer.
  3. Duplicate the selected layer (we’ll call it the template layer) x number of times.
  4. For each duplicate, tweak its position, rotation, opacity, etc., by the specific values (amounts) set by the user.

In order to make our new user flow possible, we need to change these steps to:

  1. Grab the current document.
  2. Grab the current document’s selected layer.
  3. Determine whether the selected layer is a Mosaic group or not.
    • If it’s some other layer, use it as the template layer and go to step 4.
    • If it is a Mosaic group, consider the first layer in it as the template layer, and go to step 5.
  4. Wrap the template layer inside a group, and mark that group as a Mosaic group.
  5. Remove all layers from inside the group except the template layer.
  6. Duplicate the template layer x number of times.
  7. For each duplicate, tweak its position, rotation, opacity, etc., by the specific values set by the user.

We’ve got three new steps. For the first new step, step 3, we’ll create a function named findOrMakeSpecialGroupIfNeeded that will look at the layer passed to it to determine whether or not it’s a Mosaic group. If it is, we’ll just return it. Since the user could potentially select a sublayer nested deep in a Mosaic group, we’ll also need to check the parents of the selected layer to tell if they’re one of our Mosaic groups as well:

function findOrMakeSpecialGroupIfNeeded(layer){
        //        Loop up through the parent hierarchy, looking for a special group

        var layerToCheck = layer;

        while(layerToCheck){
                if(/* TODO: is mosaic layer? */){
                        return layerToCheck;
                }

                layerToCheck = layerToCheck.parent;
        }
};

If we weren’t able to find a Mosaic group we’ll simply wrap the layer we were passed inside a Group, then tag it as a Mosaic group.

Back at the top of the file, we’ll need to pull out the Group class now too:

const { Document, Group } = require("sketch/dom");
function findOrMakeSpecialGroupIfNeeded(layer){
        //        Loop up through the parent hierarchy, looking for a special group

        var layerToCheck = layer;

        while(layerToCheck){
                if(/* TODO: is mosaic layer? */){
                        return layerToCheck;
                }

                layerToCheck = layerToCheck.parent;
        }
        
        //        Group

        const destinationParent = layer.parent;
        const group = new Group({
                name: "Mosaic Group",
                layers: [ layer ],
                parent: destinationParent
        });
        
        /* TODO: mark group as mosaic layer */
        
        return group;
};

Now we need to fill in the gaps (todo’s). To begin with, we need a means of identifying whether or not a group is one of the special groups belonging to us or not. Here, the Settings module of the Sketch library comes to our rescue. We can use it to store custom information on a particular layer, and also to read it back.

Once we import the module at the top of the file:

const Settings = require("sketch/settings");

We can then use two key methods it provides, setLayerSettingForKey and layerSettingForKey, to set and read data off a layer:

function findOrMakeSpecialGroupIfNeeded(layer){
        const isSpecialGroupKey = "is-mosaic-group";

        //        Loop up through the parent hierarchy, looking for a special group

        var layerToCheck = layer;

        while(layerToCheck){
                let isSpecialGroup = Settings.layerSettingForKey(layerToCheck, isSpecialGroupKey);

                if(isSpecialGroup) return layerToCheck;

                layerToCheck = layerToCheck.parent;
        }
        
        //        Group

        const destinationParent = layer.parent;

       layer.remove(); // explicitly remove layer from it’s existing parent before adding it to group

        const group = new Group({
                name: "Mosaic Group",
                layers: [ layer ],
                parent: destinationParent
        });
        
        Settings.setLayerSettingForKey(group, isSpecialGroupKey, true);

        return group;
};

Now that we’ve got a method that handles wrapping a layer in a mosaic group (or, if already a mosaic group, just returns it) we can now plug it into our main mosaic method just after our safety checks:

function mosaic(options){
        //       ... safety checks ...

        //        Group selection if needed:

        const group = findOrMakeSpecialGroupIfNeeded(selectedLayer);
}

Next we’ll add a loop to remove all layers from the group except the template layer (which is the first):

function mosaic(options) {
        //        ...
        
        //        Remove all layers except the first:
        
        while(group.layers.length > 1){
                group.layers[group.layers.length - 1].remove();
        }
}

Lastly, we’ll make sure that the group’s size is fitted to its new contents since the user might have originally selected a layer nested within the old group (a layer that we might have removed).

We’ll also need to make sure to set the current selection to our mosaic group itself. This will ensure that if the user is making a bunch of rapid changes to the same mosaic group it won’t become deselected. After the code we already wrote to duplicate a layer, add:

function mosaic(options) {
        //        ...
        
        //        Fit group to duplicates

        group.adjustToFit();

        //        Set selection to the group

        document.selectedLayers.clear();
        group.selected = true;
}

Try out the plugin again. You should find that editing a mosaic is much smoother now!

Improving The Interface

One other thing you might notice is the lack of synchronization between the display window and the interface inside it, in terms of them both becoming visible at the same time. This is due to the fact that when we display the window, the web interface isn’t guaranteed to have finished loading, so sometimes it’ll “pop” or “flash in” afterwards.

One way to fix this is by listening for when the web interface has finished loading, and only then show our window. There is a method, webView:didFinishNavigation:, that WKWebView will call when the current page has finished loading. We can use it to get exactly the notification we’re looking for.

Back in ui.js, we’ll extend the MochaJSDelegate instance we created to implement this method, which will in turn call the onLoadFinish argument we’ll pass to createWebView:

function createWebView(pageURL, onApplyMessage, onLoadFinish){
        const webView = WKWebView.alloc().init();

        //        Create delegate

        const delegate = new MochaJSDelegate({
                "webView:didFinishNavigation:": (webView, navigation) => {
                        onLoadFinish();
                },
                "userContentController:didReceiveScriptMessage:": (_, wkMessage) => {
                        const message = JSON.parse(wkMessage.body());
                        
                        onApplyMessage(message);
                }
        }).getClassInstance();

        //        Set load complete handler

        webView.navigationDelegate = delegate;

        //        Set handler for messages from script

        const userContentController = webView.configuration().userContentController();

        userContentController.addScriptMessageHandler_name(delegate, "sketchPlugin");

        //        Load page into web view

        webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent());

        return webView;
};

And back in the loadAndShow method, we’ll adjust it so that it only shows the window once the web view has loaded:

function loadAndShow(baseURL, onApplyMessage){
        //        ...

        const window = createWindow();
        const webView = createWebView(pageURL, onApplyMessage, () => {
                showWindow(window);
        });

        window.contentView = webView;

        _window = window;
};

Bingo! Now our window displays only when the web view has finished loading, avoiding that annoying visual flicker.

Conclusion

Congratulations, you’ve built your first Sketch plugin! 🎉

If you’d like to install and play around with Mosaic, you can download the complete plugin from GitHub. And before you go, here are a few resources that might be handy during the rest of your journey:

  • developer.sketchapp.com
    The official resource regarding Sketch plugin development. Contains several useful guides, as well as an API reference for the Sketch JavaScript library.
  • sketchplugins.com
    A fantastic and helpful community of Sketch plugin developers. Great for getting all your burning questions answered.
  • github.com/sketchplugins/plugin-directory
    Official, central GitHub repository of Sketch plugins. You can submit your plugins here and share them with the rest of the Sketch community!
Smashing Editorial
(mb, yk, il)

Source: Smashing Magazine, How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 2)

How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 1)

dreamt up by webguru in Uncategorized | Comments Off on How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 1)

How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 1)

How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 1)

Matt Curtis



This tutorial is intended for people who know and use the Sketch app and are not afraid of dabbling with code. To profit from it the most, you will need to have at least some basic experience writing JavaScript (and, optionally, HTML/CSS).

The plugin we’ll be creating is called “Mosaic”. In part one, we’ll learn about the basic files that make up a Sketch plugin; we’ll write some JavaScript and create a user interface for our plugin with the help of some HTML and CSS. The next article will be about how to connect the user interface to the core plugin code, how to implement the plugin’s main features, and at the end of it, you will also learn how to optimize the code and the way the plugin works.

I’ll also be sharing the plugin’s code (JS, HTML, CSS) and files which you’ll be able to examine and use for learning purposes.

What Are Sketch Plugins, And How Do They Work?

In Sketch, plugins are a way to add features and functionality that aren’t present in Sketch “out of the box.” Considering that there’s almost always going to be some missing feature or integration in any given program (especially given the vast number of needs any individual designer might have!), one can begin to imagine how plugins might be especially useful and powerful. Sketch plugins are able to do pretty much everything you’d expect, like manipulating the color, shape, size, order, style, grouping, and effects of layers, but also able to do things like make requests to internet resources, present a user interface, and much, much more!

On the programming side, all Sketch plugins are written in JavaScript code. Well, actually, that’s not entirely true. It’s more accurate to say that most Sketch plugins are written in JavaScript, as it’s also possible to write a Sketch plugin in one of Apple’s programming languages, Objective-C and Swift, though even they require a small amount of JavaScript knowledge.

Don’t worry though. In this article, we’ll focus on how to build Sketch plugins using JavaScript, HTML, and CSS alone. We won’t be going over the basics of HTML, CSS, or JavaScript — this article assumes at least some knowledge and experience with all of these three. The MDN developer website provides a great place to learn more about web development.

Let’s Get Started!

Firstly, What Are We Making?

In this tutorial, I’ll teach you how to build a basic, beginner-friendly plugin that will be able to create, duplicate, and modify layers, as well as present the user with a nice user interface. By doing so, my goal is to establish a fundamental knowledge on which you can build on and use it to create your own plugins.

The plugin we’ll be building is called Mosaic, and is effectively a “pattern generator”. Feed it your layers, tweak a few settings, and it’ll create a pattern:

Image showing the Mosaic plugin’s UI, and a few example patterns.

The Mosaic’s UI, and some examples of patterns made with it. (Large preview)

If you’d like to install and play around with Mosaic, you can download the completed plugin from GitHub.

A bit of history: Mosaic is inspired in large part by an old-school Adobe Fireworks plugin called Twist-and-Fade. Twist-and-Fade was pretty powerful, able to duplicate a layer any number of times while adjusting its hue, position, rotation, size, and opacity. The plugin was even able to generate animated GIFs, like this one, where it created the frames for the two rotating elements in the cassette tape:

Image showing a music cassette tape with rotating drums
Animated cassette tape (source). (Large preview)

(Here’s a video demoing Twist and Fade if you’re interested in seeing exactly how it worked.)

For the purposes of this tutorial, we’ll be building a somewhat similar plugin for Sketch, though intentionally simplified so as to keep the tutorial as accessible as possible. Specifically, our plugin will be able to:

  • Duplicate any Sketch layer (bitmap or vector) and tweak the duplicates’ layer’s position, rotation, and opacity. This will give us an introduction to manipulating layers using Sketch’s JavaScript APIs.
  • Display a user interface created using HTML, CSS, and JS, which will teach you about how to easily create an interface for the plugin, by using web technologies that you may already be familiar with. The plugin interface is pretty important since it’s how we’ll gather the user’s inputs regarding how the user wants the resulting mosaic image to look.

Creating Our Base Plugin In Ten Seconds Flat

First, we’ll be creating the “base” (or template) for the plugin we want to build. We could create all the necessary files and folders that make up a plugin manually, but luckily we don’t have to — because Sketch can do it for us. After we’ve generated the template plugin, we’ll be able to customize it as we see fit.

There’s a really quick and easy technique we can use to create the template plugin, which is pretty much my go-to method when I need to whip a plugin together to solve whatever problem I’m dealing with at a given moment. Here’s how it works:

With Sketch open, check the menu bar at the top of the screen and click Plugins -> Run Script. This will open up a dialog box that we can use to test and run the code. We can also save any code we enter in it as a plugin, which is the part we’re specifically interested in right now.

Clear whatever code is already in this dialog and replace it with the following demo code:

const UI = require("sketch/ui");

UI.message("😍 Hey there, you fantastic plugin developer you! This is your plugin! Talking to you from the digital computer screen! In Sketch! Simply stupendous!");

Next, hit Save Script as Plugin in the bottom-left of the window, enter whatever name you’d like for this plugin to have (in our case, this is “Mosaic”), then Save Script as Plugin once more.

Press “Save” in the bottom-left of the window and enter whatever name you’d like for this plugin to have. (Large preview)

Believe it or not, we’re already done — all that’s left is to eat the cake we just baked. Here comes the fun part. Opening the Plugins menu once again, you should see something like this: your brand-spanking-new plugin listed as “Mosaic”! Click on it!

(Large preview)

Congratulations, you’ve just written your first Sketch plugin!

What you should see after clicking “Mosaic” should be like the short video above, with an unobtrusive tooltip message appearing at the bottom of the screen beginning with the words “Hey there…” — which is exactly what the code we pasted in tells it to do. This is what it makes this technique so great: it makes it easy to paste, modify and test code without having to build a plugin from scratch. If you’re familiar with or have ever played with your browser’s web console, this is basically that. Having this tool in your back pocket as you build and test code is a must-have.

Let’s do a quick rundown of what the code you added does:

First, it imports the sketch/ui module of Sketch’s built-in JS library, and assigns it to the UI variable. This module contains a couple of useful interface-related methods, one of which we’ll use:

const UI = require("sketch/ui");

Next, it calls the message method (which is part of the sketch/ui module) with the string of text we want displayed in the tooltip we saw:

UI.message("😍 Hey there, you fantastic plugin developer you! This is your plugin! Talking to you from the digital computer screen! In Sketch! Simply stupendous!");

The message() method provides a great way to present an unobtrusive message to the user; it’s great for cases where you don’t need to steal focus (non-modal) and don’t need any fancy buttons or text fields. There’s also other ways to present common UI elements like alerts, prompts, and such, some of which we’ll be using as we build Mosaic.

Customizing Our Plugin’s Metadata

We now have a basic plugin to start from, but we still need to tweak it further and make it truly ours. Our next step will be to change the plugin’s metadata.

For this step, we’ll need to peek into what’s called the plugin bundle. When you hit save in the ‘Run Script’ window, Sketch saved your plugin as a folder named Mosaic.sketchplugin that you can find in the
~/Library/Application Support/com.bohemiancoding.sketch3/Plugins directory. That’s a bit long and annoying to remember; as a shortcut, you can also pull it up via Plugins -> Manage Plugins -> (right-click your plugin) -> Reveal Plugins Folder. Even though it appears in Finder as a single file, it’s actually a folder containing everything our plugin needs for Sketch to run it. The reason it appears as a single file despite being a folder is because when you first installed Sketch, Sketch registered the .sketchplugin extension as a “bundle” (a special kind of folder that appears as a file) and asked for it to automatically open in Sketch when opened.

Let’s take a peek inside. Right-click Mosaic.sketchplugin, then click “Show Package Contents”. Inside, you should see the following directory structure:

Contents/
└ Resources/
└ Sketch/
  └ manifest.json
  └ script.cocoascript

You might be wondering why there’s a file in there with the extension .cocoascript. Don’t worry — it’s just a regular JavaScript file, and only contains the code we entered earlier. Go ahead and rename this file to index.js, which will change the directory structure to look like the one below:

Contents/
└ Resources/
└ Sketch/
  └ manifest.json
  └ index.js

The most common way of organizing the files inside a plugin bundle is as follows: your code (JavaScript) and manifest.json belong in Sketch/, and resources (think images, audio files, text files, etc.) belong in Resources/.

Let’s start by tweaking the file named manifest.json. Open it inside your favorite code editor, such as Visual Studio Code or Atom.

You’ll see that at the moment there’s relatively little inside here, but we’ll add more soon. The plugin manifest serves primarily two purposes:

  1. First, it provides metadata that describes the plugin to the user — things like its name, version, the author’s name, and so on. Sketch uses this information in the Sketch -> Preferences -> Plugins dialog to create a listing and description for your plugin.
  2. Second, it also tells Sketch about how to get down to your business; that is, it tells Sketch how you’d like your plugin’s menu to look, what hotkeys to assign to your plugin, and where your plugin’s code lives (so Sketch can run it).

Considering purpose #1, describing the plugin to the user, you’ll probably notice that right now there’s no description or author given, which would be confusing for the user and make the plugin difficult to identify. Let’s fix that by adjusting the relevant keys’ values to:

{
        "description": "Generate awesome designs and repeating patterns from your layers!",
        "author": "=> Your name here <="
}

Next, let’s adjust the plugin’s identifier. This identifier uses what is called a “reverse domain notation” which is a really concise (or boring, take your pick) way to say “take your site’s domain, reverse the order, then put your product’s name at the end.” This will come out something like: com.your-company-or-your-name-its-not-that-big-a-deal.yourproduct.

You don’t have to stick to this naming convention — you can put whatever you want here, so long as it’s unique enough to avoid conflicts with other plugins (though it’s probably a good idea to stick to the RDN format, especially as it provides a simple, reusable system for your plugin identifiers).

To that effect, change your identifier to com.your-name.mosaic:

{
    "identifier": "com.your-name.mosaic"
}

I personally like to take all metadata related keys (title, author, identifier, etc.) and group them near the top of the manifest so they’re not spread out all over the place and help preserve my sanity when I need to find them.

Next, let’s take a look at the menu and commands keys. These two are responsible for telling Sketch what code to call and in response to what.

If you look at the menu key, you’ll see it contains a title key, whose value is the name our plugin will show up with in the Plugins menu. It also has an items key, which is a list of command identifiers:

{
  "menu": {
    "title": "Mosaic",
    "items": [
        "com.bohemiancoding.sketch.runscriptidentifier"
    ]
  }
}

Right now there’s only one command identifier in this list, "com.bohemiancoding.sketch.runscriptidentifier". Command identifiers always point to a command in the commands list. Right now our plugin only has one command, which is the one with this identifier:

{
  "commands": [
    {
      "script" : "script.cocoascript",
      "name" : "Mosaic",
      "handlers" : {
              "run" : "onRun"
      },
      "identifier" : "com.bohemiancoding.sketch.runscriptidentifier"
    }
  ]
}

Whenever you add a command identifier to a menu entry, Sketch will look up the command entry that has that identifier and will display the value of its name key (which in this case is “Mosaic”) and will show it in your plugin’s menu instead of the identifier.

As for the role commands play, we can think of a command entry as a way to tell Sketch what function in our plugin’s JavaScript code we want to run when that command is invoked, the “invocation” usually being the user’s click on the associated menu item. The command entry doesn’t do anything on its own, it’s just JSON — it simply provides a description to Sketch of where to look for the JavaScript it needs to run when the command is invoked.

So far, we’ve talked about what a command’s name and identifier keys do, but there are two other keys in a command that need to be addressed: script and handlers.

The script key tells Sketch where the JavaScript file that it should run is. Note how Sketch assumes that the script file in question is in the Sketch/ folder, which is why for simplicity’s sake you’ll want to make sure all your JavaScript code lives somewhere under the Sketch/ folder. Before we move on from this key it’s important that you make sure you change this key’s value to index.js, just like we renamed the file earlier. Otherwise, Sketch won’t be able to find and run your JavaScript file.

The value of the handlers key is what Sketch looks at to determine what function in your JavaScript to call. Here, we only have one handler set: run, with the value onRun. run is the name of a predefined, built-in Sketch action. This run action will always be called when a user clicks a menu item that references this command. onRun is the name of a function in the auto-generated script.cocoascript file (which we renamed to index.js), and the function we want to be called when the run event occurs, i.e., when the user clicks the menu item.

In the example we have so far, this process plays out something like this:

  1. The user clicks our menu item.
  2. Sketch finds the command associated with that menu item.
  3. Sketch finds the script file the command refers to and runs it (which in this case means it executes the JavaScript in index.js).
  4. Since this command was invoked by a menu item click, it’s considered a run action. That means Sketch will look at the command’s handlers.run value for the function to call next, which in this case is onRun.
  5. Sketch calls the onRun function.

Commands are most commonly called in response to a user clicking on one of your menu items, but they can also be called in response to other user actions, such as the user changing the selection or a property on a layer. However, for this plugin, we won’t be using any of these other actions. (You can learn more about actions and how they work in the Action API help page.)

Before we move on from this manifest, we’ll want to make two other tweaks. Right now, our menu has the structure:

Mosaic
└ Mosaic

Image showing Mosaic menu item redundantly nested inside another menu named Mosaic

Pretty redundant, right? (Large preview)

…which is a bit redundant since our plugin only has one menu item. It also adds a bit of unnecessary friction for our user as our plugin now takes two clicks to invoke rather than one. We can fix this by adding isRoot: true to our menu:

{
  "menu": {
    "title" : "Mosaic",
    "items" : [
            "com.bohemiancoding.sketch.runscriptidentifier"
    ],
    "isRoot": true
}
}

This tells Sketch to place the first level of menu items directly under the Plugins menu, rather than nesting them under the menu’s title.

Hit save and return to Sketch. You should see that now Mosaic -> Mosaic has been replaced by just Mosaic — perfect!

Image showing the Mosaic plugin’s UI

Mosaic’s UI. (Large preview)

As for our second tweak, let’s go ahead and rename this command identifier to something less unwieldy. Since command identifiers only need to be unique within the context of an individual plugin, we can safely rename it to something more concise and obvious, like "open":

{
  "commands": [
    {
            ...
            "identifier" : "open"
    }
],

"menu": {
    ...
    "items" : [
            "open"
    ]
  }
}

Before we move on, it’s useful to note that menus can contain also other menus. You could easily create a sub-menu by nesting another { title: ..., items: ... } entry inside another menu’s items list:

{
  "menu": {
    "title" : "Mosaic",
    "items" : [
      "open",
      {
        "title" : "I'm a sub-menu!",
        "items" : [
                "another-command-identifier"
        ]
      }
    ]
  }
}

Building The Plugin’s User Interface

So far, we’ve written some demo code and customized our plugin’s manifest. We’ll now move on to creating its user interface, which is essentially a web page embedded in a window (similarly to the browsers you’re familiar with using):

The plugin’s window. (Large preview)

Image showing the components making up our plugin’s interface: window and web view

The components making up our plugin. (Large preview)

The Window

Mosaic’s user interface design has its own window, which we can consider the most basic component; we’ll start with it. In order to create and display a window, we’ll have to make use of a class that’s built into macOS by default, called NSWindow. Over the remainder of this tutorial, we’ll actually be doing this quite a bit (using built-in APIs like NSWindow) which might seem a little daunting if you’re unfamiliar with it, but don’t worry — I’ll explain everything along the way!

Note: While we’re talking about built-in APIs, the reason we’re able to use this class at all is thanks to a bridge present in the JavaScript runtime used by Sketch plugins. This bridge automatically imports these built-in classes, methods, and functions that would normally only be available to native applications.

Open Sketch/index.js in your code editor, delete what’s already there, and paste in the following:

function onRun(context){
  const window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
    NSMakeRect(0, 0, 145, 500),
    NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
    NSBackingStoreBuffered,
    false
  );

  window.releasedWhenClosed = false;

  window.makeKeyAndOrderFront(nil);
};

Let’s take a look at what this first bit of code does:

function onRun(context){

Remember earlier when we talked about commands and how they function, and we told Sketch to call in response to a menu-click was called onRun? (If you need a refresher, revisit that part above, then come back.) All this bit does is create that function. You’ll also notice our onRun function takes a context argument. This is an argument Sketch will call your command handlers with that can provide us with certain information. Later on, we’ll use it in order to get the URL of our plugin bundle on the user’s computer.

const window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer(
  NSMakeRect(0, 0, 145, 500),
  NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
  NSBackingStoreBuffered,
  false
);

Here we’re actually doing a few things:

  1. First, we call alloc() on NSWindow; this basically means “set aside some memory for an instance of NSWindow”. It’s sufficient to know that you’ll have to do this for every instance of a native class you want to create. The alloc method is available in every native class.
  2. Next, we call NSWindow’s initializer method (that is, the method that actually creates an instance of NSWindow), which is named initWithContentRect:styleMask:backing:defer:. You’ll notice that’s different from what we call in our code above — it’s got a bunch of colons (:) between every argument. Since we can’t use that syntax in JavaScript, Sketch conveniently renames it to something we can actually use by replacing the colons with underscores, which is how we get its JS name: initWithContentRect_styleMask_backing_defer.
  3. Next, we pass in each of the arguments the method needs. For the first argument, contentRect, we supply a rectangle with a size large enough for our user interface.
  4. For styleMask, we use a bitmask which says that we want our window to have a close button, a title bar, and to be resizable.
  5. The next two arguments, backing and defer, are always going to be set to NSBackingStoreBuffered and false, so we don’t really need to worry about them. (The documentation for this method goes into further detail as to why this is.)
window.releasedWhenClosed = false;

window.makeKeyAndOrderFront(null);

Here we set NSWindow’s releasedWhenClosed property to false, which means: “Hey! don’t delete this window from memory just because the user closes it.” Then we call makeKeyAndOrderFront(null) which means: “Move this window to the forefront, and give it keyboard focus.”

Web View: The Interface

To make things easier, I’ve already written the HTML and CSS code of the plugin’s web user interface we’re going to be using; the only remaining code we’re going to have to add to it will deal with making sure we’re able to communicate between it and our Sketch plugin code.

Next, download the HTML and CSS code. Once you’ve downloaded it, extract it, then move the folder named “web-ui” into our plugin’s Resources folder.

Note: Writing and optimizing the actual HTML/CSS code is outside of the scope of this tutorial, as its focus is on JavaScript which powers the plugin’s core features; but there are a ton of tutorials on the web on this topic, should you want to learn more.

If you run our plugin now, you’ll see that it shows a window — yay, progress! But it’s empty, without a title, and not particularly useful yet. We need to get it to show our web interface. In order to do that, we’ll need to use another native class, WKWebView, which is a view specifically made for displaying web content.

We’ll add the code needed to create our WKWebView beneath the code we wrote for our window:

function onRun(context){
    //        Create window

    const window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer(
            NSMakeRect(0, 0, 145, 500),
            NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
            NSBackingStoreBuffered,
            false
    );

    window.releasedWhenClosed = false;

    //        Create web view, and set it as the view for our window to display

    const webView = WKWebView.alloc().init();

    window.contentView = webView;

    //        Load our UI into the web view

    const webUIFolderURL = context.scriptURL
            .URLByDeletingLastPathComponent()
            .URLByAppendingPathComponent("../Resources/web-ui/");

    const indexURL = webUIFolderURL.URLByAppendingPathComponent("index.html");

    webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL);

    //        Make window key and move to front

    window.makeKeyAndOrderFront(nil);
};

If we run our plugin now, we’ll see that now we’ve got a window open that displays our web user interface. Success!

Again, before moving on, let’s examine what the code we added does:

const webView = WKWebView.alloc().init();

This should look familiar — it’s basically the same as what we did when we made our NSWindow: allocate memory for a web view, then initialize it.

window.contentView = webView;

This line of code tells our window to display the web view we just made.

const webUIFolderURL = context.scriptURL
  .URLByDeletingLastPathComponent()
  .URLByAppendingPathComponent("../Resources/web-ui/");

Here our goal is to create a URL that points to the web-ui folder that we made earlier. In order to get that URL, we need some way to figure out where our plugin’s bundle is in the user’s filesystem. Here we use the context.scriptURL property, which gives us the URL of the currently running script. However, this doesn’t give us a JavaScript String as you might expect, but an instance of a native class, NSURL, that has a few methods on it that make manipulating URL strings easier.

We need to turn what context.scriptURL gives us —

file://path-to-your-plugin/Contents/Sketch/index.js

— into:

file://path-to-your-plugin/Contents/Resources/web-ui/

Step by step:

  1. Calling URLByDeletingLastPathComponent() the first time gives us file://path-to-your-plugin/Contents/Sketch/
  2. Calling URLByDeletingLastPathComponent() again gives us file://path-to-your-plugin/Contents/
  3. And lastly, adding Resources/web-ui/ onto the end using URLByAppendingPathComponent("Resources/web-ui/") gives us file://path-to-your-plugin/Contents/Resources/web-ui/

We also need to create a second URL that points directly to the index.html file:

const indexURL = webUIFolderURL.URLByAppendingPathComponent("index.html");

Finally, we tell our web view to load index.html and give it access to the contents of the web-ui folder:

webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL);

Alright. So far, we have a window that displays our web user interface, just like we wanted. However, it’s not quite yet complete — our original design doesn’t have a title bar (or “chrome”), but our current window does. There’s also the fact that when we click inside a Sketch document, that document moves in front of our window, which isn’t what we want — we want the user to be able to interact with the plugin window and the Sketch document without having to constantly refocus from one window to the other.

To fix this, we first need to get rid of the default window chrome and keep only the buttons. Adding the two lines of code below will get rid of the title bar.

Note: Like before, all of the properties and methods we’re using below are documented in NSWindow’s documentation page.

window.titlebarAppearsTransparent = true;
window.titleVisibility = NSWindowTitleHidden;

These next two lines of code will remove the window buttons (also known as “traffic lights” in MacOS lingo) that we don’t need — “zoom” and “minimize” — leaving only the “close” button:

window.standardWindowButton(NSWindowZoomButton).hidden = true;
window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true;

While we’re at it, let’s also go ahead and change the window’s background color to match that of our web UI:

window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1);

Next, we need to do something to keep our floating plugin window on top of other windows, so the user can interact with their Sketch documents without having to worry about the Mosaic’s window disappearing. We can use a special type of NSWindow for this, called NSPanel, which is able to “stay on top” of other windows. All that’s needed for this is to change NSWindow to NSPanel, which is a single-line code change:

const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(

Now we tell our panel window to float (stay on top of all others), and only take keyboard/mouse focus when necessary:

window.floatingPanel = true;
window.becomesKeyOnlyIfNeeded = true;

We can also tweak our window so that it automatically reopens in the last position it was at:

window.frameAutosaveName = "mosaic-panel-frame";

This line basically says “remember this window’s position by saving it with Sketch’s preferences under the key mosaic-panel-frame”.

All together, we now have the following code:

function onRun(context){
    //        Create window

    const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(
            NSMakeRect(0, 0, 145, 500),
            NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
            NSBackingStoreBuffered,
            false
    );

    window.becomesKeyOnlyIfNeeded = true;
    window.floatingPanel = true;

    window.frameAutosaveName = "mosaic-panel-frame";

    window.releasedWhenClosed = false;

    window.standardWindowButton(NSWindowZoomButton).hidden = true;
    window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true;

    window.titlebarAppearsTransparent = true;
    window.titleVisibility = NSWindowTitleHidden;

    window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1);

    //        Create web view, and set it as the view for our window to display

    const webView = WKWebView.alloc().init();

    window.contentView = webView;

    //        Load our UI into the webview

    const webUIFolderURL = context.scriptURL
            .URLByDeletingLastPathComponent()
            .URLByAppendingPathComponent("../Resources/web-ui/");

    const indexURL = webUIFolderURL.URLByAppendingPathComponent("index.html");

    webView.loadFileURL_allowingReadAccessToURL(indexURL, webUIFolderURL);

    //        Make window key and move to front

    window.makeKeyAndOrderFront(nil);
};

Organizing The Code

Before we move to the next part, it’s a good idea to organize our code so that it’s easier to navigate and tweak. Since we still have a lot more code to add and we want to avoid index.js becoming a messy dumping ground for all of our code, let’s split things up a bit and move our UI-specific code into a file named ui.js, under the Sketch folder. We’ll also extract some of the UI tasks we do, like creating the web view and window, into their own functions.

Create a new file called ui.js and insert the code below inside it:

//        Private

var _window;

function createWebView(pageURL){
        const webView = WKWebView.alloc().init();

        webView.loadFileURL_allowingReadAccessToURL(pageURL, pageURL.URLByDeletingLastPathComponent());

        return webView;
};

function createWindow(){
        const window = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(
                NSMakeRect(0, 0, 420, 646),
                NSWindowStyleMaskClosable | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable,
                NSBackingStoreBuffered,
                false
        );

        window.becomesKeyOnlyIfNeeded = true;
        window.floatingPanel = true;

        window.frameAutosaveName = "mosaic-panel-frame";

        window.releasedWhenClosed = false;

        window.standardWindowButton(NSWindowZoomButton).hidden = true;
        window.standardWindowButton(NSWindowMiniaturizeButton).hidden = true;

        window.titlebarAppearsTransparent = true;
        window.titleVisibility = NSWindowTitleHidden;
        
        window.backgroundColor = NSColor.colorWithRed_green_blue_alpha(1, 0.98, 0.98, 1);

        return window;
};

function showWindow(window){
        window.makeKeyAndOrderFront(nil);
};

//        Public

function loadAndShow(baseURL){
        if(_window){
                showWindow(_window);

                return;
        }

        const pageURL = baseURL
                .URLByDeletingLastPathComponent()
                .URLByAppendingPathComponent("../Resources/web-ui/index.html");

        const window = createWindow();
        const webView = createWebView(pageURL);

        window.contentView = webView;
        
        showWindow(_window);

        _window = window;
};

function cleanup(){
        if(_window){
                _window.orderOut(nil);
                _window = null;
        }
};

//        Export

module.exports = { loadAndShow, cleanup };

There are a couple of key changes we made here that are important to note. Besides the fact that we’ve created specific functions for the creation, hiding and showing of our window and its web view, we’ve also modularized our user interface code.

Notice the module.exports = { loadAndShow, cleanup } line at the bottom? This is a way for us to specify exactly what objects and functions scripts who import this UI code can use (and hiding those we don’t want to them to worry about), which means we now have a more organized API for interacting with, showing and destroying our UI.

Recommended reading: Unleashing The Full Potential Of Symbols In Sketch

Let’s see what this looks like in practice. Back in index.js, remove the old code and add the following:

const UI = require("./ui");

function onRun(context){
        UI.loadAndShow(context.scriptURL);
};

We’re using a special function that Sketch automatically makes available to us, require, to import our ui.js code and assign the returned module to the UI variable. This gives us access to a simplified API for triggering our user interface. Things are much tidier now and easy to find!

Conclusion

Well done — you’ve come far! In the next part of this tutorial, we’ll give our web UI the ability to send us a message when the “Apply” button is clicked, and we’ll focus on the main plugin functionality: actually generating layer mosaics!

Smashing Editorial
(mb, yk, il)

Source: Smashing Magazine, How To Build A Sketch Plugin With JavaScript, HTML And CSS (Part 1)

Collective #529

dreamt up by webguru in Uncategorized | Comments Off on Collective #529



C523_divi

Our Sponsor

The Future of WYSIWYG

Divi takes WordPress to a whole new level with its incredibly advanced visual builder technology. You’ve never built a WordPress website like this before.

Try it

















C529_lunacy4

Lunacy 4.0

Lunacy 4.0 is a full-fledged graphic editor with icons, photos, masked images and illustrations integrated and ready to use. It’s Sketch for Windows with design assets.

Check it out



C529_templates

CodeSandbox Templates

If you work with CodeSandbox, then your prototyping workflow will certainly benefit from the new option to create and use templates.

Read it




Collective #529 was written by Pedro Botelho and published on Codrops.


Source: Codrops, Collective #529

How To Integrate Social Media Into Mobile Web Design

dreamt up by webguru in Uncategorized | Comments Off on How To Integrate Social Media Into Mobile Web Design

How To Integrate Social Media Into Mobile Web Design

How To Integrate Social Media Into Mobile Web Design

Suzanne Scacca



There are a number of reasons why social media is a popular form of socialization and communication today. For starters, it gives us a chance to connect with exponentially more people than in-person communities allow for (which is fantastic for both consumer and business). It’s also encouraged a new style of communication where brevity and visual storytelling rules.

So, why aren’t we using more social media-like features in mobile web design?

To be clear, I’m not referring to the kinds of social media elements we already see on websites, like:

  • Social logins
  • Social follow icons
  • Social share icons
  • Social feeds
  • <li.Instagram galleries

  • YouTube embeds
  • Pinnable images.

I’m talking about drawing inspiration from the abbreviated way in which we talk to others there. After all, mobile websites, PWAs, and native apps give us very little space to tell a story and engage an audience with it. Adopting a social media-inspired design would be helpful in quickly getting our message across on mobile screens.

These elements, in particular, are worth exploring in your mobile design work.

1. Use a Notification Symbol to Direct Visitors to Action

You don’t have much space or time to waste on mobile, so why literally spell out what kind of action you want visitors to take? A lot of the symbols we use on social media can easily be repurposed for mobile websites.

One such symbol is a notification ticker, a lot like the ones we’re accustomed to seeing in the header or footer of social media apps when there’s a message or reminder we need to be made aware of. Like this blue one found in the bottom bar on Facebook:

Facebook menu notification

Facebook uses a small blue dot to signify that a new notification awaits you. (Source: Facebook) (Large preview)

On occasion, the Red Bull website will put a similar-looking red ticker on its hamburger menu icon (this one is flashing though):

Red Bull menu notification

The Red Bull mobile website displays a flashing red ticker on the hamburger menu. (Source: Red Bull) (Large preview)

This flashing notification has nothing to do with alerting me to account activity (because I’m not logged into the website). However, it does certainly draw my eye to the navigation before anything else.

If you have something pertinent you want visitors to see in the navigation or header of the site, a notification icon is a good way to grab their attention fast. And it doesn’t have to be a colored dot the way Facebook or Red Bull have handled it. You could also use a number counter like the ones that appear when items sit in a shopping cart or emails in an inbox.

2. Boost Branding with Hashtags and Handles

The way we talk to one another on social media is quite unique. Not only do many people use acronyms to truncate how much they say in a tiny amount of space, but we’ve also adopted a quicker way of getting our messages in front of target users.

Take, for example, this message I’ve written on Twitter about a post Jad Joubran recently wrote about PWAs.

Basic Twitter message

Example of a basic message shared on Twitter. (Source: Twitter) (Large preview)

Now, I could leave my message as is and hope that Jad runs across the mention or that people interested in learning how to build PWAs find it. But there’s just too much noise on social media, which is why the usage of the handle (@) and hashtag (#) symbols has become helpful in getting our messages in front of the right people:

Twitter message with hashtags and handles

Example of a Twitter message with hashtags and handles. (Source: Twitter) (Large preview)

Take a look at the message above and note the differences. First, I’ve included hashtags in this post for #pwa and #progressivewebapp. That way, if someone is interested in related topics, it’ll be easier to locate this post now.

In addition, I’ve tagged Jad. This way, he’ll see my shout-out. I’ve also tagged Smashing Magazine since that’s the magazine in which the article appeared. This is good for them since it’ll increase the visibility of the brand while helping people who encounter the post make a direct connection between #pwa and @smashingmag.

The hashtag and handle have become such an innate part of how we communicate online, that I’m surprised more brands don’t use them on their websites. And I’m not talking about listing social media handles on a page. I mean actually integrating branded hashtags or handles within their designs as eos does here:

eos website hashtag

eos includes a branded hashtag within an image. (Source: eos) (Large preview)

A couple of years back, I saw more hashtags and handles incorporated into web designs. Today, I don’t see it as much.

My guess is that designers have moved away from placing handles and hashtags into designs since visitors can’t readily copy or click and do anything with them. But there is value in placing branded handles and hashtags into your designs on mobile.

Think of it as a watermark for your brand images. Like the example above, people won’t just walk away thinking about how cool that chapstick “egg” looks. They’ll take note of the hashtag sitting perpendicular to it, too. And for those that are on their way to becoming loyal eos customers, that hashtag will stick with them.

3. Add Trust Marks into the Design

There are certain social media platforms that give brands and public figures the ability to verify their identity. That way, anyone who wants to follow them will know who the person on the other side of the profile actually is (instead of, say, a bot or someone pretending to be them).

Rather than slap a “Verified Profile” label on these profiles, platforms like Twitter and Instagram use a tiny symbol that lets people know it’s okay to trust that the user is who they say they are. And it comes in the form of a small blue checkmark next to their username.

Instagram trust mark

Instagram uses a small blue checkmark to let people know it’s a real profile.. (Source: Instagram) (Large preview)

Trust marks are already used on the web to let visitors know when a site is safe enough to engage with and make a purchase through. However, they usually come in the form of big security provider logos like Norton Security that build consumer trust just before checkout.

Instead, you should find ways to leverage smaller trust marks to reinforce trust throughout the entire experience. Here’s how Sephora does this for its store:

Sephora trust marks

Sephora uses the same trust mark stamps to call attention to more notable products. (Source: Sephora) (Large preview)

There are two trust marks present in the screenshot above.

The GlamGlow product has a red-and-white stamp on it that says “Allure Readers’ Choice Award Winner”. You already know how much people trust in the reviews and recommendations of other consumers, so you can imagine what this sort of symbol does to pique their interest and build trust in the product.

The Farmacy product has a green-and-white stamp on it that says “Clean at Sephora”. This is a label Sephora slaps onto any product that’s free of questionable ingredients. For customers that are extra conscious about where their products come from and what they’re made from, this symbol will quickly direct their attention to the kinds of products they’re looking for.

4. Lead with a Singular Memorable Image

When you scroll through your social media feed, you’re not likely to see post after post with galleries of images attached to them. Unless, that is, someone just went on vacation and they want to show off everything they did or saw.

Usually, most of the social media posts you encounter keep it simple: a text message with a complementary image attached to it. And if the image didn’t come courtesy of the link they’re promoting, then they’ll attach something equally as memorable and relevant.

Social media feeds are full of posts from the people we’re connected to, so it’s important to have one strong image that helps ours stand out among the crowd. A mobile website would benefit from that same approach.

In this case, I’m going to point you to this promotional element on the West Elm mobile website for the approaching July 4th holiday in the United States:

West Elm GIF

A sparkler GIF used to promote West Elm’s July 4th promotion. (Source: West Elm) (Large preview)

Since sparklers are a big part of how we celebrate Independence Day, this sparkler GIF is an incredibly effective, yet simplistic way to draw visitors’ attention to the relevant promotion.

Not only is the GIF memorable, but it’s very relevant to what online shoppers are looking for at the moment. Plus, it all fits within the space of a smartphone screen, which makes it a more convenient way to read about the promotion before clicking through to claim the 20% offer.

5. Make Your Brand Meme-like

When brands use social media, they have to think about more than just pairing a carefully crafted message with an engaging image. They also have to consider the consistency of their posts. In some cases, brands will use color to tie their posts together. Others will rely on the messaging itself to create a cohesive identity.

Then, there are brands that have turned their brands into memes. Old Spice’s “The Man Your Man Could Smell Like” or Terry Crews campaigns are some of the more successful and memorable examples of how to do this.

It’s not just brands like Old Spice or Dollar Shave Club whose humorous advertising become memes that can pull this off. Take a brand like Oreo, for example.

Oreo is a household name. And, yet, would anyone have considered sharing posts about Oreo cookies with others? Before 2013, I’m not so sure. After Oreo published its now-famous post during the Super Bowl blackout, though, things changed.

Oreo Super Bowl meme

Oreo gave a boost to its already iconic image during the 2013 Super Bowl. (Source: Oreo) (Large preview)

This might not be a meme on the level of Old Spice. However, it most certainly is on a similar level of trendiness and shareability.

Oreo has continued to find ways to turn its iconic Oreo cookie image into a meme-like status symbol.

The Oreo cookie meme

Oreo has turned its cookie into a meme of its own. (Source: Oreo) (Large preview)

You know how everyone and their mother has been sharing cookies notices on their websites, thanks to GDPR? Oreo utilizes its brand image to have a little fun with it.

As you can see here, the drop-down creatively uses the Oreo image while also playing on the word “cookie” itself. It’s a fantastic example of how to be creative, even in the smallest of spaces and for a limited amount of time. It certainly grabbed my attention enough to deem it worth sharing here.

6. Embrace the Selfie

I recognize that selfies don’t always have the most positive of connotations, but it’s really difficult to have a discussion about using social media-like elements in design without addressing them. So, I’m going to go out on a limb here and say that mobile websites would benefit from including selfie-like portraits… when not used in a phony or obnoxious context.

I mean, that’s the main complaint about selfies, right? They’re staged and not at all realistic of a person’s actual life. Or they’re not staged because they’re taken at the worst possible time and in the least professional of contexts.

That said, selfies do stand out from super-glossy headshots and other staged company photos. And when you present them on a mobile interface, it gives a website (and the brand behind it) a more social-like presence. In other words, you’re inviting people to engage with you, not to just casually glance through copy and photos on their way to mindlessly converting. There’s something more to this experience when a selfie is present.

One example of this that I particularly love comes from Aleyda Solis, an SEO consultant and author.

Aleyda Solis selfies

Aleyda Solis uses selfies as promotional images on her website. (Source: Aleyda Solis) (Large preview)

Just looking at the above screenshot out of context, I feel like I’m scrolling through her personal feed on Instagram. And because I’m so accustomed to seeing interesting-looking photos on Instagram and then immediately seeking out the captions for more information on them, I’m compelled to do the same here. Talk about Pavlov’s dog, right?

For brands with a recognizable figure or team behind them, a selfie could be a great way to up your visitors’ engagement with a website. Just make sure it paints the person or people in a positive light.

7. Use Filters to Tell Individual Stories

Way, way back in the day, we used to take photos using film and pray that the images came out okay and would be acceptable enough to frame. Then, we got digital cameras that allowed us to see what our pictures looked like in real-time, though it often led to too many rounds of picture-taking to try to capture the perfect lighting or shot.

Nowadays, our smartphones and social media platforms make all of this so much simpler. We can take photos wherever we are, whenever we feel like it and many of the tools we need to clean up a shot and apply an attractive filter are already built into our apps.

Needless to say, filters are a big part of what makes sharing photos on social media so appealing to users.

Now, it’s not as though brands haven’t utilized filters before to spruce up their branding or photography. However, have you considered what using different filters in different contexts could do for your mobile website? They could effectively turn different pages or products into unique experiences or stories of their own.

Abel is an online perfume shop that sells a small collection of perfumes, with scents like pink iris, red santal and green cedar. Notice the trend? Each scent is described by a distinct color, as this example of golden neroli demonstrates:

Abel’s golden neroli scent

An example of one of Abel’s product pages. (Source: Abel) (Large preview)

Although the perfume itself is clear in color, the design of this image gives the bottle a golden color to match its namesake. Now, here’s where it gets interesting:

Abel golden filter

Abel applies a color-specific filter to images on each product page. (Source: Abel) (Large preview)

This is one of the images lower on the product’s page. While I suspect the sunset captured in the photo is real, it’s obvious that a filter has been applied to lighten and warm the overall tone of the image.

The same is done with another image further down on the page:

Abel image filters

Another filter-enhanced image on Abel’s product page. (Source: Abel) (Large preview)

Again, the emphasis is placed on making the image lighter and warmer in tone. And if you look at the snippet of text just above, you can see that Abel even compares the sensation of this perfume to “the warm warm blanket of the night falling over Lisbon”.

So, rather than get hung up on designing your mobile website with one singular color palette, consider the individual emotion and identity of each of its pages or elements. You may find that filters and colors help you tell a stronger and unique story for each than the words alone could.

The Benefits Of A Social Media-Inspired Mobile Design

As we attempt to unlock more ways to design for mobile without stifling creativity or overwhelming the user experience, I think it’s important to look to other kinds of media for inspiration.

It’s not like we haven’t already found ways to tell a visual story through design on smaller or more isolated screens. Just look at video game design. Social media is another type of media that’s successfully carved out a style of its own. And considering how addictive and engaging social media often is for consumers, it’s a good platform to turn to for design inspiration.

Smashing Editorial
(ra, yk, il)

Source: Smashing Magazine, How To Integrate Social Media Into Mobile Web Design