Collective #583

Inspirational Website of the Week: basement.studio Everything on basement is bold: from its striking typography to the brilliant effects and playful interactivity. Fantastic work. Get inspired This content is sponsored via Thought Leaders Clubhouse: Make 2020 your most productive year Clubhouse is a Read more

How To Use FOMO To Increase Conversions

dreamt up by webguru in Uncategorized | Comments Off on How To Use FOMO To Increase Conversions

How To Use FOMO To Increase Conversions

How To Use FOMO To Increase Conversions

Suzanne Scacca



Consumers are motivated by need and desire. And sometimes, just sometimes, they’re motivated by FOMO. That’s right: we can now add the ‘Fear Of Missing Out’ to the list of drivers that get consumers onto our websites and into our apps.

With that said, when we take a closer look at what FOMO really means and the negative impact it can have on consumers, is it something we really want to be encouraging as we build digital experiences for them? My answer to that is:

Yes, but you must use FOMO responsibly.

FOMO can be a really effective tool to add to a marketing and sales strategy. As a web designer, though, you need to find ethical ways to appeal to your users’ fear of missing out. Today, I’m going to show you some options for doing this.

A More Ethical Way To Design with FOMO

FOMO stands for “fear of missing out”, and while it might seem like some innocuous acronym like YOLO or LMAO, this isn’t a cute way of saying “Wish I were there!”.

The fear part of FOMO is all too real.

A 2013 study titled “Motivational, emotional, and behavioral correlates of fear of missing out” defined FOMO as:

A pervasive apprehension that others might be having rewarding experiences from which one is absent, FoMO is characterized by the desire to stay continually connected with what others are doing.

One of the conclusions from the report was that “FoMO was associated with lower need satisfaction, mood, and life satisfaction.”

It’s not just scientists taking note of the negative effects of FOMO in marketing, social media or otherwise. The Competition and Markets Authority went after hotel booking sites for using misleadingly urgent and deceptive discount marketing messages to increase sales.

Even without the fear of retribution from some standards authority, you really need to think about how your web and mobile apps leave your users feeling. A little bit of envy might be fine, but once the general sentiment trickles over to jealousy, disappointment or stress, it’s time to reassess what you’re doing and why.

Let’s take a look at some ways you can leverage the underlying concept of “missing out” and strip away the fear elements.

Quick note: All of the examples below are from mobile apps, however, you can use these design principles on websites and PWAs as well.

Gently Remind Visitors About Limited Availability

There’s nothing wrong with presenting limits to your users on what’s available or for how long it will remain available. It only becomes a problem when how you convey this sense of urgency or limitation causes stressful decision-making.

This is something I talked about in a recent post, “How to Stop Analysis Paralysis with Web Design”.

Basically, when you induce stress in your visitors or consumers, it makes the decision-making process more difficult and can lead to regretful purchases or no purchases at all. In that last article, the focus was on the drawbacks of presenting customers with too many choices.

However, the same kind of response (i.e. dissatisfaction and overwhelm) can happen when you put pressure on them to make a choice on the spot.

So, instead of displaying a large timer counting down the minutes left to buy items in their shopping cart or a bright red banner that screams “24-Hour Sale!”, use more gentle reminders around the site or app.

Best Buy has an entire section on its product pages dedicated to in-store and online availability:

Best Buy out of stock

Best Buy lets customers know when products are out of stock in store and online. (Source: Best Buy) (Large preview)

Now, if this were a product with only one color or memory option, I’d suggest removing it from the online inventory altogether. If you can’t provide a date when the product will become available again or put customers on a waitlist, don’t bother teasing them with an out-of-stock listing.

That said, this item has multiple variations, which makes the “sold out” notice quite potent.

Paul Messinger, a professor of business and researcher at the University of Alberta, commented on this phenomenon:

Sold-out products create a sense of immediacy for customers; they feel that if one product is gone, the next item could also sell out. Our research shows there’s also an information cascade, where people infer that if a product is sold out, it must have been good and therefore a similar available product will also be desirable.

What’s also nice about displaying sold-out products is that it reduces the number of choices consumers have to make. Granted, some may be unhappy because the silver phone they wanted is unavailable, but, as Messinger says, this limitation on what they can buy might encourage them to try another variation of the product.

One of my absolute favorite examples of gently nudging consumers to use or buy your products is Hulu:

Hulu app expiring content

The Hulu app has an entire tab dedicated to “Expiring” content. (Source: Hulu) (Large preview)

There is an entire tab in the app that lets users know which content is about to expire.

For those of you who stream content like a maniac (like myself), you know how easy it is to lose track of shows and movies you’ve added to your list. You also know how hard it can be to find the perfect thing to watch when you have dozens of options sitting in your queue, especially if you use more than one streaming service.

That’s why this “Expiring” tab is brilliant. The second I see it, I think, “Either use it or lose it, Suzanne” — which is incredibly motivating. Also, the fact that I have a much shorter list to work with helps me get to a decision more quickly.

This would be useful for e-commerce websites, for sure. If you have products that are low in inventory, give them a dedicated space for shoppers to peruse — kind of like a bargain bin without the bargain.

If your website runs a number of offers simultaneously, you could use a similar approach as well. Create a page for “Offers” or “Rewards” and break out a separate tab that shows users all the offers that are about to expire.

Call Attention to Rewards

When selling something online — be it a subscription to a repository of plugins or a store full of products — don’t forget to enable account registration. Sure, it’s a nice touch for users that want the convenience of saving account details so they don’t have to input them with each new purchase. There’s another reason to encourage your users to register though:

So you have a way to call attention to their spendable rewards.

FOMO isn’t always the fear of missing out on what others are doing. Sometimes it’s just a fear of missing the chance to get a really good deal. Promoting attractive sales offers (“75% off everything in store!”) is one way to do that, but, again, you have to recognize that that’s only going to stir up issues caused by the paradox of choice.

A softer but still effective way to compel users to buy sooner rather than later is to show off their rewards totals or expiration dates.

As a Gap customer, this is one of my favorite things about shopping with them. Whether I’m in store, on the app, shopping through the website or looking through my email, I receive these kinds of reminders:

Gap rewards reminder

Gap reminds logged in users when they have rewards to spend. (Source: Gap) (Large preview)

The “Redeem your Super Cash” reminder is the first thing I see when I log in. Even if I’ve gone to the app with the intention of just window browsing, that rewards reminder (and the impending expiration) almost always motivates me to buy something so I don’t lose my member perks.

Unlike sales banners that promote generic offers, this approach works really well because you’re appealing to loyal customers — the ones who’ve already signed up for an account and have a history of buying from you.

And if you’re worried about a banner of that size taking up too much space in your app or mobile website, think again:

Gap pulsing blue rewards reminder

Gap uses a pulsing blue ticker in the top-left corner to remind users about unspent rewards. (Source: Gap) (Large preview)

Gap doesn’t continually show the rewards reminder.

See the icon in the top left corner with the circle over it? That circle is pulsing. It’s there to let customers know that there’s something to look at before they check out. And that something are the rewards they need to spend before they lose them.

Hotels.com, on the other hand, dedicates an entire page to rewards:

Hotels.com Rewards tab

Hotels.com users can access their free night rewards on the “Rewards” tab. (Source: Hotels.com) (Large preview)

It’s similar to that urge people feel to log into social media just to check on what’s going on and to make sure they’re not missing anything. This “Rewards” tab should send a similar vibe: “Hmmm… I wonder how close I am to my free night?”

Although you can’t see it here, Hotels.com has a policy about how long customers can hold onto these earned nights before they lose them. (It’s just below this section.) By gently reminding users about this stipulation, it likely encourages its rewards members to book more trips so they can get their free night.

Encourage Sharing with Friends and Family

One of the problems with building FOMO into a website — much like any marketing you do for business — is that it’s coming from you. Until you’ve earned the trust of visitors and users, how are they supposed to believe a product marked as a “Top Seller” really is what you claim it to be? Social proof is supposed to help mitigate these kinds of concerns, but even that can be faked.

You know what I think is a more effective way to generate FOMO? Let your customers and clients do it for you.

Here’s how Airbnb does it:

Airbnb 'Invite friends' feature

Airbnb rewards its users for inviting friends. (Source: Airbnb) (Large preview)

The “Invite friends” feature encourages users to let their friends, family and colleagues know about how awesome the Airbnb experience is.

Hey, I just booked this awesome apartment in Montreal for Christmas. You’ve got to check this out! Oh yeah, you also get $40 off your first booking!

Even the headline on the landing page encourages them to share the experience; not just do it to get free travel credit (though that’s a nice incentive, too):

Airbnb referral program

Airbnb encourages its users to share their love of travel by rewarding them and their referrals with travel credits. (Source: Airbnb) (Large preview)

Imagine that friend who’s busy running a business and in dire need of a vacation. They receive this offer from you — a person they know and trust. Of course, their reaction is going to be, “I need to do that, too!” And with a discount code in hand, that’s a pretty strong source of motivation to get in the app and make a purchase.

You’ll find another great example of generating FOMO through your users from the 23andMe website:

 23andMe 'Share your Ancestry'

The home page for 23andMe invites users to ‘Share your Ancestry’. (Source: 23andMe) (Large preview)

For those of you who haven’t signed up for one of these genetic testing services, it’s actually pretty cool. You submit a saliva sample and they tell you what your ancestral background is (as well as how it can affect your health). But it’s more than just, “Your maternal family originates from Turkey.” It gets super-specific on what parts of the world your ancestors are from.

Notice that banner in the screenshot above that says “Share your Ancestry”? That’s where users find auto-generated social posts that are designed to be share-worthy (they look like Facebook and Instagram Story cards):

23andMe social sharing

23andMe auto-generates social posts users can share with their friends and followers. (Source: 23andMe) (Large preview)

This is my ancestral breakdown according to 23andMe. So, let’s say I want to joke about how boringly anti-nomadic my ancestors were on Twitter. I could edit the banner or share it as is. And guess what? That’s free advertising for 23andMe, even if I chose to ditch the logo they placed at the bottom of the file.

As those posts reach social media connections — those that know the user or those that are only acquainted with them online — FOMO starts to rear its head. “Oooh! I really want one of these! Where’d you find this out?”

With this kind of FOMO marketing on your site or app, you can stop relying so much on heavily-discounted sales events and other urgency-inducing tactics (which will cost you more in the long run). Instead, let your users generate that intensified interest.

Use More Grounded Photos and Designs

You’ve no doubt heard about lifestyle influencers using shady promotional tactics to increase sales.

One of the most well-known examples of this is the Fyre Festival, which created a bunch of buzz on social media thanks to promotional videos of celebrities and supermodels partying it up in the Caribbean. The people behind this failed festival didn’t care about the experience. They focused solely on the image of it and consumers ate it up with a spoon — until they realized that image was a lie once they got there.

Then, you have micro-influencers who try to make money from affiliate sales. However, all is usually not what it seems as Jordan Bunker explained to The Guardian:

All isn’t how it is perceived on Instagram. People assume I have a great life and everything is handed to me. I live with my parents and I work from a desk in my room; it’s not like I have a separate working space or office.

That’s not the only deception. Influencers often make their luxurious lives seem like something that’s easy to achieve. The reality, however, is that many of them have to work really hard to stage their life, every second of every day, hoping to get the perfect shot that will make consumers want to follow them or buy the stuff they promote.

But as Lucie Greene, an analyst who specializes in consumer behavior, pointed out:

We’re seeing a rising awareness of how social media use and influencer culture affects mental health, from Fomo (Fear of Missing Out) to driving compulsive, addictive consumption, to feelings of isolation.

Granted, the messages alone that influencers send to followers are often problematic. But so, too, are the images. So, as you design your website and integrate photos from your clients or from stock photo sites, think about what message you’re really sending.

Sephora, for instance, promotes its products with photos of the actual products. You might see a model or two on the top of the home page. For the most part, though, the focus is on the products.

That said, cosmetics and other beauty products can be used to convey a certain image and lifestyle — one that consumers desperately want. So, is Sephora missing out on an opportunity to create a “Sephora Lifestyle” by not photographing models using its products?

Sephora Inspire community

Sephora lets its users’ photos inspire the right kind of FOMO. (Source: Sephora) (Large preview)

Unlike many other retailers who might share photos of models living their lives in some far-off, exotic locale while wearing their products, Sephora doesn’t do that. The only time you really see photos of its cosmetics and products in action is here, in its “Inspire” community.

So, rather than leave its customers pining for some life that they may unconsciously associate with the red lipstick they were thinking of picking up, real customers get the chance to paint a more realistic portrait of its products.

Sephora Inspire gallery

A gallery of product photos from the Sephora Inspire page. (Source: Sephora) (Large preview)

As consumers grow weary of artificially enhanced photos and scenarios, you’re going to find it harder to make them feel like they’re missing out. However, by allowing your customers to provide a real look at what your products can do (and this goes for any kind of product, physical or digital), that’s where you’ll start to see consumers responding to feelings of missing out.

Before I wrap up here, I want to point out that this isn’t just for companies that sell affordable products.

The Inner Circle, for example, is an exclusive dating app. In order to join, users must first be prescreened and approved.

Now, you might think that a luxury brand like that would want to use influencer-like photos to show users how much they’re missing out by not dating in their “class”. But they don’t.

The Inner Circle dating app with bar photo

The Inner Circle luxury dating app doesn’t focus on the luxurious side of dating. (Source: The Inner Circle) (Large preview)

In this first example from the app’s signup page, you can see that the focus is on finding a popular spot to hang out and meet people. While the black-and-white filter does give it a swankier vibe, there’s nothing about the people in the photo that necessarily screams “Exclusive!”

The same thing goes for this photo:

The Inner Circle dating app with date in the park photo

The Inner Circle paints dating in a positive and natural light. (Source: The Inner Circle) (Large preview)

This is the kind of date most people would go on: a date in the park. The people in the photo aren’t all glammed up or wearing clothes made by high-end luxury designers.

These photos feel accessible. They let users know that, at the end of the day, they’re using this app to make real-life connections. There’s nothing exclusive about that.

And if a luxury brand like The Inner Circle can send that kind of message to its users with photos, then any brand should be able to do the same and be successful with it. Just be honest in what you’re portraying, whether it’s a photo of someone cooking with your products or a look inside the real (not illustrated) dashboard of your SaaS.

If you want to give prospects the feeling that they’re about to miss out on something worthwhile, just be real with them.

Wrapping Up

Maybe not today and maybe not tomorrow, but deceptive FOMO tactics will eventually catch up with you when customers start to realize they were misled by inflated numbers, exaggerated scenarios or seemingly time-sensitive or exclusive offers.

Remember: the websites and apps you build for clients shouldn’t just attract and convert customers. They also need to help your clients retain that business and loyalty over the long term. By being more responsible with the messages you’re sending, you can help them accomplish that.

Smashing Editorial
(ra, yk, il)

Source: Smashing Magazine, How To Use FOMO To Increase Conversions

Performing iOS Animations On Views With UIKit And UIView

dreamt up by webguru in Uncategorized | Comments Off on Performing iOS Animations On Views With UIKit And UIView

Performing iOS Animations On Views With UIKit And UIView

Performing iOS Animations On Views With UIKit And UIView

Saravanan V



I have been an iOS developer for over a decade now and have rarely seen articles that consolidate all possible ways to perform animations in iOS. This article aims to be a primer on iOS animations with the intent of exhaustively covering the different ways of doing the same.

Given the extensiveness of the topic, we would cover each part succinctly at a fairly high level. The goal is to educate the reader with a set of choices to add animations to his/ her iOS app.

Before we start off with topics related to iOS, let us take a brief look at animation speed.

Animating At 60FPS

Generally in videos, each frame is represented by an image and the frame rate determines the number of images flipped in the sequence. This is termed as ‘frames per second’ or FPS.

FPS determines the number of still images flipped within a second, which literally means that the more the number of images/ frames, more details/ information are displayed in the video. This holds true for animations as well.

FPS is typically used to determine the quality of animations. There is a popular opinion that any good animation should run at 60fps or higher — anything less than 60fps would feel a bit off.

Do you want to see the difference between 30FPS and 60FPS? Check this!

Did you notice the difference? Human eyes can definitely feel the jitter at lower fps. Hence, it is always a good practice to make sure that any animation you create, adheres to the ground rule of running at 60FPS or higher. This makes it feel more realistic and alive.

Having looked at FPS, let’s now delve into the different core iOS frameworks that provide us a way to perform animations.

Core Frameworks

In this section, we will touch upon the frameworks in the iOS SDK which can be used for creating view animations. We will do a quick walk through each of them, explaining their feature set with a relevant example.

UIKit/ UIView Animations

UIView is the base class for any view that displays content in iOS apps.

UIKit, the framework that gives us UIView, already provides us some basic animation functions which make it convenient for developers to achieve more by doing less.

The API, UIView.animate, is the easiest way to animate views since any view’s properties can be easily animated by providing the property values in the block-based syntax.

In UIKit animations, it is recommended to modify only the animatable properties of UIVIew else there will be repercussions where the animations might cause the view to end up in an unexpected state.

animation(withDuration: animations: completion)

This method takes in the animation duration, a set of view’s animatable property changes that need to be animated. The completion block gives a callback when the view is done with performing the animation.

Almost any kind of animation like moving, scaling, rotating, fading, etc. on a view can be achieved with this single API.

Now, consider that you want to animate a button size change or you want a particular view to zoom into the screen. This is how we can do it using the UIView.animate API:

let newButtonWidth: CGFloat = 60

UIView.animate(withDuration: 2.0) { //1
    self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) //2
    self.button.center = self.view.center //3
}

Here’s what we are doing here:

  1. We call the UIView.animate method with a duration value passed to it that represents how long the animation, described inside the block, should run.
  2. We set the new frame of the button that should represent the final state of the animation.
  3. We set the button center with its superview’s center so that it remains at the center of the screen.

The above block of animation code should trigger the animation of the button’s frame changing from current frame:

Width = 0, Height = 0

To the final frame:

Width = Height = newButtonWidth

And here’s what the animation would look like:

animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion

This method is like an extension of the animate method where you can do everything that you can perform in the prior API with some physics behaviors added to the view animations.

For example, if you want to achieve spring damping effects in the animation that we have done above, then this is how the code would look like:

let newButtonWidth: CGFloat = 60
UIView.animate(withDuration: 1.0, //1
    delay: 0.0, //2
    usingSpringWithDamping: 0.3, //3
    initialSpringVelocity: 1, //4
    options: UIView.AnimationOptions.curveEaseInOut, //5
    animations: ({ //6
        self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth)
        self.button.center = self.view.center
}), completion: nil)

Here’s the set of parameters we use:

  1. duration
    Represents the duration of the animation determining how long the block of code should run.
  2. delay
    Represents the initial delay that we want to have before the start of the animation.
  3. SpringWithDamping
    Represents the value of the springy effect that we want the view to behave. The value must be between 0 to 1. The lower the value, the higher the spring oscillation.
  4. velocity
    Represents the speed at which the animation should start.
  5. options
    Type of animation curve that you want to apply to your view animation.
  6. Finally, the block of code where we set the frame of the button that needs to be animated. It is the same as the previous animation.

And here’s what the animation would look like with the above animation configuration:

UIViewPropertyAnimator

For a bit more control over animations, UIViewPropertyAnimator comes handy where it provides us a way to pause and resume animations. You can have custom timing and have your animation to be interactive and interruptible. This is very much helpful when performing animations that are also interactable with user actions.

The classic ‘Slide to Unlock’ gesture and the player view dismiss/ expand animation (in the Music app) are examples of interactive and interruptible animations. You can start moving a view with your finger, then release it and the view will go back to its original position. Alternatively, you can catch the view during the animation and continue dragging it with your finger.

Following is a simple example of how we could achieve the animation using UIViewPropertyAnimator:

let newButtonWidth: CGFloat = 60
let animator = UIViewPropertyAnimator(duration:0.3, curve: .linear) { //1
    self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth)
    self.button.center = self.view.center
}
animator.startAnimation() //2

Here’s what we are doing:

  1. We call the UIViewProperty API by passing the duration and the animation curve.
  2. Unlike both the above UIView.animate API’s, the animation won’t start unless you specify it by yourself i.e. you’re in full control of the complete animation process/ flow.

Now, let’s say that you want even more control over the animations. For example, you want to design and control each and every frame in the animation. There’s another API for that, animateKeyframes. But before we delve into it, let’s quickly look at what a frame is, in an animation.

What Is A frame?

A collection of the view’s frame changes/ transitions, from the start state to the final state, is defined as animation and each position of the view during the animation is called as a frame.

animateKeyframes

This API provides a way to design the animation in such a way that you can define multiple animations with different timings and transitions. Post this, the API simply integrates all the animations into one seamless experience.

Let’s say that we want to move our button on the screen in a random fashion. Let’s see how we can use the keyframe animation API to do so.

UIView.animateKeyframes(withDuration: 5, //1
  delay: 0, //2
  options: .calculationModeLinear, //3
  animations: { //4
    UIView.addKeyframe( //5
      withRelativeStartTime: 0.25, //6
      relativeDuration: 0.25) { //7
        self.button.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.maxY) //8
    }

    UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.25) {
        self.button.center = CGPoint(x: self.view.bounds.width, y: start.y)
    }

    UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25) {
        self.button.center = start
    }
})

Here’s the breakdown:

  1. duration
    Call the API by passing in the duration of the animation.
  2. delay
    Initial delay duration of the animation.
  3. options
    The type of animation curve that you want to apply to your view animation.
  4. animations
    Block that takes all keyframe animations designed by the developer/ user.
  5. addKeyFrame
    Call the API to design each and every animation. In our case, we have defined each move of the button. We can have as many such animations as we need, added to the block.
  6. relativeStartTime
    Defines the start time of the animation in the collection of the animation block.
  7. relativeDuration
    Defines the overall duration of this specific animation.
  8. center
    In our case, we simply change the center property of the button to move the button around the screen.

And this is how the final animations looks like:

CoreAnimation

Any UIKit based animation is internally translated into core animations. Thus, the Core Animation framework acts as a backing layer or backbone for any UIKit animation. Hence, all UIKit animation APIs are nothing but encapsulated layers of the core animation APIs in an easily consumable or convenient fashion.

UIKit animation APIs don’t provide much control over animations that have been performed over a view since they are used mostly for animatable properties of the view. Hence in such cases, where you intend to have control over every frame of the animation, it is better to use the underlying core animation APIs directly. Alternatively, both the UIView animations and core animations can be used in conjunction as well.

UIView + Core Animation

Let’s see how we can recreate the same button change animation along with specifying the timing curve using the UIView and Core Animation APIs.

We can use CATransaction’s timing functions, which lets you specify and control the animation curve.

Let’s look at an example of a button size change animation with its corner radius utilizing the CATransaction’s timing function and a combination of UIView animations:

let oldValue = button.frame.width/2
let newButtonWidth: CGFloat = 60

/* Do Animations */
CATransaction.begin() //1
CATransaction.setAnimationDuration(2.0) //2
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)) //3

// View animations //4
UIView.animate(withDuration: 1.0) {
    self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth)
    self.button.center = self.view.center
}

// Layer animations
let cornerAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.cornerRadius)) //5
cornerAnimation.fromValue = oldValue //6
cornerAnimation.toValue = newButtonWidth/2 //7

button.layer.cornerRadius = newButtonWidth/2 //8
button.layer.add(cornerAnimation, forKey: #keyPath(CALayer.cornerRadius)) //9

CATransaction.commit() //10

Here’s the breakdown:

  1. begin
    Represents the start of the animation code block.
  2. duration
    Overall animation duration.
  3. curve
    Represents the timing curve that needs to be applied to the animation.
  4. UIView.animate
    Our first animation to change the frame of the button.
  5. CABasicAnimation
    We create the CABasicAnimation object by referring the cornerRadius of the button as the keypath since that’s what we want to animate. Similarly, if you want to have granular level control over the keyframe animations, then you can use the CAKeyframeAnimation class.
  6. fromValue
    Represents the starting value of the animation, i.e. the initial cornerRadius value of the button from where the animation must start off.
  7. toValue
    Represents the final value of the animation, i.e. the final cornerRadius value of the button where the animation must end.
  8. cornerRadius
    We must set the cornerRadius property of the button with the final value of the animation else the button’s cornerRadius value will get auto-reverted to its initial value after the animation completes.
  9. addAnimation
    We attach the animation object that contains the configuration of the entire animation process to the layer by representing the Keypath for which the animation needs to be performed.
  10. commit
    Represents the end of the animation code block and starts off the animation.

This is how the final animation would look like:

This blog is a great read to help create more advanced animations as it neatly walks you through most of the Core Animation framework APIs with instructions guiding you through every step of the way.

UIKitDynamics

UIKit Dynamics is the physics engine for UIKit which enables you to add any physics behaviors like collision, gravity, push, snap, etc, to the UIKit controls.

UIKitDynamicAnimator

This is the admin class of the UIKit Dynamics framework that regulates all animations triggered by any given UI control.

UIKitDynamicBehavior

It enables you to add any physics behavior to an animator which then enables it to perform on the view attached to it.

Different kinds of behaviors for UIKitDynamics include:

  • UIAttachmentBehavior
  • UICollisionBehavior
  • UIFieldBehavior
  • UIGravityBehavior
  • UIPushBehavior
  • UISnapBehavior

The architecture of UIKitDynamics looks something like this. Note that Items 1 to 5 can be replaced with a single view.

Let us apply some physics behavior to our button. We will see how to apply gravity to the button so that it gives us a feeling of dealing with a real object.

var dynamicAnimator   : UIDynamicAnimator!
var gravityBehavior   : UIGravityBehavior!

dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1

gravityBehavior = UIGravityBehavior(items: ) //2
dynamicAnimator.addBehavior(gravityBehavior) //3

Here’s the breakdown:

  1. UIKitDynamicAnimator
    We have created a UIKitDynamicAnimator object which acts as an orchestrator for performing animations. We have also passed the superview of our button as the reference view.
  2. UIGravityBehavior
    We have created a UIGravityBehavior object and pass our button into the array elements on which this behavior is injected.
  3. addBehavior
    We have added the gravity object to the animator.

    This should create an animation as shown below:

    Notice how the button falls off from the center (its original position) of the screen to the bottom and beyond.

    We should tell the animator to consider the bottom of the screen to be the ground. This is where UICollisionBehavior comes into picture.

    var dynamicAnimator   : UIDynamicAnimator!
    var gravityBehavior   : UIGravityBehavior!
    var collisionBehavior : UICollisionBehavior!
    
    dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1
    
    gravityBehavior = UIGravityBehavior(items: ) //2
    dynamicAnimator.addBehavior(gravityBehavior) //3
    
    collisionBehavior = UICollisionBehavior(items: ) //4
    collisionBehavior.translatesReferenceBoundsIntoBoundary = true //5
    dynamicAnimator.addBehavior(collisionBehavior) //6
  4. UICollisionBehavior
    We have created a UICollisionBehavior object and passed along the button so that the behavior is added to the element.
  5. translatesReferenceBoundsIntoBoundary
    Enabling this property tells the animator to take the reference views boundary as the end, which is the bottom of the screen in our case.
  6. addBehavior
    We have added collision behavior to the animator here.

    Now, our button should hit the ground and stand still as shown below:

    That’s pretty neat, isn’t it?

    Now, let us try adding a bouncing effect so that our object feels more real. To do that, we will use the UIDynamicItemBehavior class.

    var dynamicAnimator   : UIDynamicAnimator!
    var gravityBehavior   : UIGravityBehavior!
    var collisionBehavior : UICollisionBehavior!
    var bouncingBehavior  : UIDynamicItemBehavior!
    
    dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1
    
    gravityBehavior = UIGravityBehavior(items: ) //2
    dynamicAnimator.addBehavior(gravityBehavior) //3
    
    collisionBehavior = UICollisionBehavior(items: ) //4
    collisionBehavior.translatesReferenceBoundsIntoBoundary = true //5
    dynamicAnimator.addBehavior(collisionBehavior) //6
    
    //Adding the bounce effect
    bouncingBehavior = UIDynamicItemBehavior(items: ) //7
    bouncingBehavior.elasticity = 0.75 //8
    dynamicAnimator.addBehavior(bouncingBehavior) //9
  7. UIDynamicItemBehavior
    We have created a UIDynamicItemBehavior object and pass along the button so that the behavior is added to the element.
  8. elasticity
    Value must be between 0-1, it represents the elasticity i.e. the number of times the object must bounce on and off the ground when it is hit. This is where the magic happens — by tweaking this property, you can differentiate between different kinds of objects like balls, bottles, hard-objects and so on.
  9. addBehavior
    We have added collision behavior to the animator here.

Now, our button should bounce when it hits the ground as shown below:

This repo is quite helpful and shows all UIKitDynamics behaviors in action. It also provides source code to play around with each behavior. That, in my opinion, should serve as an extensive list of ways to perform iOS animations on views!

In the next section, we will take a brief look into the tools that will aid us in measuring the performance of animations. I would also recommend you to look at ways to optimize your Xcode build since it will save a huge amount of your development time.

Performance Tuning

In this section, we will look at ways to measure and tune the performance of iOS animations. As an iOS developer, you might have already used Xcode Instruments like Memory Leaks and Allocations for measuring the performance of the overall app. Similarly, there are instruments that can be used to measure the performance of animations.

Core Animation Instrument

Try the Core Animation instrument and you should be able to see the FPS that your app screen delivers. This is a great way to measure the performance/ speed of any animation rendered in your iOS app.

Drawing

FPS is vastly lowered in the app that displays heavy content like images with effects like shadows. In such cases, instead of assigning the Image directly to the UIImageView’s image property, try to draw the image separately in a context using Core Graphics APIs. This overly reduces the image display time by performing the image decompression logic asynchronously when done in a separate thread instead of the main thread.

Rasterization

Rasterization is a process used to cache complex layer information so that these views aren’t redrawn whenever they’re rendered. Redrawing of views is the major cause of the reduction in FPS and hence, it is best to apply rasterization on views that are going to be reused several times.

Wrapping Up

To conclude, I have also summed up a list of useful resources for iOS animations. You may find this very handy when working on iOS animations. Additionally, you may also find this set of design tools helpful as a (design) step before delving into animations.

I hope I have been able to cover as many topics as possible surrounding iOS animations. If there is anything I may have missed out in this article, please let me know in the comments section below and I would be glad to make the addition!

Smashing Editorial
(dm, yk, il)

Source: Smashing Magazine, Performing iOS Animations On Views With UIKit And UIView

Make Your Own Expanding And Contracting Content Panels

dreamt up by webguru in Uncategorized | Comments Off on Make Your Own Expanding And Contracting Content Panels

Make Your Own Expanding And Contracting Content Panels

Make Your Own Expanding And Contracting Content Panels

Ben Frain



We’ve called them an ‘opening and closing panel’ so far, but they are also described as expansion panels, or more simply, expanding panels.

To clarify exactly what we’re talking about, head on over to this example on CodePen:

Easy show/hide drawer (Multiples) by Ben Frain on CodePen.

Easy show/hide drawer (Multiples) by Ben Frain on CodePen.

That is what we’ll be building in this short tutorial.

From a functionality point of view, there are a few ways to achieve the animated open and close that we are looking for. Each approach with its own benefits and trade-offs. I’m going to share the details of my ‘go-to’ method in detail in this article. Let’s consider possible approaches first.

Approaches

There are variations on these techniques, but broadly speaking, the approaches fall into one of three categories:

  1. Animate/transition the height or max-height of content.
  2. Use transform: translateY to move elements into a new position, giving the illusion of a panel closing and then re-render the DOM once the transform is complete with the elements in their finishing position.
  3. Use a library that does some combination/variation of 1 or 2!

Considerations Of Each Approach

From a performance perspective, using a transform is more effective than animating or transitioning the height/max-height. With a transform, the moving elements are rasterized and get shifted around by the GPU. This is a cheap and easy operation for a GPU so performance tends to be much better.

The basic steps when using a transform approach are:

  1. Get the height of the content to be collapsed.
  2. Move the content and everything after by the height of the content to be collapsed using transform: translateY(Xpx). Operate the transform with the transition of choice to give a pleasing visual effect.
  3. Use JavaScript to listen to the transitionend event. When it fires, display: none the content and remove the transform and everything should be in the right place.

Doesn’t sound too bad, right?

However, there are a number of considerations with this technique so I tend to avoid it for casual implementations unless performance is absolutely crucial.

For example, with the transform: translateY approach you need to consider the z-index of the elements. By default, the elements that transform up are after the trigger element in the DOM and therefore appear on-top of the things before them when translated up.

You also need to consider how many things appear after the content you want to collapse in the DOM. If you don’t want a big hole in your layout, you might find it easier to use JavaScript to wrap everything you want to move in a container element and just move that. Manageable but we have just introduced more complexity! This is, however, the kind of approach I went for when moving players up and down in In/Out. You can see how that was done here.

For more casual needs, I tend to go with transitioning the max-height of the content. This approach doesn’t perform as well as a transform. The reason being that the browser is tweening the height of the collapsing element throughout the transition; that causes a lot of layout calculations which are not as cheap for the host computer.

However, this approach wins from a simplicity point of view. The pay-off of suffering the afore-mentioned computational hit is that the DOM re-flow takes care of the position and geometry of everything. We have very little in the way of calculations to write plus the JavaScript needed to pull it off well is comparatively simple.

The Elephant In The Room: Details And Summary Elements

Those with an intimate knowledge of HTML’s elements will know there is a native HTML solution to this problem in the form of the details and summary elements. Here’s some example markup:

<details>
    <summary>Click to open/close</summary>
    Here is the content that is revealed when clicking the summary...
</details>

By default, browsers provide a little disclosure triangle next to the summary element; click the summary and the contents below the summary is revealed.

Great, hey? Details even support the toggle event in JavaScript so you can do this kind of thing to perform different things based upon whether it is open or closed (don’t worry if that kind of JavaScript expression seems odd; we’ll get to that in more detail shortly):

details.addEventListener("toggle", () => {
    details.open ? thisCoolThing() : thisOtherThing();
})

OK, I’m going to halt your excitement right there. The details and summary elements don’t animate. Not by default and it is not currently possible to get them animating/transitioning open and closed with additional CSS and JavaScript.

If you know otherwise, I’d love to be proved wrong.

Sadly, as we need an opening and closing aesthetic we’ll have to roll up our sleeves and do the best and most accessible job we can with the other tools at our disposal.

Right, with the depressing news out of the way, let’s get on with making this thing happen.

Markup Pattern

The basic markup is going to look like this:

All the content here
</div>

We have an outer container to wrap the expander and the first element is the button which serves as a trigger to the action. Notice the type attribute in the button? I always include that as by default a button inside a form will perform a submit. If you find yourself wasting a couple of hours wondering why your form isn’t working and buttons are involved in your form; make sure you check the type attribute!

The next element after the button is the content drawer itself; everything you want to be hiding and showing.

To bring things to life, we will make use of CSS custom properties, CSS transitions, and a little JavaScript.

Basic Logic

The basic logic is this:

  1. Let the page load, measure the height of the content.
  2. Set the height of the content onto the container as the value of a CSS Custom Property.
  3. Immediately hide the content by adding an aria-hidden: "true" attribute to it. Using aria-hidden ensures assistive technology knows that content is hidden too.
  4. Wire up the CSS so that the max-height of the content class is the value of the custom property.
  5. Pressing our trigger button toggles the aria-hidden property from true to false which in turn toggles the max-height of the content between 0 and the height set in the custom property. A transition on that property provides the visual flair — adjust to taste!

Note: Now, this would be a simple case of toggling a class or attribute if max-height: auto equalled the height of the content. Sadly it doesn’t. Go and shout about that to the W3C here.

Let’s have a look how that approach manifests in code. Numbered comments show the equivalent logic steps from above in code.

Here is the JavaScript:

// Get the containing element
const container = document.querySelector(".container");
// Get content
const content = document.querySelector(".content");
// 1. Get height of content you want to show/hide
const heightOfContent = content.getBoundingClientRect().height;
// Get the trigger element
const btn = document.querySelector(".trigger");

// 2. Set a CSS custom property with the height of content
container.style.setProperty("--containerHeight", `${heightOfContent}px`);

// Once height is read and set
setTimeout(e => {
    document.documentElement.classList.add("height-is-set");
    3. content.setAttribute("aria-hidden", "true");
}, 0);

btn.addEventListener("click", function(e) {
    container.setAttribute("data-drawer-showing", container.getAttribute("data-drawer-showing") === "true" ? "false" : "true");
    // 5. Toggle aria-hidden
    content.setAttribute("aria-hidden", content.getAttribute("aria-hidden") === "true" ? "false" : "true");
})

The CSS:

.content {
  transition: max-height 0.2s;
  overflow: hidden;
}
.content[aria-hidden="true"] {
  max-height: 0;
}
// 4. Set height to value of custom property
.content[aria-hidden="false"] {
  max-height: var(--containerHeight, 1000px);
}

Points Of Note

What about multiple drawers?

When you have a number of open-and-hide drawers on a page you’ll need to loop through them all as they will likely be differing sizes.

To handle that we will need to do a querySelectorAll to get all the containers and then re-run your setting of custom variables for each content inside a forEach.

That setTimeout

I have a setTimeout with 0 duration before setting the container to be hidden. This is arguably unneeded but I use it as a ‘belt and braces’ approach to ensure the page has rendered first so the heights for the content are available to be read.

Only fire this when the page is ready

If you have other stuff going on, you might choose to wrap your drawer code up in a function that gets initialised on page load. For example, suppose the drawer function was wrapped up in a function called initDrawers we could do this:

window.addEventListener("load", initDrawers);

In fact, we will add that in shortly.

Additional data-* attributes on the container

There is a data attribute on the outer container that also gets toggled. This is added in case there is anything that needs to change with the trigger or container as the drawer opens/closes. For example, perhaps we want to change the color of something or reveal or toggle an icon.

Default value on the custom property

There’s a default value set on the custom property in CSS of 1000px. That’s the bit after the comma inside the value: var(--containerHeight, 1000px). This means if the --containerHeight gets screwed up in some way, you should still have a decent transition. You can obviously set that to whatever is suitable to your use case.

Why Not Just Use A Default Value Of 100000px?

Given that max-height: auto doesn’t transition, you may be wondering why you don’t just opt for a set height of a value greater than you would ever need. For example, 10000000px?

The problem with that approach is that it will always transition from that height. If your transition duration is set to 1 second, the transition will ‘travel’ 10000000px in a second. If your content is only 50px high, you’ll get quite a quick opening/closing effect!

Ternary operator for toggles

We’ve made use of a ternary operator a couple of times to toggle attributes. Some folks hate them but I, and others, love them. They might seem a bit weird and a little ‘code golf’ at first but once you get used to the syntax, I think they are a more straightforward read than a standard if/else.

For the uninitiated, a ternary operator is a condensed form of if/else. They are written so that the thing to check is first, then the ? separates what to execute if the check is true, and then the : to distinguish what should run if the check if false.

isThisTrue ? doYesCode() : doNoCode();

Our attribute toggles work by checking if an attribute is set to "true" and if so, set it to "false", otherwise, set it to "true".

What happens on page resize?

If a user resizes the browser window, there’s a high probability the heights of our content will change. Therefore you might want to re-run setting the height for containers in that scenario. Now we are considering such eventualities, it seems like a good time to refactor things a little.

We can make one function to set the heights and another function to deal with the interactions. Then add two listeners on the window; one for when the document loads, as mentioned above, and then another to listen for the resize event.

All Together

With the page load, multiple drawers, and handling resize events, our JavaScript code looks like this:

var containers;
function initDrawers() {
    // Get the containing elements
    containers = document.querySelectorAll(".container");
    setHeights();
    wireUpTriggers();
    window.addEventListener("resize", setHeights);
}

window.addEventListener("load", initDrawers);

function setHeights() {
    containers.forEach(container => {
        // Get content
        let content = container.querySelector(".content");
        content.removeAttribute("aria-hidden");
        // Height of content to show/hide
        let heightOfContent = content.getBoundingClientRect().height;
        // Set a CSS custom property with the height of content
        container.style.setProperty("--containerHeight", `${heightOfContent}px`);
        // Once height is read and set
        setTimeout(e => {
            container.classList.add("height-is-set");
            content.setAttribute("aria-hidden", "true");
        }, 0);
    });
}

function wireUpTriggers() {
    containers.forEach(container => {
        // Get each trigger element
        let btn = container.querySelector(".trigger");
        // Get content
        let content = container.querySelector(".content");
        btn.addEventListener("click", function(e) {
            container.setAttribute("data-drawer-showing", container.getAttribute("data-drawer-showing") === "true" ? "false" : "true");
            content.setAttribute("aria-hidden", content.getAttribute("aria-hidden") === "true" ? "false" : "true");
        });
    });
}

You can also play with it on CodePen over here:

Easy show/hide drawer (Multiples) by Ben Frain on CodePen.

Easy show/hide drawer (Multiples) by Ben Frain on CodePen.

Summary

It’s possible to go on for some time further refining and catering for more and more situations but the basic mechanics of creating a reliable opening and closing drawer for your content should now be within your reach. Hopefully, you are also aware of some of the hazards. The details element can’t be animated, max-height: auto doesn’t do what you hoped, you can’t reliably add a massive max-height value and expect all content panels to open as expected.

To re-iterate our approach here: measure the container, store it’s height as a CSS custom property, hide the content and then use a simple toggle to switch between max-height of 0 and the height you stored in the custom property.

It might not be the absolute best performing method but I have found for most situations it is perfectly adequate and benefits from being comparatively straightforward to implement.

Smashing Editorial
(dm, yk, il)

Source: Smashing Magazine, Make Your Own Expanding And Contracting Content Panels

Smashing Podcast Episode 3 With Jina Anne: What Are Design Tokens?

dreamt up by webguru in Uncategorized | Comments Off on Smashing Podcast Episode 3 With Jina Anne: What Are Design Tokens?

Smashing Podcast Episode 3 With Jina Anne: What Are Design Tokens?

Smashing Podcast Episode 3 With Jina Anne: What Are Design Tokens?

Drew McLellan



Jina Anne In this episode of the Smashing Podcast, we’re talking about Design Tokens. What are they, what problem do they solve, and how can they be used within an existing Design System? Drew McLellan talks to someone who is much more than a token expert: Jina Anne.

Show Notes

Transcript

Drew: She’s a design systems advocate and coach. While at Amazon, she was senior design systems lead and she was lead designer on the Lightning Design System at Salesforce, while at Apple she led the CSS architecture and style guide for the Apple Online Store. She’s worked with GitHub, Engine Yard, and the Memphis Brooks Museum of Art and more. She founded and organizes Clarity, the first design systems conference, and is on the Sass core team where she leads the brand design and website for Sass. When it comes to design systems, you’d be hard pushed to find anyone more qualified, but did you know that she’s never seen a sidewalk? My smashing friends, please welcome Jina Anne. Hello, Jina.

Jina Anne: Hello.

Drew: How are you?

Jina Anne: I’m smashing.

Drew: I wanted to talk to you today about design tokens, which I think is a phrase many of us have probably heard passed about, but we perhaps aren’t sure what it means. But before we get to that, I guess we should talk a little bit about design systems. I mean, design systems are your thing, right?

Jina Anne: Yeah. It rules everything around me. Yeah.

Drew: I think that there’s something that we’re seeing is becoming increasingly common in projects and people are making them public and seems to be a real movement around design systems. But I think there are plenty of organizations that don’t have them in place still. What problem does a formalized design system solve from your point of view?

Jina Anne: It can solve many problems. I think some of the more common problems that people seek to solve is around maintainability and consistency. That usually has to do with design debt or in some cases code debt, some cases both. I also look at it as a… Like, it’s not just about the code or the design, but also the problems around how people work together. So, I look at it as a way to also solve some of the issues around communication and workflow process and so on.

Drew: Are design systems then something exclusively that are useful to really big teams and big organizations?

Jina Anne: I don’t think so. I’ve seen them work really well with smaller teams or sometimes even with a lone designer. They definitely help with larger teams for sure, but they are definitely not exclusive to large teams. In fact, I think if you see yourself perhaps growing at some point to be a large team, then having the system in place already will help you do that more efficiently.

Drew: What did you think are the sort of symptoms that somebody might be looking for if they’re working and they’re still having problems? What do those problems look like that might be solved by putting a design system in place?

Jina Anne: There’s a few, duplication of efforts, duplication of code. You might have a breakdown in communication where things just aren’t being built the way they’re expected to be built. It could come down to things that aren’t documented well, so people don’t really quite know what the best thing is to use or where to look. Yeah, there are all sorts of signs.

Drew: I guess design systems are generally a concept, rather than a specific technical solution. In your work, you must see people using all sorts of different tools to achieve design systems.

Jina Anne: Yeah.

Drew: What are some of the more common ways that people actually go about it?

Jina Anne: I think the most common ways are having a component library done in code and often cases you’ll see it in it like a React library or an Angular library, whatever, platform you’re using. There’s usually also a website associated with it that will display those components. Then you’ll usually see perhaps like a Sketch or a Figma library as well.

Jina Anne: But one of the things that I like to stress to people is that if you look at that website that displays your documentation and your components, that website is not actually your design system. It’s a representation of your design system. So, I think a lot of people spend a lot of time on making this gorgeous, beautiful website and it’s fine. They’re nice to look at and they’re nice to share and they help a lot with communicating what you’re doing and even with recruiting.

Jina Anne: But it’s the system itself that it represents that I want people to spend their love and care into, so thinking through what’s going into that website, like the content and how you’ve organized things, how you’ve named things, the things that you’re systemizing, so, yeah. I think a lot of people think about the artifacts, like the deliverables, but really it’s a lot more than that. It’s a lot of process and workflow as well.

Drew: Is it exclusively web projects that the design system would help with?

Jina Anne: Not at all. It is the most common, I believe, from, at least, what I’ve seen, but design systems definitely can cover many things. In the digital space, you have native platforms, but even outside the digital space, I think a lot of people talk about design systems in a digital product space. But they’ve been around for ages for traditional medias and real-world scenarios. If you have seen the NASA graphic standards manual from like the ‘70s, that was a design system. It just was across all the different like rockets and spacesuits and all that, instead of digital products.

Drew: So, I guess, there must be some overlap between things, traditional things like brand guidelines and that sort of documentation that I think probably people are familiar with in all sorts of walks of life. There must be a crossover between that sort of documentation of a system and a more modern concept of a design system.

Jina Anne: Yeah, I believe so. I think a lot of people forget that it’s all about branding. The whole reason any of this even started and why we want to display these things in a uniform or unified way is all about the brand because brand isn’t just logos. It’s how people use and experience your company’s service or product or whatever it is that you offer. So, yeah, absolutely.

Drew: So, I’ve got a design system in place, I mean an organization. We’ve done a whole lot of work. We’ve got a design system. There are creatives within the organization working in maybe, like you mentioned, Figma or Sketch. We’ve got web designers using that in a CSS. Perhaps we’ve got a mobile team doing like Android and iOS development, building apps. Loads of people working with a design system contributing into it and consuming stuff from it. Where do design tokens come in? What problem do they solve?

Jina Anne: Ooh, yes. Let me first take it back to a story. When I first joined at Salesforce, I was actually part of a small project team. It was a different product, it’s like a productivity tool like tasks and notes and things like that. We were only three designers and I was the only one that, I guess, I wouldn’t say brave enough, but maybe interested enough to work with the Android designs. The other two designers, I think, just weren’t quite as interested. So, I was basically the main designer on our Android app. Then I also did a lot of design for iOS app and, of course, the web application as well and the marketing website, so lots of different projects in play.

Jina Anne: With the website, since I like to design and code, it was pretty straightforward. I could go ahead and build the buttons and typography and everything that we needed for the web application or the marketing website, document it in code and deliver that.

Jina Anne: However, with both the Android and iOS app, I don’t really know how to code for that and so I wasn’t able to deliver the same thing. So, I was having to do a ton of redlines specs, which, if you’re not familiar with redlines, it’s essentially where you are specking out every single spacing, font size, color, anything to indicate how to build it for the engineer. I would do these for many, many, many screens and, of course, a lot of those screens had variations because maybe you’re showing what happens when you clicked that button or when a certain state happens. So, doing this across many, many screens and then saving those up to Dropbox and then documenting it in a Wiki. That was the process that I was having to do at the time.

Jina Anne: I usually think about things in a CSS way, like especially the C in CSS, so I usually think, “Oh, well, font sizes should only need to be declared one time because it’s going to cascade everywhere.” But I found that with certain engineers that I’ve worked within the past, if you don’t spec it, and I guess with native it works a little differently, they’re not going to build it and so I would have to be very explicit and name pretty much everything per screen. I was just like, “Oh, why is it like this?” Then any time we made any changes, I had to go back through and change all those screens again. It was not fun at all.

Jina Anne: Fast forward to when I moved over to the core team of Salesforce, I had been working in the Sass website and I’ve been playing around with using a YAML file to store the data for colors, typography, spacing and so on and was looping over that data to create the style guide, as well as the Sass variables in the classes. The reason I did that was we open-sourced the Sass website and I wanted people to be able to contribute to the design as well. But I didn’t want to make it a tedious process where you had to update the style guide along with any colors that you’re adding and so doing it this way, just kind of automated that process.

Jina Anne: I showed that to the team at Salesforce and then that kind of is where the concept of design tokens spawned off of. So they built a tool called Theo and there’s other tools out now that do the same thing like Style Dictionary. But the idea of it is you have this automated tool that takes the data that you give it and generates the code. You might think, “Well, that might be over-engineering variables. Why not just use variables?”

Jina Anne: Well, the idea is, as you alluded to earlier, like native platforms just take those attributes in a totally different way and so trying to scale design to Android and iOS, whatever other platforms that get Salesforce. We had some people on Java, we had some people on React yet, some people on Angular, PHP, not just internally at Salesforce, but also externally with all our partners and customers that were building their own applications. So, this was a way to store our visual information as data and then, in an automated way, generate the variables or the XML data you needed or the JSON data, whatever format that particular platform looked for.

Jina Anne: Then what was great about it was we found, let’s say a color doesn’t pass contrast ratios. I didn’t have to then notify the Android team and the iOS team and the web team. I just made that change and then they would get that change automatically the next time that they would pull in the latest. So, it just really helped streamline a lot of that and helped us be able to take off some of the burdens of updating visual designs from the engineers and that let us do that.

Drew: So, instead of being sort of variables within one particular code base, within your own React codebase or within your PHP or within your Java or wherever, they’re like variables across an entire organization? Is that fair to say?

Jina Anne: Correct. Correct. Then what’s cool is things like colors, for example, like transparent colors, you do that differently in Android, like eight-digit hex, instead of RGBA like you would with web. So that tool that you use, if you’re using one that is built to think through all this, does that transformation for you. So, rather than saying RGBA 50 comma, 40 comma, whatever the color, you can just say color background card or something like that. It’s really more of a named entity now and then you can all be speaking the same language, even though it might render a different syntax.

Drew: Right. So, although variables kind of the nuts and bolts of how it might be implemented, the idea is kind of much bigger than just what you’d think of as just variables. I mean, I guess in a way like RSS could be called just variables. But, actually, the way it enables us to distribute blog content and podcasts and everything has a much wider impact than just the core technology that’s there.

Jina Anne: Yeah, I think that’s actually a really good metaphor. I do see a lot of people when they use it or talk about it in their own design system website, they’re usually only talking about like Sass variables or CSS variables. I think that’s why there’s this confusion, like, “Well, isn’t that just variables?” It’s, like, “Why are we renaming it?” But it is that much broader application of it with a whole process around it. It even gets into like how you distribute those variables across components, like on a global level or on an individual component level. You can have multi-layers and so on. It can get pretty interesting.

Drew: So, I suppose as well as helping in the maintenance, you mentioned being able to change a color in one central location and then have everything that is, using those design tokens, be able to pick it up when the next build or next refresh from the system, presumably this has the potential to enable all sorts of other interesting things. I know a lot of people make sort of white-labeled products. It’s the same core product, but it’s customized with different design tweaks for different and things. So, using design tokens could actually be a solution for those sorts of applications as well, the need to span more than just one particular codebase.

Jina Anne: Right. Yeah. So, that was definitely a use case at Salesforce. We have a lot of, I don’t know why I’m still using present tense, but we had a lot of customers that wanted to be able to brand their UI that they were using. So, we had this concept of certain variables that we wanted to actually be seen more as like a constant, like maybe it’s an error color versus colors that were meant to be configured, like brandable colors. So, for some people’s needs that can get interesting, too, white labeling or offering any sort of theming, dark mode or night mode, even offering a feature, which you may have seen in Gmail, but it’s like that comfortable, cozy, compact spacing density. So, there are all sorts of extra stuff that you can get with it across multiple products very quickly, which is really nice.

Drew: It is really an extension of core principles of programming where you make sure that you’ve really defined things once in one place, so you don’t have multiple instances so it’s easy to update. But it is looking at that as a much, much bigger idea than just one small element of a product, looking at it across everything and centralizing that.

Jina Anne: Yeah, so we definitely looked at these as our source of truth. However, in case anybody is worried about like, “Well, Android does things differently than iOS,” or you might have some concerns there. Depending on how you’ve architected things, you can still solve for those use cases. So, we would have a global token set that all our products would basically import in, but then we made them in a way where you could either alter it for that particular context or extend it, like offer maybe additional tokens that only that particular context needs. So, you can still give the fine-tune experience that you need to give to each of those context, while bringing in the most common shared things.

Drew: On a technical level, how would this actually work? Is there like a common file format the different systems share? Is there like an established standard for how you declare your design tokens?

Jina Anne: It’s interesting that you asked that. There’s actually a community group formed through… W3C has all these community groups. It’s not really exactly a working group, but it’s still like an initiative across various people that are in this space trying to come up with a recommendation of what those standards could be. Even how people store their data can change. Like it could be YAML, it could be JSON, it could even be a spreadsheet. Then what you export would be different because you might be using Sass, you might be using LESS, you might be using some sort of XML base system. We actually don’t want to tell you which of those things to use because depending on our use case, you might need to use spreadsheets instead of JSON or YAML or you might need to use XML instead of Sass or LESS or even CSS variables. That’s because everybody’s products are so different and have different needs.

Jina Anne: But what we can standardize on is around the tooling to generate these things. The reason we want to try to come to some sort of standard is because so many design tools are starting to implement this, InVision, Adobe, Figma. All these tools are looking at design tokens because there is a need to not just make this a code-based thing, but make this a design tool-driven thing as well. We don’t want to do it in a way where those tools don’t feel like they can innovate. We want them to be able to innovate, but at least offer some sort of standards so that new tool-makers can get into this space and already have sort of an established understanding of how to set that up. So, while we’re not going to get strict on your format of what file format you’re using or what tool you’re using, we’re going to more try to standardize on like the internal process and basically the API of it.

Drew: Because like I said, once that API has been defined, the tooling can spring up around it that speaks with that API for whatever tools that people want to use. So, somebody could write up a Java library that speaks that API, and then anything that’s using Java could make use of it and so on. Are there any tools currently that support design tokens in any way?

Jina Anne: Yeah. On the code side, I mentioned already Theo and Style Dictionary. There’s also one called Diez, D-I-E-Z. That’s kind of newer to the space and it’s taking it beyond, just like doing the transformation process, but kind of treating design tokens as a component in a way and so that’s cool.

Jina Anne: Then on the design side, InVision already has it in their DSM tool, which is their Design System Manager tool. The last I looked at it, it was just colors and typography, but I do know when I… I talked to Evan, who is one of the main folks behind that product. He did tell me other things like spacing should be coming into play, if it’s not already. I haven’t looked at it super recently. I know there are newer tools that are really catching my eye, like modules and interplay. Both of those are code-driven design tools.

Jina Anne: Then I’ve been told that it’s supposed to come into some of the stuff that Figma and Adobe are doing, so I’m not sure if I’m revealing secrets. I don’t think I am. I think it’s all stuff they’ve talked about publicly. But, yeah, I’m really excited because I think while it was something that we were doing really just making our design system work easier, it’s kind of almost accidentally created a path for bringing design tools and code cluster together. That’s really exciting to me.

Drew: The makers of these various tools, are they working with the design tokens community group?

Jina Anne: Yeah, a lot of them have joined. Since I’m a chair member, I get to see by email, everybody who joins. It sends me a notice. What’s cool is not only just seeing all these design tool people joining, but also seeing big companies. I saw like Google and Salesforce and all that, so it’s really exciting. Because I think it shows that this really matters to where a lot of people are doing on a large scale and small scale and that’s pretty cool.

Drew: So, if I was sort of listening to this and thinking about my own projects, thinking, “Ah, yes, design tokens are absolutely the answer to all these problems that I’m having,” where would I go to find out more to start learning and start maybe using design tokens?

Jina Anne: It’s a really good question. There are a few articles and I can send you some links to include with this, but I think one of the first articles, which I wish I had written, but Nathan Curtis wrote and that he actually kind of helped bring attention to them. I think he inspired a lot of people to start using them, so he kind of discusses what they are and how to use them, his recommended way.

Jina Anne: I don’t like the title of this next article I’m going to mention, but it’s called Design Tokens for Dummies. I’m not a fan of using that terminology, but it is a pretty well thought-through article that goes to pretty much everything about them. There was a CSS Tricks article by Robin Randall recently that just explains really what they are. I did a All You Can Learn Library session for Jared Spool a while back, but it is a membership-based thing so you would have to have access to that to see it. I know there’s been a lot of presentations and stuff, but there’s not like an official book to it yet. But that’s perhaps something I’m working on. It’s like one of two books I’m working on, actually.

Drew: So, if I’m a toolmaker or I work for maybe a big organization that’s having these sorts of problems and they’ve got some ideas about maybe contributing to the process of designing how the standard works, is the design tokens community group something that I could get involved in?

Jina Anne: Absolutely. I think you’ll want a GitHub because that’s where all of the public discussions and notes and things are happening. Then on the W3C community group website, you can create an account there. Having that account enables you to join other community groups as well. But then, yeah, at that point once you’ve created your account there and… I think it asks if you have any affiliations, like if you work for a big company or anything like that, just so it’s transparent, like if you have any, I wouldn’t say necessarily bias, but like a certain interest. It just helps everybody understand where you’re coming from. Anyway, at that point, yeah, you join and you’re pretty much in.

Drew: It’s quite an open process then.

Jina Anne: Yeah.

Drew: What’s in the future for design tokens? What’s coming down the line?

Jina Anne: I’m really excited about what’s going on with the community group. Kaelig’s been doing most of the leading of it. He’s the co-chair with me and I really love seeing his passion behind this. My particular interests in this are really around the education of it. So, kind of similarly to the work I’ve been doing with the Sass community, I kind of want to do a little bit of that for the design token community, like talk through how to educate people on what this is and not just make it an API doc, but also like where to get started, how to get into this. That’s something I’m interested in project-wise.

Jina Anne: I’m also really keen to see where this evolves, especially with all these design tool companies getting involved. Then a lot of people mostly think about design tokens as a visual abstraction, but really what it came from was the same technology that you used for localizing content. You wrap things in strings and then you can pass through different stuff, so bringing it back to its roots. I’d love to see the application of this apply in different ways, like interactions and content. I’m not really super keen on AR/VR-type stuff, but how does it maybe manifest there? Yeah, really just seeing it kind of go beyond just like the visual layer of what we see.

Drew: I guess that’s the beauty of having an open process like the W3C community group, is that people who do have specialisms in things like AR and VR can contribute to the conversation and bring their expertise to it as well.

Jina Anne: Absolutely.

Drew: I’ve been learning a lot about design tokens today. What have you been learning about lately?

Jina Anne: I’m always trying to learn something, but I’ve actually been occasionally taking some cocktail classes. Yeah. I’m not really with the interest of becoming a bartender, but more of just having an appreciation for cocktails. What’s cool about these classes is they’re beyond just making cocktails. They actually talk about business practices and ethical practices, the hygiene of your bar, all sorts of stuff like that, so it’s been really fascinating because I think I have like this weird fantasy of one-day leaving tech and maybe going into that. Let’s see.

Drew: Do you have a favorite cocktail?

Jina Anne: Manhattan.

Drew: It’s good. It’s good.

Jina Anne: Yeah.

Drew: You can’t go wrong with a Manhattan.

Jina Anne: I have been ordering a lot of Old Fashioneds lately so that would probably be number two.

Drew: Do you have a favorite bourbon?

Jina Anne: Ooh. The first one that came to mind is Angel’s Envy. It’s like finished in port barrels that have kind of this slightly port-like essence to it. Their rye is really good, too. It’s like finished in rum barrels, so it almost has like a banana bread-like flavor to it.

Drew: This is a direction I wasn’t expecting to go in today.

Jina Anne: Yeah.

Drew: Was there anything else you’d like to talk about design tokens?

Jina Anne: My take is, just like with design systems, people are going to use them in different ways and also there might be people out there that don’t even need to use this. If you just have like an editorial website that is pretty straightforward, maybe all you really need are CSS variables and that’s it. There’s no need to over-engineer things.

Jina Anne: This is really more for people that really need to scale or if you have a theming context then maybe. But, yeah, it’s really not meant for everyone. So, just because it’s becoming kind of a hot thing to talk about, you might not need to even bother with it.

Drew: If you, dear listener, would like to hear more from Jina, you can follow her on Twitter where she’s @Jina, or find her and all her projects on the web at sushiandrobots.com. Thanks for joining us today, Jina. Do you have any parting words?

Jina Anne: Design systems are for people.

Smashing Editorial
(dm, ra, il)

Source: Smashing Magazine, Smashing Podcast Episode 3 With Jina Anne: What Are Design Tokens?

Collective #566

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


C566_gifolio

Gifolio

Gifolio is a brilliant collection of design portfolios presented using animated GIFs. By Roll Studio.

Check it out



C566_masks

Masks

An interactive presentation on masking techniques originally created for a Creative Front-end Belgium meetup hosted by Reed. By Thomas Di Martino.

Check it out




C566_mike

Supermaya

Supermaya is an Eleventy starter kit designed to help you add rich features to a blog or website without the need for a complicated build process.

Check it out


C566_darkmode

Dark Mode

Varun Vachhar shares the challenges he encountered when migrating from Jekyll to Gatsby related to dark mode.

Read it












C566_fresh

Fresh Folk

A beautiful mix-and-match illustration library of people and objects made by Leni Kauffman.

Check it out


C566_arcticvault

GitHub Archive Program

The GitHub Archive Program will safely store every public GitHub repo for 1,000 years in the Arctic World Archive in Svalbard, Norway.

Check it out



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


Source: Codrops, Collective #566

Abstracting WordPress Code To Reuse With Other CMSs: Concepts (Part 1)

dreamt up by webguru in Uncategorized | Comments Off on Abstracting WordPress Code To Reuse With Other CMSs: Concepts (Part 1)

Abstracting WordPress Code To Reuse With Other CMSs: Concepts (Part 1)

Abstracting WordPress Code To Reuse With Other CMSs: Concepts (Part 1)

Leonardo Losoviz



Making code that is agnostic of the CMS or framework has several benefits. For instance, through its new content editor Gutenberg, WordPress enables to code components which can be used for other CMSs and frameworks too, such as for Drupal and for Laravel. However, Gutenberg’s emphasis on re-utilization of code is focused on the client-side code of the component (JavaScript and CSS); concerning the component’s backend code (such as the provision of APIs that feed data to the component) there is no pre-established consideration.

Since these CMSs and frameworks (WordPress, Drupal, Laravel) all run on PHP, making their PHP code re-usable too will make it easier to run our components on all these different platforms. As another example, if we ever decide to replace our CMS with another one (as has recently happened that many people decried WordPress after its introduction of Gutenberg), having the application code be agnostic from the CMS simplifies matters: The more CMS-agnostic our application code is, the less effort will be required to port it to other platforms.

Starting with application code built for a specific CMS, the process of transforming it to CMS-agnostic is what, in this article, I will call “abstracting code”. The more abstract the code is, the more it can be re-used to work with whichever CMS.

Making the application completely CMS-agnostic is very tough though — even possibly impossible — since sooner or later it will need to depend on the specific CMS’s opinionatedness. Then, instead of attempting to achieve 100% code reusability, our goal must simply be to maximize the amount of code that is CMS-agnostic to make it reusable across different CMSs or frameworks (for the context of this article, these 2 terms will be used interchangeably). Then, migrating the application to a different framework will be not without pain, but at least it will be as painless as possible.

The solution to this challenge concerns the architecture of our application: We must keep the core of the application cleanly decoupled from the specifics of the underlying framework, by coding against interfaces instead of implementations. Doing so will grant additional benefits to our codebase: We can then focus our attention almost exclusively on the business logic (which is the real essence and purpose of the application), causing the code to become more understandable and less muddled with the limitations imposed by the particular CMS.

This article is composed of 2 parts: In this first part we will conceptualize and design the solution for abstracting the code from a WordPress site, and on the 2nd part we will implement it. The objective shall be to keep the code ready to be used with Symfony components, Laravel framework, and October CMS.

Code Against Interfaces, Rely On Composer, Benefit From Dependency Injection

The design of our architecture will be based on the following pillars:

  1. Code against interfaces, not implementations.
  2. Create packages, distribute them through Composer.
  3. Dependency Injection to glue all parts together.

Let’s analyze them one by one.

Code Against Interfaces, Not Implementations

Coding against interfaces is the practice of interacting with a certain piece of code through a contract. A contract, which is set up through an interface from our programming language (PHP in our case since we are dealing with WordPress), establishes the intent of certain functionality, by explicitly stating what functions are available, what inputs are expected for each function, and what each function will return, and it is not concerned with how the functionality must be implemented. Then, our application can be cleanly decoupled from a specific implementation, not needing to know how its internals work, and being able to change to another implementation at any time without having to drastically change code. For instance, our application can store data by interacting with an interface called DataStoreInterface instead of any of its implementations, such as instances of classes DatabaseDataStore or FilesystemDataStore.

In the context of WordPress, this implies that — by the end of the abstraction — no WordPress code will be referenced directly, and WordPress itself will simply be a service provider for all the functions that our application needs. As a consequence, we must consider WordPress as a dependency of the application, and not as the application itself.

Contracts and their implementations can be added to packages distributed through Composer and glued together into the application through dependency injection which are the items we will analyze next.

Create Packages, Distribute Them Through Composer

Remember this: Composer is your friend! This tool, a package manager for PHP, allows any PHP application to easily retrieve packages (i.e. code) from any repository and install them as dependencies.

Note: I have already described how we can use Composer together with WordPress in a previous article I wrote earlier this year.

Composer is itself CMS-agnostic, so it can be used for building any PHP application. Packages distributed through Composer, though, may be CMS-agnostic or not. Therefore, our application should depend on CMS-agnostic packages (which will work for any CMS) as much as possible, and when not possible, depend on the corresponding package that works for our specific CMS.

This strategy can be used to code against contracts, as explained earlier on. The packages for our application can be divided into two types: CMS-agnostic and CMS-specific ones. The CMS-agnostic package will contain all the contracts and all generic code, and the application will exclusively interact with these packages. For each CMS-agnostic package containing contracts, we must also create a CMS-specific package containing the implementation of the contracts for the required CMS, which is set into the application by means of dependency injection (which we’ll analyze below).

For example, to implement an API to retrieve posts, we create a CMS-agnostic package called “Posts”, with contract PostAPIInterface containing function getPosts, like this:

interface PostAPIInterface
{
  public function getPosts($args);
}

This function can be resolved for WordPress through a package called “Posts for WordPress”, which resolves the contract through a class WPPostAPI, implementing function getPosts to simply execute WordPress function get_posts, like this:

class WPPostAPI implements PostAPIInterface
{
  public function getPosts($args) {
    return get_posts($args);
  }
}

If we ever need to port our application from WordPress to another CMS, we must only implement the corresponding CMS-specific package for the new CMS (e.g. “Posts for October CMS”) and update the dependency injection configuration matching contracts to implementations, and that’s it!

Note: It is a good practice to create packages that only define contracts and nothing else. This way, it is easy for implementers to know exactly what must be implemented.

Dependency Injection To Glue All Parts Together

Dependency injection is a technique that allows declaring which object from the CMS-specific package (aka the “service provider”) is implementing which interface from the CMS-agnostic package (aka the “contract”), thus gluing all parts of the application together in a loosely-coupled manner.

Different CMSs or frameworks may already ship with their own implementation of a dependency injection component. For instance, whereas WordPress doesn’t have any, both Symfony and Laravel have their own solutions: DependencyInjection component and Service Container respectively.

Ideally, we should keep our application free from choosing a specific dependency injection solution, and leave it to the CMS to provide for this. However, dependency injection must be used also to bind together generic contracts and services, and not only those depending on the CMS (for instance, a contract DataStoreInterface, resolved through service provider FilesystemDataStore, may be completely unrelated to the underlying CMS). In addition, a very simple application that does not require an underlying CMS will still benefit from dependency injection. Hence, we are compelled to choose a specific solution for dependency injection.

Note: When choosing a tool or library, prioritize those ones which implement the corresponding PHP Standards Recommendation (in our case, we are interested in PSR-11), so they can be replaced without affecting the application code as much as possible (in practice, each solution will most likely have a custom initialization, so some re-writing of application code may be unavoidable).

Choosing The Dependency Injection Component

For my application, I have decided to use Symfony’s DependencyInjection component which, among other great features, can be set-up through YAML and XML configuration files, and it supports autowiring, which automatically resolves how different services are injected into one another, greatly reducing the amount of configuration needed.

For instance, a service Cache implementing a contract CacheInterface, like this one:

namespace MyPackageMyProject;
class Cache implements CacheInterface
{
  private $cacheItemPool;
  private $hooksAPI;

  public function __construct(
    CacheItemPoolInterface $cacheItemPool, 
    HooksAPIInterface $hooksAPI
  ) {
    $this->cacheItemPool = $cacheItemPool;
    $this->hooksAPI = $hooksAPI;
  }

  // ...
}

… can be set as the default service provider through the following services.yaml configuration file:

services:
  _defaults:
    bind:
      MyPackageMyProjectHooksAPIInterface: '@hooks_api'

  hooks_api:
    class: MyPackageMyProjectContractImplementationsHooksAPI

  cache:
    class: MyPackageMyProjectCache
    public: true
    arguments:
      $cacheItemPool: '@cache_item_pool'

  cache_item_pool:
    class: SymfonyComponentCacheAdapterFilesystemAdapter

As it can be observed, class cache requires two parameters in its constructor, and these are resolved and provided by the dependency injection component based on the configuration. In this case, while parameter $cacheItemPool is manually set, parameter $hooksAPI is automatically resolved through type-hinting (i.e. matching the expected parameter’s type, with the service that resolves that type). Autowiring thus helps reduce the amount of configuration required to glue the services and their implementations together.

Make Your Packages As Granular As Possible

Each package must be as granular as possible, dealing with a specific objective, and containing no more or less code than is needed. This is by itself a good practice in order to avoid creating bloated packages and establishing a modular architecture, however, it is mandatory when we do not know which CMS the application will run on. This is because different CMSs are based on different models, and it is not guaranteed that every objective can be satisfied by the CMS, or under what conditions. Keeping packages small and objective then enables to fulfill the required conditions in a progressive manner, or discard using this package only when its corresponding functionality can’t be satisfied by the CMS.

Let’s take an example: If we come from a WordPress mindset, we could initially assume that entities “posts” and “comments” will always be a part of the Content Management System, and we may include them under a package called “CMS core”. However, October CMS doesn’t ship with either posts or comments in its core functionality, and these are implemented through plugins. For the next iteration, we may decide to create a package to provide for these two entities, called “Posts and Comments”, or even “Posts” under the assumption that comments are dependent on posts and bundled with them. However, once again, the plugins in October CMS don’t implement these two together: There is a plugin implementing posts and another plugin implementing comments (which has a dependency on the posts plugin). Finally, our only option is to implement two separate packages: “Posts” and “Comments”, and assign a dependency from the latter to the former one.

Likewise, a post in WordPress contains post meta attributes (i.e. additional attributes to those defined in the database model) and we may assume that every CMS will support the same concept. However, we can’t guarantee that another CMS will provide this functionality and, even if it did, its implementation may be so different than that from WordPress that not the same operations could be applied to the meta attributes.

For example, both WordPress and October CMS have support for post meta attributes. However, whereas WordPress stores each post meta value as a row on a different database table than where the post is stored, October CMS stores all post meta values in a single entry as a serialized JSON object in a column from the post table. As a consequence, WordPress can fetch posts filtering data based on the meta value, but October CMS cannot. Hence, the package “Posts” must not include the functionality for post meta, which must then be implemented on its own package “Post Meta” (satisfiable by both WordPress and October CMS), and this package must not include functionality for querying the meta attributes when fetching posts, which must then be implemented on its own package “Post Meta Query” (satisfiable only by WordPress).

Identifying Elements That Need To Be Abstracted

We must now identify all the pieces of code and concepts from a WordPress application that need be abstracted for it to run with any other CMS. Digging into an application of mine, I identified the following items:

  • accessing functions
  • function names
  • function parameters
  • states (and other constant values)
  • CMS helper functions
  • user permissions
  • application options
  • database column names
  • errors
  • hooks
  • routing
  • object properties
  • global state
  • entity models (meta, post types, pages being posts, and taxonomies —tags and categories—)
  • translation
  • media

As long as it is, this list is not yet complete. There are many other items that need abstraction, which I will not presently cover. Such items include dealing with the location of assets (some framework may require to place image/font/JavaScript/CSS/etc. files on a specific directory) and CLI commands (WordPress has WP-CLI, Symfony has the console component, and Laravel has Artisan, and there are commands for each of these which could be unified).

In the next (and final) part of this series of articles, we will proceed to implement the abstraction for all the items identified above.

Evaluating When It Makes Sense To Abstract The Application

Abstracting an application is not difficult, but, as shall be observed in the next article, it involves plenty of work, so we must consider carefully if we really need it or not. Let’s consider the advantages and disadvantages of abstracting the application’s code:

Advantages

  • The effort required to port our application to other platforms is greatly reduced.
  • Because the code reflects our business logic and not the opinionatedness of the CMS, it is more understandable.
  • The application is naturally organized through packages which provide progressive enhancement of functionalities.

Disadvantages

  • Extra ongoing work.
  • Code becomes more verbose.
  • Longer execution time from added layers of code.

There is no magic way to determine if we’ll be better off by abstracting our application code. However, as a rule of thumb, I’ll propose the following approach:

Concerning a new project, it makes sense to establish an agnostic architecture, because the required extra effort is manageable, and the advantages make it well worth it; concerning an existing project, though, the one-time effort to abstract it could be very taxing, so we should analyze what is more expensive (in terms of time and energy): the one-time abstraction, or maintaining several codebases.

Conclusion

Setting-up a CMS-agnostic architecture for our application can allow to port it to a different platform with minimal effort. The key ingredients of this architecture are to code against interfaces, distribute these through granular packages, implement them for a specific CMS on a separate package, and tie all parts together through dependency injection.

Other than a few exceptions (such as deciding to choose Symfony’s solution for dependency injection), this architecture attempts to impose no opinionatedness. The application code can then directly mirror the business logic, and not the limitations imposed by the CMS.

In the next part of this series, we will implement the code abstraction for a WordPress application.

Smashing Editorial
(rb, dm, yk, il)

Source: Smashing Magazine, Abstracting WordPress Code To Reuse With Other CMSs: Concepts (Part 1)

Collective #565

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



C565_2019

The 2019 Web Almanac

The Web Almanac is an annual state of the web report combining the expertise of the web community with the data and trends of the HTTP Archive.

Check it out







C565_gauges

Gauges

Amelia Wattenberger coded up a gauge example from Fullstack D3’s Dashboard Design chapter as a React component.

Check it out









C565_innerwolf

My Inner Wolf

An eclectic visual composition of our inner worlds: a project on absence epilepsy seizures by Moniker in collaboration with Maartje Nevejan.

Check it out








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


Source: Codrops, Collective #565

Become An HTML Email Geek With These Videos From Rémi Parmentier

dreamt up by webguru in Uncategorized | Comments Off on Become An HTML Email Geek With These Videos From Rémi Parmentier

Become An HTML Email Geek With These Videos From Rémi Parmentier

Become An HTML Email Geek With These Videos From Rémi Parmentier

Rachel Andrew



Creating an HTML email can feel like stepping back a few years as a web developer. All of our new layout functionality is unavailable to us &mdasj; email clients render the same layout in completely different ways. Just when we think we have it all fixed, another email client shows up with a new set of bugs.

Not too long ago, Rémi Parmentier, an HTML Email developer, ran a session with practical front-end techniques for building modern, cross-client emails. A few weeks later, he gave a wonderful talk at SmashingConf Freiburg highlighting some of the common struggles and shared useful strategies for avoiding problems in email development.

There was so much useful information contained in these sessions that we wanted to release them more widely — including the webinar transcript and references to slides and resources. If you have ever struggled with email development, these will give you a great starting point to understand why an email isn’t rendered properly, and how to squash those nasty bugs quickly.

If you enjoy learning from these videos, check out Smashing Membership. Starting from this month, we will be showing some of the live sessions we run every month to a wider audience — absolutely free of charge to view. However, if you’d like to join the discussion live and perhaps have your work reviewed by an expert, join Smashing Membership. For the price of one coffee a month, you can support the creation of more content like this.

Now get ready to learn everything you need to know about HTML email!

Webinar: HTML Email with Rémi Parmentier

Resources And Transcript

Rémi Parmentier: Thanks, everyone, for coming to my presentation. My name is Rémi Parmentier. Some of you might know me from Twitter or from my blog under the nickname hteumeuleu. I’ve been doing HTML emails for as long as I’ve been working in this industry. For the past few years, I’ve started to give training in HTML emails as well I am spending a lot of time online on Slack, on Twitter, on forums to help people find solutions for their email problems. This gave me a pretty good view of most of the coding problems that people have and how to actually solve them. I started working on this email coding guidelines project this year. This was greatly inspired by some of the work that’s been done on the web about I think a decade ago.

Rémi Parmentier: About a decade ago, there was a lot of trends of web guidelines being shared by people from many different companies. First one was the most famous one was this code guide by Mark Otto, who was then working at Twitter. The point of the document was to share a lot of guidelines about how HTML and CSS should be coded within the company. There was a lot of good practices shared in this document, like which doctype you should use or to close your tag and such. I think this is really interesting to have.

Rémi Parmentier: In the email world, Ted Goas from Stack Overflow actually made a very similar document with a lot of content as well about how they’re building the emails at Stack Overflow. This really gave me the lust to make a similar document that everyone could share within their company or everyone could pick good practices for building HTML emails. We’re going to see a few of these best practices and you’ll be able to see the document afterwards online. Let’s start ahead.

Rémi Parmentier: The first thing that I usually share is to use the HTML5 doctype. Whenever I help people online of open HTML email, it makes me sad to see that a lot of people are still using HTML4 doctype or XHTML 1. The first reason to use the HTML5 doctype is that it’s really nice. Actually, it’s very short. You can type it by hand, you can remember it, and that’s already a good reason to use it.

Rémi Parmentier: The most important reason to use the HTML5 doctype is that when an email is displayed in webmail, our doctype is usually removed and we inherit from the webmail’s doctype. Most webmails use the HTML5 doctype, so even for you wish you could use HTML1 or HTML4 doctype, this won’t work because webmails will remove it.

Rémi Parmentier: I made this little illustration of how this actually works. On the left, you can see an email address coded. It’s got a style tag and it’s got a div and an H1 inside. What happens when a webmail like Gmail, for example, wants to display this content, it will pick the style tags and pick the content within the body, and it will prefix the styles, it will remove all the styles that it won’t support, and then it will include this inside the HTML of the actual webmail, because webmails are actually just HTML and CSS. This means that even if I use an HTML4 doctype, because Gmail uses HTML5 doctype, my code will be random thanks to that doctype. This is a good thing to have in mind.

Rémi Parmentier: I made this about this, about which doctype you should use in HTML emails, about three years ago already, but what I saw back then was that most of the email clients already were using an HTML5 doctype. A few of them didn’t have a doctype at all, like on mobile apps sometimes, but a lot of them were on HTML5.

Rémi Parmentier: It’s important to know that you can end up on different doctypes because there can be differences. The first one is that HTML5 actually have spaces between images. If you slice some big image inside your email, you will see something like this if you try it with an HTML5 doctype.

Rémi Parmentier: Let me actually show you this with a little demo. Here, I have this … Oops, it’s the wrong one. Here I have this little demo of a T-Rex. It’s actually three images. Here with an HTML1 doctype, everything is working fine, but if I use an HTML5 doctype instead, boom, you have white lines appearing between each images.

Rémi Parmentier: Now, I’m not exactly sure why this happens, but I think it’s because when HTML5 upgraded, they cannot change some of the way that images are supposed to behave according to the specification, so now it looks more like a paragraph with text, so there are lines in between images.

Rémi Parmentier: Email Geeks have found very good solutions to the service. One of the solutions is to actually add a display block style to every images. Once you do this, it will remove the white lines between the images. Another solution to avoid this if you can’t use display block is to add a vertical align middle style and then you will remove these white lines as well.

Rémi Parmentier: This is a first quirk that you can encounter with HTML5 doctype, but there is another interesting case is that you can’t display block a table cell in WebKit without a doctype. This one is really interesting as well. I’ve got a table for this as well, which would be right here.

Rémi Parmentier: Here I’ve got a table with three little dinosaurs next to each others. Usually when we’ve got tables like this and we want to make our emails optimized for mobiles, what we can do is apply the display block to our TDs and then they will stack on each others like this.

Rémi Parmentier: As we can see here, we have an HTML5 doctype. This is working fine, but if I would ever end up in an image client that will remove the doctype, then this won’t work anymore in WebKit. As you can see now, it’s back to the regular pattern display.

Rémi Parmentier: I think this has to do with legacy websites and quirk modes and all of these things, but one solution that was found by the email community is to actually use TH tags instead of TD. If I remove every TD here by TH, you can see that, here, even without a doctype, it’s working again. This is some kind of the quirks that you have to deal with in HTML emails because of not only email clients behave but also rendering engines like WebKit here.

Rémi Parmentier: The second best practice I’d want to share with you today is to use the lang attributes. The lang attribute in HTML is to define the language of your document. This is very important for accessibility, and mostly this is because accessibility tools like screen readers will be able to pick the right voice for it.

Rémi Parmentier: Once again, let me show you a demo of this live, and hopefully it won’t crash. Here I have this very nice email from Mailchimp. As it was said before, I am French, so my computer is set in French. My screen reader is in French as well, so every time we’ll see some new content, it will try to read it in French. I will stop my screen reader now. You try to see when we’ll get to this paragraph and see how it will read it.

Rémi Parmentier: I know that I don’t really have a good English accent, but this is even worse than mine. If you don’t set the lang attributes, your content will be read on whatever default language is for your users. The quick phase here is to add the lang attributes, and then I can restart my screen reader.

Screenreader:: Mailchimp Presents has a new collection of original content made with entrepreneurs in mind. In recent months, we’ve rolled out documentaries, short-form series and podcasts that live only on Mailchimp. Today, we officially launch a platform.

Rémi Parmentier: As you can hear, even for my screen reader, and my system is still set in French, once the screen reader is actually on HTML contents, it will use another voice, an English voice there, to read the content which makes the experience much, much better here.

Rémi Parmentier: One small difference that we have in HTML emails with the lang attribute is that, just like for the doctype, the doctype might not be picked up by webmails, because webmails will only take just styles and the content of the body. It’s usually a good practice to add the lang attribute as well on the wrapper that you have on your content inside your body, so you’ll make sure that this will get picked by webmails as well.

Rémi Parmentier: Now a third best practice that I like is to actually use styles over HTML attributes. This is really something that people hate about HTML emails because they feel that they have to use all the HTML attributes, they have to use all code, and this makes emails look very different from the web, but there is really no reason for this at all unless you need to support very old email clients like Lotus Notes 6 or similar.

Rémi Parmentier: In this example here, in the first example, you can see I’ve used valign, align and bgcolor attributes in HTML, but all of those can be very easily and robustly replaced by the corresponding styles. Here I only have one style attribute and inside I have the vertical align CSS property, text align and background color.

Rémi Parmentier: One reason I like to do this is because it makes go cleaner and more readable. All your presentational properties are grouped in a single style attribute instead of being all over the place with valign, align and all the stuff. This makes it, in my opinion, very, very better to read and to maintain.

Rémi Parmentier: There’s another reason I like to use styles over attributes is that it helps taking over email clients’ own styles. For example, on the French webmail of Orange, the webmail’s UI actually has a CSS that has a rule that sets every TD to vertical align top. Because of this rule, if you were to use only HTML attributes like valign=middle, the CSS role from the webmail would override with the HTML attributes because this is how the cascade works in HTML and CSS.

Rémi Parmentier: Instead, if we use an inline style with a vertical align property on the TD here, well, this style will take over the webmail style because inline styles are more important than external style sheets. Using styles over attributes is also a good way to fight other email clients’ and webmails’ default styles.

Rémi Parmentier: There are a few exceptions to the attributes that I still use. The first exceptions is to center a table in Outlook 2007 to 2019 on Windows, because as Scott said in the introduction, Outlook uses Word as a rendering engine in those versions and it’s not really good at understanding CSS, at least for some properties.

Rémi Parmentier: For example, here, it would understand the margin properties for pixel values, but it wouldn’t understand the margin zero auto value to center a table. We still need the align=center attribute to center elements and data, especially in Outlook, but we no longer need to use which attributes as in the first example here. This can be replaced by the width style instead.

Rémi Parmentier: Now other exception in Outlook as well is when you want to define a fluid image width. In the first example, I use a width attribute with 100% value. The thing is that Outlook actually doesn’t deal with percentage width for images the same way as it should be in CSS.

Rémi Parmentier: The percentage in Outlook is actually matching the physical image size and not the parent size in the HTML. If you’ve got an image that’s 600-pixel wide and you use a width=50%, then your image will actually be 300 pixels no matter what the size of your parent in HTML is.

Rémi Parmentier: Usually, to avoid any quirks with this is then I always define a fixed width in pixels for Outlook using the width attribute in HTML, and then using a style, I use a width with 100%. Outlook will only pick the attribute value here and not the style value.

Rémi Parmentier: Then, another exception I have when I use styles over attributes is to reset the default styles of the table. By default, the HTML tables have borders and padding inside and cells, et cetera. The proper way to do this in CSS is to set border zero, border spacing zero, our padding is zero, our border is zero, the first ones on the table, and expanding your border actually for each cell of your table.

Rémi Parmentier: This is pretty much why I don’t really like to do it the CSS way because you need to repeat the padding and border for every TD of your table, while if you use the attributes, you only need to use them on the table, and then you’re all set for any … no matter on any cells you have inside your table. This is probably something I will change my mind in a few years maybe, I hope, but for now, I’m still used and I prefer using the attribute way for resetting default styles on tables.

Rémi Parmentier: Now another best practice I’d like to share is, do not split the visuals. This was actually a very common practice maybe a decade ago. When we had large images, it was always better, at least it was always shared that you should split it to make download faster and things like that, but this is not true today.

Rémi Parmentier: Not splitting visual actually has a lot of benefits. The first one is that it’s easier to maintain. If you have a big visual in your email and it’s Friday night and your project manager comes at you and asks you to change it at the last minute, well, you don’t have to open Photoshop and slice your images again and where you’ve got everything. You can just replace that image and you’re done.

Rémi Parmentier: It’s also better for accessibility because you have a single image, you have a single element, so a single alt attribute. This is simpler and better for accessibility. One thing it’s also better for is for web performance, because downloading 100 kilobytes image is theoretically faster than downloading five image of 20 kilobytes.

Rémi Parmentier: That’s because for each image of 20 kilobytes, the request to the server needs to be made and we need to wait the answer five times. Even for the really small micro-transactions between the client and the server, this add up the more image you have, and it can slow down the download of your email image, so this is something to avoid.

Rémi Parmentier: Next, on the WebKit, there’s also a very weird behavior. Whenever you use a CSS transform on sliced images, WebKit will have very thin lines between split images. I would just show you a demo of this as well. Back to my first T-Rex image here, if I add a small transform here that will scale the image, here you can see that at this ratio, there are very small lines that appear within each slices of my image.

Rémi Parmentier: This is really due to WebKit not handling well the way they should scaled images like this. Maybe there’s a node size somewhere and it doesn’t compute properly, so you end up with small hair lines like this. Yes, the best practice here is to avoid to split your visuals.

Rémi Parmentier: This is actually something that will happen inside email clients because in Outlook.com, for example, if your email is bigger than the actual view of emails inside the clients, then your email will be resized using a CSS transform to feed the view port of the email client. This is something that you should be wary of.

Rémi Parmentier: Finally about splitting visual, I always try not to do it because this kind of things happens. This is something that was shared on Reddit almost 10 years ago. This is an email by LinkedIn and the face of this young lady, it was cut in half, maybe because some text was longer than expected or maybe because here the user chose to set up his email client with a bigger font than expected, so all kind of things can happen inside email clients, just like on the web. If you want to avoid these kind of strange situations, just don’t split visuals.

Rémi Parmentier: Next, this is a big one. This is tables for layouts. This surely is the most common thing that people think about when they think about HTML emails. It always annoys because we mostly don’t really need tables for layouts, except for one email client, and that is the Outlooks on Windows from 2007 to the latest 2019 version.

Rémi Parmentier: The reason of that, as we said before, is because all of those versions of Outlooks use Word as a rendering engine. Word is not really good in interpreting HTML and CSS. There is this documentation online about what it should be capable of, but it’s pretty hard to read and to make sense of, so I try to make this diagram to actually make sense of it.

Rémi Parmentier: From this documentation, what it says is that CSS supports in Outlook will actually vary from which elements you use CSS on. It will be different in body and span than in div and p and then all the other supported HTML tags.

Rémi Parmentier: First, if you have a body and span, you can only use what Microsoft calls Core CSS properties. That’s the color property, the font, text align and background color property. On the body element and the span element, you can only use those four CSS properties.

Rémi Parmentier: Then, on divs and paragraphs, you can use all those four properties from the Core level, but you can also use two new properties from what Microsoft calls the Coreextended level. In this level, you have two new properties, the text indent and margin properties.

Rémi Parmentier: Then, for all the other tags, you can use properties of the two previous levels, and you have what Microsoft calls the Full CSS support with many more CSS properties, but I think the most interesting are the width, height, padding, border and this kind of properties for defining elements.

Rémi Parmentier: This means here that if you want to use width and height properties and make it work in Outlook, you won’t be able to do this on a div because div only support Coreextended and Core CSS properties. You will need to use tables for those CSS properties, and the same thing for padding and border.

Rémi Parmentier: I usually narrow it down to the few following guidelines to use tables. I try to only use a table when I want to set a fixed width on an element. If I need an element to be a certain width, then I will use a table and define the width from that table.

Rémi Parmentier: Also, if I want to set two block elements side by side, because even Outlook doesn’t really support any advanced CSS layout property, so even float is not really well-supported, so if you need to have two elements side by side, then as you make a table with two cells, and those two elements will be next to each others then. Then I use tables whenever I need to set a padding, a background color or border style. This make it very reliant, very robust to use a table for those styles only.

Rémi Parmentier: Now a problem with tables is something we’ve learned in the way a long time ago is that tables are not made for presentation. They are made for actual data tables. This can be very problematic for screen readers especially. In order to improve accessibility here, we will use the role=presentation attribute whenever we will make a layout table.

Rémi Parmentier: Let me show you a quick example of how this will change the way your email is interpreted by a screen reader. I will take a new demo here. I’ve got this email from Jacadi, which is a French children clothing brand. They have this table here with different sizes of products. This is actually a table inside the code. I’ve pre-recorded a video here to show you how this is read by a screen reader.

Screenreader: Counting pairs, web content. Blank, blank, blank. Table 1 column. Nine rows. Blank. Column 1 of 1. Row 2. Nine Level 2 tables, seven columns. One row, Column 1 of 1. Blank. Column 3 of 7. Blank. Column 4 of 7. Blank. Column 5 of 7. Blank. Column 7 of 7. End of table. Row 3 of 9, blank. Column 1 of 1. Row 4 of 9, Row 2 table, seven columns, one blank. Column 1 of 7. Blank. Blank. End of table. Row 5 of 9, blank. Row 6 of 9, blank. Column, blank, blank, column end of table. Row 7 of 9, blank. Row 8 of 9 Row 2 table, blank. Column 1, blank. Column end of table. Row 9 of 9 blank. Column end of table.

Rémi Parmentier: This is terrible. This is so annoying. Now let’s see how we can fix these cells. The way we can fix this is by adding the role=presentation attributes. This is not something that it reads from tables to tables, so we need to add this attribute whenever we’ll have a new table. We have a few nested tables here, so we’ll add a few. Here is how the results sound.

Screenreader: Blank. Blank. Voice-over off.

Rémi Parmentier: This is so much better. This is so much smoother and it makes for much nicer experience. I hope this convinced you that you should always use as less tables as you can, but if you do, use role=presentation attributes on those tables.

Rémi Parmentier: Now, one step that we can take even further is that since tables are mostly for Outlook, we can use conditional comments to make those tables only visible on Outlook. Conditional comments are actually something that was available in Internet Explorer as well until I think I9. With these, if MSOs are in text, we can tell the borders that all the following contents within that conditional comment will be available only for MSO clients, so that’s mostly Outlook.

Rémi Parmentier: Then, between those opening and closing tables comments, we can have a div with a role or stuff that will come just like for a regular web border, although webmails will pick the div and Outlook will pick the table. This is video how I got most of my emails.

Rémi Parmentier: Now another small good practice to have is to use margin or padding for spacing. This is mostly to avoid empty containers, empty cells like this where we have a role within a cell with a height of 20 and then we have TDs with width of 20 to create margin all along with this content. I still see this done a lot, and this make your code really, really heavy. It’s less readable and it’s really bad in my opinion.

Rémi Parmentier: The proper way to do something like this would be to use a table as well if you want and have the padding style on the first TD, and then inside use margin to space tags between each others. This works again really well in every popular image client and in Outlook as well.

Rémi Parmentier: Now the small quirk that can happen in the Outlook and Windows is that there is the background color. If you use the background color on any of these elements with margin, it actually bleeds through the margin. Here’s an example where I should have a margin between the red background and blue background, but in Outlook, the margin is actually the same color of the background of that element. In those cases, then the solution is to maybe use another table and nest your content like this to space elements, but if you don’t use background, then margin is really safe even in Outlook.

Rémi Parmentier: Finally, this is perhaps my favorite recommendation. It’s to make it work without style tags. It’s not necessarily about having this raw HTML rendering, but thinking about progressive enhancements and graceful degradation and about how your emails will look without this guideline. This is something pretty unusual in cooperation of the web because it doesn’t happen on the web, but not having a style tag actually happens a lot on email clients.

Rémi Parmentier: First, not all email clients support style tags. Perhaps one of the most common example I see is Gmail on its mobile applications on iOS and Android lets you configure a third-party email address. You can use your Yahoo or Outlook.com address inside the Gmail app. If you do so, then every emails that you check won’t have support for style tags. This is what Email Geeks have nicknamed GANGA for Gmail apps with non-Gmail accounts. This is a very common occurrence that you can have.

Rémi Parmentier: Then you have a lot of cases for smaller or local or international email clients like SFR in France or Yandex and Mail.ru in Russia, et cetera. Even to this day, there are a lot of email clients that don’t support style tag, so if you want to make your code more robust, make sure that it can work without style tag.

Rémi Parmentier: Sometimes it’s also temporary. For example, in the past year or so, Gmail has had two days where style tags were completely removed from every email on every one of their email clients. We don’t know why this happened. There has been zero communication on that, but there’s a good chance that maybe they detected some kind of attacks that use certain styles, and so they needed to remove it very fastly and secure their users, so they removed style tag support for a few hours or almost a day. If you were to send a campaign that day, you were out of luck if your emails required style tags to work.

Rémi Parmentier: Sometimes also it’s contextual. For example, in Gmail, when you forward an email to someone, then you won’t have any style tags anymore, or when an email is viewed in its unclean version, you know when you have a view entire messaging at the bottom of your email because it was too long, if you view your email in that window, you won’t be able to have a style tag.

Rémi Parmentier: Then finally, sometimes it’s buggy. For example, in Yahoo Android in the app, the head is removed, so every style tag inside it are removed as well, but only the first head. We don’t really usually think as HTML documents are in multiple heads, but you can actually totally do this.

Rémi Parmentier: This has been pretty much a common practice now for a few years to deal with this bug in Yahoo. If you have a second head with your style with it, then it will work fine in Yahoo Android and in most email clients as well. We have just this empty head first so that Yahoo will strip it, and this will work.

Rémi Parmentier: Now, what I mean by making an email works is that the email should adjust its layer to any width without horizontal scroll and the email should reflect the branding of the sender. This can be colors often, this can be fonts or whatever, but make sure that it works without styles.

Rémi Parmentier: In order to do this, we can use inline styles. This is why most emails still use inline style, and I really recommend to do this for most of your styles. Make sure that the brand, the colors and everything can come up with just inline style.

Rémi Parmentier: Then, to tackle mobile emails to make sure that your emails can work fine from desktop to mobile, we have different solutions. The first one is to make your email fluid. I’ve got a little demo here as well, which I will show you right now.

Rémi Parmentier: This is an email that I’ve worked on almost four years ago for a French magazine, GEO. It’s got a lot of interesting things here. The first one is this grid here. If I try to resize it to make it responsive, you can see that it’s 100% fluid and it will scale accordingly to whatever the width for the image client is.

Rémi Parmentier: This works absolutely well without even a single style tag. This is just two tables on top, one for each lines, and we’ve got image inside it and the image are set with a fluid width, and so this works well enough even without style tags. This is good to have elements like this that can scale accordingly.

Rémi Parmentier: Now, this might not be the most optimal for every email, so another technique is to make your content hybrid. “Hee-breed,” or “hi-breed,” I’m not sure how you pronounce it, sorry for that, hybrid comes from the fact that you can still use media queries, but only as progressive enhancements, and then you need to make sure that your layout can fall back gracefully even without styles.

Rémi Parmentier: I would go back to this exact same email that I just showed you. A little bit lower here, we’ve got this gallery of user portraits. We can scale it as well. We have three columns here and then it will get on to two columns, and then only to one column.

Rémi Parmentier: The way this works here is using div width display in my block. We’ve got actually three divs like this next to each others and they all have a width of 33%. They will set so three can sit next to each others. They all have a minimum width of 140 pixels, so if there is no longer enough room to fit all those three elements because they’re in display inline block, they will naturally match even CSS flow down next to each others. This is a pretty good way to make it work like this.

Rémi Parmentier: I also use CSS and media queries here to make it a little bit more graceful when you have content here. If I disable the styles here, if I remove all of this, you can see that the layout has changed a little bit. We still have two columns, but they’re more stuck together. The layout still works appropriately where we can go from three to two to one layouts even without any styles, just with both div display and line blocks.

Rémi Parmentier: Then, perhaps the final, most popular way to make your emails work on mobiles is to make them mobile-first, to code them mobile-first. I will once again go back to that exact same email. You can see here that … Oops, it’s not fitting. I’ve got these two email columns next to each others. If I resize my window a little bit smaller, they will stack on each others.

Rémi Parmentier: Now because this is coded mobile-first, it means that this is actually the default layout for this zoom. On them, I use a min-width media query to change the layouts on desktop, on larger window sizes to make this work. If I remove all the styles here, just like I did before, you can see that now, our images are stacked on each others just like on mobile. This is what you’ll get when you code mobile-first. You get mostly your mobile view, but larger on desktop. This is really a lot of considerations to have when you’re coding emails for mobiles and for every email clients.

Rémi Parmentier: That’s pretty much it for me. All those recommendations, all those guidelines, you can find them online on GitHub, where I have these documents available. I really strongly encourage you really to share it within your colleagues and also to contribute to it.

Rémi Parmentier: If you think you have good recommendations that could apply to every emails you will code, feel free to share with me, feel free to contribute to this document as well. Hopefully you will have some questions. You can find me on Twitter or on my blog or you can send me an email as well if you have any questions after this session. Thank you.

Scott: Thank you very much, Rémi. “Re-my.” That was really very good. I’ve had a lot of questions about … Oh, hey, Vitaly.

Vitaly: Hello. Hello, Rémi. I’m so sorry about being late. Hello, everybody, dear Smashing members. I had a train delay and all. Scott, you wanted to say something? Sorry I interrupted you.

Scott: No. There was just two questions I was going to get out of the way. One was from Pawan, who’s a very, very active member of the Smashing membership. He is asking us, any thoughts on applying fonts consistently through HTML email?

Rémi Parmentier: Sorry, can you repeat?

Scott: Do you have any thoughts about applying fonts consistently through HTML email?

Rémi Parmentier: Yes. Well, for fonts, I usually encourage my clients to use web fonts in emails because it’s always better when you can have your own brand fonts. Now the thing to have in mind is that it won’t work everywhere. When using web fonts, especially, it almost works nowhere. It works in Apple Mail and in Thunderbird and maybe a few local email clients, but that’s really it. It doesn’t work in Gmail, it doesn’t work in Yahoo. If you can adapt to that, if that’s good for you, then go ahead and do it.

Rémi Parmentier: Now, the problem that you can have with web fonts like this is that if you try to use really funky fonts like Lobster or Pacifico on Google fonts, if it falls back to something like Arial or Helvetica, your email will definitely look very, very different. If you can use Montserrat and it falls back to Helvetica, that’s less a problem in my opinion. It really depends on the fonts you want to use and how much you are ready to not have this font in the cases where it won’t work.

Scott: That’s a really good point. There’s Zach Leatherman, who’s a very active member with Smashing and a presenter at SmashingConf, he’s done a lot of presentations about the fallback on fonts, so that’s interesting to make that correlation between email and web-based fonts.

Scott: Before I hand it over to Vitaly, my other question is, a lot of people are talking about interactive emails. There was actually, not this past SmashingConf, I believe the SmashingConf before, there was a presentation about interactive emails where you can actually complete an action just with one click of a button in an email, and mostly it’s based on AMP email. I was just curious, what do you know, what is AMP email and what’s the support for it currently?

Rémi Parmentier: AMP for Email is still something relatively new. It was announced by Google about a year ago, but it was only made available in Gmail desktop webmail about a few months ago, I think, in maybe April or something. AMP for Email is basically bringing the AMP Javascript framework to HTML email so that now inside Gmail, you can use interactive components like carousels or accordions, and you’ve got also, more interestingly, in my opinion, have live data.

Rémi Parmentier: If you’re selling clothes, for example, you can make sure that the clothes you’re presenting in your email are available in stock and are the ones in the best interest for your customer that’s viewing this email. This brings a lot of new customizations and possibilities for emails like that.

Rémi Parmentier: The thing is that it’s very still in its infancy and it mostly only works on Gmail desktops so far. It should come in on Gmail mobiles in the coming months, but then, there is also Yahoo and Outlook.com I think who said they were interested in implementing it.

Rémi Parmentier: Maybe this is something that will actually grab attention and go in the future. Yes, this is something I’m looking into and I’m really interested in. It’s still very hard to say if it will work and be successful, but there are a lot of interesting things in it.

Scott: Definitely. That falls back on what I was asking at the beginning before you started the presentation is, is there going to be some sort of standard that comes across for email clients? That’s my dream is that that will happen. On that note, Vitaly, I’m going to hand over to you for some questions.

Vitaly: Excellent. Thank you so much, Scott. Actually, Rémi, that was a brilliant presentation. Thank you so much. I learned-

Rémi Parmentier: Oh, thank you.

Vitaly: … a lot. I was a little bit not shocked, but in a way, I felt like it’s just wrong that we’re preaching these best practices for email which are not necessarily best practices full stop in 2019. It’s really about time that web standards have evolved.

Vitaly: We do have an open question from Pawan. Just before we do that, I have a couple, but one thing I wanted to know from somebody who’s so deeply motivated by the beauty and horror of email, I do have to find out, do you sleep well at night?

Rémi Parmentier: Oh, yes.

Vitaly: Excellent.

Rémi Parmentier: It depends because I have two small children, so not every night, but it’s not because of email.

Vitaly: Okay. The thing is, if you look back, let’s say, over the last, I don’t know, how many years have you been now in this madness?

Rémi Parmentier: Almost 15 years, but I really started digging into emails maybe five years ago, or maybe a little bit more, but yeah, about five years.

Vitaly: I’m curious, then, do you see that there has been a lot of progress in terms of email client supporting new features, broadening CSS support, Gmail, support of media queries and all? Do you see that the differences have been remarkable over the last five years or is it a very slow progress? Just so we can set expectations of what we should be expecting coming up next on the platform.

Rémi Parmentier: I would say both. It’s been both slow, but there has been progress. If you look back five years ago, five years ago, Gmail didn’t support media queries, and neither did Yahoo, I think, and neither did Outlook.com. Media queries are a huge tool to make email works well on mobile. The simple fact that those emails were able to adapt and add this to their list of CSS properties and features supported is actually a very good thing.

Rémi Parmentier: Now, it’s always a bit frustrating because it definitely doesn’t move as fast as the web is moving nowadays where you can see new features added in Chrome or Firefox every week and new articles about it. Things are moving slowly for really unknown reasons. That’s perhaps the biggest problem of emails is that everything is really opaque.

Rémi Parmentier: We don’t know how things work within Gmail or within Outlook and we have a lot of advantages for the web, people from the Chrome team, from the Firefox team sharing all the new advances in their browsers, but this is not the case in email clients, and this is really perhaps the most frustrating thing is that if you see a bug, if you have a problem, you pretty much have no one to talk to.

Vitaly: It’s a little bit loud here. I’m just in a park, I promise. Pawan is wondering, do you have any thoughts on embedding HTML forms in emails? Is it a good idea or not?

Rémi Parmentier: It can work. This is actually something that’s done a lot by us in the presentation you mentioned. Mark Robbins was the godfather of interactive emails. A lot of people actually use form in emails. Just like everything, you just need to realize that this won’t work everywhere. You need to think about, what happens if my form doesn’t work? Do I show something different? Do I have a link that sets to a form on my website? This is perhaps the hardest part, when you try to think of advances in emails like that. Every time, you need to think about what happens if this doesn’t work and what will I show to the people when it won’t work.

Vitaly: That makes sense. Well, I have so many questions. If you do have a few minutes, I just wanted-

Rémi Parmentier: Yeah, sure.

Vitaly: Because just today, I had to send out a wonderful email to our wonderful Smashing subscribers. One thing that stuck with me, and I wasn’t really sure how to deal with it. Not every client who understand media queries. Gmail does. You will have the media rule and then it will be all fine, but then, for some reason, when we’re sending out with Mailchimp and we do inline styles, actually inline styles in the attributes, what happens is you have the inline styles say font size 21 pixel, let’s say, on H2. Then you have a media that overrides it with font size 28 or something else.

Vitaly: Am I correct to assume that it’s probably a good idea to avoid bang importance one way or the other, because it will override whatever you have in the inline styles? If you have a media rule, and then that media rule, you actually have font size 30 pixels importance, will it override inline styles or not in most-

Rémi Parmentier: Yeah, definitely importance will override inline style.

Vitaly: But then it’s included in the media rule, right? If a client doesn’t understand media, they wouldn’t know-

Rémi Parmentier: Yes, exactly. Yes, which is why you once again need to think what happens if media is not supported. There, your inline style will be picked up. Maybe you will need to have the mobile-first approach and have the smaller font size inline and then use a min-width media query to have the different font size on desktop.

Vitaly: Makes sense. When you start building, do you actually build mobile-first or do you build desktop-first?

Rémi Parmentier: Well, it really depends. As I just show in my last three examples between-

Vitaly: Oh, sorry, I must have missed a few things.

Rémi Parmentier: Yeah. Between the three examples or if we do mobile-first, these are different approaches that you can have and that makes sense, depending on the contents you have. Most of the time, I usually go mobile-first, but it really depends on how you want your fallback to display. Sometimes it makes sense to have more desktop layouts and sometimes it makes more sense to have more mobile layouts.

Vitaly: For testing, we’re using Mailchimp just to see how it looks in different clients, but Doug Working is asking, do you have any recommendations for tools to test email code to see how it looks in different email clients?

Rémi Parmentier: Yes. There are two very good and very popular email tools that will allow you to take screenshots of how your email render across many, many email clients. Those are Litmus and Email on Acid. They work really similarly for email testing.

Rémi Parmentier: You just import your code and you will get screenshots very fast of how your email looks. This is really how I recommend to test emails because, of course, you need to do some ports manually as well, but it’s so much faster when you have a tool like this that it’s really more professional and you will win a lot of time by working with tools like this.

Vitaly: But then, it basically takes screenshots that you have to analyze. If you discover something like a major bug, how do you debug? Any tools for remote debugging, so to say?

Rémi Parmentier: Yeah. Debugging is the hardest part. In webmails, actually, it’s pretty easy because since the webmail is just a webpage, you can fire up your browser inspector tools and inspect the webmail’s code. This is really something interesting to do. I encourage everyone to do it at least once in a while because you will see how the webmail transforms your code in ways that you maybe have never imagined, like prefixing and renaming the classes you can have in your code.

Rémi Parmentier: This is a good way to see if maybe an image client has removed some of your styles or maybe if you did a mistake somewhere. For webmail, this is the best way to debug. For other email clients like Outlook, this is really a try-and-retry approach where you just send a code, change something, resend the email-

Vitaly: It sounds like fun.

Rémi Parmentier: Yeah, this can be a bit irritating. With the experience, you do less and less of this, but yes, unfortunately, there are no developer to see in Outlook.

Vitaly: That makes sense. One more thing that actually came up as well, is it safe to use SVG in emails? Or if you’re having the same image, would you prefer to use SVG or would you recommend to stay away from SVG and use PNG or JPEG instead, or God forbid GIF?

Rémi Parmentier: GIFs are actually still very popular in email-

Vitaly: I know. I noticed.

Rémi Parmentier: … but there are actually no reason because PNG is just as well-supported as GIFs for that matter. Regarding SVGs, just as my previous answers, I will say do it if you can manage to make it fall back to something I think for other email clients.

Rémi Parmentier: I think SVG works very well in Apple Mail, in Mac OS and iOS. It might work in a few more email clients, but I don’t think it works well in webmails. If you can have a distant SVGs that you call maybe in … For example, if you use a picture tag, you can have a source with your SVG, so this will be picked up by Apple Mail. Inside this picture, you can have an image tag as a fallback with a regular PNG or JPEG. This will work in other email clients.

Rémi Parmentier: There are different ways to tackle this kind of things, but SVG is definitely not the first format for images that you were shown when you built emails, but this is definitely something you can use, even though it won’t work everywhere. If you can have the proper fallback, then go ahead and use it.

Vitaly: Willow Cheng is asking, would you have recommendation on design tools which could let you design and export email in HTML?

Rémi Parmentier: No. Unfortunately, nothing that I can think of right now. Because most of the time, tools that will offer you to generate your HTML from design tool will be really rubbish because it will be either completely outdated and not work well in most modern versions of email clients, so I would actually recommend to stay away from those tools. From design point of view, I’m not sure there are any tools that will let you export clean, proper HTML for emails.

Vitaly: That’s actually an answer I was expecting, to be honest. Maybe just one final question. I’m sure I’ll have more later, but I know you do also have family and all and it’s quite late as well, and I get to meet you in Freiburg, so this is just a couple of weeks from now, so at SmashingConf Freiburg. This is going to be exciting.

Vitaly: I do have a question, though, still. I remember for a while, maybe a year ago, maybe two years ago, I found these two resources which were great. One of them was responsiveemailpatterns.com. The other is responsiveemailresources, or something like that, .com. One of them has gone away. It’s just down I think at this point, but I will also post the link later. Can you recommend some websites, resources where you can get copy-pastes almost email codes, snippets or something that you can reuse on a daily basis? I have heard that you might be working on something. Was I wrong?

Rémi Parmentier: I’m not sure, but I won’t talk about this for now, but it’s always [inaudible 01:04:56] snippets of codes that you can share because there are a lot of factors inside an email that can make your code behave differently. Every time there’s a tool that says it makes bulletproof backgrounds or bulletproof buttons, for example, you can always very easily, very shortly find email clients in which this doesn’t work properly. This is always a problem.

Rémi Parmentier: I remember the websites we were talking about, about responsive patterns, but I actually don’t know who were maintaining those. I don’t think they are ever really updated. As for websites, I can’t think of any right now. Maybe it will come later, that’s too bad, but the two things I will recommend is, if you’re into Twitter, follow the Email Geeks hashtag. That’s #emailgeeks, G-E-E-K-S. There are always a lot of people sharing good resources and the latest good articles that are always interesting.

Rémi Parmentier: The other thing I recommend is to join the Email Geeks at Slack channel. This is a really good community that’s growing a lot. There are all sorts of channels for marketing or for design or for code. People are really, really nice there and really always trying to help and almost available at any hours of the day, so this is incredible. If you look up for Email Geeks Slack on Google, you will see a subscription page that you can join. I hope you can join and just say “Hi” if you come.

Vitaly: Just one final, just the really, really last one, and then I’ll let you go. Sorry, excuse me if you mentioned it already in the session, but I’m wondering, as of today, as of 2019, looking at the best practices and the email clients, what are the baseline where you would say, let’s support this kind of client?

Vitaly: Because at this point, when we think about a 8, sometimes you obviously want to search something accessible to a 8, but you’re not going to optimize for a 8. We’re getting to the point where some companies can actually start dropping a 9 in the same way, but again, we’re quite far away yet.

Vitaly: When it comes to email clients, is Outlook 2013 still a thing? I remember the big update that Outlook brought in 2013 changed a lot of things in email, if I remember correctly. As of today, when we look into the landscape of email clients, what is the baseline we absolutely have to support at least?

Rémi Parmentier: I think the-

Vitaly: To support.

Rémi Parmentier: The others’ basis is Outlook 2007, because this is something actually pretty annoying is that this is used in a lot of big companies, and those big companies don’t pays new license for new versions of Outlook every year and they pay for a decade or so. There are still quite a lot of people I think using those older versions. This is still something that we have to account for.

Rémi Parmentier: Now, it’s not really that much a problem because between Outlook 2007 and Outlook 2019, unfortunately there weren’t that much of progress made because it’s still Word as a rendering engine. I think this is maybe the worst case we have to support mainly because, yes, we are not getting rid of those versions of Outlook anytime soon, I think.

Vitaly: That’s very optimistic, a bright outlook in life. I like that. I respect that. Thank you so much, Rémi, for being with us today and sharing all the wonderful insights.

Rémi Parmentier: Thank you for having me.

Vitaly: Of course. Will you be kind enough to share the slides of your presentation as well?

Rémi Parmentier: Yes, absolutely.

Vitaly: If you have any other resources that come to your mind, please send them over to us and we’ll publish them, too.

Rémi Parmentier: Sure.

Vitaly: All right? That’s been very exciting. It wasn’t actually as dirty as I thought it would be. Just humble in a way, even. I didn’t see anything that would screech and make me feel uncomfortable at night when I want to sleep. Thank you so much for that, Rémi.

Rémi Parmentier: Thank you.

Vitaly: On that note, Scott, any other updates we should keep in mind or anything we need to mention?

Scott: I was going to ask you, Vitaly. Tomorrow, we have another Smashing TV.

Vitaly: Yes. Friends, we’re trying something else and something new every time. Apparently, well, finally, today we got … I hope we received, because I didn’t get the confirmation yet, but we’re supposed to receive the first copies of the Smashing Print or our new printed magazine dedicated to topics that are often not covered well enough on the web, or maybe that just got lost in the myriad of workflows.

Vitaly: The first issue is dedicated to ethics and privacy. As a dedication to that, we’re going to have a live session, a live stream on Smashing TV tomorrow with five panelists, all contributors to this first issue of Smashing Print. It’s going to be broadcasted on YouTube. If you go on Smashing.TV, you’ll find the links, but we also will be publishing an article tomorrow featuring the links and everything.

Vitaly: The printed magazine, that by the way, Smashers, the ones with $9 plan are getting it for free, and the members with $5 plan are getting the ebook and the heavy discount on the ebook as well. Rémi is getting a printed magazine as well just because he’s so awesome.

Rémi Parmentier: Thank you.

Scott: Thanks, Rémi.

Vitaly: Beyond that, we also have a few more things coming up, I think.

Scott: On the 13th, Mr. Paul Boag, who has been a very prominent mentor in the Smashing community, many Smashing Conferences, many webinars, August 13th, Paul Boag is doing the customer journey mapping where UX and marketing meet.

Vitaly: Then we have Cassie Evans on August 20th exploring the interactive web animation with SVG. This is going to be fun as well. If you actually ever wanted to do a bit more or try to figure out a better workflow for SVG animation, that’s definitely a session not to miss, so looking forward to that.

Vitaly: All right, I think we’re good here. Any more announcements, major announcements, Scott, that we need to share with the world around us?

Scott: You’re making me feel like I’m forgetting something, but … SmashingConf Freiburg?

Vitaly: Yes, we do have a SmashingConf Freiburg, where Rémi is going to speak as well, but we also have the videos of Toronto conference which will be released today, or maybe tomorrow. Maybe they already released. See how well-prepared I am. Watch out for that and you’ll get them, you’ll find them also in your dashboard, so keep that in mind. All right. I think we’re good!

Scott: Okay. Thank you everybody for attending. Thank you-

Vitaly: Thanks, everyone, for attending.

Rémi Parmentier: Bye! Thank you and bye.

Vitaly: Thank you and see you next time. Thank you, Rémi. Bye-bye.

Rémi Parmentier: Thanks. Bye.

Vitaly: See you next time.

SmashingConf Freiburg Presentation “Think Like An Email Geek”

At the end of the Webinar, Vitaly mentions that Remi will be speaking at Freiburg. You don’t have to wait for that as we also have that video to share with you, along with the slides and resources.

We hope you enjoyed this look into HTML email. If you would like to enjoy more of this kind of content, plus the chance to interact with the presenters and other members while helping to support the creation of independent content for web designers and developers join us here.

Smashing Editorial
(ra, vf, il)

Source: Smashing Magazine, Become An HTML Email Geek With These Videos From Rémi Parmentier

Better Design With Deep Thinking

dreamt up by webguru in Uncategorized | Comments Off on Better Design With Deep Thinking

Better Design With Deep Thinking

Better Design With Deep Thinking

Eric Olive



Interruptions, administrative tasks, and too many meetings are among the common complaints voiced by today’s professionals. When was the last time someone complained about a canceled meeting? In other words, everyone understands what hinders productivity, right?

Not so fast, says computer scientist Cal Newport. While we all realize that interruptions and fragmented time are troublesome, we fail to recognize:

  • The frequency of interruptions: We convince ourselves that we are focusing on one task at a time, such as a complex interaction design problem. Yet, every ten minutes or so, we check email or answer a text. Yes, we’re performing one task at a time, but the duration of that task is brief.
  • The cost of these interruptions: As Newport explains on a recent episode of Hidden Brain: “Even those very brief checks that switch your context even briefly can have this massive negative impact on your cognitive performance. It’s the switch itself that hurts, not how long you actually switch.” (Emphasis mine)

This task switching was the focus of a study by business professor Sophie Leroy. She gave participants a cognitively demanding activity, such as solving a puzzle, and then briefly interrupted them before they completed it. When they returned to the original task, their performance dropped. As Leroy explains, these “results indicate it is difficult for people to transition their attention away from an unfinished task and their subsequent task performance suffers.”

Leroy calls this carryover from one activity to another “attention residue,” meaning that people are still thinking about the previous task even as they turn to the new one.

The most effective way to avoid attention residue is to structure your work in a way that reduces interruptions. Such structure requires understanding the difference between deep and shallow work.

Deep Work, Shallow Work, And Why They Matter

“Deep work is the ability to focus without distraction on a cognitively demanding task,” writes Newport in his book Deep Work. This work allows us to absorb, understand, and act on complicated information. Examples including coding, complex project plans, user research, and sophisticated design work.

Shallow work refers to tasks that do not require extensive thought and focus such as filling out expense reports and answering emails, texts, and Slack messages.

Shallow tasks are necessary. The question is how much time to devote to shallow and deep work and how to structure work in a way that facilitates reflection and concentration.

Left image: Design is deep work. Right image: Filling out a checklist is shallow work.

Left: Design is deep work. Right: Filling out a checklist is shallow work. (Image credits: FirmBee | raw pixel) (Large preview)

The Solution: Five Practical Tips For Pursuing Deep Work

Tip 1: Jump Into Design Work

Avoid the temptation to text or check email first thing. Put your phone on do not disturb. Get out your sketch pad or open your design tool and challenge yourself to solve one gnarly design problem by 10:00 am.

While this tip sounds like common sense, it’s not quite so straightforward because we are conditioned to respond to signals around us: “External triggers are cues from our environment that tell us what to do next. These are the dings and pings that prompt us to check our email, answer a text, or look at a news alert,” explains habit expert Nir Eyal in a post about distraction.

Eyal continues: “Competition for our attention can come from a person as well, such as an interruption from a coworker when we are in the middle of doing focused work.”

Computer scientist Cal Newport expands on this point by explaining the biology behind the itch to respond. When we don’t reply promptly to a text or email, we feel like we are ignoring someone from our tribe. Emotionally, it’s the modern-day equivalent of ignoring someone who is tapping on our shoulder as we sit around the fire. In short, it’s difficult to ignore messages and requests from co-workers.

Difficult but not impossible. Extend jumping into design work by blocking out untouchable time on your calendar. What about emergencies? “The short answer is that there really never are any,” writes podcaster and New York Times bestselling author, Neil Pasricha in Why You Need an Untouchable Day Every Week. These untouchable days involve deep, creative work.

While most professionals cannot set aside an entire day each week, they can mark two-hour blocks on their calendar a few times each week. Colleagues simply see “busy” when viewing your calendar. While not foolproof, this quiet signal shows that you know how to manage your time in order to engage in the deep work that your job requires.

Tip 2: Kickstart Your Brain With Useful Questions

By definition, deep work takes time and considerable brain resources. Sometimes we need a cognitive boost before tackling the problem head-on. When this is the case, ease into deep work by composing a list of questions to stimulate reflection. For example:

  • What is the organization trying to accomplish?
  • How does this site, product, or app align with that goal?
  • If revising an existing design: What would I do differently if I could recreate the design from scratch?
  • What would I do now if there were no legacy system constraints?

Note that these questions involve design but also encourage reflection beyond the immediate design challenge. The latter is important because the longer you work on a product or project, the easier it is to develop design blinders.

Kickstart your brain (Image credit: geralt) (Large preview)

Easing into deep work or jumping in with both feet are often useful as long as it’s possible to avoid those nettlesome distractions. Even so, everyone gets stuck and needs time to regroup and let the mind wander.

Tip 3: Schedule Unstructured Thinking Time

Just as designers and other professionals need time to think through complex problems, they also need time to let the mind wander. The reason is the science behind “shower moments,” when ideas seem to arrive out of the blue.

In fact, the brain needs time for incubation, the psychological term for the unconscious recombination of thought processes after they are stimulated by conscious mental effort such as working on a specific design problem. In other words, when you set aside a strenuous mental task and do something less demanding, the brain is able to process and organize your thoughts to form new ideas.

Effective leaders value unstructured thinking time as outlined in How to Regain the Art of Lost Reflection. Jeff Weiner, CEO at LinkedIn, blocks at least 90 minutes for reflection and describes these buffers as “the single most important productivity tool” he uses. Susan Hakkarainen, Chairman and co-CEO of Lutron Electronics, uses 40-minute walks to reflect explaining that “Thinking is the one thing you can’t outsource as a leader. Holding this time sacred in my schedule despite the deluge of calls, meetings, and emails is essential.”

In short, designers should take their cues from these business leaders. Give your brain a break.

Tip 4: Vote It Off The Island

This tip comes from the Harvard Business Review article Stop Doing Low-Value Work by Priscilla Claman. She cites the example of a controller who was producing monthly reports that nobody read. He sent a list to his colleagues asking them to identify the three or four most important reports. He simply stopped writing the reports that no one was reading.

Another approach is to request permission to not do something such as asking customers if they really want their receipts. The point, writes Claman, is to stop doing something that is not important but to ask first to avoid getting in trouble. It’s vital that we stop ourselves from doing unimportant work.

Designers can identify possibly unimportant work by asking if:

  • Every wireframe must include detailed annotations;
  • Every design deliverable must include a detailed design document;
  • It’s really necessary to produce many variations of a design when studies about choice and decision making show that too many options make it harder to reach a decision.

No one wants to feel as if their work is sitting on a virtual shelf. By asking clients and stakeholders what matters to them, you’ll cater to their needs and save time by discarding unnecessary tasks.

The next step is to assess the remaining important work to determine how much time you can, and should, devote to deep thinking.

Tip 5: Distinguish Deep And Shallow Work

Follow the steps below to make this assessment concrete, something you can point to and share with your boss.

  1. Identify the activities that you consider deep work such as planning a usability test, drawing wireframes, or mocking up a prototype.
  2. Identify shallow work activities like answering emails, attending administrative meetings or meetings tangentially related to your core responsibilities.
  3. Estimate the amount of time you spend on deep and shallow work each week.
  4. Meet with your boss for thirty minutes and ask her what she thinks the ratio of deep to shallow work should be. Ask for a specific number. If you disagree, politely ask if you may experiment with a different ratio for one month.
  5. Then, stick to the agreed-upon number for one month. Document any changes to your productivity, anything that contributes to a better product or service. After one month, report these findings to your boss.

This approach offers two advantages:

  • It’s usually wise to solicit the boss’s support.
  • A single proposal about deep work will not change an entire organization. Involving management, however, can serve as a catalyst for broader change just as the Google Ventures Design Sprint influenced the design process at Google and beyond.

Why Deep Work Makes Everything Better

Deep work allows designers and developers to thrive by leveraging their skills to solve complex problems and create better products and designs. Better products are likely to boost the bottom line while thriving and highly satisfied employees are more likely to stay (reducing turnover) and put their best selves forward.

Perhaps the best news for employers is that deep work does not require adding staff. The solution, explains computer scientist Cal Newport, is to re-configure work and communication. In other words, it’s not more people; it’s the same people managing work differently.

For example, agencies often answer to clients and need to be available at a moment’s notice. Rather than require every employee to be tethered to a phone or laptop, Newport suggests assigning a different employee each day to a dedicated email or a special “bat phone.” This shows the client their importance to the agency while also allowing designers to concentrate on designing, building, and solving problems.

Conclusion

Deep work is the ability to focus on challenging tasks like design and coding. Frequent interruptions make deep work nearly impossible and impose a high financial cost. In this piece, we’ve described five tips for maximizing the time you devote to deep work.

  1. Jump into design work.
    Draw fresh wireframes or work on a new design problem before checking emails and Slack messages. Block two-hour chunks on your calendar to allow time for deep thinking.
  2. Kickstart your brain with useful questions.
    Take a few minutes to ask what you are trying to accomplish and how it aligns with the company’s keep performance indicators (KPIs). Alignment with KPIs is especially important for user experience designers who are frequently asked to justify their budget
  3. Schedule unstructured thinking time.
    Take a walk, stare out the window, or whatever allows your mind to wander. This “downtime” allows the brain to form new connections.
  4. Vote it off the island.
    Are you writing reports that no one reads? Are you scheduling meetings that your co-workers find less than useful? Ask your colleagues if it’s okay to stop. They might respond with a gleeful “yes!”
  5. Distinguish deep and shallow work.
    Then, meet with your boss to arrive at the right balance between these two types of work.

Further Reading on SmashingMag:

Smashing Editorial
(ah, il)

Source: Smashing Magazine, Better Design With Deep Thinking

Adapting Agile For Part-Time Teams

dreamt up by webguru in Uncategorized | Comments Off on Adapting Agile For Part-Time Teams

Adapting Agile For Part-Time Teams

Adapting Agile For Part-Time Teams

Philip Kiely



<p>The formal notion of the Agile software development method is about as old as I am (the Agile Manifesto was published in February 2001). I point this out not to <a href="https://xkcd.com/1686/">make you feel old</a>, but instead to demonstrate that Agile has had a long time to infiltrate software development. While the methodology advocates for &ldquo;co-located, dedicated teams,&rdquo; in its ubiquity Agile is frequently applied to teams partially or fully composed of part-time workers. While there are lessons to be taken from the practice, Agile must be adapted to support, rather than hinder, part-time teams.</p>

<p>In this article, we’ll consider applying Agile to a team of 5-10 people each working 20 hours per week on a project. We’ll further consider the frequent intersection of remote work with part-time teams and discuss situations where contributors work as few as 5 hours per week on a project. We’ll also hear from professors Armando Fox at the University of California, Berkeley and Barbara Johnson at Grinnell College with their thoughts on part-time Agile teams.</p>

<h3 id="why-does-part-time-work-happen">Why Does Part-Time Work Happen?</h3>

<p>While the &ldquo;5 developers for 20 hours&rdquo; example may seem contrived, many situations lead to the scenario. You may have:</p>

<ul>
<li>Developers assigned to multiple clients, projects, or teams within a single company,</li>
<li>A team with contractors or co-op interns,</li>
<li>Volunteers working on an open-source or community project, or</li>
<li>An after-hours team working on a startup or product.</li>
</ul>

<p>While we will examine the many challenges involved in managing teams under these constraints, usually the alternative to working part-time with someone isn’t their full-time efforts, the alternative is not being able to work with them at all. While part-time workers and teams often require extensive compromises, with clear and effective management they can still be a huge net positive to a team and business.</p>

<h3 id="tenets-of-agile">Tenets Of Agile</h3>

<p>Given its prevalence in the software development industry, everyone understands Agile slightly differently. To get through adapting the framework together, we need a shared vocabulary to define &ldquo;regular&rdquo; Agile, you know, the kind that advocates for &ldquo;dedicated, co-located teams.&rdquo; Agile implements practices, rituals, and roles to promote effective work.</p>

<p>Agile, as implemented, involves certain practices:</p>

<ul>
<li>&ldquo;Sprints&rdquo; are discrete units of time, often 2 weeks, that determine the cycle of work for Agile teams.</li>
<li>&ldquo;Stories&rdquo; or &ldquo;user stories&rdquo; are well-scoped units of work that a single team member can complete in some fraction of the sprint.</li>
<li>Often, teams organize their stories on &ldquo;kanban boards&rdquo; or similar methods of tracking story state: to do, in progress, in review, and done in a given sprint.</li>
</ul>

<p>Agile revolves around four rituals:</p>

<ol>
<li><strong>Sprint Planning</strong><br />
This is a meeting that opens each sprint with writing, estimating, prioritizing, and assigning stories that the team intends to complete for the sprint.</li>
<li><strong>Daily Stand-Up</strong><br />
A chance for teams to meet every day to discuss the previous day’s progress, discuss the day’s work, and raise any roadblocks. Ideally, the meeting is very short (5-15 minutes) and is near the start of the workday to minimize the interruption of dedicated work time.</li>
<li><strong>Sprint Review</strong><br />
This is part of a meeting which ends each sprint with a review of work accomplished, new backlog items, missed estimates, and other quantifiers of team progress.</li>
<li><strong>Sprint Retrospective</strong><br />
A discrete meeting or block of time for discussing what went well and what to improve about how the team operates in qualitative terms.</li>
</ol>

<p>Agile teams usually have distinct, cross-functional roles. Common roles include:</p>

<ul>
<li>The &ldquo;project manager/team lead&rdquo; manages the team, assigns work, reports to management, assists team members, and performs other managerial duties.</li>
<li>The &ldquo;scrum master&rdquo; is responsible for leading Agile rituals.</li>
<li>A &ldquo;product owner/product manager&rdquo; represents the client or end-user to the team. They have an active hand in writing stories, reviewing product functionality, and communicating progress to clients and expectations to the team.</li>
<li>An &ldquo;individual contributor&rdquo; is any member of the team whose main responsibility is building the product. Developers, designers, QA specialists and writers are all examples of individual contributors.</li>
</ul>

<p>While these definitions are important for our shared understanding, the major theme of this article is that achieving your team’s goals is more important than implementing &ldquo;proper&rdquo; Agile. If this doesn’t exactly match your setup, common elements should help apply upcoming recommendations to your experience.</p>

<figure class="

">

<a href="https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e0200d18-740a-45d3-ab60-096581b5d70b/board-irfan-simsar-unsplash.jpg">

<img
srcset="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e0200d18-740a-45d3-ab60-096581b5d70b/board-irfan-simsar-unsplash.jpg 400w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_800/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e0200d18-740a-45d3-ab60-096581b5d70b/board-irfan-simsar-unsplash.jpg 800w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1200/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e0200d18-740a-45d3-ab60-096581b5d70b/board-irfan-simsar-unsplash.jpg 1200w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1600/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e0200d18-740a-45d3-ab60-096581b5d70b/board-irfan-simsar-unsplash.jpg 1600w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_2000/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e0200d18-740a-45d3-ab60-096581b5d70b/board-irfan-simsar-unsplash.jpg 2000w"
src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e0200d18-740a-45d3-ab60-096581b5d70b/board-irfan-simsar-unsplash.jpg"
sizes="70vw"
alt="'Scrum Board' by İrfan Simsar on Unsplash"
/>

</a>

<figcaption class="op-vertical-bottom">
(Image credit: ‘İrfan Simsar’ on <a href='https://unsplash.com/'>Unsplash</a>) (<a href='https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e0200d18-740a-45d3-ab60-096581b5d70b/board-irfan-simsar-unsplash.jpg'>Large preview</a>)
</figcaption>

</figure>

<h3 id="constraints-of-part-time-work">Constraints Of Part-Time Work</h3>

<p>Immediately, we see how the constraints of part-time work cut into standard Agile. First off, in a given two-week sprint, each employee may spend 2 hours in sprint planning, 10 times 15 minutes in stand-up, 1 hour in sprint review, and 30 minutes in sprint retrospective, for a total of 6 hours in Agile meetings. For a full-time employee, that’s only 7.5% of their 80-hour fortnight, for a half-time employee it doubles to 15%. Add in other meetings and account for context switching and suddenly your individual contributors have very little time left each week to individually contribute.</p>

<p>Thus, part-time work exacerbates the need for good capacity estimation and up-front planning while reducing the time available for it. Fortunately, Agile’s notion of story points applies well. Story points estimate effort rather than time and thus stay constantly effective between full-time and part-time workers, though of course part-time workers will take longer to achieve the same amount of story points, which you can account for by measuring the team’s velocity.</p>

<p>Even if your development team is part-time, your clients may not be. Customer support, emergency bug fixes, outage repairs, and even regular communication can be more difficult with part-time work adding additional overhead.</p>

<figure class="

">

<a href="https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/107f0a17-6c3c-4678-ae1c-d67d231d80c4/watch-brad-neathery-unsplash.jpg">

<img
srcset="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/107f0a17-6c3c-4678-ae1c-d67d231d80c4/watch-brad-neathery-unsplash.jpg 400w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_800/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/107f0a17-6c3c-4678-ae1c-d67d231d80c4/watch-brad-neathery-unsplash.jpg 800w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1200/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/107f0a17-6c3c-4678-ae1c-d67d231d80c4/watch-brad-neathery-unsplash.jpg 1200w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1600/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/107f0a17-6c3c-4678-ae1c-d67d231d80c4/watch-brad-neathery-unsplash.jpg 1600w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_2000/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/107f0a17-6c3c-4678-ae1c-d67d231d80c4/watch-brad-neathery-unsplash.jpg 2000w"
src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/107f0a17-6c3c-4678-ae1c-d67d231d80c4/watch-brad-neathery-unsplash.jpg"
sizes="100vw"
alt="'Man in a watch typing' by Brad Neathery on Unsplash"
/>

</a>

<figcaption class="op-vertical-bottom">
(Image credit: ‘Brad Neathery’ on <a href='https://unsplash.com/'>Unsplash</a>) (<a href='https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/107f0a17-6c3c-4678-ae1c-d67d231d80c4/watch-brad-neathery-unsplash.jpg'>Large preview</a>)
</figcaption>

</figure>

<h3 id="frequently-intersecting-constraints">Frequently Intersecting Constraints</h3>

<p>While not all part-time teams will experience these additional challenges, in my experience part-time work often overlaps with remote work, different time zones and availabilities, and classification of workers as temporary, contractors, or interns instead of employees. This is not an article about any of these things, but they bear mentioning.</p>

<p>Part-time work adds significant overhead to the already difficult task of finding a regular time when everyone is available to meet. If some team members work in the mornings and others in the evenings or are located across the world from each other, scheduling quickly becomes impossible. GitLab has published <a href="https://about.gitlab.com/handbook/communication/">extensive documentation on remote communication</a> that might be helpful.</p>

<p>Working with contractors, student interns, temporary hires, or other non-permanent teams or team members brings its own advantages and challenges. That said, however, someone got to the table, the Agile framework treats them as an equal member of the team and stakeholder in the project.</p>

<figure class="

">

<a href="https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7abbdc79-3c84-487b-a3b9-c9b9d099b3d6/meeting-you-x-ventures-unsplash.jpg">

<img
srcset="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7abbdc79-3c84-487b-a3b9-c9b9d099b3d6/meeting-you-x-ventures-unsplash.jpg 400w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_800/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7abbdc79-3c84-487b-a3b9-c9b9d099b3d6/meeting-you-x-ventures-unsplash.jpg 800w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1200/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7abbdc79-3c84-487b-a3b9-c9b9d099b3d6/meeting-you-x-ventures-unsplash.jpg 1200w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1600/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7abbdc79-3c84-487b-a3b9-c9b9d099b3d6/meeting-you-x-ventures-unsplash.jpg 1600w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_2000/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7abbdc79-3c84-487b-a3b9-c9b9d099b3d6/meeting-you-x-ventures-unsplash.jpg 2000w"
src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7abbdc79-3c84-487b-a3b9-c9b9d099b3d6/meeting-you-x-ventures-unsplash.jpg"
sizes="100vw"
alt="'Untitled' (Meeting) by You X Ventures on Unsplash."
/>

</a>

<figcaption class="op-vertical-bottom">
(Image credit: ‘You X Ventures’ on <a href='https://unsplash.com/'>Unsplash</a>) (<a href='https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7abbdc79-3c84-487b-a3b9-c9b9d099b3d6/meeting-you-x-ventures-unsplash.jpg'>Large preview</a>)
</figcaption>

</figure>

<h3 id="redefining-rituals-for-part-time-teams">Redefining Rituals For Part-Time Teams</h3>

<p>Now that we’ve framed the challenges that part-time work creates, let’s focus on solutions. While I’ve seen a number of successful modifications to Agile rituals for part-time teams, I reached out to Professor Armando Fox, co-author of <em>Engineering Software as a Service: An Agile Approach Using Cloud Computing</em> with David Patterson. In an email interview, he emphasized two key goals of agile rituals to retain:</p>

<blockquote>“The reason Agile is a good fit [for part-time teams] is the idea of using user stories as the unit of work. The key to doing this successfully is up-front planning and continuous check-ins.”<br /><br />&mdash; Armando Fox</blockquote>

<p>Sprint planning condenses up-front planning to a single high-value meeting. For part-time teams, the product owner, scrum master, and team lead (who may be only one or two people, more on that later) should do as much pre-meeting work as possible to define well-scoped tickets for the individual contributors to estimate and take. Fox said &ldquo;if stories are tightly-circumscribed, branches are short-lived, stories require modest amounts of code that can be delivered with good test coverage, and code quality is maintained through continuous code review (pull requests) as well as the use of code quality measurement tools, the team can successfully divide-and-conquer even if they’re not always working at the same time.&rdquo; That’s definitely a lot of &ldquo;if&rdquo; statements, working in this manner will take dedicated effort from the entire team, but should result in a quality product.</p>

<p>The other half of the equation is continuous check-ins. Agile’s daily stand-ups work great for co-located full-time teams, if everyone’s in the office by 9 or 10 AM the meeting happens more or less naturally. It’s tempting to replace this with an asynchronous check, like status-report emails, but Fox advocates that teams stick to the ritual. &ldquo;The team needs to check-in frequently &mdash; we recommend daily 5-minute stand-ups &mdash; so that any red flags can be spotted early. Even part-time teams can find 5 minutes a day that the whole team is available. Email isn’t good for this; an interactive meeting, where people can also mention blocking items and others can immediately speak up with suggestions, is the best format,&rdquo; he wrote.</p>

<p>For a part-time team, it may also be tempting to do away with regular meetings entirely and rely solely on the start and end of sprint check-ins. Fox warns that &ldquo;every team [that he has] coached at Berkeley has said that they quickly realized that once-a-week team meetings were nowhere near enough to keep everyone on the same page.&rdquo;</p>

<p>Sprint reviews and retrospectives are important components of Agile. If teams do not regularly evaluate their working practices and performance, bad interactions will continue unchecked and discontent will grow. However, the velocity measurement and end-of-sprint re-assignment tasks can be handled by the scrum master outside of meeting times, and the team leader can use one-on-one meetings and their perception of team mood in stand-ups and sprint planning to reduce the need for sprint review and retrospective.</p>

<p>If you absolutely need to cut back on the number and duration of Agile meetings, cut review and retrospective first. That said, it is important to celebrate the team’s progress each sprint and give people space to air grievances. A decent compromise can be to extend the last stand-up of each sprint to accomplish this communication within the team.</p>

<h3 id="defining-roles-on-a-part-time-agile-team">Defining Roles On A Part-Time Agile Team</h3>

<p>This section depends entirely on the composition of the team. However, there are a few useful heuristics for assigning roles. Responsibilities assigned should minimize communication overhead (which scales worse-than-linearly with team size), fit individual contributors&rsquo; abilities, and account for team members&rsquo; schedules and availability.</p>

<p>For this section, I turned to Professor Barbara Johnson, who teaches a team software development course that I am currently enrolled in at Grinnell College. She wrote &ldquo;I have sometimes seen teams come to rely upon what might be called a &lsquo;chief organizer&rsquo; who combines the roles of not only a scrum master (who organizes the team) but also the product owner (who coordinates and documents the client’s needs and feedback). This lessens the cognitive overhead of the rest of the team, who then can focus more on moving the project’s code and testing suite forward with each iteration.&rdquo; This matches my experience with part-time teams.</p>

<p>If possible, condense the managerial positions (team lead, product manager, scrum master) into a single role and assign that role to the &ldquo;fullest-time&rdquo; team member. If you have a team of 10 where only 1 person is full-time or otherwise has greater availability, that person should have as many organizational and communication responsibilities as feasible. Part-time teams require just as much communication as full-time teams and an even greater logistical effort, so concentrating that work in one person massively reduces communication overhead.</p>

<p>However, frequently this isn’t possible, either because no one has extra availability or because those people are better suited to individual contributor roles. In that case, I still advocate for condensing managerial responsibilities as much as possible but breaking the product owner back out into its own role. In this case, it’s important to be realistic when estimating how much further work these people will be able to do on user stories considering their other work for the team and client.</p>

<p>Most of the members of the part-time team will be individual contributors. There are two competing philosophies for individual contributors: generalist teams and teams of specialists. Imagine that your team is developing a web application. A generalist team would be composed of entirely full-stack developers. These developers would never be blocked on others&rsquo; work as, in theory, they are equally comfortable on anything from design to deployment. Alternately, if a designer, front-end engineer, back-end engineer, and site reliability engineer comprise a team, they will be fast and effective at their own work because they only spend their time on the thing that they’re best at.</p>

<p>As a team organizer, you may find yourself with a team of generalists, a team of specialists, or a mix. Putting together a part-time team of solid performers is hard enough without restricting yourself to one type of individual contributor, so, fortunately, both types bring something useful to the table. If you can recognize which of your individual contributors are generalists and which are specialists, you can assign tasks more effectively to maximize the impact of their limited work time.</p>

<p>Finally, on teams where people are working ten or fewer hours per week, it is tempting to throw out roles entirely and just say &ldquo;do what you can.&rdquo; Per our theme, these super-part-time teams need even more structured communication but have even less time for it. If everyone has such limited, scattered availability that you cannot justify assigning roles at all, it’s probably worth re-examining the structure, goals, and feasibility of the project.</p>

<figure class="

">

<a href="https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/6f510c00-a18e-41c2-87fc-899948283ffe/man-saulo-mohana-unsplash.jpg">

<img
srcset="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/6f510c00-a18e-41c2-87fc-899948283ffe/man-saulo-mohana-unsplash.jpg 400w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_800/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/6f510c00-a18e-41c2-87fc-899948283ffe/man-saulo-mohana-unsplash.jpg 800w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1200/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/6f510c00-a18e-41c2-87fc-899948283ffe/man-saulo-mohana-unsplash.jpg 1200w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1600/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/6f510c00-a18e-41c2-87fc-899948283ffe/man-saulo-mohana-unsplash.jpg 1600w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_2000/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/6f510c00-a18e-41c2-87fc-899948283ffe/man-saulo-mohana-unsplash.jpg 2000w"
src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/6f510c00-a18e-41c2-87fc-899948283ffe/man-saulo-mohana-unsplash.jpg"
sizes="100vw"
alt="'At the bustling Times Square' by Saulo Mohana on Unsplash"
/>

</a>

<figcaption class="op-vertical-bottom">
(Image credit: ‘Saulo Mohana’ on <a href='https://unsplash.com/'>Unsplash</a>) (<a href='https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/6f510c00-a18e-41c2-87fc-899948283ffe/man-saulo-mohana-unsplash.jpg'>Large preview</a>)
</figcaption>

</figure>

<h3 id="client-communication">Client Communication</h3>

<p>Software development is slow, complex work, and part-time teams only magnify that truth. Agile includes the client in the process by writing user stories, rapid prototyping, a quick release schedule, and consistent communication.</p>

<p>As a part-time team, communicate reasonable expectations to the client. For a half-time team, remember that development time is cut by more than half, build an extra buffer into doubled estimates. As development time is limited, it is critical to solicit complete, accurate specifications when meeting with the client or end-users to avoid wasting your efforts.</p>

<p>Don’t let part-time work make you fall behind on client communication. Even if there is very little progress to report, soliciting regular feedback and posting updates at a reasonable cadence should increase the client’s patience with the slow development pace.</p>

<h3 id="conclusion-goals-methods">Conclusion: Goals &gt; Methods</h3>

<p>You can get a lot done in a part-time schedule. Outside of coding, 10-20 hours per week is enough time to train for a first marathon. With a strong team and good working practices, it is enough time to bring a great product to the market. Using Agile to encourage up-front planning and continuous check-ins with user stories, regular stand-ups, and well-defined roles will allow even part-time teams to overcome communication barriers and work effectively towards a shared goal.</p>

<h4><span class="rh">Further Reading</span> on SmashingMag:</h4>

<ul>
<li><a title="Read 'Bringing A Healthy Code Review Mindset To Your Team'" href="https://www.smashingmagazine.com/2019/06/bringing-healthy-code-review-mindset/" rel="bookmark">Bringing A Healthy Code Review Mindset To Your Team</a></li>
<li><a title="Read 'Creating Authentic Human Connections Within A Remote Team'" href="https://www.smashingmagazine.com/2019/08/creating-authentic-human-connections-remote-team/" rel="bookmark">Creating Authentic Human Connections Within A Remote Team</a></li>
<li><a title="Read 'Building Diverse Design Teams To Drive Innovation'" href="https://www.smashingmagazine.com/2018/05/building-diverse-design-teams-innovation/" rel="bookmark">Building Diverse Design Teams To Drive Innovation</a></li>
<li><a title="Read 'The Case For Brand Systems: Aligning Teams Around A Common Story'" href="https://www.smashingmagazine.com/2019/06/case-brand-systems-align-teams/" rel="bookmark">The Case For Brand Systems: Aligning Teams Around A Common Story</a></li>
</ul>

Smashing Editorial
(dm, yk, il)

Source: Smashing Magazine, Adapting Agile For Part-Time Teams