Smashing magazine

S'abonner à flux Smashing magazine
Recent content in Articles on Smashing Magazine — For Web Designers And Developers
Mis à jour : il y a 1 heure 15 min

How To Make Life Easier When Using Git

ven, 03/27/2020 - 12:30
How To Make Life Easier When Using Git How To Make Life Easier When Using Git Shane Hudson 2020-03-27T11:30:00+00:00 2020-03-27T13:53:06+00:00

Git was released almost 15 years ago. In that time it has gone from underdog to unbeaten champion, git init is often the first command run on a new project. It is undoubtedly an important tool that many of us use on a daily basis, and yet it is often seen as magic: brilliant, but scary.

There’s been a lot written about getting started with git, understanding how git works under the hood or techniques for better branching strategies. In this article, we will specifically target the stuff that just makes your life better in a small way.

Finding Your Old Socks

The whole point of git is to be able to save your work, to switch context and do something else. It could be to backup the code for the future, or to be able to make progress on a few different features asynchronously. It would be awful to have to throw out v2 just because there was a bug in v1, it would be equally a shame to have files named like v1_final_bug_fixed which notoriously become an impossible mess.

We know life is easier, to some extent, with our updates neatly compartmentalised into git branches that can be shared with other team members. However, I’m sure you can agree, there are often times when you’ve context switched and when you go back it’s impossible to find the right branch. Was it ever committed? Maybe it was stashed? Maybe it wasn’t committed and now the work is in the wrong branch and everything is going awful and I am awful at my job! We’ve all been there.

Sort Branches By Date

My first attempt at figuring out how to find lost work, in a short blog post titled “How to find the branch you lost in git” was to sort the branches by date. This outputs every single branch you’ve got locally beginning with the one most recently committed to. It’s not fancy or surprising but it has helped me many times.

# To sort branches by commit date git branch --sort=-committerdate Previous Branch

What can you do if you didn’t commit, switched branch then wanted to get back to it? You could probably work out frorm the branch list anyway, if you’ve some idea of the branch name. But what if it wasn’t a branch, if it was a “detached HEAD”, a specific commit.

It turns out there is a way to do this with ease:

# Checkout previous branch git checkout -

The - acts as a shorthand for @{-1} which is a syntax you can use for going back any given amount of checkouts. So if, for example, you had checked out branch feature/thing-a then feature/thing-b then bugfix/thing-c, you can use @{-2} to get back to feature/thing-a.

# Checkout branch N number of checkouts ago git checkout @{-N} Show Information About All Branches

If you are looking for a way to see what the last commit in each branch was, you can use option flags v to show a list of all branches with the last commit ID and message from each. If you do it twice (vv) then it will also show the upstream remote branch that it is linked to.

# List branches along with commit ID, commit message and remote git branch -vv That One File

We’ve all done it: Somehow, a single file was left in the wrong branch. Do you need to redo all of your work, or copy and paste between the two branches? Nope, thankfully there’s a way to do it.

It’s a bit odd, especially given git checkout - goes back a previous branch; if you use -- after a branch name on checkout then it will let you specify the specific file you’re looking for. It’s not something you would guess, but really handy once you know it.

git checkout feature/my-other-branch -- thefile.txt Make Status Easier To Read

In a tweet, Tomasz Łakomy mentioned about reducing the output of git status using -sb flags and said, “I’ve been using git for YEARS and nobody told me about this.” This isn’t strictly about finding lost files, but there’s cases where simplifying the output could make it easier to see what’s been changed.

Most git commands have flags like this so it’s always worth looking into how you can use them to customise your workflow!

# Usually we would use git status to check what files have changed git status # Outputs: On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: README.md Untracked files: (use "git add <file>..." to include in what will be committed) another-file my-new-file # Using the flags -sb we can shorten the output git status -sb # Outputs: ## master M README.md ?? another-file ?? my-new-file See Everything That Has Happened

There are times when something goes completely wrong — such as accidentally discarding staged changes before commiting them. When git log isn’t enough to get back to what you were last doing and none of the above tips are helpful, then there’s git reflog.

Everything you do in git that changes where HEAD@{} points to (such as push/pull/branch/checkout/commit) will update the reference log so it essentially acts as a history of everything you’ve done no matter which branch you’re on. This contrasts with git log which is everything that has changed over time for the particular branch.

Overview all in one place

With the commit ID, you are able to do git show to see the change and if it’s definitely the one you want you can use git checkout or even select a specific file as shown above.

# See the reference log of your activity git reflog --all # Look at the HEAD at given point from reflog git show HEAD@{2} # Checkout the HEAD, to get back to that point git checkout HEAD@{2} Staged Files That Were Never Commited

In the extreme case that git reflog is unable to help you get your files back (e.g. if you ran a hard reset with staged files), there’s one more trick up your sleeve. Every change is stored in .git/objects which on an active project would be full of files and impossible to decipher. There is, however, a git command called git fsck which is used to verify integrity (check for corrupt files) within a repository. We are able to use this command with the --lost-found flag to find all files that are not related to a commit; these files are called a “dangling blob”.

It will also find “dangling trees” and “dangling commits” — you can use --dangling if you want but --lost-found has the advantage that it extracts all of the appropriate files into a folder .git/lost-found. On an active project, it’s likely you will have a lot of these dangling files without even knowing about it; git has a garbage cleanup command that runs regularly to get rid of them.

So, by using --lost-found, you’re then able to list the files and see the time/date they were made which makes it a lot easier to see the files you’re looking for. Note that each individual file will still be an individual file (you cannot use checkout) and all files will have unrecognisable names (a hash) so you will need to copy the files you want.

# This will find any change that was staged but is not attached to the git tree git fsck --lost-found # See the dates of the files ls -lah .git/lost-found/other/ # Copy the relevant files to where you want them, for example: cp .git/lost-found/other/73f60804ac20d5e417783a324517eba600976d30 index.html Git As A Team

Using Git as a single user is one thing but when you’re on a team of people — usually with a mix of backgrounds and technologies — Git can become both a blessing and a curse. It can be powerful for sharing the same codebase, getting code reviews, and seeing progress of the whole team. But at the same time, everyone needs to have a shared understanding of how the team intends to use it. Whether it is branch naming conventions, how you structure a commit message or exactly which files are committed, it’s essential to have good communication and talk about how you will all use the tool.

It’s always important to consider how easy it is to on-board a new developer, what would happen if they began committing without knowing some of the agreed principles and conventions? It wouldn’t be the end of the world, but it would likely cause some confusion and take time to get things back to the agreed approach.

This section has some tips and tricks for getting the repository itself to know the conventions, to automate and declare as much as possible. In the ideal case, any new contributor would almost straight away be working the same way as the rest of the team.

Same Line Endings

By default, Windows uses DOS line endings \r\n (CRLF) while Mac and Linux both use UNIX line endings \n (LF) and really old versions of Mac used to use \r (CR). So as a team grows, it becomes more likely that mismatched line endings will become a problem. Usually, these are an inconvenience; they (probably) won’t break your code but will make commits and pull requests show all kinds of irrelevant changes. Quite often people will just ignore them — it’s quite a hassle to go through and change.

There is a solution to this: You can get everyone on the team to set their local configs to automatic line endings.

# This will let you configure line-endings on an individual basis git config core.eol lf git config core.autocrlf input

Of course, that would mean making sure the new contributor does that and it’s so easy to forget to tell them. So how would we do it for the whole team? Well the way Git works is it checks for a config file in the repository at .git/config, then it checks the user’s system-wide config at ~/.git/config then checks the global config at /etc/gitconfig. These are all useful at times but it turns out that none of those can be set through the repository itself. You can add repository-specific configurations but that will not carry over to other members of the team.

There is, however, a file that does get committed to the repository. It’s called .gitattributes. You won’t have one by default, so make a new file and save it as “*.gitattributes*”. This file is used for setting attributes per file; for example, you could make git diff use exif data for image files instead of trying to diff a binary file. In this case, we can use a wildcard to make the setting work for all files, essentially acting as a team-wide config file.

# Adding this to your .gitattributes file will make it so all files # are checked in using UNIX line endings while letting anyone on the team # edit files using their local operating system’s default line endings. * text=auto Auto-Collapse

It’s a well-known solution to add package-managed files (such as node_modules/) to the .gitignore file in order to keep compiled files locally and not add them to the repository. However, sometimes there are files that you do want to check in but don’t want to see each time in the pull request.

For this situation (at least on GitHub), you can add paths annotated with linguist-generated to your .gitattributes file and check that file in at the root of the repository. This will collapse the files in the pull request, so you can still see they were changed without the full contents of the change.

Anything to reduce stress and cognitive load of code reviewing is going to help improve the quality of the code reviews and reduce the time it takes.

For example, if you have a Unity project, you would want to check-in your asset files but not actually care about them so you can add it to the attributes file like so:

*.asset linguist-generated Use Git Blame More Often

This is a tip that Harry Roberts suggested in his post about Git, “Little Things I Like To Do With Git.” He says to alias git blame to git praise so it feels like a positive action. This seems like semantics — renaming something doesn’t change what it does at all. But whenever I’ve seen any team speak about using Git’s blame feature, everyone tenses up, and I certainly do, too. It’s a natural reaction to think it’s a negative thing… it really shouldn’t be!

It’s a powerful feature knowing who last touched the code you’re looking at. Not to blame them or even to praise them, but simply to ask the right person questions and to save time figuring out who to talk to.

Not only should you think of git blame as a good thing (call it ‘praise’ if you want to), but you should think of it as a communication tool that will help the entire team reduce confusion and prevent wasting time figuring out who knows about what. Some IDEs such as Visual Studio include this feature as annotations (without any negative connotation at all) of each function so you can instantly see who last modified it (and therefore who to talk to about it).

Git Blame For A Missing File

Recently, I saw a developer on the team trying to figure out who removed a file, when it was, and why it was removed. This seems like a useful time for git blame but that works based on lines in a file; it doesn’t help with stuff that isn’t there any more. There is, however, a solution. The old trusty git log. If you look at the log with no arguments, then you will see a long list of all the changes on the current branch. You can add a commit ID to see the log for that specific commit, but if you use -- (which we’ve used before to target a specific file), then you can get the log for a file — even one that no longer exists.

# By using -- for a specific file, # git log can find logs for files that were deleted in past commits git log -- missing_file.txt Commit Message Template

One thing that eventually gets mentioned within teams is that commit messages could be improved. Maybe they could reference a project management tool’s ID for the bug the commit fixes or maybe you want to encourage some text instead of an empty message.

This one needs to be run manually each time someone clones the repository (as git config files are not committed to the repository), but it is handy because you can have a shared file in the repository (named anything you want) that can act as the commit message template.

# This sets the commit template to the file given, # this needs to be run for each contributor to the repository. git config commit.template ./template-file Git As Automation

Git is powerful for automation. This is not immediately obvious but if you consider that it knows all of your past activity within the repository — plus that of other contributors — it has a lot of information that can be very useful.

Git Hooks

Quite often you will find that within a team you all want to be doing repeated tasks while you work. This could be ensuring tests and code linters pass before it lets you push using the pre-push hook, or to enforce a branch naming strategy using the pre-commit hook. Here on Smashing Magazine, Konstantinos Leimonis wrote an article titled “How To Ease Your Team’s Development Workflow With Git Hooks” which is all about improving workflow using Git Hooks.

Manual Automation

One of the key automation features that Git has is git bisect. This is something that many people have heard of but probably not used. The purpose of it is to work through the git tree (the history of commits) and work out where a bug was introduced. The simplest way to do this is manually; you run git bisect start, give it the good and bad commit IDs, then git bisect goodor git bisect bad for each commit.

This is more powerful than it seems at first because it doesn’t iterate linearly through the git log, which you could do manually and it would be a repetitive process. It, instead, uses a binary search so it’s an efficient way to go through the commits with the least amount of steps.

# Begin the bisect git bisect start # Tell git which commit does not have the bug git bisect good c5ba734 # Tell git which commit does have the bug git bisect bad 6c093f4 # Here, do your test for the bug. # This could be running a script, doing a journey on a website, unit test etc. # If the current commit has bug: git bisect bad # If the current commit does not have the bug git bisect good # This will repeat until it finds the first commit with the bug # To exit the bisect, either: # Go back to original branch: git bisect reset # Or stick with current HEAD git bisect reset HEAD # Or you can exit the bisect at a specific commit git bisect reset <commit ID> Taking It Further: Automating The Scientific Method

In his talk “Debugging With The Scientific Method,” Stuart Halloway explained how Git’s bisect functionality could be used to automate debugging. It focuses on Clojure but you don’t need to know that language to find the talk interesting and useful.

“Git bisect is actually partial automation of the scientific method. You write a little program that will test something and git will bounce back and fourth cutting the world in half each time until it finds the boundary at which your test changes.”

— Stuart Halloway

At first, git bisect can feel interesting and quite cool but in the end not very useful. Stuart’s talk goes a long way to showing how it’s actually counterproductive to debug in the way most of us usually do. If you, instead, focus on the empirical facts whether or not a test passes, you can run it against all commits since a working version and reduce the “feeling around in the dark” kind of debugging that we are used to.

So how do we automate git bisect? We pass it a script to run for each appropriate commit. Previously, I said we can manually run a script at each step of the bisect but if we pass it a command to run then it will automatically run the script at each step. This could be a script you write specifically to debug this one particular issue, or it could be a test (unit, functional, integration, any type of test could be used). So you could write a test to ensure the regression doesn’t happen again and use that test on previous commits.

# Begin the bisect git bisect start # Tell git which commit does not have the bug git bisect good c5ba734 # Tell git which commit does have the bug git bisect bad 6c093f4 # Tell git to run a specific script on each commit # For example you could run a specific script: git bisect run ./test-bug # Or use a test runner git bisect run jest On Every Commit In The Past

One of the strengths of git bisect is the efficient use of binary searches to iterate through history in a non-linear way. However, sometimes a linear crawl through history is exactly what you need. You could write a script that reads git log and loops through each commit executing code, but there’s a familiar command that can do this for you git rebase.

Kamran Ahmed wrote a tweet about using rebase to run a test suite on every commit to see which commit fails the test:

Find the commit that broke the tests

$ git rebase -i --exec "yarn test" d294ae9

This will run "yarn test" on all the commits between d294ae9 and HEAD and stop on the commit where the tests fail

— Kamran Ahmed (@kamranahmedse) February 2, 2020

We’ve already looked at using git bisect to do this efficiently so that’s generally more useful for this use-case, but what if we could have all of the other use-cases running a script for a given set of commits?

There’s room to be creative here. Maybe you want a way to generate a report of how your code has changed over time (or maybe show history of tests) and parsing the git log is not enough. This is perhaps the least directly useful trick in this article, but it’s interesting and raises the possibility of doing things that maybe we wouldn’t realise is possible.

# This will run for every commit between current and the given commit ID git rebase -i --exec ./my-script Further Reading

It’s impossible to more than scratch the surface of git in an article — it would end up being a book! In this article, I have chosen little tricks that could be new to even someone that’s been using git for years.

There’s so much more to Git from the foundations through to complex scripting, precise configurations and integrating into the terminal, so here are some resources to look at if this has piqued your interest:

  • Git Explorer
    This interactive website makes it easy to figure out how to achieve what you are trying to do.
  • Dang it Git!
    Everyone at some point gets lost in git and doesn’t know how to solve an issue. This gives solutions to a lot of the most common issues people have.
  • Pro Git
    It’s a book and yet it is available online for free too, so Pro Git is an invaluable resource for understanding git.
  • Git Docs
    It’s become a meme to tell developers to read the manual, but seriously both the git docs website and man git (for example man git-commit) go into detail about the internals of git and can be really useful.
  • Thoughtbot
    The git category on Thoughtbot has some very useful tips for using git.
  • Git Hooks
    The git hooks website has resources and ideas for all the available git hooks.
  • Demystifying Git Internals
    Trees, blobs… these terms can seem a bit odd. This article explains some of the fundamentals of how Git works internally which can be useful (as shown already) to use Git to it’s full potential.
  • Git From Beginner To Advanced
    Mike Riethmuller wrote this useful article that is ideal for beginners to Git.
  • Little Things I Like To Do With Git
    It was this article by Harry Roberts that made me realise how much more there is to Git after you’ve learned enough to move code around.
  • Atlassian’s Advanced Git Tutorials
    These tutorials go into detail about many of the topics mentioned in this article.
  • Github Git Cheatsheet
    It’s always handy to have a good cheatsheet for tools like Git.
  • Git Shortcuts
    This article goes into depth about the various flags git commands have and recommends lots of aliases to use.
Smashing Editorial (ra, il)
Catégories: Programmation

How To Increase Mobile Conversions With Category Page Design

jeu, 03/26/2020 - 13:30
How To Increase Mobile Conversions With Category Page Design How To Increase Mobile Conversions With Category Page Design Suzanne Scacca 2020-03-26T12:30:00+00:00 2020-03-26T13:35:43+00:00

For e-commerce designers, it’s easy to focus on designing the home page, individual product pages as well as the checkout experience because they’re obvious stepping stones along the mobile shoppers’ journey. Based on the following data, though, category pages also have a role to play — as the intermediary between search engines and e-commerce websites.

Jill Kocher Brown, the SEO Director of JumpFly, shared the following research at SMX West 2020:

SEO Jill Kocher Brown research - ecommerce category page vs. product page performance SEO Jill Brown shares research on ecommerce category page vs. product page performance. (Source: Slideshare) (Large preview)

After evaluating the top 30 ecommerce websites, Brown found that product category pages outperform product pages in terms of ranking keywords and traffic.

Considering how many top of funnel customers use mobile search to find what they’re looking for online, we need to put a greater focus on designing ecommerce category pages for mobile.

Today, I’m going to provide you with some tips for designing mobile e-commerce category pages that will get you more visits from search (and, consequently, conversions on-site).

How To Design Ecommerce Category Pages For Mobile

Let’s jump right in:

1. Only Include Essential Elements on the Page

This is more or less what we should aim for when designing e-commerce category pages for mobile:

A wireframe for an ecommerce category page on mobile An example wireframe for an ecommerce category page on mobile. (Source: created with Wireframe.cc) (Large preview)

The elements we need to include above the fold are:

  • The navigation bar (it can disappear upon scrolling or stick to the top of the page),
  • A descriptive category page title,
  • The total number of products in the category,
  • Filter options,
  • Sort settings,
  • At least one or two matching products.

As for why these elements need to be above the fold, let me show you an example.

According to SEMrush (and Google), “kong dog toys” is a popular search term that dog toy shoppers are looking for:

SEMrush data on “kong dog toys” with 33,100 monthly search volume SEMrush reveals that 'kong dog toys' has a monthly search volume of 33,100. (Source: SEMrush) (Large preview)

One of the top matching results for the search term is this category/brand page on the PetSmart website:

PetSmart category page for kong dog toys PetSmart’s product category page for Kong brand dog toys. (Source: PetSmart) (Large preview)

The next four swipes on the page take shoppers through informational sections, videos and subcategories like this:

PetSmart Kong brand information, video and subcategories PetSmart includes a bunch of information about Kong brand at the top of the category page. (Source: PetSmart) (Large preview)

Here’s the problem with this:

For visitors on the website exploring pet products, this information is great as it educates them on the very popular Kong brand. However, for visitors that went out of their way to search for “kong dog toys” in Google, they don’t need all of this information. It’s just getting in the way of the shopping experience.

While I’m not a fan of Best Buy’s inclusion of an ad above the header or a sponsored product as the first shown, the concise layout for the top of the category page is well done:

Best Buy category page for 'activity trackers' Best Buy’s category pages are concise in detail and display products right away. (Source: Best Buy) (Large preview)

What’s more, Best Buy includes additional category information (just as PetSmart did). However, it wisely places this information below search results:

Best Buy category information appears below search results Best Buy includes category information below search results. (Source: Best Buy) (Large preview)

Why does Best Buy do this and why should you?

For one, you want shoppers who are new to a product category or brand to still have this information available to them. And considering how well-trained consumers are to look below-the-fold for more information (thanks, Amazon), this works on mobile.

In addition, this is useful for SEO. Without this category description, you’d have to leave it to your meta title and description to influence the rankability of the page. With a search-optimized informational section like this, you can improve the chances of your category page getting to the top of search.

2. Show the Most Convincing Product Details

As you can see, we don’t have a lot of room on these mobile e-commerce category pages. So, when shoppers finally get to the matching product results, you want to make it as painless as possible for them to find the ones looking for.

Here are the details that should be included with each product listing:

  • A crystal-clear and attractive product image,
  • The product name (along with a short description if the name/brand doesn’t spell out what it is),
  • The price,
  • The star rating and number of reviews.

The only one of the elements above that’s optional is the rating/reviews and that’s only the case if your site is new and you don’t want a lack of reviews to turn people off.

As for adding other elements to the product listings, be careful with this. If it doesn’t add any value (in other words, it doesn’t make it easier to choose one product from another), leave it out.

Take, for instance, this “kong dog toy” category page from Chewy:

Chewy category page for 'kong dog toy' The Chewy category page and results for 'kong dog toy'. (Source: Chewy) (Large preview)

This category page design as a whole is much more concise than how competitor PetSmart handles theirs. However, there’s quite a bit of waste here. Namely, there are two repetitive strings of text that need to go:

  1. “More Choices Available” under the product images;
  2. “Free 1-2 day shipping over $49 🚚” between the price and rating.

The free shipping notice could easily appear as a dismissable sticky bar at the top of the site. And “More Choices Available” doesn’t need to be here at all. By tightening up the product details, mobile shoppers can more quickly get through the search results that are available.

Here’s an example from BH Cosmetics of product listings that could stand to be trimmed back:

BH Cosmetics makeup brushes category page BH Cosmetics displays makeup brush sets on the corresponding category page. (Source: BH Cosmetics) (Large preview)

The “Add to Bag” buttons all need to go. Unless shoppers can look at a single product image and know that’s what they need, these buttons are useless on this page.

I also think the “XX% OFF” is unnecessary. There’s no reason to overcomplicate this. The scratched-out original price and new lower price in pink should be enough to call attention to the offer.

This isn’t the only way to display inventory/options on an e-commerce website, so you’ll have to evaluate each product element based on your specific case.

So you can see what I’m talking about, here’s what a search for “Santorini Greece hotels” shows on Expedia:

Expedia results for 'Santorini Greece hotels' The search results page on Expedia for 'Santorini Greece hotels'. (Source: Expedia) (Large preview)

And on Booking.com:

Booking.com results for 'Santorini Greece hotels' The search results page on Booking.com for 'Santorini Greece hotels'. (Source: Booking.com) (Large preview)

Both include the essential details needed for each listing. However, they include additional details to help users make a decision.

However, there’s a big difference in how this extra information is displayed. On Expedia, users can see that “Breakfast included” is a top feature and that there are only two rooms left at the special price. This is useful information. On Booking.com, however, there’s a mess of details in green displayed directly below the price. It’s difficult to read and I’m not sure all of the details are necessary.

If in doubt, start with the bare minimum. Then, use A/B testing to confirm whether or not other details improve click-through and conversion rates.

3. Manage Your Mobile Category Page Sizes

There are two reasons why we need to be careful about page sizes when designing e-commerce category pages:

  • With as many images and data that appears on these kinds of pages, it can severely hurt loading times.
  • The more products you display at once, the more analysis paralysis your shoppers will experience.

So, the first thing to do is create a limit on how long the page can get.

While you might be tempted to use infinite scroll or an auto-load that reveals more product images as visitors scroll down the page, it’s better for performance if you use pagination links like Walmart does:

Walmart category page pagination Walmart uses pagination at the end of its product category pages. (Source: Walmart) (Large preview)

Another tip you can take from Walmart is its product view setting. By default, products appear in a grid on its category pages:

Walmart category page grid view By default, Walmart displays category products in a grid layout. (Source: Walmart) (Large preview)

By clicking the button to the left of “Sort & Filter”, users can change the alignment to list view:

Walmart category page list view Users can adjust Walmart’s category page to display products in a list layout. (Source: Walmart) (Large preview)

While this is more a matter of personal taste, you can see that the list layout does actually display more products at once, so users might find this choice of layout quite useful in speeding up their shopping experience.

One last thing to think about:

You can’t assume that your default sorting method is what all customers automatically prefer. For example, Sephora’s default sort is by “Bestselling”:

Sephora sorting products by bestselling By default, Sephora sorts its category pages by 'Bestselling' products. (Source: Sephora) (Large preview)

As we know, consumers have other things they’re concerned about when shopping for things online. Affordability is one of them, so sorting by “Price Low to High” might make more sense. Reviews and ratings are something else they look for, so “Top Rated” might be their preferred sorting method:

Sephora customers can change category page sorting by Bestselling, Top Rated, New, Price High to Low, Price Low to High Sephora customers can change how category pages are sorted. (Source: Sephora) (Large preview)

And when it comes to filters, don’t be stingy.

Sephora, for instance, only allows customers to filter by two factors:

Sephora customers can filter category page results by Brand and Price Range Sephora customers can filter category page results by Brand and Price Range. (Source: Sephora) (Large preview)

This assumes that customers are familiar with beauty brands. For those that aren’t, this can significantly impair their ability to find the products they’re looking for as it’ll take more time to consider all the options available.

Instead, what you should do is use your own product categories and tags to provide users with more comprehensive filtering options. After all, if that data helps you better organize and sell your inventory, it should do the same for your customers.

Ulta does a good job of this:

Ulta customers can filter category page results by Purpose, Type, Brand and more Ulta customers can filter category page results by Purpose, Type, Brand and more. (Source: Ulta) (Large preview)

This isn’t just beneficial in terms of user-friendliness either (though that’s a big part of it). By empowering shoppers to create smaller lists of products to peruse, you’re also enabling them to speed up their shopping experience as options are reduced and page loading times improve.

Wrapping Up

In sum, be mindful of how you design your mobile e-commerce category pages. Even though the research shows that these pages enjoy higher click-through rates and visits from search engines than individual product pages, bad design choices will make your website the exception to the rule.

Smashing Editorial (ra, yk, il)
Catégories: Programmation

How Should Designers Learn To Code? Git, HTML/CSS, Engineering Principles (Part 2)

mer, 03/25/2020 - 15:00
How Should Designers Learn To Code? Git, HTML/CSS, Engineering Principles (Part 2) How Should Designers Learn To Code? Git, HTML/CSS, Engineering Principles (Part 2) Paul Hanaoka 2020-03-25T14:00:00+00:00 2020-03-25T16:37:33+00:00

Literally, tomes have been written on version control. Nevertheless, I will start by sharing a brief explanation and other introductory content to whet your appetite for further study.

Version control (not to be confused with version history) is basically a way for people to collaborate in their own environments on a single project, with a single main source of truth (often called the “master” branch).

I’ll go over today is the bare minimum you’ll need to know in order to download a project, make a change, and then send it to master.

There are many types of version control software and many tools for managing and hosting your source code (you may have heard of GitLab or Bitbucket). Git and GitHub are one of the more common pairs, my examples will reference GitHub but the principles will apply to most other source code managers.

Aside:

Collecting Data, The Powerful Way

Did you know that CSS can be used for collecting statistics? Indeed, there's even a CSS-only approach for tracking UI interactions using Google Analytics. Read a related article →

Your First Contribution

Before doing these steps, you’ll need a few things set up:

  1. A GitHub account,
  2. Node and NPM installed on your computer,
  3. A high tolerance for pain or a low threshold for asking others for help.
Step 1: Fork (Get A Copy Of The Code On Your GitHub Account)

On GitHub, you will fork (fork = create a copy of the code in your account; in the following illustration, the blue, orange, red, and green lines show forks) the repository (repo) in question.

By creating branches off of the master, it’s possible for multiple people to contribute to different areas of a project and then merge their work together. (Large preview)

You do this by navigating to the repo in GitHub and clicking the “Fork” button, currently at the top right-hand corner of a repo. This will be the “origin” — your fork on your GitHub account.

As an example, navigating to https://github.com/yourGitHubUsername/liferay.design should show your fork of the Liferay.Design repo.

This is victorvalle’s GitHub fork. (Large preview) Step 2: Clone (Download The Code To Your Computer)

In your terminal, navigate to where you’d like to store the code. Personally, I have a /github folder in my /user folder — it makes it easier for me to organize it this way. If you’d like to do that, here are the steps — after typing these commands into your terminal window, press the ↵ key to execute:

cd ~/ ## you'll usually start in your root directory, but just in case you don't this will take you there mkdir github ## this creates a "github" folder — on OSX it will now be located at users/your-username/github cd github ## this command navigates you inside the github folder

Now that you’re in the /github folder, you will clone (download a copy of the code onto your computer) the repo.

clone https://github.com/yourGitHubUsername/liferay.design

Once you enter this command, you’ll see a bunch of activity in the terminal — something like this:

Cloning into 'liferay.design'... remote: Enumerating objects: 380, done. remote: Total 380 (delta 0), reused 0 (delta 0), pack-reused 380 Receiving objects: 100% (380/380), 789.24 KiB | 2.78 MiB/s, done. Resolving deltas: 100% (189/189), done. Step 3: Install (Get It Running On Your Machine)

Navigate into the /project folder. In this case, we’ll enter cd liferay.design. Most projects will include a README.md file in the /root folder, this is typically the starting place for installing and running the project. For our purposes, to install, enter npm install. Once it’s installed, enter npm run dev.

Congratulations! You now have the site available on your local computer — typically projects will tell you where it’s running. In this case, open up a browser and go to localhost:7777.

Step 4: Commit (Make Some Changes And Save Them)

A commit is a collection of changes that you make; I’ve heard it described as saving your progress in a game. There are many opinions on how commits should be structured: mine is that you should create a commit when you’ve achieved one thing, and if you were to remove the commit, it wouldn’t completely break the project (within reason).

If you aren’t coming to a repo with a change in mind, a good place to go is the ‘Issues’ tab. This is where you can see what needs to be done in the project.

If you do have an idea for some change, go ahead and make it. Once you’ve saved the file(s), here are the steps required to create a commit:

git status ## this will print out a list of files that you've made changes in git add path/to/folder/or/file.ext ## this will add the file or folder to the commit git commit -m 'Summarize the changes you've made' ## this command creates a commit and a commit message

Tip: The best recommendation I’ve ever seen for commit messages is from Chris Breams’s “How To Write A Git Commit Message”. A properly formed Git commit subject line should always be able to complete the following sentence: “If applied, this commit will [your subject line here].” For more info on commits, check “Why I Create Atomic Commits In Git” by Clarice Bouwer.

Step 5: Push (Send Your Changes To Your Origin)

Once you’ve made some changes on your computer, before they can be merged into the master branch (added to the project), they need to be moved from your local to your remote repo. To do this, enter git push origin in the command line.

Step 6: Pull Request (Ask For Your Changes To Be Merged Into Upstream)

Now that your changes have gone from your fingers to your computer, to your remote repository — it’s now time to ask for them to be merged into the project via a pull request (PR).

The easiest way to do this is by going to your repo’s page in GitHub. There will be a small message right above the file window that says “This branch is X commits ahead repo-name:branch” and then options to “Pull request” or “Compare”.

Clicking the “Pull request” option here will take you to a page where you can compare the changes and a button that says “Create pull request” will then take you to the “Open a pull request” page where you’ll add a title and include a comment. Being brief, but detailed enough in the comment, will help project maintainers understand your proposed changes.

There are CLI tools like Node GH (GitHub also recently released a beta of their CLI tool) that allow you to initiate and manage pull requests in the terminal. At this point you may prefer to use the web interface, and that’s great! So do I.

The ‘Pull request’ and ‘Compare’ options will appear once your fork has diverged from the upstream repo. (Large preview) Bonus Step: Remote (Link All The Repos)

At this point, we have three repository references:

  1. upstream: the main repo that you’re tracking, often it’s the repo that you forked;
  2. origin: the default name of the remote that you clone;
  3. local: the code that is currently on your computer.

So far, you have #2 and #3 — but #1 is important because it’s the primary source. Keeping these three things in-line with each other is going to help the commit history stay clean. This helps project maintainers as it eliminates (or at least minimizes) merge conflicts when you send pull requests (PR’s) and it helps you get the latest code and keep your local and origin repositories up-to-date.

Set An Upstream Remote

To track the upstream remote, in your terminal enter the following:

git remote add upstream https://github.com/liferay-design/liferay.design

Now, check to see what remotes you have available — enter git remote -v into your terminal, you should see something like:

origin and upstream are the most common labels for remotes — ‘origin’ is your fork, ‘upstream’ is the source. (Large preview) origin https://github.com/yourGitHubUsername/liferay.design (fetch) origin https://github.com/yourGitHubUsername/liferay.design (push) upstream https://github.com/liferay-design/liferay.design (fetch) upstream https://github.com/liferay-design/liferay.design (push)

This will allow you to quickly get the latest version of what is upstream — if you haven’t worked in a repo in a long time and don’t have any local changes that you want to keep, this is a handy command that I use:

git pull upstream master && git reset --hard upstream/master

GitHub Help is a great resource for this and many other questions you might have.

HTML And CSS: Starting With Semantics

On the web, there is an endless supply of resources for learning HTML and CSS. For the purposes of this article, I’m sharing what I would recommend based on the mistakes I made how I first learned to write HTML and CSS.

What Are HTML And CSS?

Before we get any further, let’s define HTML and CSS.

HTML stands for HyperText Markup Language.

Hypertext:

“Hypertext is text displayed on a computer display or other electronic devices with references (hyperlinks) to other text that the reader can immediately access.”

— “Hypertext” on Wikipedia

Markup Language:

“…a system for annotating a document in a way that is syntactically distinguishable from the text.”

— “Markup Language” on Wikipedia

In case you also don’t know what a lot of those words mean — briefly put, HTML is the combination of references (links) between documents on the web, and tags that you use to give structure to those documents.

There’s an HTML5 tag for pretty much any basic element — otherwise you can always use a div! (Large preview)

For a thorough introduction to HTML and CSS, I highly recommend the Introduction to HTML and CSS first steps, both on the Mozilla Developer Network (MDN) web docs. That, along with the excellent articles that websites such as CSS Tricks, 24 Ways and countless of others provide, contain basically everything you’ll ever need to reference with regards to HTML/CSS.

There are two main parts of an HTML document: the <head> and the <body>. - The <head> contains things that aren’t displayed by the browser — metadata and links to imported stylesheets and scripts. - The <body> contains the actual content that will be rendered by the browser. To render the content, the browser reads the HTML, provides a base layer of styles depending on the types of tags used, adds additional layers of styles provided by the website itself (the styles are included in/referenced from the <head>, or are inline), and that is what we see in the end. (Note: There is often also the additional layer of JavaScript but it’s outside of the scope of this article.)

CSS stands for Cascading Style Sheets — it is used to extend the HTML by making it easier to give documents a custom look and feel. A style sheet is a document that tells the HTML what elements should look like (and how they should be positioned) by setting rules based on tags, classes, IDs, and other selectors. Cascading refers to the method for determining which rules in a sheet take priority in the inevitable event of a rule conflict.

“‘Cascading’ means that styles can fall (or cascade) from one style sheet to another, enabling multiple style sheets to be used on one HTML document.”

Cascade — Max Design

CSS often gets a bad reputation — in sites with lots of style sheets it can quickly become unwieldy, especially if there aren’t documented, consistent methods used (more on that later) — but if you use it in an organized fashion and following all the best practices, CSS can be your best friend. Especially with the layout capabilities that are now available in most modern browsers, CSS is not nearly as necessary to hack and fight as it once was.

Rachel Andrew wrote a great guide, How To Learn CSS — and one of the best things to know before you start is that:

“You don’t need to commit to memorizing every CSS Property and Value.”

— Rachel Andrew

Instead, it’s far more vital to learn the fundamentalsselectors, inheritance, the box model, and most importantly, how to debug your CSS code (hint: you will need the browser developer tools).

Don’t worry about memorizing the syntax for the background property, and don’t worry if you forget about how exactly to align stuff in Flexbox (the CSS Tricks Guide to Flexbox is possibly one of my top-10 most visited pages, ever!); Google and Stack Overflow are your friends when it comes to CSS properties and values.

Some code editors even have built-in autocomplete so you don’t even need to search on the web in order to be able to figure out all the possible properties of a border, for example.

One of my favorite new features in Firefox 70 is the inactive CSS rules indicator. It will save you hours of time trying to figure out why a style isn’t being applied.

Kids these days have it so easy! (Large preview) Semantics

Let’s start with semantic code. Semantics refers to the meanings of words, semantic code refers to the idea that there is meaning to the markup in any given language.

There are many reasons why semantics are important. If I could summarize this, I would say that if you learn and use semantic code, it will make your life a lot easier because you will get a lot of things for free — and who doesn’t like free stuff?

For a more complete introduction to semantic code, see Paul Boag’s brief blog post on the topic.

Semantics gives you many benefits:

  1. Default styles
    For example, using a headline tag <h1> for the title of your document will make it stand out from the rest of the document’s contents, much like a headline would.
  2. Accessible content
    Your code will be accessible by default, meaning it will work with screen readers and will be easier to navigate with a keyboard.
  3. SEO benefits
    Semantic markup is easier for a machine to read, which makes it more accessible to search engines.
  4. Performance benefits
    Clean HTML is the foundation for a high-performing site. And clean HTML will also likely lead to cleaner CSS which means less code overall, making your site or app faster.

Note: For a more in-depth look into semantics and HTML, Heydon Pickering wrote “Structural Semantics: The Importance Of HTML5 Sectioning Elements” which I highly recommend reading.

Engineering Principles And Paradigms: The Basics Abstraction

There are tons of applications, tangents, and levels we could explore over the concept of abstraction — too many for this article which is intended to give you a brief introduction into concepts so that you are aware of them as you continue to learn.

Abstraction is a foundational engineering paradigm with a wide variety of applications — for the purposes of this article, abstraction is separating form from function. We’ll apply this in three areas: tokens, components, and the Don’t Repeat Yourself principle.

Tokens

If you’ve used a modern design tool for any length of time, you’ve probably encountered the idea of a token. Even Photoshop and Illustrator now have this idea of shared styles in a centralized library — instead of hard-coding values into a design, you use a token. If you’re familiar with the concept of CSS or SASS variables, you’re already familiar with tokens.

One layer of abstraction with tokens is to assign a name to a color — for example, $blue-00 can be mapped to a hex value (or an HSL value, or whatever you want) — let’s say #0B5FFF. Now, instead of using the hex value in your stylesheets, you use the token value — that way if you decide that blue-00 is actually #0B36CE, then you only have to change it in a single place. This is a nice concept.

Tokens for colors in the Lexicon Alerts component helps keep things DRY. (Large preview)

If you take this same paradigm of abstraction and go a layer further, you can token-ception — and assign a variable to a functional value. This is particularly useful if you have a robust system and want to have different themes within the system. A functional example of this would be assigning a variable like $primary-color and map that to $blue-00 — so now you can create markup and instead of referencing blue, you’re referencing a functional variable. If you ever want to use the same markup, but with a different style (theme), then you only need to map $primary-color to a new color, and your markup doesn’t need to change at all! Magic!

Components

In the past 3-4 years, the idea of components and componentization has become more relevant and accessible to designers. The concept of symbols (pioneered by Macromedia/Adobe Fireworks, later expanded by Sketch, and then taken to the next level by Figma and Framer), is now more widely available in most design tools (Adobe XD, InVision Studio, Webflow, and many others). Componentization, even more than tokens, can separate the form of something from the function of it — which helps to improve both the form and the function.

One of the more notable early examples is Nicole Sullivan’s media object component. At first glance you might not realize that a whole page is essentially composed of a single component, rendered in different ways. In this way, we can re-use the same markup (form), modifying it slightly by passing in options or parameters, and styles — and have it provide a variety of value (function).

Don’t Repeat Yourself

DRY (Don’t Repeat Yourself) is one of my favorite principles — creating things that can be reused over and over is one of the small victories you can have when coding.

While you often can’t (and arguably shouldn’t) strive to apply the DRY principle 100% of the time, every time — it’s at least beneficial to be aware of this so that as you’re working, you can consider how you can make whatever you’re working on more reusable.

A note on the Rule of Three: A corollary to the DRY principle is the rule of three — essentially, once you re-use (copy/paste) something three times, you should rewrite it into a reusable component. Like the Pirate’s Code, it’s more of a guideline than a hard and fast rule, and can vary from component to component and from project to project.

CSS And Styling Methodologies: Atomic vs. BEM

There are a lot of different ways to organize and write CSS code — Atomic and BEM are only two of the many that you’re likely to come across. You don’t have to “pick” a single one, nor do you have to follow them exactly. Most of the teams I’ve worked with usually have their own unique blend, based on the project or technology. It is helpful to be familiar with them so that over time, you can learn which approach to take depending on the situation.

All of these approaches go beyond “just” CSS and styling, and can often influence the tooling you use, the way you organize your files, and potentially the markup.

Atomic CSS

Not to be confused with Atomic Web Design — atomic (perhaps more aptly referred to as “functional”) CSS, is a methodology that essentially favors using small, single-purpose classes to define visual functions. A few notable libraries:

  1. Atomic CSS by Steve Carlson;
  2. Tachyons by Adam Morse;
  3. Tailwind CSS by Adam Wathan.

What I like about this method is that it allows you to quickly style and theme things — one of the biggest drawbacks is that your markup can get pretty cluttered, pretty fast.

Check John Polacek’s article on CSS-tricks for a full introduction to Atomic CSS.

BEM

The BEM philosophy is a great precursor to a lot of the modern JavaScript frameworks like Angular, React, and Vue.

“BEM (Block, Element, Modifier) is a component-based approach to web development.”

BEM: Quick Start

Basically, everything that can be reused is a block. Blocks are comprised of elements, something that can’t be used outside of a block, and potentially other blocks. Modifiers are things that describe the status of something or the way it looks or behaves.

Personally, I like the theory and philosophy of BEM. What I do not like is the way that things are named. Way too many underscores, hyphens, and it can feel unnecessarily repetitive (.menu, .menu__item, etc).

Recommended reading: BEM For Beginners written by Inna Belaya

Thank U, Next(.js)

After you have sufficiently mastered these topics, don’t worry, there is still plenty to learn. Some suggestions:

  1. Functional and object-oriented programming
    We touched on it lightly, but there’s plenty more to learn beyond CSS.
  2. Higher-level languages and frameworks
    Typescript, Ruby, React, Vue are the next things you’ll tackle once you have a strong grasp of HTML and CSS.
  3. Querying languages and using data
    Learning about GraphQL, MySQL, REST APIs will take your coding ability to the next level.
Conclusion: Designers Who Code != Software Engineers

Hopefully, this article has shown you that learning to code isn’t as difficult as you may have previously thought. It can take a lot of time, but the amount of resources available on the internet is astounding, and they’re not decreasing — quite the opposite!

One significant point that I want to emphasize is that “coding” is not the same as “software engineering” — being able to fork a repo and copy/paste in code from Stack Overflow can get you a long way, and while most, if not all, software engineers that I know have done that — you must use your new-found skills with wisdom and humility. For everything you can now access with some engineering prowess, there is that much more that you don’t know. While you may think that a feature or style is easy to accomplish because — “Hey, I got it working in devtools!” or “I made it work in Codepen.” — there are many engineering processes, dependencies, and methods that you probably don’t know that you don’t know.

All of that is to say — don’t forget that we are still designers. Our primary function is to add business value through the lens of understanding customer or user problems and synthesizing them with our knowledge of design patterns, methods, and processes. Yes, being a “designer who writes code” can be very useful and will expand your ability to add this value — but we still need to let engineers make the engineering decisions.

Anything Amiss?

There’s a good chance that something in this post was obscure, obtuse, and/or obsolete and I’d love the opportunity to make it better! Please leave a comment below, DM me, or @mention me on Twitter so I can improve.

Further Reading
  1. Coding Bootcamps vs. Computer Science Degrees: What Employers Want and Other Perspectives (Kyle Thayer)
  2. How To Start Using Sketch And Framer X (by Martina Pérez, Smashing Magazine)
  3. Introduction To Linux Commands (by Paul Tero, Smashing Magazine)
  4. Become A Command-Line Power User With Oh My ZSH And Z (by Wes Bos, Smashing Magazine)
  5. A list of the common cmd.exe and Unix commands that you can use in PowerShell (Microsoft Docs)
  6. regular-expressions.info (by Jan Goyvaerts)
  7. regexone.com (learn regular expressions with simple interactive exercises)
  8. Batch Resizing Using Command Line and ImageMagick (by Vlad Gerasimov, Smashing Magazine)
  9. Shortcuts And Tips For Improving Your Productivity With Sublime Text (by Jai Pandya, Smashing Magazine)
  10. Visual Studio Code Can Do That? (by Burke Holland, Smashing Magazine)
  11. Why version history is not version control (by Josh Brewer)
  12. Modern Version Control With Git (by Tobias Günther, Smashing Magazine)
  13. Hello World” (a GitHub step-by-step guide)
  14. How to Install Node.js and NPM on a Mac (by Dave McFarland)
  15. How to Install Node.js and NPM on Windows (by Dejan Tucakov)
  16. Why I Create Atomic Commits In Git (by Clarice Bouwer)
  17. How to Write a Git Commit Message (by Chris Breams)
  18. Semantic code: What? Why? How? (by Paul Boag)
  19. Structural Semantics: The Importance Of HTML5 Sectioning Elements (by Heydon Pickering, Smashing Magazine)
  20. Designing for Performance: Chapter 4. Optimizing Markup and Styles (by Lara C. Hogan, O’Reilly Media)
  21. The media object saves hundreds of lines of code (by Nicole Sullivan)
  22. Let’s Define Exactly What Atomic CSS is (by John Polacek, CSS Tricks)
  23. BEM For Beginners: Why You Need BEM (by Inna Belaya, Smashing Magazine)
  24. Javascript for Cats: An Introduction for New Programmers
  25. Roadmap.sh: Frontend Developer
  26. Functional Programming vs OOPS : Explain Like I’m Five
  27. Why, How, and When to Use Semantic HTML and ARIA (by Adam Silver, CSS Tricks)
  28. HTML Semantics (an eBook by Smashing Magazine)
  29. The Fundamentals - HTML + CSS (on Syntax.fm)
  30. Cascade and inheritance (westciv.com)
  31. CSS Tricks (by Chris Coyier)
  32. Getting Started With CSS Layout (by Rachel Andrew, Smashing Magazine)
  33. Introduction to HTML (MDN web docs)
  34. CSS first steps (MDN web docs)
  35. JavaScript First Steps (MDN web docs)
  36. 24 Ways (by Drew McLellan)
Smashing Editorial (mb, yk, il)
Catégories: Programmation

Upcoming Web Design Conferences (April 2020 – August 2020)

mar, 03/24/2020 - 10:00
Upcoming Web Design Conferences (April 2020 – August 2020) Upcoming Web Design Conferences (April 2020 – August 2020) Jan Constantin 2020-03-24T10:00:40+01:00 2020-03-25T01:35:01+00:00

Please note that dates are subject to change due to COVID-19, so it would be best to check the websites for further information regarding their conference dates and schedules.

We’re putting our heart and soul into crafting personal, inclusive and valuable events for all of us to become better professionals. With online workshops, we aim to give you the same experience and access to experts as in an in-person workshop, without needing to leave your desk. So you can learn at your own pace, in your own time, and follow interactive exercises along the way.

An illustration of Topple the Smashing Cat wearing jungle clothers and holding a burning torch Excited and ready for the adventure, but think your manager could need just a little bit more persuasion? Don’t worry — we’ve prepared a neat lil’ template: Letter For The Boss Template. Good luck!

Boost your skills online and learn practical, actionable insights from experts in the industry, live. With insightful takeaways, interactive exercises, access to experts, slides, recordings and a friendly Q&A.

Now, enough for the plug! Let’s dive into our list for April to August:

April 2020

ScanAgile 2020
“The presentations and workshops are suitable for developers, scrum masters, product owners, team leaders, agile coaches, project and program managers, management consultants as well as executives.”

  • When: April 1-2, 2020
  • Where: Helsinki, Finland
ScanAgile 2020

Frontcon 2020
“FrontCon is a two-day conference that focuses on front-end concepts and technologies. This year, there will be 23 speakers, 270+ attendees, and 4 workshops.”

  • When: April 1-3, 2020
  • Where: Riga, Latvia
Frontcon 2020

DevConf Johannesburg 2020
“DevConf is a community driven, developer focused, one-day conference hosted annually. The aim of the conference is to provide software developers a buffet of tools, practices and principles applicable to tackling current and future challenges in the South African software development environment. It's an event where attendees can learn, network and be inspired regardless of their specific technology stack and programming language of choice.”

  • When: April 2, 2020
  • Where: Johannesburg, South Africa
DevConf Johannesburg 2020

GenerateJS 2020
“Generate is brought to you by leading design magazine brands net and Creative Bloq. At our latest conference, once again hosted at Rich Mix in Shoreditch, you’ll be able to attend awesome talks on all things JavaScript, including the latest libraries, most fashionable frameworks and more than a hint of vanilla JS. Not only that but you’ll also get to network with fellow devs, grill JS experts, check out great web tech and unwind with some of our Creative Bloq break activities. And even once the conference is at an end, we have more on offer: we’d love for you to join us for a beverage or two in the bar.”

  • When: April 2, 2020
  • Where: London, United Kingdom
GenerateJS 2020

MIDWEST PHP 2020
“Midwest PHP is the only conference to offer a full digital library, giving you access to even more sessions day or night! ”

  • When: April 2-4, 2020
  • Where: Mineapolis, MN, USA
MIDWEST PHP 2020

vueday 2020
“VueDay the first international conference in Italy entirely about Vue.js. Vue is a progressive framework for building user interfaces. Vue is designed from the ground up to be incrementally adoptable. The core library is focused on the view layer only, and is easy to pick up and integrate with other libraries or existing projects.”

  • When: April 3, 2020
  • Where: Verona, Italy
vueday 2020

UXinsight 2020
“UXinsight is an international event for UX research professionals and anyone interested in UX research. This years’ theme focusses on the creative part of UX research. UX research is a field born in academia, but most UX researchers work in the creative field functioning as a bridge between technology and people. In our increasingly fast and agile working environments we need to be even more creative to deliver solid research. Let’s celebrate creativity together!”

  • When: April 6-7, 2020
  • Where: Breda, Netherlands
UXinsight 2020

The Lead Developer New York 2020
“The Lead Developer New York is a two-day conference packed full of inspirational and practical sessions from the world’s top technical leaders, focussed around three core themes: teams, tech and tools. Engineering leaders learn to nurture high performing teams, apply the best tech and tools for the job, and thrive as they meet the challenges of software engineering leadership.”

  • When: April 7-8, 2020
  • Where: New York, NY, USA
The Lead Developer New York 2020

HolyJS 2020 Piter
“HolyJS 2020 Piter will be the ninth in a row JavaScript conference held by JUG Ru Group. More than 1000 JS developers will be brought together to discuss the present and future of JavaScript community with the world's leading experts and watch dozens of frontend talks and much more. We'll dwell on both backend and desktop.”

  • When: April 10-11, 2020
  • Where: St Petersburg, Russia
HolyJS 2020 Piter

ODSC East 2020 - Open Data Science Conference
“Open Data Science will bring together the open source and data science communities to help foster the growth of open source software used in data science. The primary focus will be on the languages and tools that enable effective data analysis.”

  • When: April 13-17, 2020
  • Where: Boston, MA, USA
ODSC East 2020 - Open Data Science Conference

Ai x Summit
“This is the most important Industry AI Event of the year, hear from fellow CxOs, executives, chief data scientists, and thought leaders. Learn how AI and Data Science techniques are transforming business and prepare your company for the next wave of innovation by learning about: Deep Learning, Real-time Prediction, New product development, Data Visualization, Machine Learning, AI Tools and frameworks, Case studies, Automation, Sentiment Analysis, Open source AI/Data Science, Best practices, Law, Ethics and Governance.”

  • When: April 14-17, 2020
  • Where: Boston, MA, USA
Ai x Summit

JS Kongress 2020
“The focus of JS Kongress on April 15-16 2020 is Scaling JS – Pushing the Limits: Massive Platforms, Data-Driven Architectures, and Modern APIs. The #DeepTrack is about all things JavaScript. YOU create the program!”

  • When: April 15-16, 2020
  • Where: Munich, Germany
JS Kongress 2020

5G Africa Forum - Next Digital Revolution in Africa
“"Next Digital Revolution in Africa" 5G network is the next generation of mobile internet connectivity, offering faster speeds and more reliable connections on smartphones and other devices than ever before. It is the fifth generation of cellular mobile communications, which will ultimately replace 4G LTE to provide faster and more reliable service with lower latency. The conference will look at the progress that has been made to date and the challenges ahead for policy-makers and stakeholders. Key areas being covered include connectivity, future deployment and business model impact. It will look at what a 5G world might look like and where Africa sits at a global level as it seeks to deliver on making 5G a reality by 2020. The forum will offer the ideal space for networking with industry players; senior managers, decision-makers, and practitioners operating in the industries and making the most of banking technologies.”

  • When: April 15-16, 2020
  • Where: Johannesburg, South Africa
5G Africa Forum - Next Digital Revolution in Africa

DragonPy
“Python Best Practices for the modern Web and Data Scientists A Python conference in Ljubljana, Slovenia, taking place on April 18 & 19, 2020. Followed by three days of sprints.”

  • When: April 18-19, 2020
  • Where: Ljubljana, Slovenia
DragonPy

SmashingConf San Francisco 2020
“Let’s rock’n’roll! For SmashingConf SF 2020, April 21–22, we’re bringing back two full days packed with front-end, UX and all that jazz! Live sessions on performance, accessibility, security, interface design, debugging and fancy CSS/JS techniques — and a few surprises along the way.”

  • When: April 20-23, 2020
  • Where: San Francisco, CA, USA
SmashingConf San Francisco 2020

Devopsdays Baltimore 2020
“DevOpsDays is a worldwide series of technical conferences covering topics of software development, IT infrastructure operations, and the intersection between them. DevOpsDays Baltimore 2020 is run by volunteers from the Baltimore area and will be hosted at the Columbus Center (iMET) in downtown Baltimore on April 21-22, 2020. The event features single-track agenda with a combination of talks (30 minute open format and ignite format) and self-organized open space content. More information can be found on our website. ”

  • When: April 21-22, 2020
  • Where: Baltimore, MD, USA
Devopsdays Baltimore 2020

NDC Porto 2020
“NDC Porto 2020 is a 4 day event with workshops 21-22 April followed by a 2 day conference 23-24 April. From 21-24 April 2020, NDC Porto will offer a combination of talks, lightning talks and panels.”

  • When: April 21-24, 2020
  • Where: Porto, Portugal
NDC Porto 2020

UX Healthcare London 2020
“We live in a world of constant change. Technology is evolving more rapidly than anyone would have ever thought. In healthcare, this change is not embraced as much as in other industries. Most healthcare systems weren’t designed for this world. With UX Healthcare we aim to make a difference, because better design is needed in the healthcare industry. From clinicians, healthcare insurances to hospital equipment manufacturers - our goal is to help healthcare across the world to implement the best user experiences possible.”

  • When: April 22-24, 2020
  • Where: London, United Kingdom
UX Healthcare London 2020

Uphill Conf 2020
“Uphill Conf is a two days conference on top of Mount Gurten with awesome speakers and unique workshops. Learn about the latest trends in frontend web technologies in an inspiring, open environment. Meet and connect with our speakers and other like-minded, passionate developers.”

  • When: April 23-24, 2020
  • Where: Bern, Switzerland
Uphill Conf 2020

HalfStack Charlotte 2020
“An authentic, high value experience for attendees and sponsors focused on UI-centric JavaScript and web development. The priority for HalfStack is the attendee experience, with great food, drinks, talks, swag, and community. Hosted by London's longest-lived JavaScript meetup group, HalfStack is coming to Charlotte for the first time. HalfStack is a UI-centric, one-day single track conference hosted in a relaxed environment. HalfStack carefully curates talks that inspire and inform the audience in a highly interactive and entertaining manner. An initimate feeling where each attendee has time to meet one another; maximum capacity for HalfStack Charlotte is 200 attendees.”

  • When: April 24, 2020
  • Where: Charlotte, NC, USA
HalfStack Charlotte 2020

beyond tellerrand // DÜSSELDORF 2020
“beyond tellerrand celebrates the 10th edition in Düsseldorf. Join for two days of conference with the renowned familiar atmosphere to attend inspiring and exciting talks plus full-day workshops and side events around those dates. Not to forget the many networking opportunities.”

  • When: April 27-29, 2020
  • Where: Düsseldorf, Germany
beyond tellerrand // DÜSSELDORF 2020 May 2020

UX Burlington 2020
“UX Burlington is an event tailored for UX professionals seeking to stay ahead of the curve and push their work to the next level. UX Burlington is not a 101 event—we’d say more like a 301. Attendees include designers, developers, content producers, researchers, digital strategists, and product and brand managers. Every year 200+ UX practitioners attend to hear and learn from experts like yourself. In addition to keynotes, the conference runs two parallel tracks for part of the day, one catering to developers and the other a more general track tailored to UX/UI designers, researchers, and marketers.”

  • When: May 1, 2020
  • Where: Burlington, VT, USA
UX Burlington 2020

Texas Linux Fest 2020
“Texas Linux Fest is a weekend event geared towards individual users, rather than an expensive multi-workday expo that might cater primarily to sponsored attendees. Whether you use free software and Linux at home, in your place of business, in your school or non-profit, or you are simply curious, Texas Linux Fest offers something for you.”

  • When: May 1-2, 2020
  • Where: Austin, TX, USA
Texas Linux Fest 2020

Into The Box 2020
“Into The Box is a 2-day, 2-track event with speakers from around the world presenting on topics surrounding modern web and mobile technologies, development processes, software craftsmanship and infrastructure. We will be located in the Hyatt Place The Woodlands locate at 1909 Research Forest Drive, The Woodlands, Texas 77380. Into The Box also offers 1 full day of training workshops, 2 conference days with over 30+ sessions, breakfast, hot lunches, and our now famous Mariachi Party!”

  • When: May 7-8, 2020
  • Where: The Woodlands, TX, USA
Into The Box 2020

HalfStack Tel Aviv 2020
“An authentic, high value experience for attendees and sponsors focused on UI-centric JavaScript and web development. The priority for HalfStack is the attendee experience, with great food, drinks, talks, swag, and community. Hosted by London's longest-lived JavaScript meetup group, HalfStack is coming to Tel Aviv for the first time. HalfStack is a UI-centric, one-day single track conference hosted in a relaxed environment at the Bascula Circus Theatre. HalfStack carefully curates talks that inspire and inform the audience in a highly interactive and entertaining manner. An initimate feeling where each attendee has time to meet one another; maximum capacity for HalfStack Tel Aviv is 300 attendees.”

  • When: May 11, 2020
  • Where: Tel Aviv, Israel
HalfStack Tel Aviv 2020

Web Rebels 2020
“Web Rebels is a non-profit community conference for anyone who loves developing applications and services using web technology. Two days, one track, 16 speakers.”

  • When: May 14-15, 2020
  • Where: Oslo, Norway
Web Rebels 2020

Dutch Clojure Days 2020
“The Annual International Gathering of Clojure Enthusiasts and Practitioners in the Netherlands! We welcome you to the 5th edition of our free and non-profit Clojure conference organised by the community, for the community with a full day of amazing talks in a friendly welcoming atmosphere.”

  • When: May 16, 2020
  • Where: Amsterdam, Netherlands
Dutch Clojure Days 2020

Voxxed Days Frontend Bucharest 2020
“This developer conference aims to bring together popular speakers, core developers of popular open source technologies and professionals willing to share their knowledge and experience on frontend development. With several tracks on different topics (JS, Angular, React, React Native, Web, Mobile, GraphQL, PWA, VueJS, HTML, CSS, Typescript, Frontend testing, UI/UX design, and so on) attendees can satisfy their curiosity and learn new skills while enjoying and having fun!”

  • When: May 19-20, 2020
  • Where: Bucharest, Romania
Voxxed Days Frontend Bucharest 2020

DevDay Faro 2020
“DEVDAY'20 is a deep tech festival for developers and tech enthusiasts. Save the dates on 2020/05/22-23 to join us in Faro/Portugal for talks, workshops and discussions. This year on May 22nd, we'll kick off the event with 5 all-day workshops on the latest concepts of software development. On May 23rd, we invite you to enjoy 10 selected talks on two stages all about coding and tech-related subjects.”

  • When: May 22-23, 2020
  • Where: Faro, Portugal
DevDay Faro 2020

DigiMarCon Cruise 2020 - Digital Marketing Conference At Sea
“Immerse yourself in topics like digital strategy, programmatic advertising, web experience management, usability / design, mobile marketing & retargeting, customer engagement, user acquisition, social media marketing, targeting & optimization, video marketing, data science & big data, web analytics & A/B testing, email marketing, content marketing, conversion rate optimization, search engine optimization, paid search marketing, geo-targeting, predictive analysis & attribution, growth hacking, conversion rate optimization, growth marketing tools, marketing & sales automation, sustainable growth strategies, product marketing & UX / UI and much, much more!”

  • When: May 23-28, 2020
  • Where: Baltimore, MD, USA
DigiMarCon Cruise 2020 - Digital Marketing Conference At Sea

PGCon 2020
“PGCon is an annual conference for users and developers of PostgreSQL, a leading relational database, which just happens to be open source. PGCon is the place to meet, discuss, build relationships, learn valuable insights, and generally chat about the work you are doing with PostgreSQL. If you want to learn why so many people are moving to PostgreSQL, PGCon will be the place to find out why. Whether you are a casual user or you've been working with PostgreSQL for years, PGCon will have something for you.”

  • When: May 27-28, 2020
  • Where: Ottawa, Canada
PGCon 2020 June 2020

2020 AI & Innovation
“Artificial Intelligence is based on the research of fundamental and applied sciences. Through the evolution of information and engineering, it has gradually penetrated and changed not only our lives but our work style, which has resulted in bringing new experiences and convenience. And yet we’re facing with an unprecedented challenge and a crisis of privacy. An agenda, such diversified and interdisciplinary, ACEAI and the 8th ISFAS sincerely invite all relevant professionals in both academic and the industry to present and to exchange. All relevant abstracts/full papers in regards to “Fundamental and Applied Sciences” and “Engineering and Information” are welcomed, especially in the fields of AI, 5G, IoT and Blockchain.”

  • When: June 1-4, 2020
  • Where: Taipei, Taiwan
2020 AI & Innovation

Amsterdam JSNation Conference 2020
“Amsterdam JSNation is going to be the main happening of the JS scene in 2020. The conference unites library authors and core teams with fresh ideas, great people, and a summer Amsterdam in the background. We recognize JavaScript development as an art of engineering, and that's why the conference offers both a JS-driven art exhibition and audiovisual performances during the afterparty. After the event, we'll explore the well-known Amsterdam museums together, and later on, we'll gather for a JS hangout in the Vondelpark.”

  • When: June 3-5, 2020
  • Where: Amsterdam, Netherlands
Amsterdam JSNation Conference 2020

NDC Oslo 2020
“From 8-12 June 2020, Oslo Spektrum will once again host NDC Oslo. NDC Oslo is a 5-day event with 2 days of pre-conference workshops and 3 days of conference. The conference will cover topics such as: NET Framework - Agile - C++ - Cloud - Database - Design - Devops - Embedded - Front-End Framework - Fun - Functional Programming - Gadgets - Internet of Things - Javascript - Microsoft - Misc Languages - Mobile - People - Programming Languages - Security - Techniques - Testing - Tools - UX – Web and more.”

  • When: June 8-12, 2020
  • Where: Oslo, Norway
NDC Oslo 2020

SmashingConf Austin 2020
“The Smashing Cat is coming to Austin, Texas, y’all! Meet an inclusive, practical and friendly conference for front-end developers and designers who love their work. One track, two days, 14 speakers and 500 truly smashing attendees. But most importantly: a community that cares, shares and learns from each other.”

  • When: June 8-11, 2020
  • Where: Austin, TX, USA
SmashingConf Austin 2020

RightsCon Costa Rica 2020
“Originally called the Silicon Valley Human Rights Conference, RightsCon rotated between San Francisco and another global city. Now, RightsCon is an annual event that rotates its location each year to new host cities around the world that are power centers for technology and human rights. In 2019, we hosted RightsCon in Tunis, Tunisia, and we look forward to gathering in San José, Costa Rica, in 2020.”

  • When: June 9-12, 2020
  • Where: San José, Costa Rica
RightsCon Costa Rica 2020

Craft Conference 2020
“CRAFT is about software craftsmanship, which tools, methods, practices should be part of the toolbox of a modern developer and company, and it is a compass on new technologies, trends. You can learn from the best speakers and practitioners in our community.”

  • When: June 9-12, 2020
  • Where: Budapest, Hungary
Craft Conference 2020

Pixel Pioneers Bristol 2020
“A one-day conference of practical and inspiring design and front-end talks, featuring eight world-class speakers, preceded by a workshop day. Here's what you get for your conference ticket: - Eight practical sessions with actionable takeaways, - First dibs on limited tickets for workshops and side events, - Drinks and refreshments, - After-party with complimentary drinks.”

  • When: June 11-12, 2020
  • Where: Bristol, UK
Pixel Pioneers Bristol 2020

Accessibility Club Summit 2020
“After last year's very first and hugely successful summit in Berlin we are giddy with excitement to announce our next summit for 2020! Again, the summit will be jointly run by multiple web accessibility and inclusive design related meetups from all over Europe, and again there will be a premiere: For the first time, the Accessibility Club will meet outside of Germany, this time welcoming you to Amsterdam! The summit will take place right after CSS Day 2020 and again feature a full-day barcamp a second day with community run workshops. There are still a lot of details to be figured out, but you should definitely save the date already!”

  • When: June 13-14, 2020
  • Where: Amsterdam, Netherlands
Accessibility Club Summit 2020

KubeCologne Conference 2020
“KubeCologne is about Cloud-Native Thinking, Learning Kubernetes and its ecosystem, networking and community love! Be part of the second KubeCologne Conference on June 17th in Mediapark Cologne, learn and love Kubernetes® and Cloud-Native Thinking! Be part of the second KubeCologne Conference on June 17th in Mediapark Cologne, learn and love Kubernetes® and Cloud-Native Thinking! Meet with experts and users alike to learn and share knowledge on your journey to enterprise-grade container platforms and CI/CD chains.”

  • When: June 17, 2020
  • Where: Cologne, Germany
KubeCologne Conference 2020

Swiss PGDay 2020
“This day is all about PostgreSQL - the world's most advanced open source database. Take the opportunity to meet with other people interested in PostgreSQL in Switzerland. Beside the talks we offer the chance to network during the day and are pleased to invite you for a round of drinks after the meeting. The event is suitable for everybody, from first-time users to experts and from clerks to decision-makers. It is a two track conference, a complete track in English and one in German.”

  • When: June 18-19, 2020
  • Where: Rapperswil, Switzerland
Swiss PGDay 2020

JSCONF.BE 2020
“We’re looking forward to JSCONF.BE 2020 which will take place June 22-23, 2020 in Brussels. We plan to make June 23 a day packed with valuable and exciting content for the JavaScript community! This year there will be two themes: -Security -Reactive Frameworks/Serverless Architectures. Additionally, we’ll have a handful of break-out tracks for exciting niche topics such as AI/Machine Learning, Blockchain, Augmented Reality.”

  • When: June 22-23, 2020
  • Where: Brussels, Belgium
JSCONF.BE 2020

LeadDev Manager of Managers London 2020
“Lead Dev Managers of Managers is a new, intimate, one-day conference for those leading teams of teams and managing other managers (Senior Managers, Directors, Heads and VPs of Engineering, and CTOs). Hosted by Monzo CTO Meri Williams, the event is taking place on 23 June, the day before Lead Dev London (24 & 25 June). It will feature a blend of talk sessions and practical structured discussions; help you to become a better leader & manager, build a peer network, and enable your teams to be higher performing.”

  • When: June 23, 2020
  • Where: London, UK
LeadDev Manager of Managers London 2020

OpenJS World 2020
“OpenJS Foundation’s annual event brings together the JavaScript and web ecosystem including Node.js, Electron, AMP and more. Learn and engage with leaders deploying innovative applications at massive scale.”

  • When: June 23-24, 2020
  • Where: Austin, TX, USA
OpenJS World 2020

enterJS 2020
“EnterJS opens its gates for the seventh time in 2020 and offers developers a comprehensive view of the JavaScript-based enterprise world. The focus is not only on the latest trends around the JavaScript programming language itself, but also on the frameworks and tools that are part of skillset of every JavaScript developer. Of course, the conference also takes a look at the latest technologies and frameworks. Always with the aim of being able to assess whether it is worth using them in your own team.”

  • When: June 23-26, 2020
  • Where: Darmstadt, Germany
enterJS 2020

The Perl Conference 2020
“The Perl Conference is a high-quality, inexpensive, technical Conference that celebrates the family of Perl programming languages. The beauty of The Perl Conference is that it remains accessible to everyone regardless of experience, yet it is still valuable to the most skilled programmers.”

  • When: June 23-27, 2020
  • Where: Houston, TX, USA
The Perl Conference 2020

Lead Dev London 2020
“Join our community at the Lead Dev London, where technical leaders learn to nurture high performing teams, apply the best tech and tools for the job, and thrive as they meet the challenges of software engineering leadership.”

  • When: June 24-25, 2020
  • Where: London, United Kingdom
Lead Dev London 2020

UX Healthcare Amsterdam 2020
“We live in a world of constant change. Technology is evolving more rapidly than anyone would have ever thought. In healthcare, this change is not embraced as much as in other industries. Most healthcare systems weren’t designed for this world. With UX Healthcare we aim to make a difference, because better design is needed in the healthcare industry. From clinicians, healthcare insurances to hospital equipment manufacturers - our goal is to help healthcare across the world to implement the best user experiences possible.”

  • When: June 24-26, 2020
  • Where: Amsterdam, Netherlands
UX Healthcare Amsterdam 2020

ADDC - App Design & Development Conference
“Single-track international conference for iOS & Android developers and UX/UI designers in Barcelona, Spain. ADDC aims to create an opportunity for designers and developers to meet, find new ways to work together and get inspired in an open, inclusive and collaborative space. Our talks are crafted to be valuable for both designers & developers.”

  • When: June 24-26, 2020
  • Where: Barcelona, Spain
ADDC - App Design & Development Conference July 2020

OdessaJS'2020
“Enjoy Odessa together with 500+ international participants and share your knowledge with the community. Welcome to submit your talk and get ready for 2 days of endless fun and be one of the 20+ speakers of the greatest summer Ukrainian JS gathering.”

  • When: July 4-5, 2020
  • Where: Odessa, Ukraine
OdessaJS'2020

NodeConf Colombia 2020
“NodeConf Colombia 2020 is the first international event focused on the entire Node.js ecosystem. It’s a non-profit event, where our attendees will be sharing in an environment of inclusion and respect, having access to relevant information through talks, workshops, and great experiences with the Colombian Node community.”

  • When: July 10-11, 2020
  • Where: Medellín, Colombia
NodeConf Colombia 2020

O'Reilly Open Source Software Conference (OSCON)
“OSCON: Ground Zero for the evolution of Open Source. For over 20 years, OSCON has been the focal point of the open source movement. The inception of OSCON came from an event focused on Perl and grew to cover the other scripting languages. It has since evolved into the destination for all things free and open. The event has also provided a platform for the launch of major initiatives such as Kubernetes 1.0 and OpenStack—both announced at OSCON. Today, OSCON continues to be the catalyst for innovation, bringing together large corporations and grass-roots communities to share insights and foster change. Open source helps technology to thrive, and OSCON continues on with the tradition of bringing you the latest technological advances and a path to successfully implement open source in your workflow.”

  • When: July 13-16, 2020
  • Where: Portland, OR, USA
O'Reilly Open Source Software Conference (OSCON)

CSSCAMP 2020
“One-day, one-track conference for developers and designers who work on the web. International conference dedicated to the developers, designers and engineers who work on the web and build the world’s most engaging user interfaces. Learn how to push the boundaries with the latest technologies, cutting edge techniques, and tools.”

  • When: July 15, 2020
  • Where: Barcelona, Spain
CSSCAMP 2020

Algorithm Conference 2020
“Algorithms have found their way into practically every aspect of our lives. Wherever you look, howe’er you range, algorithms are hard to miss. Increasingly being deployed to guide you along. Algorithm Conference 2020 will bring you 3 days of high-level workshops and presentations that show how algorithms have been shaping and will continue to shape every aspect of our lives. Special consideration will be given to sessions that highlight innovative technical and commercial developments in big data, artificial intelligence and blockchain technologies, their ethical and privacy implications, and how they impact and are impacted by public policies. Researchers from the academia, developers and technical managers from startups and established companies will be on hand to share insights on the current state of development in big data, artificial intelligence and blockchain technologies, and their future trajectories. Those overseeing the rollout of these technologies on the management side and people involved in influencing and advising policy makers will also be on hand to share their insights.”

  • When: July 16-18, 2020
  • Where: Austin, TX, USA
Algorithm Conference 2020

DevopsDays Medellin 2020
“DevOpsDays is an international event of technical conferences on software development, IT infrastructure and operations and the intersection between them. This year this world reference conference on DevOps arrives in Medellin July 30 and 31 of 2020. DevOpsDays events present a combination of talks and self-organized open space content. Topics often include Pipelines Integration and Continuous Deployment (CI / CD), Test Automation, Security, Lean and Organizational Culture, among others.”

  • When: July 30-31, 2020
  • Where: Medellín, Colombia
DevopsDays Medellin 2020 August 2020

THAT Conference 2020
“Over four days, folks of diverse technology backgrounds and expertise levels gather to take advantage of multiple learning mediums to maximize one’s community and career advancements. An inclusive, multi-day event for anyone passionate about learning and sharing all things mobile, web, cloud, IoT, and technology. Engage in a wide range of software development topics with 150+ sessions, massive open spaces, and culture of creating and giving back. And there’s bacon, water slides, and, you know what? Bring the whole family.”

  • When: August 3-6, 2020
  • Where: Wisconsin Dells, WI, USA
THAT Conference 2020

UX And Digital Design Week 2020
“Create experiences that people will fall in love with. Get inspiration for your current projects and advice on how to build a design team of your dreams. Find out the secrets of what makes products successful and what mistakes companies made when they were building new services.”

  • When: August 10-14, 2020
  • Where: London, UK
UX And Digital Design Week 2020

International Travel Roadshow-Kuala Lumpur
“International Travel Roadshowis a unique & well known travel roadshow which is a connects the world wide sellers (exhibitors) and Buyers (Travel agents / Tour Operators) from the local city. The Roadshow usually happens 1 day in each city to meet the hand picked outbound tour operators. ITR is not like any other travel exhibition just for the below reasons. 1Day - 1 City - 100 Buyers Pre-fix Appointment with Buyers Networking Lunch with Buyers Luxury - MICE - Business Travel Invitation to Potential Buyers Full Day Roadshow.”

  • When: August 13, 2020
  • Where: Kuala Lumpur, Malaysia
International Travel Roadshow-Kuala Lumpur

International Travel Roadshow-Singapore
“International Travel Roadshowis a unique & well known travel roadshow which is a connects the world wide sellers (exhibitors) and Buyers (Travel agents / Tour Operators) from the local city. The Roadshow usually happens 1 day in each city to meet the hand picked outbound tour operators. ITR is not like any other travel exhibition just for the below reasons. 1Day - 1 City - 100 Buyers Pre-fix Appointment with Buyers Networking Lunch with Buyers Luxury - MICE - Business Travel Invitation to Potential Buyers Full Day Roadshow.”

  • When: August 14, 2020
  • Where: Singapore, Singapore
International Travel Roadshow-Singapore

HalfStack NYC 2020
“An authentic, high value experience for attendees and sponsors focused on UI-centric JavaScript and web development. The priority for HalfStack is the attendee experience, with great food, drinks, talks, swag, and community. Hosted by London's longest-lived JavaScript meetup group, HalfStack is returning to New York for the second time. HalfStack is a UI-centric, one-day single track conference hosted in a relaxed environment. HalfStack carefully curates talks that inspire and inform the audience in a highly interactive and entertaining manner. An initimate feeling where each attendee has time to meet one another; maximum capacity for New York HalfStack is 270 attendees.”

  • When: August 14, 2020
  • Where: New York, NY, USA
HalfStack NYC 2020

International Travel Roadshow-Melbourne
“ITR Australia ( Sydney & Melbourne ) Travel Roadshow is carefully designed to create a great platform for the suppliers around the world to meet the top notch travel buyers in Australia region. Buyers and Sellers love this roadshow for the following reasons. 2 Days - 2 Cities - 60 Buyers Pre-fix Appointment with Buyers Presentation Cocktail Networking Party Invitation to Potential Buyers Full Day Roadshow.”

  • When: August 18, 2020
  • Where: Melbourne, Australia
International Travel Roadshow-Melbourne

International Travel Roadshow-Sydney
“ITR Australia ( Sydney & Melbourne ) Travel Roadshow is carefully designed to create a great platform for the suppliers around the world to meet the top notch travel buyers in Australia region. Buyers and Sellers love this roadshow for the following reasons. 2 Days - 2 Cities - 60 Buyers Pre-fix Appointment with Buyers Presentation Cocktail Networking Party Invitation to Potential Buyers Full Day Roadshow.”

  • When: August 21, 2020
  • Where: Sydney, Australia
International Travel Roadshow-Sydney

Beyond Tellerrand Berlin 2020
“Established in 2014, beyond tellerrand is back for the 7th time in Berlin. Two days of conference with talks about design, technology and many opportunities to meet old and make new friends. Don’t miss out.”

  • When: August 24-27, 2020
  • Where: Berlin, Germany
Beyond Tellerrand Berlin 2020

“Codebreeze 2020
“Codebreeze is an unconference with very little structure. Actually, it’s not a conference at all. Codebreeze is a time and place for software craftspeople to meet. We would like to have like-minded people to gather in one place and have long conversations about our craft over a drink. And to practice our coding skills.”

  • When: August 31- September 7, 2020
  • Where: Turku, Finland
Codebreeze 2020 Where Are You Going?

If you’re planning to attend any of these events, we’d love to hear your thoughts in the comments section below. What are you most excited about? What are you looking forward to learning and experiencing?

By the way, the Smashing team is constantly organizing a series of conferences and workshops! We’d love to welcome you there!

Smashing Editorial (vf, il)
Catégories: Programmation

Smashing Podcast Episode 12 With Paul Boag: What Is Conversion Optimisation?

mar, 03/24/2020 - 06:00
Smashing Podcast Episode 12 With Paul Boag: What Is Conversion Optimisation? Smashing Podcast Episode 12 With Paul Boag: What Is Conversion Optimisation? Drew McLellan 2020-03-24T05:00:00+00:00 2020-03-24T07:36:16+00:00

Paul BoagIn this episode of the Smashing Podcast, we’re talking about the user experience around converting site visitors into customers. Can our selling techniques leave customers feeling cheated? And how can that be avoided? I spoke to conversion optimisation specialist Paul Boag to find out.

Show Notes Weekly Update Transcript

Drew McLellan: He’s a user experience consultant, digital transformation expert, and conversion rate optimization specialist hailing from the southwest of the UK. He is the author of many books, including User Experience Revolution from Smashing Magazine, and the forthcoming title Click! How to Encourage Clicks Without Shady Tricks. He’s also a veteran web design podcaster with a show running more or less weekly for 15 years. So we know he’s an expert at user experience design, but did you know he’s also the world authority on papier-mache? My Smashing friends, please welcome Paul Boag. Hi, Paul. How are you?

Paul Boag: Oh, I’m smashing, apparently.

Drew: So we’re in the middle of a global pandemic.

Paul: Yeah, and you’ve just made me say I’m feeling smashing in the middle of a pandemic. That’s great. Thanks.

Drew: What I want to know is, what’s on your shopping list?

Paul: Oh, dear. Do you know, this pandemic has changed very little in my life. Social distancing, I’ve been doing that for 18 years. I’ve worked from home for 18 years. We homeschooled our son. My wife works from home. Nothing has changed in my life. In fact, if anything, I’m now more sociable because everybody’s creating these WhatsApp groups and things, where, “Oh, let’s all pull together as a community.” So I’m having to talk to people now. It’s just dreadful, dreadful time.

Drew: Oh, wow. I’ll tell you what’s on my shopping list.

Paul: Oh, yeah.

Drew: It’s a new book of yours.

Paul: Oh. That was smooth, Drew. I’m super impressed by that.

Drew: It’s a heck of a title, How to Encourage Clicks Without Shady Tricks. Tell me about that.

Paul: Well, that wasn’t the original title that I wanted. Do you know this story?

Drew: No, I don’t know this story.

Paul: Oh, okay. I got vetoed by Vitaly.

Drew: Oh, dear.

Paul: Because I wanted to call it Encouraging Clicks Without Being a… But apparently that’s not professional enough. So the basis of the book is that we all need to improve our conversion rate. Websites aren’t there, although we talk about being user-centric and user focused, and all those things are entirely correct, but at the end of the day, websites have to create and return on investment for whoever owns them. And that’s entirely understandable and as it should be. But increasingly, people are under enormous pressure to improve their conversion rates. Marketers have got targets they’ve got to meet, designers are under pressure. And part of the problem is, in the early days when your website is rubbish, it was easy to increase your conversion rate.

Paul: And so as a result, then that set expectations, because the conversion rate went up quite a lot every year. And so management ended up expecting that to happen over the long term, and of course it becomes harder and harder. So the result is that people inevitable are turning to dark patterns. Not because necessarily they want to, but because they’re under pressure to. They’re under pressure to bring about results.

Paul: So the premise of this book is, first of all, to explain why dark patterns are a bad idea. And not from an ethical point of view. I don’t feel I’m the kind of person that can preach on ethics. But I talk about it from a purely business point of view, that these are the business reasons why dark patterns are ultimately damaging. And then that inevitably leads to the question of, well, if dark patterns aren’t the answer, then what is? And that’s what the majority of the book is exploring, that, what you can do to improve your conversion rate without resorting to these kinds of more manipulative techniques. So I actually got really excited about this book. It’s been one of the most enjoyable ones to write, and I actually think it’s probably the most practical and tangible book for the biggest majority of people out of the ones I’ve written.

Drew: So in a previous episode of this podcast, I talked to Michael and Trina about their book on ethical design.

Paul: Yes.

Drew: Also from Smashing magazine.

Paul: Yeah.

Drew: I guess that makes your book a good complement to that one, if they’re looking at the ethics of it, and maybe your approach is slightly more from the practical and business side.

Paul: Absolutely, yeah.

Drew: And not just the ethics.

Paul: Yeah. And I was quite chuffed when I found out that my book would be following on from theirs. I felt that that was a really good relationship between the two. Because don’t get me wrong, I think the ethics of how we design online and the decisions that we make and those kinds of things is massively important. And I think we’re in a very dangerous time in terms of that kind of thing, with many of the decisions that are being made, especially by larger organizations. But that’s not an area that I am an expert in, or that I feel I can comment on. But what I am seeing is significant long-term consequences of adopting these more manipulative techniques. Because I think there’s a perception that users are unaware that they’re being manipulated. Because these techniques work, people go, “Oh, okay, therefore people aren’t aware that we’re manipulating them. So everything’s fine.”

Paul: The truth is very different from that. Those things, these forms of manipulation, are happening on a subconscious level, yes. And they work because they’re subconscious, but people are still consciously aware of it. I’ve done a lot of usability testing on things like hotel booking sites, which are well known for this kind of thing. And the truth is, people will go, “Oh, I hate all this manipulative crap.” But then they’re still influenced by it. So it’s the impact of the fact that people are aware of it, and then also it’s got a lot of hidden costs associated with it. You tend to see high returns, you tend to see more contacting of support and those kinds of things. And a lot of organizations are not joined up enough to realize that that kind of thing is happening because of these dark patterns.

Drew: I guess it’s a bit like going to a theme park and buying lunch there. You know that you’re being way overcharged, but you want your lunch at the theme park, and so it leaves, not literally, a bad taste in your mouth, hopefully. But there’s a bit of that regret there, that you know that you’re being shafted but you go along with it all the same. But you might not be keen to return next time you’re budgeting your holiday.

Paul: Absolutely. But then there’s also the element of buyer’s remorse, that a lot of time if you bounce someone … You can bounce people into doing pretty much anything you want. And that’s fine, take out ethics for a minute. But you could argue, but that’s fine from a business point of view. But what you end up with is an audience of customers who are suffering from buyer’s remorse. Buyer’s remorse is extremely dangerous, because that’s what leads people to complain online, that’s what leads people to return items and all of those kinds of things. So it’s incredibly important that people are happy with their decision, they’re happy with their purchase. And that’s really what the book is about, is how do you get people to a point as fast as possible where they’re happy with their decision without them then afterwards regretting that decision?

Drew: So say that you’ve been using some of these perhaps slightly underhanded techniques on your site, and you’ve seen that it’s converting well, you’re turning visitors into customers quite effectively. But you want to, perhaps you’re seeing more returns or you’re seeing some bad reviews, or you’re seeing some of the consequences of this buyer’s remorse that we were talking about, and you want to try and improve things, get rid of the underhanded techniques, and bring in a more ethical or more customer friendly ways of converting people. How are you going to know if you’re actually having an effect? You presumably have to come up with some way of measuring your conversion before you can start making changes?

Paul: Yeah, absolutely. And I think, again, this is something that many organizations are quite poor at, is being clear about how they’re going to measure success. Now, yes, your conversion rate is one metric you should absolutely be following. But even with conversion, you need to be a little bit more sophisticated than how many people are buying. You also need to pay attention to average order value, you need to pay particular attention to lifetime value. So how much are customers worth over their entire life? Because you may well find that you’re getting quite high churn of customers if you’re using dark patterns and things like that.

Paul: But really, conversion should be just one of the metrics that you’re measuring. There’s also things like, you need to be paying attention to engagement, how engaged are people with your content. Because that makes a big difference in whether they eventually go on to convert. So you’re looking at things like, how much of your videos do they watch? How long do they spend on your site and what are they looking at while they’re doing it? Are they engaging on social media and those kinds of things? And then the final aspect is obviously usability. You need to be measuring how quickly someone can complete a particular task on their website, and how easy they find the system to use, and various different other criteria.

Paul: And there are loads of mechanisms that you can use for measuring those different things. There’s some great tools out there. And also some good metrics that you can adopt. So for example, with usability there’s something called the system usability scale, which could be a very useful metric to measure. But equally, there are tools like maze.design, is one that I often use, which will measure how long it’s taking someone to make a purchase, for example, get through the checkout. So yeah, having that broad range of metrics, you’re not just focusing on how many sales did we make this quarter. You’ve got to look at the bigger picture.

Drew: Are there any dangers that you could end up measuring the wrong thing?

Paul: Yes. Yes, absolutely. And so as a result, I think any metric that you’re looking at, that’s why you really need a range of metrics. If you just focus in on one particular metric, so for example, a lot of marketing professionals are judged on the number of leads that they’ve generated in a particular quarter or whatever. If you just have one metric like that, then it’s going to, A, skew the reality of what’s going on, but B, it’s going to end up encouraging some less than perfect behavior. So let me give you an example. I worked with a company that produces project management software. And they had a marketing department and they had a sales department. And the marketing department was tasked with generating leads. That was their job. They had to generate as many leads as possible.

Paul: The sales department were judged and assessed on how many leads they converted. Now, the website was owned by the marketing department. So the marketing department came to the conclusion that it was a really good idea to, the product demo that they had on the website, they were going to make people register before they could see the product demo. Because that would generate a large number of emails and a large number of leads to help them meet their target. Sure enough, it did. It generated a huge number of leads, a lot of people just gave up and went away, but many people did actually sign up to see the demo.

Paul: Now, the problem that that created is, the majority of those leads weren’t good quality leads. They were people that were nowhere near the point of being ready to talk to a salesperson, and so when the salesperson contacted them, they weren’t interested. They didn’t want to talk to them. But the salesperson had already wasted the time and the effort in calling them. And then they also had to filter through all the people that entered “Donald Duck@Disney” as their email address. So actually they created a huge amount of internal work for the sales team, and the sales team conversion rate plummeted through the floor. Because they had all these poor quality leads. So that’s a great example of how things can go wrong if your metrics are too narrow and too skewed in a particular direction.

Drew: And I guess a lot of it comes down to understanding who the user is. In order to turn somebody into a customer, you need to understand who they are. I guess so much about user experience design is effectively putting yourself in the place of your user and empathizing with what they’re trying to do. So how do we go about understanding who our user is?

Paul: Well, again, there are lots of different ways of doing that, depending on your time and your budget and things like that. I’m a great believer in actually meeting with users. I think there is a bit of a tendency at the moment towards, we’ve got all these wonderful analytics and survey tools and that kind of thing. And sure enough, those are great. I’m not in any way knocking them. But if you’re trying to convince somebody to take action, as you say, you need to empathize with them. And knowing that somebody has 2.3 children, works in the city, and I don’t know, spends their weekends kayaking, doesn’t really help you to know and empathize with them as people.

Paul: So personally, I’m a much bigger fan of actually speaking to people and doing user interviews. Even if they’re over the phone or remotely, which they have to be at the moment. They’re very much worthwhile in terms of getting to know people. Now, that said, I think another thing that I love to do, and just kind of blows you away, you can’t do this at the moment, but hopefully you will be able to soon, which is, you go and visit people in their homes. Now, the reason that I find this so valuable is because you find out about the reality of their experience in a way that you would never get from just talking to them over the phone or from a survey.

Paul: Now, I’m not saying you need to do this a lot. Probably doing it once is enough. But essentially … Let me give you an example. I was once testing an e-commerce site, and so I decided to visit some people in their home and actually test the site with them in their own home. So I went to visit this one lady, and she opened the door, and immediately all these cats came out and crawled around my legs and disappeared off. And she was a stereotypical cat lady. I’m sorry to be rude, but she really was. Every surface in the house was covered with knickknacks and ornaments relating to cats in some way. There were pictures of cats on the wall. She had a total of nine cats, which is just insane.

Paul: So we talked for a while, and we sat down to use this, to test with this website. And we used her computer, which I tell you took 10 minutes to boot up, because it was this old tower computer, it was an absolute nightmare. And that whole desk was covered with clutter and knickknacks and things. And she had post-it notes all around her screen. Now, the minute she sat down in front of that computer, a cat jumped on her lap. So she spent the rest of that usability session trying to juggle a cat that was on her lap. The cat got so fed up at one point that it wasn’t getting enough attention that it decided to crawl across the keyboard and sit on the keyboard. Which I know you understand, because you’ve got a cat and I’ve seen pictures of your cat doing the same thing.

Drew: I feel seen.

Paul: Yeah, exactly. And then, on top of which, I asked her at one point, “Add a product to the basket,” which she was able to do. And then I said, “Now, go to the basket,” and I realized there’s no way she’s going to find the basket. Because she had a post-it note stuck on the screen over the top of the basket. Now, that is the real world experience. We sit down and look at our websites and we think they’re so easy to use and so simple. But if you’re juggling with a cat and if you’re living in chaos, or you’ve got distractions and that kind of stuff, then you don’t have that clean, clear mental point of view to approach the website. You are under what is called cognitive load.

Drew: So I guess one solution to that might be for every design studio to be equipped with cats.

Paul: Yeah, absolutely. And not only that, but equipped with (bad) computers. Because we all sit, don’t we? I’m doing it right now, I’m sitting in front of a lovely iMac with this gorgeous screen. And that’s not what most people … I remember another occasion I was designing a website for an elderly audience. Well, I say I was designing it, I was doing the UX side of things. And I was getting quite frustrated with the designer, because the designer was a young guy, and he did these beautiful interfaces that was all subtle and lovely and gorgeous. And I was saying, “I’m sorry, but this old audience are not going to be able to see what you’re doing, and they’re not going to be able to click on all these little links and stuff. And you’ve got to make it more brash and horrible,” which obviously he didn’t want to do.

Paul: So I came into the office one day with a pair of reading glasses and a pair of ski gloves. And I made him put on the reading glasses and put on the ski gloves. Now, he didn’t need reading glasses, just to be clear on that. And I said, “Now use the site.” And of course he couldn’t. He couldn’t see properly, he had lost motor control in his hands because he had these big, thick ski gloves on. So that helped him to empathize and understand what his audience was going through. And so things like that, I think, are really important to do. Obviously that’s a bit of an extreme example, it was me making a point and rubbing my designer’s nose in it. But you get the idea.

Drew: You mentioned the cognitive load of buying. Making personal decisions online can be fairly overwhelming at times. Are there things that we should be doing that are going to help the customer have a better experience and be more likely to convert, more likely to actually make a purchasing decision?

Paul: Yeah. It’s really funny, cognitive load is a fascinating thing in terms of how it affects us. So what cognitive load is basically, is having to think too much. We have two systems in our brain. We have system one and system two. And system one is that unconscious decision making that we make all the time, and system two is our conscious mind. Now, our conscious mind is incredibly powerful, but it easily gets overwhelmed. It easily gets tired out. And that’s known as cognitive load. And when we are overwhelmed, when our cognitive load goes up, it has all kinds of really bad impacts on conversion rate. So suddenly your website feels hard to use, it feels untrustworthy and a little bit suspicious, and it feels just downright bad. So our conscious minds are very cynical as well, so we start not believing what’s being said on the site. And it really has an enormous impact.

Paul: So the way that you lower cognitive load is really about simplifying your website. So removing unnecessary distractions that are on the website. It’s about being consistent in your website. So buttons don’t move around, things don’t change. But not only consistent within your own website, consistent with people’s expectations from a website. So to give you an example of what I mean, let’s say I asked you to search on a website. Where would you look? You’d look in the top right-hand corner, wouldn’t you?

Drew: Right.

Paul: Everybody looks at top right-hand corner, so the first thing, they look at the top right-hand corner, then they look for an input field. They enter their search query in the input field, and they press the button next to it. That’s what’s called procedural knowledge. We have learned that that is a procedure that, if we go to a website, look at the top right-hand corner, use the input field, click the button, we will search on that website. But the minute that you break that procedural knowledge, our cognitive load goes up. So at that point we’re starting to go, “Well, hang on, where’s the button?” Or, “Why isn’t the search field the way it’s supposed to look?” Or, “Why isn’t it in the top right-hand corner?” So that consistency with expectations matters a lot.

Paul: And then our mood matters as well. Bizarrely, you know what it’s like, some days you wake up and you’re in a really good mood. And everything seems to be easier. And then other days you wake up in a bad mood, everything seems to be harder. So actually, the mood we’re in affects our level of cognitive load. So things like design delighters, nice little friendly copy, colorful graphics, all those things, they help as well to put us in a good mood that lowers our cognitive load. So it’s really mood, inconsistencies in the interface, confusing, too much information being displayed, and then finally priming people. So in other words, setting their expectations about what will happen and why it will happen.

Drew: I guess all these things weigh into how much trust somebody has in the website. And I think trust is quite a big factor, isn’t it, in inciting someone to actually buy from you?

Paul: Oh, enormous.

Drew: Because anyone can build a website online, we all know that. We’re web people. And there are thousands of places that you can buy the same product or service from, quite often. So there needs to be some way of building up trust. Are there other ways that we can build up trust in a site?

Paul: Yeah. You’re right, people buy from people they trust and from organizations they trust. So when it comes to trust, a lot of it is about humanity. Being a human being. You know how many times you go to a website and it just feels like it’s spouting marketing BS at you? Do you know what I mean? The great example I use in a book, where there’s some copy on a university website. I think it was the University of Essex website. And basically that copy was written in the third person. So it’s talking about the reader as students, it was talking about themselves as the University of Essex. And it just felt, it lacked any kind of humanity and any sense that they cared about you or liked you. And simply turning that around and writing it in the first person, so talking about “we” and talking about “you,” makes an enormous difference in making that connection with people.

Paul: Other ways that you can do that, obviously, is through things like social proof. You can build trust by demonstrating that you’re a trustworthy brand. But again, you’ve got to accept that people are very cynical these days. So it’s not a matter of just slapping some logos on your website and going, “There’s your social proof.” Or slapping a text testimonial. Because people know that some companies just make that stuff up. So one of the things, actually a product of your own, actually, Perch, I don’t think you do this any more, but for a long time on your website you used to have testimonials that came straight from Twitter. They were pulled straight out of Twitter. And that was such a good idea, because those testimonials, people can click through and see that there’s a real human being behind it.

Paul: Another example is videos. If you’ve ever watched video testimonials on websites, where the person that’s speaking is beautifully lit, has got perfect teeth, and says a whole spiel about how great the company is without pausing, without going, “um,” without making mistakes, they’re obviously just reading off a script. That’s insincere. However, if you have a shitty video that’s filmed on a webcam, that the audio’s a bit crap, that’s actually more effective. Because it’s more real. Great example of this is, there’s a guy called Paul Jarvis who sells an online course called Chimp Essentials, which teaches you how to use MailChimp. And if you go to chimpessentials.com, he’s got all these video, just like he’s obviously just chatting to someone over a webcam and them talking about how great the course was and how much it helped. And that is so powerful, because it’s authentic, it’s real, it’s human. And that’s what it’s about. It’s about coming across as a human being and making a connection with people.

Paul: So yeah, I’m a huge fan of that kind of sincerity and openness and honesty. Buffer is another example of that. Buffer, they lay out everything online. You can see how much their employees are paid, you can see how much they earned in the last month, you can see what their diversity range of staff and employees are. You can see everything about that company. And so you know they’re not hiding anything. You know that they’re being sincere and open. And that goes such a long way.

Drew: So we understand who our customer is. We want them to buy from us. Is there a single moment when a conversion happens on our site?

Paul: No. No, conversion is very much a journey. So it’s a series of micro-interactions. And I think that’s part of the problem that people have, is that they perceive, “Okay, they’ve clicked on the ‘buy now’ button, we’re done.” Or they’ve sent us a contact form, we’re done. And actually it’s a lot more nuanced than that. There are many, many steps in a journey that someone goes on. So let’s take, I don’t know, donating to charity, for example. So the first interaction might be, you see an update that a friend shares on social media about some crisis in the world. So your first point of conversion really is just clicking on that link in that social media update, which takes you to a blogpost. And then your second conversion is actually reading that blogpost and looking at it.

Paul: And your third, maybe, is to sign up for updates about that particular crisis. And then maybe you receive some emails about it. So your next conversion point is actually opening those emails and reading the content. And then it might be that they, in those emails, ask you to make a donation. So the next step is to make a single donation, one-time donation. And then they’ll follow up with you again, and that might turn into a monthly donation. And then that might lead you to actually start volunteering for them or fundraising for them. And eventually it might even lead to you leaving a legacy when you die.

Paul: So actually, any point of conversion is just a step in an ongoing journey. And we need to start thinking of conversion as a journey of relationship with a customer, rather than, “Okay, we’ve got them to sign on the dotted line, we’re done.” Because there’s so much more potential than just that.

Drew: So every interaction you have with that customer is a point where really you’re selling with them. It’s always be closing, right? ABC.

Paul: Yeah. Yes, you know, I hadn’t thought of that. Yes, it’s absolutely straight off of that, isn’t it? Yeah.

Drew: So you’ve carefully designed a site, you’ve done your best to ensure that you’re going to get some good conversions without any dirty tricks, without anything underhand. You launch the site. Is that it? Are you done?

Paul: No.

Drew: What should we be doing over time?

Paul: You’re asking questions that I know you know the answers to. That’s the sign of a great interviewer, when you’re happy to ask questions that other people might need the answer. No, of course it is. You’ve run Perch for years, you know that you can’t just start something and then walk away from it. When it comes to conversion, really that initial launching is the very, very beginning of the process. And actually, what is important in the journey is that ongoing optimization, that ongoing monitoring an improvement. It’s interesting, I’ve literally just written a report for a company outlining this approach. So basically it begins, you go through a cycle. And the cycle begins with, you try and identify problem areas in your site. So typically you would look at your analytics. And you’d look at pages that have got a high dropout rate for the number of visitors that they have to that particular page. So a high percentage of dropouts. So you know that something is going wrong on that page. So that’s your first step. Then you try and narrow down, well, what’s going wrong on that page?

Paul: Now, you can either do that through session recorders, which allows you to watch back users interacting with that particular page, and you might be able to spot where it’s going wrong. Perhaps you’re having problems with a form or perhaps they scroll straight past some critical button, or something else. Alternatively, if that doesn’t work, you might want to do some remote usability testing, and that’s so cheap and easy these days, using services like usertesting.com or User Brain. There are all these great services that make it really easy to test those kinds of pages. So that will enable you, probably, to work out what the problem is. Once you’ve done that, then the next step is, now we need to identify how we’re going to fix that problem. And in that particular case, you can have a couple of different approaches.

Paul: If the problem is relatively easy to fix, so if it’s just things like changing imagery or changing button colors or that kind of very simple thing, then probably you’ll want to go straight to A/B testing. So you use something like Google Optimize to send some of your users to an alternative version of the page with these small changes being made. You see whether that improves things. And if it does, you push it live. If it’s more substantial changes, then you’ll probably want to mock that up or prototype that before you go to all the expense and time of building it properly. And then you can test that either by doing some more usability testing, or if it’s just a static mockup, in other words, it’s not an interactive thing, then you might want to do something like a first-click test, where you say, “Okay, where would you click on this mockup in order to complete X task?” And see whether people are clicking in the right place.

Paul: Or another test that you can do is something called a five-second test, where you show them the mockup for five seconds, take it away, and you ask them what they recalled. And that’s a really good way for ascertaining whether or not they spotted that call to action they previously scrolled straight past. So you have to use a bit of imagination, but basically you then test your hypothesis, if you like, about how to fix it. Presuming you’re right, you then roll it out. Now, you’re not at the end of the process then. Because you now go back to the beginning again. You look at, “Well, what’s the next page that people are most exiting the site from?” And you repeat the process. And you just keep doing that, really, forever, slowly and incrementally improving your conversion rate over time.

Drew: This all sounds very logical, very attractive to somebody who, like me, who’s a business owner and I’ve got digital product, and I think, yes, I could be doing this. Some of the listeners will be freelancers working on an hourly rate for a customer who has these sorts of problems. And I can see it might be difficult to convince that customer that this is what they should be doing, this is something they should invest in. Because all the time spent in even just setting up some monitoring and setting up something to measure conversion is money that that client is going to have to pay out for the designer to do it. What would you say to those designers? Is there an effective way they can persuade their client that this is what they should be doing?

Paul: Yeah. This is a tricky one, because it’s very hard to persuade anybody of anything, in my opinion. People become very entrenched in their ways of thinking. But it’s worth finding out what they care about. Because there will be certain metrics that they want to move. It might be they want more leads, it might be they want more quality leads, it might be that they want to reduce their cost of sale. Whatever it is. And then you start talking about these kinds of optimization techniques in that context. That said, you’re never going to get someone to commit to a major program of incremental design and usability testing and all those things in one go. What I would start with is just trying to encourage them to go through that cycle once. So it might be that you even have to install the analytics on your dime. But it’s not a big deal, is it, to add something like Google Analytics or something like Hotjar for session recorders.

Paul: So you basically then just take them through it once. You say, “Okay, well, let’s give it a go for one time. Let’s see if we can make a difference to the conversion rate by looking at the analytics, by mocking up one thing, and just improving that one thing.” If that works, you rinse and repeat. They don’t necessarily need to commit to an ongoing retainer where you’re continually optimizing it. This could be done as a series of sprints, effectively, going through the loop one thing at a time. In terms of more general stuff, like for example, just simplifying the interface, then in those kinds of cases, often it’s a matter of actually showing them what better might look like. Now, I’m afraid to even say this in front of you, Drew, because I remember many, many years ago … Or no, it wasn’t you, actually, I was about to say that it was you I remember going on about speculative design. But it wasn’t. Yeah, you’re off the hook.

Paul: It was you ranting about the fold. That was the thing that I’m remembering. Anyway, that’s beside the point. So one of the things you can do there is actually try … For the first time, I’m not saying do this regularly. But if you’ve got an existing client and you’re seeing glaring problems, mock up an alternative version of doing a particular page, and then do those five-second tests that I mentioned, or do a, what was the other one, a first click test. And see whether those can make improvements, and show that evidence to the client. So you can use a tool like usabilityhub.com that will allow you to do those tests really easily. If you don’t want to do that because you don’t want to put the effort of mocking those things up, the other thing that you can do is just record a few videos of people using the website. And then edit down all of the bits of them moaning and complaining about how crap the site is to use into a two-minute horror reel, and send it to the client. That can do it as well.

Drew: So would these generally be, would these be the tips you’d give somebody who was just wanting to get some quick wins to start? They’ve done no optimization, and they just want to get started. Are these the same sort of things they’d do for a quick win?

Paul: Yeah, to some extent. Often I find, where I start, if I get a new client, the thing I normally start with is simplifying the user interface. Because inevitably sites end up bloated with a load of things that don’t really help. So the way that I tend to do it is, I’ll take a particular page, let’s say a home page, for example, and I will systematically look at every single element on that page. And I will ask myself three questions in order. Question number one I ask is, could I remove this element? If I removed this element, what would be the negative consequences of doing so? So you’d be amazed at how much you can just strip out of a website. And of course, every element that’s on the screen is every element a user is having to process and look at. Every element adds to their cognitive load. So anything that you can remove, great.

Paul: Then if you can’t remove an element because it’s critical to the completion of a key task or convincing users to take action or whatever else, then the next question you ask yourself is, can I hide this element? Could I move it deeper in the information architecture? Could I put it under a tab? Could I put it under an accordion? Whatever else, just to get it out of the site for the majority of people. So that often helps. And then if the answer is, well, this really is absolutely critical, so I’ll give you an example, maybe you’re forced to have some compliance copy on your website. That happens, I get that a lot with my bigger clients. “Oh, yes, legal department says we have to have this.”

Paul: So my third option, my final option, is can I visually shrink this? So can I de-emphasize it, put it in the footer or make it smaller or make it lighter text? Anything to draw attention away from that and focus it on stuff that really matters. So that’s almost always my first starting point with any kind of conversion, is just to simplify everything. The other thing that I do alongside that, which is a really useful starting point, is called objection handling. So I will make a list of as many reasons that someone might choose not to act as possible. And I then make sure that those are all addressed clearly on the website. Because often they’re not. So a classic example of that might be, somebody comes to sign up for a newsletter. Now, you think, when you sign up to a newsletter all these things go through your head, are they going to sell me email address? Are they going to spam me? Is the content going to be relevant? Can I unsubscribe in one click?

Paul: All of these objections. Are you addressing those? And not only are you addressing them, but are you addressing them at the point that you want people to convert? So for example, yes, you probably say something about whether you’re going to sell their email address or how much you’re going to email them and stuff. That’ll be in your privacy policy. But that’s going to be buried in a completely different part of the site where no one ever looks. And to be honest, it’s all illegible anyway because it’s written in legalese. So answering people’s questions at the point they have them is also another really good starting point for just giving your conversion rate that little boost.

Drew: That’s fantastic. And I think all these tips are things that you go into in quite a lot of depth in the book.

Paul: Mm-hmm (affirmative).

Drew: I found it to be a really great read, I’ve enjoyed browsing through it so far. I know it’s in the late stages of production and it’s coming out from Smashing magazine this spring, 2020.

Paul: Mm-hmm (affirmative).

Drew: That’s Click: How to Encourage Clicks Without Shady Tricks. And you can find out more about the book if you go to encouragingclicks.com. And then when it’s released you can go to smashingmagazine.com/books and you’ll be able to find it and buy it from there. Now, Paul, I guess if people are listening to this, I presume that they like podcasts. You’ve been podcasting for I guess almost 15 years now?

Paul: Yeah. Yeah, we were the first web design podcast in the world, that’s my claim to fame.

Drew: There we go. If a listener hasn’t come across the Boagworld podcast, what sort of thing could they expect from it?

Paul: Nonsense, generally. No, it’s a season-based show that covers all aspects of web design in a pretty broad sense. We don’t do a lot on development, to be honest. So it’s mainly design, project management, content creation, all of those kinds of things. A lot of UX stuff, because that’s my personal passion. It’s quite a laid-back conversational show. We have seasons, and different seasons are on different topics. So for example, there’s a whole season dedicated to conversion rate optimization, if people want to learn more about that as a subject area. So you can pick and choose which seasons you listen to. Yeah, I don’t think there’s a huge amount more to say about it. The current season has been one about almost like a virtual meet-up, where we’re having conversations with people listening to the shows. You can come along and join in. But next season will be something totally different. So it’s a bit of an eclectic mix, to be honest.

Drew: I’ve listened to it on and off for a good number of those 15 years, and it’s always an enjoyable listen. So I would recommend that people check it out if they haven’t done so already. So I’ve been learning from you about honest ways to convert users into customers. What have you been learning about lately, Paul?

Paul: I’ve been getting slowly more and more obsessed with psychology. Because obviously that relates quite a lot to both user experience design and conversion rate optimization, so I’ve been realizing how little I know about psychology. So it started off very simply, by following a guy called Joe Leach, who’s written a free e-book that you can download called Psychology for Designers. So that got me thinking more about psychology and understanding how to approach the subject. And then I’ve started to read proper psychology books now. I feel like I’m a bit more of a grownup in the field. So for example, earlier I was talking about system one and system two, that comes from a book called Thinking Fast, Thinking Slow, that I would highly recommend.

Paul: It’s a bit of a stodgy read at places. It’s not the easiest book to read. But it’s very, very much applicable to the kind of world that we’re looking at. So a lot about psychology. I’m also always nosing into things like marketing and sales as well, because I’m quite interested of how people apply sales techniques offline. So all that stuff I was talking about, like when I talked about objection handling, that comes from traditional sales, basically. So yeah, those are the two big areas at the minute.

Drew: If you, dear listener, would like to hear more from Paul, you can follow him on Twitter, where he’s @Boagworld, or find his podcast, blog, and details of how you can hire him to consult on your digital projects at boagworld.com. Thanks for joining us today, Paul. Do you have any parting words?

Paul: Keep safe, I guess, at the moment. That’s the sad thing that you’re having to say, isn’t it? And yeah, just start experimenting with conversion rate optimization. You’ll be amazed at the results you see.

Smashing Editorial (dm, ra, il)
Catégories: Programmation

Announcing Smashing Online Workshops

lun, 03/23/2020 - 19:00
Announcing Smashing Online Workshops Announcing Smashing Online Workshops Rachel Andrew 2020-03-23T18:00:00+00:00 2020-03-23T19:40:28+00:00

We had to postpone our SmashingConf in San Francisco until 10th–11th November 2020 and, like so many of you, our team will be staying firmly put at home for the next month or more. However, we know that many of you are still hoping to develop your skills, and we had workshops ready to go. We decided to find a way to bring the workshops to your home office, trying to keep as much of the live experience as possible. So, meet Smashing Online Workshop.

Topple the Smashing Cat and a laptopRemote, live, interactive and practical. That’s Smashing Workshops.

We have two workshops to announce today, and if there is demand, we hope to be able to bring you more of the workshops you might be missing from our live events. By doing so, we hope we can help you continue to learn and interact with the speakers and each other, and also help out our workshop leaders who are losing income by being unable to run their workshops in person right now.

Upcoming workshops

Apr 2–17, Thu & Fri, 9–11:30 AM PDT
Smart Interface Design Patterns with Vitaly Friedman.

You’ll study 100s of hand-picked interface design examples in this one. We’ll be designing interfaces together, starting from accordions, to mega-drop-downs, sliders, feature comparisons, car configurators — all the way to timelines and onboarding. And: we’ll be reviewing and providing feedback to each other’s work. This workshop is spread over five days, 2h each day, with a huge amount to learn and take away.

Apr 14–15, Tue & Wed, 9–11:30 AM PDT
CSS Layout Masterclass with Rachel Andrew.

Over two days learn the key skills you need to learn CSS Layout and put it into practice in your work. A mix of theory and pragmatic advice in terms of how to deal with browser support.

Your Questions Answered

We know that a big reason why people come to Smashing Workshops is the chance to ask questions of the expert, and perhaps have a sticky issue they are facing at work discussed in person. It’s certainly one of the reasons I love leading workshops. Every time I teach CSS in-person, I learn more about the ways people are using CSS, and the challenges you face. So each workshop has dedicated time for chat and Q&A. We hope that you’ll bring your questions and ideas to the room, talk with us in the workshop, and learn from your peers, too.

Join Us

We hope you’ll join us as we bring our workshops online, there is some special early bird pricing for the initial registrations. We’d also love to know which other workshop topics and speakers you would like to see online. Read more about the workshops and sign up here.

Smashing Editorial (vf)
Catégories: Programmation

Inspired Design Decisions With Otto Storch: When Idea, Copy, Art And Typography Became Inseperable

lun, 03/23/2020 - 14:00
Inspired Design Decisions With Otto Storch: When Idea, Copy, Art And Typography Became Inseperable Inspired Design Decisions With Otto Storch: When Idea, Copy, Art And Typography Became Inseperable Andrew Clarke 2020-03-23T13:00:00+00:00 2020-03-23T13:36:26+00:00

For the past few years, books about HTML and CSS have almost vanished from my studio bookshelves. I replaced them with books on art direction, editorial, and graphic design.

Recently, I was browsing a new addition to my library and was captivated by one magazine spread. I loved the way its designer has playfully combined images and typography to create a design which was full of energy and movement. To remind myself to take another look at this design, I snapped a picture of it with my iPhone.

When I first saw that striking design, I hadn’t heard of the designer who’d created it, Brooklyn-born Otto Storch. Although he was an award-winning graphic designer, unlike many of his contemporaries, Storch and his work have been largely overlooked.

Storch amassed a vast body of work, and it’s an incredible shame that his work isn’t more widely known, especially online. There’s no Wikipedia page devoted to Storch, and no one has published a book about him or his work.

I’m not only influenced by Otto Storch’s work, but also by the fact he was a prolific designer with a strong work ethic. I’m inspired by how he took what he’d learned from Alexey Brodovitch, combined it with his approach to design, and made distinctive and engaging work. I hope I can do that too.

A selection of covers from Otto Storch’s time as art director for McCall’s Magazine. A selection of covers from Otto Storch’s time as art director for McCall’s Magazine. (Large preview)

I’ve never heard Otto Storch‘s name mentioned during a design conference or seen him referenced in a book about web design. But discovering him has made me want to make more people aware of the man and his work.

He’s also made me consider the role of creativity in an industry which is business focussed, fast-moving, and has practical as well as technical constraints. Publishing can be a cut-throat business, and the magazines Storch worked on weren’t high-fashion. What he made wasn’t art, but that didn’t mean it wasn’t creative. Storch understood that ideas are as essential to effective communication as pictures and the written word. Throughout his career, Storch worked hard to include ideas despite the limitations of his medium. That’s an approach which is as essential on the web today as it was in magazines in the 1960s.

Previously On “Inspired Design Decisions” More From The “Inspired Design Decisions” Series
  1. Inspired Design Decisions: Avaunt Magazine
  2. Inspired Design Decisions: Pressing Matters
  3. Inspired Design Decisions: Ernest Journal
  4. Inspired Design Decisions: Alexey Brodovitch
  5. Inspired Design Decisions: Bea Feitler
  6. Inspired Design Decisions: Neville Brody
Inspired By Otto Storch

Otto Storch was born in 1913, and during the 1930s, he began his career in the forgotten art of pre-digital photographic retouching. During the 1950s, Storch took evening classes and studied design under Alexey Brodovitch who encouraged him to get a job working on a magazine.

Success didn’t happen overnight, and it took seven years of freelancing before Storch Better Living magazine in New York hired him as an assistant art director. McCall published several titles including Popular Mechanics, Blue Book and Red Book, and McCall’s Magazine itself. Storch moved to McCall’s Magazine where he built on what he’d learned from Brodovitch and his experience designing advertising materials, album covers, book covers, and magazines.

Storch wasn’t afraid to make opinionated choices and its this assertiveness which makes much of his work distinctive.

“Good art direction does not come from an uncertain person. I am capable of intense feeling and was willing to lose a popularity contest with departmental editors when necessary. The visual responsibility of the magazine was mine.”

— Otto Storch

Like Bea Feitler, Storch carried on Alexey Brodovitch’s legacy of imaginative magazine layouts. He understood the double-page spread is a creative canvas and made it a feature of his work, sometimes by allowing elements to flow between pages. Other times, Storch made the gutter an integral part of his design.

Storch often used large headlines and images to unify his spreads. For ‘On the cob or off,’ its a corn cob which drips butter on both pages. For another feature, ‘The Forty-winks reducing plan,’ he allowed his subject to stretch out, resting on a bed of running text. This copy sinks under the weight of the sleeping model.

The Forty-winks Reducing Plan. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. The Forty-winks Reducing Plan. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. (Large preview)

The large black-and-white graphic in ‘Why teen-age marriages are falling apart’ isn’t confined to just one page. Instead, it occupies three out of four columns on the spread and so dominates the design. The gravity of a headline in the middle of those concentric circles pulls the eye towards it.

Why Teen-Age Marriages Are Fally Apart. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. Why Teen-Age Marriages Are Fally Apart. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. (Large preview)

In ‘Girls Are Silly, Aren’t Boys Awful,’ Storch placed two children forehead to forehead with the gutter between them. He emphasised this tension by aligning his text in opposite directions.

Girls Are Silly, Aren’t Boys Awful. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. Girls Are Silly, Aren’t Boys Awful. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. (Large preview)

Storch made combining images and text look obvious and effortless, but the results he achieved came from years of experience and practice.

For ‘Make fashions fresh as paint,’ Storch’s tightly packed text fits perfectly into a compartment in an artist’s paintbox. The models in this spread for McCall’s Patterns also fit inside the box. Storch’s playful and unexpected use of scale adds yet another dimension to this design.

Make Fashions Fresh as Paint. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. Make Fashions Fresh as Paint. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. (Large preview)

Storch believed that in editorial design, a strong idea, copy, images, and typography are integral. I think the same is true in web design, despite its apparent differences to print.

Storch understood typography could do much more than present readable content and he had a knack for turning type into graphical objects. In print design for left-to-right languages, the left page is called “verso”, and the right is called “recto.” For McCall’s extract of a book called ‘The First to Know,’ Storch mirrored the recto and verso pages, then set his text into a circle which reflects the circular telephone dial.

The First to Know by Louella Parsons. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. The First to Know by Louella Parsons. Spread from McCall’s Magazine Art direction by Otto Storch. Recreated by Andy Clarke. (Large preview)

There’s plenty Otto Storch, and his designs can teach us about the work we do on the web today. Like Alexey Brodovitch, Storch’s mastered his canvas and rather than be limited by it; he used his pages to present content in ways which made it not just understandable, but also more appealing. This appeal matters, because it connects people with a brand, a product, or a story, and that matters to any business, whatever the medium.

Otto Storch might be a new addition to my list of inspiring designers, but his designs are already influencing mine.

Shape up

The W3C’s CSS Shapes Module Level 1 has been a Candidate Recommendation recommendation since 2014, and all contemporary desktop and mobile browsers have implemented its shape-outside, shape-margin, and shape-image-threshold properties.

[src="shape.png"] { float: left; shape-outside: url(shape.png); shape-margin: 20px; } It’s rare to see CSS Shapes used for anything more elaborate than wrapping text around images, like this. It’s rare to see CSS Shapes used for anything more elaborate than wrapping text around images, like this. (Large preview)

Web designers aren’t aware of the creative potential offered by CSS Shapes, and that there’s no longer a reason to not use them. It’s also possible web developers still think Shapes have poor support in browsers. Still, with all contemporary browsers now supporting Shapes — and their properties degrading gracefully in legacy browsers — there’s currently no reason to avoid using them.

Do More With Shapes

This design by Otto Storch was one of the first to get my attention. I admired the structural simplicity of its two justified columns of copy, and how the placement of his images — with text wrapped around them to create organic shapes — playfully filled the page with energy and movement.

 This movement- filled design uses CSS Shapes and the HTML picture element. Left: By a Stroke of Beauty. Spread from McCall’s Magazine Art direction by Otto Storch. Right: This movement- filled design uses CSS Shapes and the HTML picture element. (Large preview)

I rarely see layouts with this kind of energy online, so my design includes four brightly coloured Beetles, each Volkswagen placed at an angle to contrast with the two tall columns of text. I need only two structural elements to implement this Storch-inspired design; the main element and an aside. Each of these elements contains paragraphs of running text, plus two picture elements which enable me to swap small images for larger ones:

<main> <picture>…</picture> <p>…</p> <p>…</p> <picture>…</picture> <p>…</p> <p>…</p> </main> <aside> <picture>…</picture> <p>…</p> <p>…</p> <picture>…</picture> <p>…</p> <p>…</p> </aside>

These picture elements fit to the edges of small screens, but I still need whitespace on both sides of my paragraphs of running copy. By using viewport width units, that space always remains in proportion to those screens:

p { margin-right: 10vw; margin-left: 10vw; } I cropped these pictures to make them the appropriate size for small screens. I cropped these pictures to make them the appropriate size for small screens. (Large preview)

The picture element is one of the most useful additions to HTML. By combining media queries with multiple images, a browser can select an image which is most appropriate for a layout.

Structural elements stack vertically and I introduce larger images for medium-size screens. Structural elements stack vertically and I introduce larger images for medium-size screens. (Large preview)

I use the media property and min-width value most often, and while this design requires only two images per picture element, its possible to add more images and even combine media values to create complex queries:

<picture> <source srcset="large.png" media="(min-width: 48em)"> <img src="small.png" alt="Volkswagen Beetle"> <</picture>

The images in these pictures contain cropped versions of my Beetles which are best suited to small screens. I apply the same width to all my images, then add a shape-margin in preparation for the CSS Shapes which come next:

picture { width: 160px; shape-margin: 20px; } Shapes from images are often easier and quicker to implement than using polygon coordinates. Shapes from images are often easier and quicker to implement than using polygon coordinates. (Large preview)

I find shapes from images easier and quicker to implement than using polygon coordinates. To develop a shape from an image, it needs an alpha channel which is wholly or partially transparent. When images are partially transparent, the shape-image-threshold property can control the areas which form the shape.

I can use the same image for more than one shape. Even though my design includes four differently coloured cars, I need just two shape images:

main picture:first-of-type, aside picture:first-of-type { float: left; shape-outside: url(shape-1-sm.png); } main picture:last-of-type, aside picture:last-of-type { float: right; shape-outside: url(shape-2-sm.png); }

With my small screen design complete, I introduce larger images for medium size screens as well as shape images to match. I apply new widths for the images to fit larger screens:

@media (min-width: 48em) { main picture:first-of-type { width: 290px; shape-outside: url(shape-1-lg.png); } main picture:last-of-type { width: 230px; shape-outside: url(shape-2-lg.png); } aside picture:first-of-type { width: 230px; shape-outside: url(shape-3-lg.png); } aside picture:last-of-type { width: 290px; shape-outside: url(shape-4-lg.png); } } This design doesn’t just tell the story of the Volkswagen Beetle, its layout hints at how fun this iconic car was to drive. This design doesn’t just tell the story of the Volkswagen Beetle, its layout hints at how fun this iconic car was to drive. (Large preview)

Although my design for larger screens might look complex at first glance, the layout couldn’t be simpler, and those main and aside elements form two symmetrical columns:

@media (min-width: 64em) { body { display: grid; grid-template-columns: 1fr 1fr; } }

Whitespace plays a big part in this large screen design. With those columns introduced, the 10vw horizontal margins I applied to my paragraphs earlier means that whitespace comprises 40% of this layout.

Just as Otto Storch used his pages to present content in ways which made it appealing as well as understandable, this design doesn’t just tell the story of the Volkswagen Beetle, its layout hints at how fun this iconic little car was to drive.

Make text look delicious

Like Brodovitch, Otto Storch excelled in combining images with text, and he often carved copy into shapes which mirrored them. In this design, Storch created a delicious text block shaped like a glass. We rarely find techniques like this used online, but they can help to draw readers into a story whatever the medium. Inspired by Storch, for my next design, I sculpted my copy to reflect the shape of a Volkswagen Beetle.

I sculpted my copy to reflect the shape of a Volkswagen Beetle. I sculpted my copy to reflect the shape of a Volkswagen Beetle. (Large preview)

My design includes three alternative layouts. A single column of scrolling content for small screens, a 2x2 grid for medium screens, and a large screen design with a horizontally scrolling content area.

There are four structural elements needed to implement these three designs, one main element for my content, plus large images of three brightly coloured Beetles. I enclose these elements with a section, then add a decorative, presentation division which represents a tarmac road:

<section> <img src="shape-1.png" alt=""> <main> <h1>Get bitten by the bug</h1> </main> <img src="img-1.png" alt="Volkswagen Beetle"> <img src="img-2.png" alt="Volkswagen Beetle"> </section> <div> </div> The finished small screen design. The finished small screen design. (Large preview)

I don’t need my horizontally scrolling panel to appear on small screens, so add only foundation styles and shapes which sculpt my text into the shape of a Beetle. I start by aligning paragraph text to the centre, and setting it in uppercase. While I wouldn’t normally set text an entire block of text in this way, the solid uppercase letterforms help to emphasise the Beetle shape:

p { text-align: center; text-transform: uppercase; }

Early drafts of the CSS Shapes specification included a shape-inside property which would’ve enabled us to wrap text on the inside of shapes as Storch did. I’m disappointed that the W3C postponed this feature until CSS Shapes Module Level 2 which is still an Editor’s Draft. You can achieve similar effects using shape-outside, but I, for one, can’t wait until we can use type as creatively as Otto Storch online.

Two alpha-transparent PNG images create the classic Beetle shape. Two alpha-transparent PNG images create the classic Beetle shape. (Large preview)

I add two shape images to my paragraph. Text will flow between these images to mirror the face of a Beetle:

<p> <img src="shape-2.png" alt=""> <img src="shape-3.png" alt=""> … </p>

I specify dimensions for these two images and set their opacity to zero as I don’t want them seen by a viewer:

p img { width: 100px; height: 125px; opacity: 0; }

These images are purely presentational and convey no content or meaning, so to remove any semantics from them, I add role attributes. To take them out of from the accessibility tree, I also add aria-hidden attributes to these two images:

<img src="shape-2.png" alt="" role="presentation" aria-hidden="true">

To carve my text into the shape of the iconic Volkswagen, I apply shape-outside using the same two images, floating the first image left and the second to the right:

p img:nth-of-type(1) { float: left; shape-outside: url(shape-l.png); } p img:nth-of-type(2) { float: right; shape-outside: url(shape-r.png); }

I don’t want my presentation division visible to assistive technologies either, so I add those same role and aria-hidden attributes to this too:

<div role="presentation" aria-hidden="true"> </div>

As I don’t need the division to be visible to people using small screens, I set its display property to none:

div { display: none; } A symmetrical 2x2 grid with text sculpted into the iconic shape of the Volkswagen Beetle on medium-size screens. A symmetrical 2x2 grid with text sculpted into the iconic shape of the Volkswagen Beetle on medium-size screens. (Large preview)

My small screen design is stylish, like the Beetle, but the extra space available on medium-size screens allows me to place my sculpted text alongside the pictures it’s imitating.

Before implementing any design, I make a storyboard. Before implementing any design, I make a storyboard. (Large preview)

Before implementing any design, I make a storyboard to decide how to rearrange elements as screen sizes change. For medium-sized screens, I arrange my four elements in a 2x2 symmetrical column grid. By using minmax values for sizing these columns, I ensure they fill all available space, but their width never shrinks below 400px:

@media (min-width: 48em) { section { display: grid; grid-template-columns: minmax(400px, 1fr) minmax(400px, 1fr); grid-gap: 2vw; align-items: end; } }

For larger screens, I also need two rows. They should be equal in height and occupy all available vertical space:

@media (min-width: 64em) { body { display: grid; grid-template-rows: 1fr 1fr; }

A large, horizontally scrolling content area dominates this design and is wider than the viewport. The panel includes four columns — three for images and one for my sculpted copy — and each one is a minimum of 400px wide. By setting the maximum width to the viewport and allowing scrolling only on the horizontal axis, any content which is outside the viewport is hidden but still accessible:

section { grid-template-columns: repeat(4, minmax(400px, 1fr)); max-width: 100vw; overflow-x: scroll; } A presentational division which represents the road under the wheels of my Beetle shapes. A presentational division which represents the road under the wheels of my Beetle shapes. (Large preview)

Below my content is a presentational division which represents the road under the wheels of my Beetle shapes. This element is invisible on smaller screen sizes, so to make it visible, I change the display property from none to block, then add a light grey background colour. The grid properties I previously set on the body element defines the height of this division:

div { display: block; background-color: #a73448; } }

Webkit’s Dave Hyatt originally proposed CSS Reflections as far back as 2008, but so far they haven’t been implemented in other browser rendering engines. CSS Reflections are currently only supported by Google Chrome.

As you might imagine, reflections create a copy of an element. A reflection can appear either above, below or to the left or right. Just as in the physical world, when an element changes in some way, its reflection follows.

There are three experimental properties available for CSS Reflections. Its direction and an optional offset which controls the distance between an element and its reflection. You can also apply a mask to any reflection to change its appearance, for example, by using a gradient mask to fade the intensity of a reflection gradually.

CSS Reflections have limited support in browsers, but they can still add an extra dimension to a design for browsers which have implemented them. I want to add reflections only when a browser supports them and when the screen is large enough to use them to full effect.

CSS Shapes sculpt text into this delicious design. CSS Shapes sculpt text into this delicious design. (Large preview)

To achieve the result I’m looking for, I use nested media and feature queries which first test a viewport’s minimum width, then whether a browser supports -webkit-box-reflect:below. I add the reflections and change the colour of my presentational division from red to grey:

@media (min-width: 64em) { @supports (-webkit-box-reflect:below) { section { -webkit-box-reflect: below 0 linear-gradient(transparent, white); } div { background-color: #f0f0f1; } } } Mirror symmetry

This striking black and red spread from McCall’s Patterns is one of Storch’s most distinctive designs. There’s a reassuring symmetry to its layout and how Storch used the same colours on its two pages. I was immediately drawn to his design and want to achieve a similar effect.

A playful but reassuring symmetry in this large screen design. A playful but reassuring symmetry in this large screen design. (Large preview)

The HTML I need to implement this design couldn’t be simpler. Just two structural elements, one main and an aside, which both contain picture elements:

<main> <picture>…</picture> <p>…</p> </main> <aside> <picture>…</picture> <p>…</p> </aside>

These main and aside elements also each contain a paragraph of text. To achieve the rotations needed for this design, I wrap each line of text inside a span element. I wish there was a better, more semantic alternative to these presentational elements, but without additional styles, they don’t disrupt the readability of my paragraphs:

<p> <span>Although </span> <span>designed in the </span> <span>1930s, due to </span> <span>World War II, </span> <span>civilian Beetles </span> <span>only began to </span> <span>be produced in </span> <span>significant </span> <span>numbers by the </span> <span>end of the 1940s.</span> </p>

I start by applying a dark grey background colour to the body element:

body { background-color: #262626; } Mirroring parts of a design on small screens to create a consistent experience across all screen sizes. Mirroring parts of a design on small screens to create a consistent experience across all screen sizes. (Large preview)

Then, a minimum height ensures that my main and aside elements always fill the viewport height. To centre their content both horizontally and vertically, I apply flexbox properties and set their direction to column:

main, aside { display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 100vh; padding: 2rem 0; box-sizing: border-box; color: #fff; }

I want the colour of my main Beetle matched by the subsequent panel, so I set its background colour to the same red:

aside { background-color: #a73448; }

Whereas long passages of uppercase text are generally more difficult to read than those set in mixed case, uppercase is appropriate for shorter pieces and can create a stylish look:

p { margin: 0 2rem; text-align: center; text-transform: uppercase; } Structural elements stack vertically and I introduce larger images for medium-size screens. Structural elements stack vertically and I introduce larger images for medium-size screens. (Large preview)

In my small-screen design, the main and aside elements stack vertically and their heights match that of the viewport. For medium-size screens, I reset the minimum height of those elements to fill half the viewport:

@media (min-width: 48em) { main, aside { min-height: 50vh; padding: 2rem; }

The extra space available on medium-size screens allows me to style my paragraphs by changing the writing mode, so their text is displayed vertically and reads from right to left:

p { max-height: 12em; margin: 0; text-align: left; writing-mode: vertical-rl; }

Changing the display property on these span elements to block splits my paragraph onto multiple lines. Then, line-height adds space between the lines, which allows room for my rotations:

p span { display: block; line-height: 2; } Before implementing any design, I make a simple storyboard to demonstrate how my elements will flow across a selection of screen sizes. Before implementing any design, I make a simple storyboard to demonstrate how my elements will flow across a selection of screen sizes. (Large preview)

Transforms, including rotate, scale, and translate have been a part of CSS for almost two decades. Using transform involves adding a transform-function like rotate, then a value in parenthesis.

To achieve the effect I’m looking for; I rotate the first six lines of my text anti-clockwise by fifteen degrees. The last six lines are rotated by the same amount but in the clockwise direction. All remaining lines remain unaltered:

p span:nth-child(-n+6) { transform: rotate(-15deg); } p span:nth-child(n+12) { transform: rotate(15deg); }

In the future, you’ll be able to use functions like rotate independently of the transform property, but as I write this, only Firefox has implemented individual transforms.

To make room for my rotated text, I add margins to two of my lines:

p span:nth-child(6) { margin-left: 1em; } p span:nth-child(12) { margin-right: 1em; } }

This design becomes more striking with the space available on large screens. For them, I apply grid values to the body element to create two symmetrical, equal-height columns:

@media (min-width: 64em) { body { display: grid; grid-template-columns: 1fr 1fr; }

I apply a symmetrical three-column grid to both main and aside elements which both extend to the full viewport height:

main, aside { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-column-gap: 0; padding: 2rem; min-height: 100vh; }

I spread the main picture across second and third columns, and the aside picture into the first and second columns:

main picture { grid-column: 2 / -1; grid-row: 1; padding: 0 5vw; } aside picture { grid-column: 1 / 3; padding: 0 5vw; }

I place the paragraphs into the remaining columns, and by giving all elements the same row number, they will stay on the same line regardless of source order:

main p { grid-column: 1; grid-row: 1; } aside p { grid-column: 3; }

In this version of my design, the text should run from top to bottom instead of right to left, so I reset the writing-mode to horizontal, top-bottom and then align text to the right:

main p, aside p { max-height: none; writing-mode: horizontal-tb; } main span { text-align: right; } A playful but reassuring symmetry in this large screen design. A playful but reassuring symmetry in this large screen design. (Large preview)

Finally, I replace the rotation values and margins on my lines of text to better suit this large-screen design:

main p span:nth-child(-n+6) { transform: rotate(10deg); } main p span:nth-child(n+12) { transform: rotate(-10deg); } main p span:nth-child(6) { margin: 0 0 15px; } main p span:nth-child(12) { margin: 15px 0 0; } aside p span:nth-child(-n+6) { transform: rotate(-10deg); } aside p span:nth-child(n+12) { transform: rotate(10deg); } aside p span:nth-child(6) { margin: 0 0 15px; } aside p span:nth-child(12) { margin: 15px 0 0; } } Span columns

For many of his most memorable designs, Otto Storch allowed large images and typographic elements to spread across two pages. This technique created striking spreads, including this one where he placed a buttery corn cob on top of two columns of justified text.

A butter yellow Beetle sits on top of two columns of running text. A butter yellow Beetle sits on top of two columns of running text. (Large preview)

I want a similarly striking effect for my final Beetle-based design, and to implement it I only need three structural elements; a header — containing an SVG logo, headline, and a picture of my yellow Volkswagen — then main and aside elements:

<header> <svg>…</svg> <h1>Get bitten by the bug</h1> <figure> <picture>…</picture> </figure> </header> <main>…</main> <aside>…</aside>

Normal flow plus a few foundation styles are all I need to implement the small screen version of this design. First, I add a dark background and specify white text:

body { padding: 2rem; background-color: #262626; color: #fff; } Adding a horizontally scrolling panel is one of my favourite small-screen design techniques. Adding a horizontally scrolling panel is one of my favourite small-screen design techniques. (Large preview)

To place the headline in the centre of the page, I apply margins, set its maximum width using text-based units, then align its uppercase words to the centre:

h1 { margin: 0 auto 1.5rem; max-width: 8rem; text-align: center; text-transform: uppercase; }

Instead of resizing images, so they fit within a narrow viewport, I often allow them to spread beyond it and add a horizontally scrolling panel. This technique is one of my favourite small-screen design devices.

This figure contains an image which is wider than the viewport and contains the car’s complete profile, including its wheels. By adding overflow-x: scroll; to the figure, I make parts of the picture outside the viewport accessible:

figure { overflow-x: scroll; } A narrow column of text emphasises the vertical axis in this medium-size screen design. A narrow column of text emphasises the vertical axis in this medium-size screen design. (Large preview)

Although medium-size screens inherit many of those foundation styles, when more space becomes available, I want to emphasise the vertical axis in the design by creating a narrow column of text using wide viewport-based margins. I also reset the figure elements overflow to make all its content visible:

@media (min-width: 48em) { figure { overflow-x: visible; } p { margin-right: 25vw; margin-left: 25vw; } } A butter yellow Beetle sits on top of two columns of running text. A butter yellow Beetle sits on top of two columns of running text. (Large preview)

The largest version of my design is the most complex. It not only places a large picture of my Beetle on top of two columns of running text, but that text wraps around its wheels. I start by applying grid properties for larger screens to the body element to create a symmetrical two-column grid:

@media (min-width: 64em) { body { display: grid; grid-template-columns: 1fr 1fr; padding: 4rem; }

My header spans both columns, and then nested grid values arrange the VW logo, headline and image of my Beetle. In this nested grid, the two outer columns occupy all remaining available space, while the centre column automatically resizes to accommodate its content:

header { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr auto 1fr; grid-row-gap: 4vh; }

I place the logo and headline into this centre column:

svg, h1 { grid-column: 2; }

Then, add margins between the paragraphs:

p { margin-right: 1rem; margin-left: 1rem; }

The picture element for this design includes two images. The first is complete with wheels for small and medium screens, and the second is a car missing its wheels for large screens. To bolt wheels back onto this Beetle, I use :before pseudo-elements inside both main and aside elements. Then, I add a shape-margin to add space between them and the running text nearby:

main:before, aside:before { display: block; shape-margin: 10px; }

Using generated content, I add the rear wheel before the main element and float that wheel to the right. The shape-outside property then wraps text around this wheel:

main:before { content: url(shape-l.png); float: right; shape-outside: url(shape-l.png); }

I apply similar values to before the aside element, this time floating the wheel left:

aside:before { content: url(shape-r.png); float: left; shape-outside: url(shape-r.png); } }

The running text now wraps around the Beetle’s wheels, which makes my design more compelling without sacrificing readability or responsiveness.

Conclusion

Otto Storch created many memorable designs, but I’m sad that he and his work have largely been forgotten. There’s no Wikipedia page devoted to Storch, and no one has published a book about him or his work. Storch’s designs have plenty to offer designers who work on the web, and I hope more people will rediscover him.

His work also demonstrates how much more we can achieve online using Shapes. Despite now being well-supported, this CSS property has been overlooked almost as much as Storch himself. Shapes offer so much more than simple text wrapping, and their full potential has yet to be realised. I hope that will change, and soon.

More From The “Inspired Design Decisions” Series
  1. Inspired Design Decisions: Avaunt Magazine
  2. Inspired Design Decisions: Pressing Matters
  3. Inspired Design Decisions: Ernest Journal
  4. Inspired Design Decisions: Alexey Brodovitch
  5. Inspired Design Decisions: Bea Feitler
  6. Inspired Design Decisions: Neville Brody

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

Smashing Editorial (vf, ra, yk, il)
Catégories: Programmation

Creating Sortable Tables With React

ven, 03/20/2020 - 13:30
Creating Sortable Tables With React Creating Sortable Tables With React Kristofer Giltvedt Selbekk 2020-03-20T12:30:00+00:00 2020-03-20T13:36:31+00:00

Table sorting has always been a pretty hard issue to get right. There’s a lot of interactions to keep track of, extensive DOM mutations to do and even intricate sorting algorithms, too. It’s just one of those challenges that are hard to get right. Right?

Instead of pulling in external libraries, let’s try to make stuff ourselves. In this article, we’re going to create a reusable way to sort your tabular data in React. We’ll go through each step in detail, and learn a bunch of useful techniques along the way.

We won’t go through basic React or JavaScript syntax, but you don’t have to be an expert in React to follow along.

Creating A Table With React

First, let’s create a sample table component. It’ll accept an array of products, and output a very basic table, listing out a row per product.

function ProductTable(props) { const { products } = props; return ( <table> <caption>Our products</caption> <thead> <tr> <th>Name</th> <th>Price</th> <th>In Stock</th> </tr> </thead> <tbody> {products.map(product => ( <tr key={product.id}> <td>{product.name}</td> <td>{product.price}</td> <td>{product.stock}</td> </tr> ))} </tbody> </table> ); }

Here, we accept an array of products and loop them out into our table. It’s static and not sortable at the moment, but that’s fine for now.

Sorting The Data

If you’d believe all the whiteboard interviewers, you’d think software development was almost all sorting algorithms. Luckily, we won’t be looking into a quick sort or bubble sort here.

Sorting data in JavaScript is pretty straightforward, thanks to the built-in array function sort(). It’ll sort arrays of numbers and strings without an extra argument:

const array = ['mozzarella', 'gouda', 'cheddar']; array.sort(); console.log(array); // ['cheddar', 'gouda', 'mozzarella']

If you want something a bit more clever, you can pass it a sorting function. This function is given two items in the list as arguments, and will place one in front of the other based on what you decide.

Let’s start by sorting the data we get alphabetically by name.

function ProductTable(props) { const { products } = props; let sortedProducts = [...products]; sortedProducts.sort((a, b) => { if (a.name < b.name) { return -1; } if (a.name > b.name) { return 1; } return 0; }); return ( <Table> {/* as before */} </Table> ); }

So what’s going on here? First, we create a copy of the products prop, which we can alter and change as we please. We need to do this because the Array.prototype.sort function alters the original array instead of returning a new sorted copy.

Next, we call sortedProducts.sort, and pass it a sorting function. We check if the name property of the first argument a is before the second argument b, and if so, return a negative value. This indicates that a should come before b in the list. If the first argument’s name is after the second argument’s name, we return a positive number, indicating that we should place b before a. If the two are equal (i.e. both have the same name), we return 0 to preserve the order.

Making Our Table Sortable

So now we can make sure the table is sorted by name — but how can we change the sorting order ourselves?

To change what field we sort by, we need to remember the currently sorted field. We’ll do that with the useState hook.

A hook is a special kind of function that lets us “hook” into some of React’s core functionality, like managing state and triggering side effects. This particular hook lets us maintain a piece of internal state in our component, and change it if we want to. This is what we’ll add:

const [sortedField, setSortedField] = React.useState(null);

We start by not sorting anything at all. Next, let’s alter the table headings to include a way to change what field we want to sort by.

const ProductsTable = (props) => { const { products } = props; const [sortedField, setSortedField] = React.useState(null); return ( <table> <thead> <tr> <th> <button type="button" onClick={() => setSortedField('name')}> Name </button> </th> <th> <button type="button" onClick={() => setSortedField('price')}> Price </button> </th> <th> <button type="button" onClick={() => setSortedField('stock')}> In Stock </button> </th> </tr> </thead> {/* As before */} </table> ); };

Now, whenever we click a table heading, we update the field we want to sort by. Neat-o!

We’re not doing any actual sorting yet though, so let’s fix that. Remember the sorting algorithm from before? Here it is, just slightly altered to work with any of our field names.

const ProductsTable = (props) => { const { products } = props; const [sortedField, setSortedField] = React.useState(null); let sortedProducts = [...products]; if (sortedField !== null) { sortedProducts.sort((a, b) => { if (a[sortedField] < b[sortedField]) { return -1; } if (a[sortedField] > b[sortedField]) { return 1; } return 0; }); } return ( <table>

We first make sure we’ve chosen a field to sort by, and if so, we sort the products by that field.

Ascending vs Descending

The next feature we want to see is a way to switch between ascending and descending order. We’ll switch between ascending and descending order by clicking the table heading one more time.

To implement this, we’ll need to introduce a second piece of state — the sort order. We’ll refactor our current sortedField state variable to keep both the field name and its direction. Instead of containing a string, this state variable will contain an object with a key (the field name) and a direction. We’ll rename it to sortConfig to be a bit clearer.

Here’s the new sorting function:

sortedProducts.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; });

Now, if the direction is ‘ascending’, we’ll do as we did previously. If it’s not, we’ll do the opposite, giving us descending ordering.

Next up, we’ll create a new function — requestSort — which will accept the field name, and update the state accordingly.

const requestSort = key => { let direction = 'ascending'; if (sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); }

We’ll also have to change our click handlers to use this new function!

return ( <table> <thead> <tr> <th> <button type="button" onClick={() => requestSort('name')}> Name </button> </th> <th> <button type="button" onClick={() => requestSort('price')}> Price </button> </th> <th> <button type="button" onClick={() => requestSort('stock')}> In Stock </button> </th> </tr> </thead> {/* as before */} </table> );

Now we’re starting to look pretty feature-complete, but there’s still one big thing left to do. We need to make sure that we only sort our data when we need to. Currently, we’re sorting all of our data on every render, which will lead to all sorts of performance issues down the line. Instead, let’s use the built-in useMemo hook to memoize all the slow parts!

const ProductsTable = (props) => { const { products } = props; const [sortConfig, setSortConfig] = React.useState(null); React.useMemo(() => { let sortedProducts = [...products]; if (sortedField !== null) { sortedProducts.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; }); } return sortedProducts; }, [products, sortConfig]);

If you haven’t seen it before, useMemo is a way to cache — or memoize — expensive computations. So given the same input, it doesn’t have to sort the products twice if we re-render our component for some reason. Note that we want to trigger a new sort whenever our products change, or the field or direction we sort by changes.

Wrapping our code in this function will have huge performance implications for our table sorting!

Making It All Reusable

One of the best things about hooks is how easy it is to make logic reusable. You’ll probably be sorting all types of tables throughout your application, and having to reimplement the same stuff all over again sounds like a drag.

React has this feature called custom hooks. They sound fancy, but all they are are regular functions that use other hooks inside of them. Let’s refactor our code to be contained in a custom hook, so we can use it all over the place!

const useSortableData = (items, config = null) => { const [sortConfig, setSortConfig] = React.useState(config); const sortedItems = React.useMemo(() => { let sortableItems = [...items]; if (sortConfig !== null) { sortableItems.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; }); } return sortableItems; }, [items, sortConfig]); const requestSort = key => { let direction = 'ascending'; if (sortConfig && sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); } return { items, requestSort }; }

This is pretty much copy and paste from our previous code, with a bit of renaming thrown in. useSortableData accepts the items, and an optional initial sort state. It returns an object with the sorted items, and a function to re-sort the items.

Our table code now looks like this:

const ProductsTable = (props) => { const { products } = props; const { items, requestSort } = useSortableData(products); return ( <table>{/* ... */}</table> ); }; A Last Touch

There’s one tiny piece missing — a way to indicate how the table is sorted. In order to indicate that in our design, we need to return the internal state as well — the sortConfig. Let’s return that as well, and use it to generate styles we can apply to our table headings!

const ProductTable = (props) => { const { items, requestSort, sortConfig } = useSortableData(props.products); const getClassNamesFor = (name) => { if (!sortConfig) { return; } return sortConfig.key === name ? sortConfig.direction : undefined; }; return ( <table> <caption>Products</caption> <thead> <tr> <th> <button type="button" onClick={() => requestSort('name')} className={getClassNamesFor('name')} > Name </button> </th> {/* … */} </tr> </thead> {/* … */} </table> ); };

And with that, we’re done!

Wrapping Up

As it turns out, creating your own table sorting algorithm wasn’t an impossible feat after all. We found a way to model our state, we wrote a generic sorting function, and we wrote a way to update what our sorting preferences are. We made sure everything was performant and refactored it all into a custom hook. Finally, we provided a way to indicate the sort order to the user.

You can see a demo of the table in this CodeSandbox:

Smashing Editorial (ra, yk, il)
Catégories: Programmation

A Practical Overview Of CSS Houdini

jeu, 03/19/2020 - 13:30
A Practical Overview Of CSS Houdini A Practical Overview Of CSS Houdini Adrian Bece 2020-03-19T12:30:00+00:00 2020-03-19T14:23:21+00:00

It takes a long time for a new CSS feature or improvement to progress from an initial draft to a fully-supported and stable CSS feature that developers can use. JavaScript-based polyfills can be used as a substitute for the lack of browser support in order to use new CSS features before they’re officially implemented. But they are flawed in most cases. For example, scrollsnap-polyfill is one of several polyfills that can be used to fix browser support inconsistencies for the CSS Scroll Snap specification. But even that solution has some limitations, bugs and inconsistencies.

The potential downside to using polyfills is that they can have a negative impact on performance and are difficult to implement properly. This downside is related to the browser’s DOM and CSSOM. Browser creates a DOM (Document Object Model) from HTML markup and, similarly, it created CSSOM (CSS Object Model) from CSS markup. These two object trees are independent of one another. JavaScript works on DOM and has very limited access to CSSOM.

JavaScript Polyfill solutions run only after the initial render cycle has been completed, i.e. when both DOM and CSSOM have been created and the document has finished loading. After Polyfill makes changes to styles in the DOM (by inlining them), it causes the render process to run again and the whole page re-renders. Negative performance impact gets even more apparent if they rely on the requestAnimationFrame method or depend on user interactions like scroll events.

Another obstacle in web development is various constraints imposed by the CSS standards. For example, there are only a limited number of CSS properties that can be natively animated. CSS knows how to natively animate colors, but doesn’t know how to animate gradients. There has always been a need to innovate and create impressive web experiences by pushing the boundaries despite the tech limitations. That is why developers often tend to gravitate towards using less-than-ideal workarounds or JavaScript to implement more advanced styling and effects that are currently not supported by CSS such as masonry layout, advanced 3D effects, advanced animation, fluid typography, animated gradients, styled select elements, etc.

It seems impossible for CSS specifications to keep up with the various feature demands from the industry such as more control over animations, improved text truncation, better styling option for input and select elements, more display options, more filter options, etc.

What could be the potential solution? Give developers a native way of extending CSS using various APIs. In this article, we are going to take a look at how frontend developers can do that using Houdini APIs, JavaScript, and CSS. In each section, we’re going to examine each API individually, check its browser support and current specification status, and see how they can be implemented today using Progressive enhancement.

What Is Houdini?

Houdini, an umbrella term for the collection of browser APIs, aims to bring significant improvements to the web development process and the development of CSS standards in general. Developers will be able to extend the CSS with new features using JavaScript, hook into CSS rendering engine and tell the browser how to apply CSS during a render process. This will result in significantly better performance and stability than using regular polyfills.

Houdini specification consists of two API groups - high-level APIs and low-level APIs.

High-level APIs are closely related to the browser’s rendering process (style → layout → paint → composite). This includes:

  • Paint API
    An extension point for the browser’s paint rendering step where visual properties (color, background, border, etc.) are determined.
  • Layout API
    An extension point for the browser’s layout rendering step where element dimensions, position, and alignment are determined.
  • Animation API
    An extension point for browser’s composite rendering step where layers are drawn to the screen and animated.

Low-Level APIs form a foundation for high-level APIs. This includes:

  • Typed Object Model API
  • Custom Properties & Values API
  • Font Metrics API
  • Worklets

Some Houdini APIs are already available for use in some browsers with other APIs to follow suit when they’re ready for release.

The Future Of CSS

Unlike regular CSS feature specifications that have been introduced thus far, Houdini stands out by allowing developers to extend the CSS in a more native way. Does this mean that CSS specifications will stop evolving and no new official implementations of CSS features will be released? Well, that is not the case. Houdini’s goal is to aid the CSS feature development process by allowing developers to create working prototypes that can be easily standardized.

Additionally, developers will be able to share the open-source CSS Worklets more easily and with less need for browser-specific bugfixes.

Typed Object Model API

Before Houdini was introduced, the only way for JavaScript to interact with CSS was by parsing CSS represented as string values and modifying them. Parsing and overriding styles manually can be difficult and error-prone due to the value type needing to be changed back and forth and value unit needing to be manually appended when assigning a new value.

selectedElement.style.fontSize = newFontSize + "px"; // newFontSize = 20 console.log(selectedElement.style.fontSize); // "20px"

Typed Object Model (Typed OM) API adds more semantic meaning to CSS values by exposing them as typed JavaScript objects. It significantly improves the related code and makes it more performant, stable and maintainable. CSS values are represented by the CSSUnitValue interface which consists of a value and a unit property.

{ value: 20, unit: "px" }

This new interface can be used with the following new properties:

  • computedStyleMap(): for parsing computed (non-inline) styles. This is a method of selected element that needs to be invoked before parsing or using other methods.
  • attributeStyleMap: for parsing and modifying inline styles. This is a property that is available on a selected element.
// Get computed styles from stylesheet (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Set inline styles selectedElement.attributeStyleMap.set("font-size", CSS.em(2)); // Sets inline style selectedElement.attributeStyleMap.set("color", "blue"); // Sets inline style // Computed style remains the same (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Get new inline style selectedElement.attributeStyleMap.get("font-size"); // { value: 2, unit: "em"}

Notice how specific CSS types are being used when setting a new numeric value. By using this syntax, many potential type-related issues can be avoided and the resulting code is more reliable and bug-free.

The get and set methods are only a small subset of all available methods defined by the Typed OM API. Some of them include:

  • clear: removes all inline styles
  • delete: removes a specified CSS property and its value from inline styles
  • has: returns a boolean if a specified CSS property is set
  • append: adds an additional value to a property that supports multiple values
  • etc.
Feature detection var selectedElement = document.getElementById("example"); if(selectedElement.attributeStyleMap) { /* ... */ } if(selectedElement.computedStyleMap) { /* ... */ } W3C Specification Status Browser Support Google Chrome Microsoft Edge Opera Browser Firefox Safari Supported Supported Supported Not supported Partial support (*)

* supported with “Experimental Web Platform features” or other feature flag enabled.

Data source: Is Houdini Ready Yet?

Custom Properties And Values API

The CSS Properties And Values API allows developers to extend CSS variables by adding a type, initial value and define inheritance. Developers can define CSS custom properties by registering them using the registerProperty method which tells the browsers how to transition it and handle fallback in case of an error.

CSS.registerProperty({ name: "--colorPrimary", syntax: "<color>", inherits: false, initialValue: "blue", });

This method accepts an input argument that is an object with the following properties:

  • name: the name of the custom property
  • syntax: tells the browser how to parse a custom property. These are pre-defined values like <color>, <integer>, <number>, <length>, <percentage>, etc.
  • inherits: tells the browser whether the custom property inherits its parent’s value.
  • initialValue: tells the initial value that is used until it’s overridden and this is used as a fallback in case of an error.

In the following example, the <color> type custom property is being set. This custom property is going to be used in gradient transition. You might be thinking that current CSS doesn’t support transitions for background gradients and you would be correct. Notice how the custom property itself is being used in transition, instead of a background property that would be used for regular background-color transitions.

.gradientBox { background: linear-gradient(45deg, rgba(255,255,255,1) 0%, var(--colorPrimary) 60%); transition: --colorPrimary 0.5s ease; /* ... */ } .gradientBox:hover { --colorPrimary: red /* ... */ }

Browser doesn’t know how to handle gradient transition, but it knows how to handle color transitions because the custom property is specified as <color> type. On a browser that supports Houdini, a gradient transition will happen when the element is being hovered on. Gradient position percentage can also be replaced with CSS custom property (registered as <percentage> type) and added to a transition in the same way as in the example.

If registerProperty is removed and a regular CSS custom property is registered in a :root selector, the gradient transition won’t work. It’s required that registerProperty is used so the browser knows that it should treat it as color.

In the future implementation of this API, it would be possible to register a custom property directly in CSS.

@property --colorPrimary { syntax: "<color>"; inherits: false; initial-value: blue; } Example

This simple example showcases gradient color and position transition on hover event using registered CSS custom properties for color and position respectively. Complete source code is available on the example repository.

Animated gradient color and position using Custom Properties & Values API. Delay for each property added for effect in CSS transition property. (Large preview) Feature Detection if (CSS.registerProperty) { /* ... */ } W3C Specification Status Browser Support Google Chrome Microsoft Edge Opera Browser Firefox Safari Supported Supported Supported Not supported Not supported

Data source: Is Houdini Ready Yet?

Font Metrics API

The Font Metrics API is still in a very early stage of development, so its specification may change in the future. In its current draft, Font Metrics API will provide methods for measuring dimensions of text elements that are being rendered on screen in order to allow developers to affect how text elements are being rendered on screen. These values are either difficult or impossible to measure with current features, so this API will allow developers to create text and font-related CSS features more easily. Multi-line dynamic text truncation is an example of one of those features.

W3C Specification Status Browser Support Google Chrome Microsoft Edge Opera Browser Firefox Safari Not supported Not supported Not supported Not supported Not supported

Data source: Is Houdini Ready Yet?

Worklets

Before moving onto the other APIs, it’s important to explain the Worklets concept. Worklets are scripts that run during render and are independent of the main JavaScript environment. They are an extension point for rendering engines. They are designed for parallelism (with 2 or more instances) and thread-agnostic, have reduced access to the global scope and are called by the rendering engine when needed. Worklets can be run only on HTTPS (on production environment) or on localhost (for development purposes).

Houdini introduces following Worklets to extend the browser render engine:

  • Paint Worklet - Paint API
  • Animation Worklet - Animation API
  • Layout Worklet - Layout API
Paint API

The Paint API allows developers to use JavaScript functions to draw directly into an element’s background, border, or content using 2D Rendering Context, which is a subset of the HTML5 Canvas API. Paint API uses Paint Worklet to draw an image that dynamically responds to changes in CSS (changes in CSS variables, for example). Anyone familiar with Canvas API will feel right at home with Houdini’s Paint API.

There are several steps required in defining a Paint Worklet:

  1. Write and register a Paint Worklet using the registerPaint function
  2. Call the Worklet in HTML file or main JavaScript file using CSS.paintWorklet.addModule function
  3. Use the paint() function in CSS with a Worklet name and optional input arguments.

Let’s take a look at the registerPaint function which is used to register a Paint Worklet and define its functionality.

registerPaint("paintWorketExample", class { static get inputProperties() { return ["--myVariable"]; } static get inputArguments() { return ["<color>"]; } static get contextOptions() { return {alpha: true}; } paint(ctx, size, properties, args) { /* ... */ } });

The registerPaint function consists of several parts:

  • inputProperties:
    An array of CSS custom properties that the Worklet will keep track of. This array represents dependencies of a paint worklet.
  • inputArguments:
    An array of input arguments that can be passed from paint function from inside the CSS.
  • contextOptions: allow or disallow opacity for colors. If set to false, all colors will be displayed with full opacity.
  • paint: the main function that provides the following arguments:
    • ctx: 2D drawing context, almost identical to Canvas API’s 2D drawing context.
    • size: an object containing the width and height of the element. Values are determined by the layout rendering process. Canvas size is the same as the actual size of the element.
    • properties: input variables defined in inputProperties
    • args: an array of input arguments passed in paint function in CSS

After the Worklet has been registered, it needs to be invoked in the HTML file by simply providing a path to the file.

CSS.paintWorklet.addModule("path/to/worklet/file.js");

Any Worklet can also be added from an external URL (from a Content Delivery Network, for example) which makes them modular and reusable.

CSS.paintWorklet.addModule("https://url/to/worklet/file.js");

After the Worklet has been called, it can be used inside CSS using the paint function. This function accepts the Worklet’s registered name as a first input argument and each input argument that follows it is a custom argument that can be passed to a Worklet (defined inside Worklet’s inputArguments ). From that point, the browser determines when to call the Worklet and which user actions and CSS custom properties value change to respond to.

.exampleElement { /* paintWorkletExample - name of the worklet blue - argument passed to a Worklet */ background-image: paint(paintWorketExample, blue); } Example

The following example showcases Paint API and general Worklet reusability and modularity. It’s using the ripple Worklet directly from Google Chrome Labs repository and runs on a different element with different styles. Complete source code is available on the example repository.

Ripple effect example (uses Ripple Worklet by Google Chrome Labs) (Large preview) Feature detection if ("paintWorklet" in CSS) { /* ... */ } @supports(background:paint(paintWorketExample)){ /* ... */ } W3C Specification Status Browser Support Google Chrome Microsoft Edge Opera Browser Firefox Safari Supported Supported Supported Not supported Not supported

Data source: Is Houdini Ready Yet?

Animation API

The Animation API extends web animations with options to listen to various events (scroll, hover, click, etc.) and improves performance by running animations on their own dedicated thread using an Animation Worklet. It allows for user action to control the flow of animation that runs in a performant, non-blocking way.

Like any Worklet, Animation Worklet needs to be registered first.

registerAnimator("animationWorkletExample", class { constructor(options) { /* ... */ } animate(currentTime, effect) { /* ... */ } });

This class consists of two functions:

  • constructor: called when a new instance is created. Used for general setup.
  • animate: the main function that contains the animation logic. Provides the following input arguments:
    • currentTime: the current time value from the defined timeline
    • effect: an array of effects that this animation uses

After the Animation Worklet has been registered, it needs to be included in the main JavaScript file, animation (element, keyframes, options) needs to be defined and animation is instantiated with the selected timeline. Timeline concepts and web animation basics will be explained in the next section.

/* Include Animation Worklet */ await CSS.animationWorklet.addModule("path/to/worklet/file.js");; /* Select element that's going to be animated */ const elementExample = document.getElementById("elementExample"); /* Define animation (effect) */ const effectExample = new KeyframeEffect( elementExample, /* Selected element that's going to be animated */ [ /* ... */ ], /* Animation keyframes */ { /* ... */ }, /* Animation options - duration, delay, iterations, etc. */ ); /* Create new WorkletAnimation instance and run it */ new WorkletAnimation( "animationWorkletExample" /* Worklet name */ effectExample, /* Animation (effect) timeline */ document.timeline, /* Input timeline */ {}, /* Options passed to constructor */ ).play(); /* Play animation */ Timeline Mapping

Web animation is based on timelines and mapping of the current time to a timeline of an effect’s local time. For example, let’s take a look at a repeating linear animation with 3 keyframes (start, middle, last) that runs 1 second after a page is loaded (delay) and with a 4-second duration.

Effect timeline from the example would look like this (with the 4-second duration with no delay):

Effect timeline (4s duration) Keyframe 0ms First keyframe - animation starts 2000ms Middle keyframe - animation in progress 4000ms Last keyframe - animation ends or resets to first keyframe

In order to better understand effect.localTime, by setting its value to 3000ms (taking into account 1000ms delay), resulting animation is going to be locked to a middle keyframe in effect timeline (1000ms delay + 2000ms for a middle keyframe). The same effect is going to happen by setting the value to 7000ms and 11000ms because the animation repeats in 4000ms interval (animation duration).

animate(currentTime, effect) { effect.localTime = 3000; // 1000ms delay + 2000ms middle keyframe }

No animation happens when having a constant effect.localTime value because animation is locked in a specific keyframe. In order to properly animate an element, its effect.localTime needs to be dynamic. It’s required for the value to be a function that depends on the currentTime input argument or some other variable.

The following code shows a functional representation of 1:1 (linear function) mapping of a timeline to effect local time.

animate(currentTime, effect) { effect.localTime = currentTime; // y = x linear function } Timeline (document.timeline) Mapped effect local time Keyframe startTime + 0ms (elapsed time) startTime + 0ms First startTime + 1000ms (elapsed time) startTime + 1000ms (delay) + 0ms First startTime + 3000ms (elapsed time) startTime + 1000ms (delay) + 2000ms Middle startTime + 5000ms (elapsed time) startTime + 1000ms (delay) + 4000ms Last / First startTime + 7000ms (elapsed time) startTime + 1000ms (delay) + 6000ms Middle startTime + 9000ms (elapsed time) startTime + 1000ms (delay) + 8000ms Last / First

Timeline isn’t restricted to 1:1 mapping to effect’s local time. Animation API allows developers to manipulate the timeline mapping in animate function by using standard JavaScript functions to create complex timelines. Animation also doesn’t have to behave the same in each iteration (if animation is repeated).

Animation doesn’t have to depend on the document’s timeline which only starts counting milliseconds from the moment it’s loaded. User actions like scroll events can be used as a timeline for animation by using a ScrollTimeline object. For example, an animation can start when a user has scrolled to 200 pixels and can end when a user has scrolled to 800 pixels on a screen.

const scrollTimelineExample = new ScrollTimeline({ scrollSource: scrollElement, /* DOM element whose scrolling action is being tracked */ orientation: "vertical", /* Scroll direction */ startScrollOffset: "200px", /* Beginning of the scroll timeline */ endScrollOffset: "800px", /* Ending of the scroll timeline */ timeRange: 1200, /* Time duration to be mapped to scroll values*/ fill: "forwards" /* Animation fill mode */ }); ...

The animation will automatically adapt to user scroll speed and remain smooth and responsive. Since Animation Worklets are running off the main thread and are connected to a browser’s rending engine, animation that depends on user scroll can run smoothly and be very performant.

Example

The following example showcases how a non-linear timeline implementation. It uses modified Gaussian function and applies translation and rotation animation with the same timeline. Complete source code is available on the example repository.

Animation created with Animation API which is using modified Gaussian function time mapping (Large preview) Feature Detection if (CSS.animationWorklet) { /* ... */ } W3C Specification Status Browser Support Google Chrome Microsoft Edge Opera Browser Firefox Safari Partial support (*) Partial support (*) Partial support (*) Not supported Not supported

* supported with “Experimental Web Platform features” flag enabled.

Data source: Is Houdini Ready Yet?

Layout API

The Layout API allows developers to extend the browser’s layout rendering process by defining new layout modes that can be used in display CSS property. Layout API introduces new concepts, is very complex and offers a lot of options for developing custom layout algorithms.

Similarly to other Worklets, the layout Worklet needs to be registered and defined first.

registerLayout('exampleLayout', class { static get inputProperties() { return ['--exampleVariable']; } static get childrenInputProperties() { return ['--exampleChildVariable']; } static get layoutOptions() { return { childDisplay: 'normal', sizing: 'block-like' }; } intrinsicSizes(children, edges, styleMap) { /* ... */ } layout(children, edges, constraints, styleMap, breakToken) { /* ... */ } });

Worklet register contains the following methods:

  • inputProperties:
    An array of CSS custom properties that the Worklet will keep track of that belongs to a Parent Layout element, i.e. the element that calls this layout. This array represents dependencies of a Layout Worklet.
  • childrenInputProperties:
    An array of CSS custom properties that the Worklet will keep track of that belong to child elements of a Parent Layout element, i.e. the children of the elements that set this layout.
  • layoutOptions: defines the following layout properties:
    • childDisplay: can have a pre-defined value of block or normal. Determines if the boxes will be displayed as blocks or inline.
    • sizing: can have a pre-defined value of block-like or manual. It tells the browser to either pre-calculate the size or not to pre-calculate (unless a size is explicitly set), respectively.
  • intrinsicSizes: defines how a box or its content fits into a layout context.
    • children: child elements of a Parent Layout element, i.e. the children of the element that call this layout.
    • edges: Layout Edges of a box
    • styleMap: typed OM styles of a box
  • layout: the main function that performs a layout.
    • children: child elements of a Parent Layout element, i.e. the children of the element that call this layout.
    • edges: Layout Edges of a box
    • constraints: constraints of a Parent Layout
    • styleMap: typed OM styles of a box
    • breakToken: break token used to resume a layout in case of pagination or printing.

Like in the case of a Paint API, the browser rendering engine determines when the paint Worklet is being called. It only needs to be added to an HTML or main JavaScript file.

CSS.layoutWorklet.addModule('path/to/worklet/file.js');

And, finally, it needs to be referenced in a CSS file

.exampleElement { display: layout(exampleLayout); } How Layout API Performs Layout

In the previous example, exampleLayout has been defined using the Layout API.

.exampleElement { display: layout(exampleLayout); }

This element is called a Parent Layout that is enclosed with Layout Edges which consists of paddings, borders and scroll bars. Parent Layout consists of child elements which are called Current Layouts. Current Layouts are the actual target elements whose layout can be customized using the Layout API. For example, when using display: flex; on an element, its children are being repositioned to form the flex layout. This is similar to what is being done with the Layout API.

Each Current Layout consists of Child Layout which is a layout algorithm for the LayoutChild (element, ::before and ::after pseudo-elements) and LayoutChild is a CSS generated box that only contains style data (no layout data). LayoutChild elements are automatically created by browser rendering engine on style step. Layout Child can generate a Fragment which actually performs layout render actions.

Example

Similarly to the Paint API example, this example is importing a masonry layout Worklet directly from Google Chrome Labs repository, but in this example, it’s used with image content instead of text. Complete source code is available on the example repository.

Masonry layout example (uses Masonry Worklet by Google Chrome Labs (Large preview) Feature Detection if (CSS.layoutWorklet) { /* ... */ } W3C Specification Status Browser Support Google Chrome Microsoft Edge Opera Browser Firefox Safari Partial support (*) Partial support (*) Partial support (*) Not supported Not supported

* supported with “Experimental Web Platform features” flag enabled.

Data source: Is Houdini Ready Yet?

Houdini And Progressive Enhancement

Even though CSS Houdini doesn’t have optimal browser support yet, it can be used today with progressive enhancement in mind. If you are unfamiliar with Progressive enhancement, it would be worth to check out this handy article which explains it really well. If you decide on implementing Houdini in your project today, there are few things to keep in mind:

  • Use feature detection to prevent errors.
    Each Houdini API and Worklet offers a simple way of checking if it’s available in the browser. Use feature detection to apply Houdini enhancements only to browsers that support it and avoid errors.
  • Use it for presentation and visual enhancement only.
    Users that are browsing a website on a browser that doesn’t yet support Houdini should have access to the content and core functionality of the website. User experience and the content presentation shouldn’t depend on Houdini features and should have a reliable fallback.
  • Make use of a standard CSS fallback.
    For example, regular CSS Custom Properties can be used as a fallback for styles defined using Custom Properties & Values API.

Focus on developing a performant and reliable website user experience first and then use Houdini features for decorative purposes as a progressive enhancement.

Conclusion

Houdini APIs will finally enable developers to keep the JavaScript code used for style manipulation and decoration closer to the browser’s rendering pipeline, resulting in better performance and stability. By allowing developers to hook into the browser rendering process, they will be able to develop various CSS polyfills that can be easily shared, implemented and, potentially, added to CSS specification itself. Houdini will also make developers and designers less constrained by the CSS limitations when working on styling, layouts, and animations, resulting in new delightful web experiences.

CSS Houdini features can be added to projects today, but strictly with progressive enhancement in mind. This will enable browsers that do not support Houdini features to render the website without errors and offer optimal user experience.

It’s going to be exciting to watch what the developer community will come up with as Houdini gains traction and better browser support. Here are some awesome examples of Houdini API experiments from the community:

References Smashing Editorial (ra, il)
Catégories: Programmation

How Should Designers Learn To Code? The Terminal And Text Editors (Part 1)

mer, 03/18/2020 - 13:30
How Should Designers Learn To Code? The Terminal And Text Editors (Part 1) How Should Designers Learn To Code? The Terminal And Text Editors (Part 1) Paul Hanaoka 2020-03-18T12:30:00+00:00 2020-03-18T13:38:38+00:00

As a designer with many years of experience, I often encourage my colleagues and reports to pick up some coding skills. While many are open to the idea, others balk at the notion. I usually hear some variation of “I didn’t study design to become a developer.” Although this is a valid concern, I’d like to emphasize two points: a better understanding of the materials usually leads to better outcomes, and there is an important distinction between “coding” and “software engineering.”

This two-part series of articles should be useful for any designers out there who’d like to gain also some coding skills.

Understanding The Raw Materials

Contrary to what some may think, design isn’t about creating beautiful mockups, it’s about delivering an intuitive, functional experience to the end user. That simply can’t be done without an understanding of the building blocks of a solution. An architect isn’t going to be very good at her job if she doesn’t understand the materials her plans demand and a designer isn’t going to be very good if he doesn’t understand the materials that make his designs come to life — the code. Experience with coding helps designers understand what’s possible and what’s not and whether or not their designs will be able to effectively perform their desired functions.

I also reassure my colleagues that knowledge of coding doesn’t mean one has to become an engineer. The two refer to different, though related, skill sets. As Kyle Thayer, a PhD candidate at the University of Washington recently wrote, the field of computer science (or engineering) is about giving students “an overview of the scientific field of computing”:

“The purpose of a Computer Science degree is to give students an overview of the scientific field of computing. While this includes some programming, programming is done primarily for the purpose of learning about other areas (e.g., operating systems, algorithms, machine learning, human-computer interaction). A CS degree is a good first step into the academic field of computer science.”

Kyle Thayer

By contrast, coding simply means becoming familiar enough with a given programming language to complete a task. Asking someone to learn basic HTML or JavaScript does not necessitate their becoming a full-stack software architect. Despite what some might think, forking a repo and copy/pasting Stack Overflow answers in does not make you a software engineer — but it can increase the value you bring as a designer to a product development team.

What About “Low Code”?

Some may say that we’re entering a low code future where designers (and developers) are able to build applications through drag-and-drop functionality and a GUI (graphical user interface). So taking the time to learn a programming language isn’t “worth it.” The emergence of tools like Webflow, Modulz, FramerX, UXPin, etc., seems to support this line of reasoning. And this can be very true for many applications — it’s easier than ever to create a site or app without a single line of code. However, if you don’t understand the underlying principles, you will be capping the value you can deliver with a low code application.

Logos and screenshots showing the code behind tools developed by companies like Modulz, Studio.Design, FramerX, and others. Modulz, Studio.Design, FramerX, and other apps — there’s still a lot of code in there... (Large preview)

We’re also not yet at the point where you can build enterprise-scale applications with low code platforms. As designers we have to work in the world we live in, not the one we imagine is coming.

That being said, everyone brings a unique blend of skills to the table. Knowledge of code is not an absolute necessity and it should just be encouraged, not required.

Where To Start?

There is an endless amount of tools, languages, schools, guides, and other resources available for anyone who has access to the internet — so where to begin? An important disclaimer — I am by no means an expert, or anything close to a software engineer — and the following are insights from my personal experience, not a guaranteed path to success.

Many of the designers/developers I know have usually started hacking HTML and CSS templates on sites like MySpace, Geocities, Tumblr, Neopets, or others. Now that I have sufficiently dated myself, for anyone starting out today, I would recommend beginning in your friendly command-line interface (CLI) shell.

The Terminal: An Essential Tool

The go-to application for Hollywood directors whenever there’s a computer hacker on the screen, the terminal is simply an interface that allows you to execute actions via a text input rather than the graphical user interface (GUI) that most people are accustomed to. I’ll let real developers explain the intricacies and technical how-to, but for our purposes it’s good enough to know that familiarizing yourself with the CLI is beneficial for a number of reasons.

The terminal gives you access to your computer’s file and folder structure — the same way that you click through Finder or Explorer, you navigate using your keyboard in the terminal. It definitely takes some time getting used to, but developing your mental model in this area is foundational to working in code.

Like a lot of designers, I am using the macOS environment (formerly known as OS X), but the following applies to other *nix operating systems (Linux, Unix), and also to Windows PowerShell. While there is a lot of overlap between different modern operating systems, there are some differences that I will do my best to highlight.

Note: For a more complete introduction to the terminal, I recommend reading Paul Tero’s article, “Introduction To Linux Commands”.

Regular Expressions

A key feature in a CLI is the ability to use regular expressions (regex) in your commands. Think of regex as boolean search operations (using quotation marks to search for exact phrases or the minus sign to exclude words) on steroids — they allow you to define a pattern in a string of text so that you can perform some action on the output. Here are some real-world examples:

  1. If you have a long list of phone numbers in a variety of formats, you could define a script that would give you a consistent output based on a regular expression — e.g.: (###) ###-#### for the U.S. phone numbers format.
  2. If you want to quickly rename a group of files to a specific case — from kebab-case to CamelCase or anything in between.

I highly recommend watching Wes Bos’ Command Line Power User series — or at the very least his intro video which will give you a good idea about a few essentials commands that you can use.

Here are some basic terminal commands* to help you getting started:

  1. cd stands for “Change Directory”, type this and then a file or a folder path to go — note that you can type a folder name but it needs to be inside your current folder to go to it.
  2. ls lists the files and folders in your current folder.
  3. pwd stands for “Print Working Directory” — this will list out where you currently are in your computer.
  4. mkdir and a folder name will create a folder in your working directory.
  5. using cd with .. takes you one level up — if you’re in /users/username/documents/2019 and you enter cd ../.. you’ll end up in /users/username.
  6. Bonus tip — hitting the Tab key will autocomplete as you type a folder/file path.

Note: The following will work on the Windows command line (cmd):

  • cd, cd .., mkdir, Tab key for path autocomplete (ls and pwd won’t work).

The more modern Windows command line (Windows PowerShell) supports all of them:
  • cd, cd .., ls, pwd, mkdir, and Tab for path autocomplete.

For a complete list of commands available in PowerShell, check this Microsoft’ Help page “Using Familiar Command Names”.

Mass-File Management

You can manipulate files and folders en masse via the terminal — here are a few ideas:

  1. You can create three years of folders with subfolders for each month in a single command — using mkdir -p and {list-of-years}/{list-of-months} will create folders for each year with subfolders for each month. Use your imagination, I’m sure you can put this to good use!
  2. You can quickly clean up your desktop by using mv Screen\ Shot* Screenshots — this will move all of your files that start with “Screen Shot” to a folder named “Screenshots”.
A screenshot of a terminal window showing the commands and output of a folder creation script. Create 36 folders on your computer with a single line of code! (Large preview)

Note: These two examples will most likely only work in *nix environments — but the theory still applies. And Windows PowerShell is also a very powerful command line tool, you just need to learn its features and specific commands.

Scripting And Maintenance

Now that we have a glimpse into the power of regular expressions and the options available in the terminal we can start combining those things into scripts. One very simple, yet powerful and commonly used script is Mike G’s file renamer:

criteria=$1 re_match=$2 replace=$3 for i in $( ls *$criteria* ); do src=$i tgt=$(echo $i | sed -e "s/$re_match/$replace/") mv $src $tgt done

What this script allows you to do, is define the scope (criteria), define what you’d like to change (re_match), and what you’d like to change it to (replace) — and then execute it.

There are countless other scripts that you can create beyond creating and renaming files — Vlad’s Batch Resizing script is an excellent example of the time-saving capabilities that you can create using bash scripts.

Advanced Tips And Tricks

Something I have found over the years is that regularly resetting my computer and reinstalling the operating system helps it stay relatively clutter-free and prevents the slowdowns everyone experiences after years of digital detritus that accumulates on harddrives. For many, the prospect of wiping a computer and re-setting everything back at best sounds like a few days of work, and at worst an impossible nightmare that you may never recover from.

But it doesn’t have to be — by using a few command-line tools, once you’ve backed up, wiped, and reinstalled your OS, you can install not only your list of favorite apps, but also fonts in a matter of minutes using Homebrew. (Homebrew is for Mac and Linux only. For Windows, try Chocolatey which is a solid alternative.)

If you’re interested — we’ve created an easy-to-follow setup guide to get your computer in good shape for most development. Our guide is for macOS, but Owen Williams has written a solid guide for Windows as well.

If you don’t have the time for Wes’ entire series of tutorials about the command line — at the very least I highly recommend the following stack:

  1. Oh My ZSH
  2. zsh-autosuggestions
  3. zsh-syntax-highlighting
  4. z-jump-around
Choosing A Text Editor

There are many options when it comes to choosing a code editor — Sublime Text and VS Code (Visual Studio Code) are the two I have the most experience with and am currently using.

Sublime Text was one of the earlier text editors that became popular with front-end developers — it was the gold standard up until a few years ago. Features like multiple cursors, a powerful package manager, and highly customizable shortcuts that allowed you to quickly navigate in and between files and folders. Not to mention it was an incredibly lightweight and fast application which made it an easy choice.

VS Code (Visual Studio Code) came on the scene around 2015, it took a while for people to switch from Atom and Sublime, but VS Code has established itself as many developers’ favorite editor. In addition to pretty much all of Sublime’s features, VS Code differentiated itself with a built-in terminal and tight integration with Git. In addition, Visual Studio Code has a rich plugin ecosystem that allows you to extend and customize your environment to your heart’s delight.

All that is to say — you don’t need to be a developer to appreciate the features of a good code editor. I have found many uses for it in my daily work; two, in particular, are the ability to use multiple cursors, and using regex to find-and-replace text across folders of files. Let’s take a closer look at both.

Editing With Multiple Cursors

Picture your typical word processor — that blinking vertical line that shows where the text you’re entering will go? Now picture the ability to add more than one cursor to this window so that whatever you type will appear wherever there is a cursor!

This might not be blowing your mind just yet — so here’s an example that shows a few ways that an advanced text editor can help you create everyday efficiencies in your workflow.

A screencap showing a list of names being manipulated and turned into a list of email addresses.Mass-editing in a text editor is much faster and more intuitive than in a spreadsheet. (Large preview)

Here we have a list of names that we need to convert into email addresses — we’d also like to make them all lowercase and then sort them alphabetically. This can be done with a few keystrokes.

Using a text editor to quickly manipulate lots of text in Sublime Text (short video).

Once you paste the list in, Cmd + Shift + P brings up the Command Palette (fancy term for a searchable menu that gives you all the available functionalities). You can basically type in this menu what you want to do, pretty much anything you can do to text is available here. If it’s not, there’s likely a plugin or an extension that you can find.

We’re able to change the case and sort the lines in a matter of seconds — then pressing Ctrl + Shift + arrow keys adds cursors, then whatever we type gets added to every line — in this case, we’re turning the names into email addresses, but your wild imagination could find myriad other ways to use this.

You might be saying — well I can do this in Excel or Google Sheets, which is true, but I have found that it is a lot quicker to handle these types of things in a text editor. You avoid having to write formulas and select things with a mouse.

Which Code Editor Should I Use?

I’m a designer — so of course, my answer is “it depends”.

  • If you’re new to these concepts, I would recommend getting a free trial of Sublime — it continues to be a very lightweight app and does not consume too many system resources. You can customize Sublime’s key bindings (fancy word for hotkeys) and extend its built-in functionality with plugins.
  • If you’ve been using Sublime, Atom, or another editor — I’d recommend checking out VS Code as well. The team at Microsoft has really done an excellent job making it a powerful, yet easy-to-use text editor.

Personally, I use both editors — Sublime is lightning quick and opens in a fraction of a second allowing me to easily paste and manipulate text. But when I want to get some more serious work done, I use VS Code. It’s difficult to top the all-in-one package that VS Code provides — a vibrant plugin and extension ecosystem, powerful command palette, and hyper-customizable interface means you can really make it your own. Not to mention the fact that Microsoft is very incentivized to ensure that it’s a first-class experience for developer productivity.

Conclusion, And What’s Next?

In this first article, you will have learned the basics of the terminal, a few productivity hacks to get you started, and should have a better idea of what code editor to choose. In the next part, we’ll continue with the topics of version control, HTML and CSS, and an introduction to engineering principles.

Anything Amiss?

There’s a good chance that something in this post was obscure, obtuse, and/or obsolete and I’d love the opportunity to make it better! Please leave a comment below, DM me, or @mention me on Twitter so I can improve.

Smashing Editorial (mb, yk, il)
Catégories: Programmation

How Indigo.Design Usability Testing Takes The Guesswork Out Of Web Design

mar, 03/17/2020 - 13:30
How Indigo.Design Usability Testing Takes The Guesswork Out Of Web Design How Indigo.Design Usability Testing Takes The Guesswork Out Of Web Design Suzanne Scacca 2020-03-17T12:30:00+00:00 2020-03-17T13:18:23+00:00

Usability is critical for a website’s success, but it can be difficult to nail down in early design and development stages without a little help.

It’s not as though the research and preparation you do for a new site won’t give you insights on how to build something that’s both beautiful and functional. And having a rock-solid design system and designer-developer handoff will certainly help you bring quality control and consistency to your site.

However, it’s not always enough.

While you can make research-backed assumptions about how visitors will respond to your website or app, it’s all theory until you get it into the hands of real users.

Today, I want to look at the process of usability testing: what it is, when you should use it and how to generate data-backed insights while developing your website using Indigo.Design.

What Is Usability Testing?

Usability testing is a method used to evaluate how easy it is to get around a website or app and to complete specific tasks.

It puts the focus on what people do rather than collect opinions on how they like the design. In other words, usability testing allows you to gather behavioral feedback to make sure the site actually does what it’s supposed to do.

To conduct a usability test, you need to put your site or app in the hands of target users. The data collected from these tests will then help you reshape the site into something that’s streamlined and better tailored to your users’ preferred journey.

Moderated Vs Unmoderated Usability Testing

There are a couple of ways to approach this:

Moderated Unmoderated Type of test One-on-one Self-guided The process Moderator engages the users as they walk through the session Users follow instructions and the analytics tool maps their session Test group size Small Small to large Use cases Highly specialized domains (e.g. doctors, accountants) Geographically dispersed audience Web development stage Prototyping and onward Prototyping and onward

It’s okay if it’s not possible or feasible to run moderated tests on your website or app. With Indigo.Design, you can conduct either kind of test to painlessly gather accurate, quantifiable data from your users and take the guesswork out of design.

Usability testing allows you to gather behavioral feedback to make sure the site actually does what it’s supposed to do.

“ Usability Testing With Indigo.Design

You can start conducting usability tests as early as the prototyping stage. And, really, minimum viable products are the best kinds of websites and apps to test as it’s cheaper to iterate while you’re still in development. Plus, user feedback at this early stage will keep you from wasting time building out features or content that users don’t want or need.

To be clear, we’re not talking about soliciting opinions from stakeholders. What we need to know is whether or not real users can use your website or app successfully.

Just keep in mind that you need to bring a workable prototype to the table. That means:

  • A prototype that’s rich enough to support the usability tasks you’re going to test.
  • A medium-fidelity solution that strikes the right balance between empty-shell-of-a-website and ready-for-launch. It might not be pretty, but it has to be interactive.

Once you’ve gotten your product to this point, you can start usability testing:

1. Add Your Prototype To Indigo.Design

Adding prototypes to Indigo.Design is easy. You have two options:

Indigo.Design dashboard with prototypes and usability tests The Indigo.Design “My Projects” dashboard where prototypes are uploaded and usability tests conducted. (Image source: Indigo.Design) (Large preview)

The first option is to upload a prototype from your computer. The following file formats are accepted:

  • PNG,
  • JPG,
  • GIF,
  • Sketch.

The second option is to add the Indigo.Design plugin to Sketch and sync your prototypes to the cloud. If you’re going to use this tool to simplify handoff, this plugin is going to be a huge time saver.

Once your prototype is loaded, hover over it and click “Edit Prototype”.

Indigo.Design edit prototype button Indigo.Design users can edit prototypes with one click. (Image source: Indigo.Design) (Large preview)

If you haven’t yet confirmed that all interactions are properly set up inside Sketch, you can do that from within the Indigo.Design cloud and edit your interactions there:

Indigo.Design prototype editing and interaction setup Indigo.Design users can verify their medium-fidelity prototypes are interactive before usability testing. (Image source: Indigo.Design) (Large preview)

If the interactions aren’t properly set up, take care of that now. Create the hotspot on the interface on the left and then drag it to the corresponding card on the right to create an interaction.

2. Create A New Usability Test

From the same dashboard where prototypes are uploaded, you’ll begin your first usability test. You can do this from one of two places.

You can hover over the prototype you want to test and create a new one:

Indigo.Design new usability test button Indigo.Design users can begin new usability test for uploaded prototypes. (Image source: Indigo.Design) (Large preview)

The other option is to go to the Usability Tests tab and begin the test there:

Indigo.Design usability tests dashboard Indigo.Design “Usability Tests” dashboard where usability tests are created and managed. (Image source: Indigo.Design) (Large preview)

This is where you will eventually go to manage your usability tests and to review your test results, too.

With your new usability test initiated, this is what you’ll first see:

 create task An Indigo.Design usability test. First step is to create a task. (Image source: Indigo.Design) (Large preview)

Essentially, what you need to do with this tool is:

Determine which “tasks” you want to test. These should be important steps that get your users to complete desired goals (theirs and yours).

For example, with this being a finance management app, I expect users to primarily use this to create new budgets for themselves. So, that’s the first task I want to test:

New task “Create new budget” for usability test Adding a new task to the Indigo.Design usability test. (Image source: Indigo.Design) (Large preview)

To create the “expected success path”, you must interact with your prototype exactly as you’d expect and want your users to on the live product.

Here’s an example of what the “create new budget” path might look like and how to build it out:

Creating expected success path in usability testA quick walk-through of how to set up a new task and success path in Indigo.Design. (Image source: Indigo.Design)

Walk through your website or app on the right part of the screen.

When you’re done, confirm your work on the left before moving on to create other tasks you’ll be including in the test.

3. Put The Finishing Touches On Your Test

Creating tasks alone won’t be enough to gather the kind of data you want from your users.

For instance, if this is an MVP, you might want to explain that the experience may feel a little rough or to provide background on the solution itself (why you’ve built it, what you’re looking to do with it) so they’re not distracted by the design.

Don’t worry about your users misplacing these details in their email invitation. There’s a place to include these notes within the context of your usability test.

Go to the “Test Settings” tab:

Usability test - Welcome message, Thank You message Usability tests in Indigo.Design come with room to add a Welcome and Thank You message. (Image source: Indigo.Design) (Large preview)

Under “Messaging to show participants”, this gives you the opportunity to include a welcome message with your test. This can be a blanket welcome statement or you can provide more context on the tasks if you feel it’s needed.

The thank-you statement is also useful as it provides an end-cap to the test. You can either thank them for their time or you can provide them with the next steps or information on what to expect about the product (maybe there are more usability tests to come).

Before I move on, I want to quickly call your attention to the “Success Criteria” toggle at the top of this section:

Indigo.Design usability test settings - success criteria Indigo.Design usability test settings allow users to set strict success criteria. (Image source: Indigo.Design) (Large preview)

When enabled, this setting only allows for two results:

  • Pass
  • Fail

I’d say that you should leave this toggle set to “Off” if you want this tool to help you detect alternative paths. I’ll show you what that means in just a little bit.

For now, it’s time to grab your usability test link and start sharing it with your participants. When you click the “Start Testing” button in the top-right corner of your screen, you’ll see this:

Indigo.Design usability test link When you’re ready to start your usability test, click “Start Testing” and get your link. (Image source: Indigo.Design) (Large preview)

Copy this link and start sharing it with your participants.

If they’re Chrome users, they’ll be asked to install a browser extension that records their screen, microphone, and camera. They can enable or disable any of these.

The user will then step inside the test:

Indigo.Design usability test exampleAn example of a user walking through an Indigo.Design usability test. (Image source: Indigo.Design)

Once you’ve collected all the data you need, click the “Stop Testing” button in the top-right corner of the screen and start reviewing the results.

4. Review Your Usability Test Results

Your test results can always be found under your Usability Tests dashboard in Indigo.Design.

Indigo.Design usability test overview An overview of a usability test’s results while it’s still in progress. (Image source: Indigo.Design) (Large preview)

If you’re logging into the platform, you’ll find an overview of all your test results, past and present.

You can get a more in-depth look at your results by opening the test:

Indigo.Design usability test results Indigo.Design usability test results by task. (Image source: Indigo.Design) (Large preview)

On the left, you’ll see your test results by task. They’re broken up into:

  • Success rate: The percentage of users that took the exact steps you defined for the task.
  • Accomplished task: The number of users that completed the task. If you didn’t enable “Success Criteria”, this result will show all users who took the expected success path as well as alternative success paths.
  • Avg. time on task: The amount of time it took users to get through the task.

From this alone, you can tell quite a bit about the path you’ve laid before your users and how well-tuned it is to their mindsets and needs.

However, the right side of the screen gives us a better look at where things may have gone awry and why:

Indigo.Design test results — success path Indigo.Design provides users to see what happened along the paths of their test subjects. (Image source: Indigo.Design) (Large preview)

The top part of the screen shows us the original steps we laid down. Anywhere there’s a red mark and a number in red is where our test subjects deviated from that path.

This is much more effective than heatmap testing which only really gives us a general idea of where the users’ focus is. This clearly shows us that there’s something either wrong with the layout of the page or perhaps the content itself is poorly labeled and confusing.

Let’s look a bit closer at the bottom of the screen and the path data we have to play with:

  • Blue circles signify expected interactions,
  • Red diamonds signify unexpected interactions,
  • Orange squares signify that the participant requested help.
Expected success path in usability test Data on how many users took the expected success path in a usability test. (Image source: Indigo.Design) (Large preview)

This shows us what the expected success path looked like and how long it took to complete on average.

You can click on the stats for “Alt. Success Path” and “Failed Path” to view how things went for your other participants:

Alternative success path in usability test Data on how many users took the alternative success path in a usability test. (Image source: Indigo.Design) (Large preview)

When we allow leeway in terms of success criteria, we get a chance to see the alternative success paths.

This is useful for a couple of reasons. First, if there are enough users who took the same route and there were more of them than those on the success path, it might be worth reshaping the pathway entirely. If the alternative route is more logical and efficient, it would make sense to get rid of the path less traveled.

Failed path in usability test Data on how many users failed to complete a task in the usability test. (Image source: Indigo.Design) (Large preview)

Secondly, the alternative success path along with the failed path shows us where friction occurs along the way. This enables us to see where our users’ breaking points really are. Not that we ever want to push our users to the edge, but it’s good to have a sense of what kinds of interactions just don’t work.

For instance, let’s say one of the buttons requires a right-click instead of a regular click. I know this is something I’ve encountered in some tools and it drives me nuts because it’s almost always unexpected and counterintuitive. I wouldn’t abandon the experience over it, but your users might.

So, by comparing the alternative success path with the failed path, you can figure out what these kinds of deal-breakers are much more easily.

Look A Little Deeper

I know the numbers and pathway steps are really important to look at but don’t forget to study the other information left behind by your participants.

For instance, if your users enabled browser recording, you can “Play Video” and watch them actually go through it.

If not, you can still use the “View path” link to watch the actual steps they took (if they weren’t the expected blue-circle steps).

Indigo.Design usability test review options Indigo.Design allows users to keep tabs on what test subjects did or didn’t do to complete a task. (Image source: Indigo.Design) (Large preview)

This is what you’ll see for each of your test subjects:

Indigo.Design Click Path and Video Replay to watch step-by-step tests Indigo.Design users can view every step their test subjects took by viewing the “Click Path” or watching the “Video Replay”. (Image source: Indigo.Design) (Large preview)

This particular view might be more useful to you than video since you can track the actual clicks on each static page. Not only do you see every part of the website where they clicked, but you also see in which order they made those clicks.

And like I said before, if you can identify trends where these alternative success paths or failed paths took your users, you can more quickly stamp out issues in your web design. It’s only when those clicks are all over the place or users give up on completing any of the tasks that you have a real problem.

Wrapping Up

Using a design system does not automatically imply good usability. You need to be able to design more than just consistently beautiful UIs.

That’s what’s so nice about the solution we’ve just looked at. With usability testing built into Indigo.Design, the focus isn’t just on shipping pixel-perfect websites. Whether you plan on doing moderated or unmoderated usability testing, you now have a tool that can accurately map your users’ journeys and the difficulties they would otherwise face.

Smashing Editorial (ra, il)
Catégories: Programmation

Implementing Infinite Scroll And Image Lazy Loading In React

lun, 03/16/2020 - 13:00
Implementing Infinite Scroll And Image Lazy Loading In React Implementing Infinite Scroll And Image Lazy Loading In React Chidi Orji 2020-03-16T12:00:00+00:00 2020-03-16T13:38:52+00:00

If you have been looking for an alternative to pagination, infinite scroll is a good consideration. In this article, we’re going to explore some use cases for the Intersection Observer API in the context of a React functional component. The reader should possess a working knowledge of React functional components. Some familiarity with React hooks will be beneficial but not required, as we will be taking a look at a few.

Our goal is that at the end of this article, we will have implemented infinite scroll and image lazy loading using a native HTML API. We would also have learned a few more things about React Hooks. With that you can be able to implement infinite scroll and image lazy loading in your React application where necessary.

Let’s get started.

Creating Maps With React And Leaflet

Grasping information from a CSV or a JSON file isn’t only complicated, but is also tedious. Representing the same data in the form of visual aid is simpler. Shajia Abidi explains how powerful of a tool Leaflet is, and how a lot of different kinds of maps can be created. Read article →

The Intersection Observer API

According to the MDN docs, “the Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport”.

This API allows us to implement cool features such as infinite scroll and image lazy loading. The intersection observer is created by calling its constructor and passing it a callback and an options object. The callback is invoked whenever one element, called the target, intersects either the device viewport or a specified element, called the root. We can specify a custom root in the options argument or use the default value.

let observer = new IntersectionObserver(callback, options);

The API is straightforward to use. A typical example looks like this:

var intObserver = new IntersectionObserver(entries => { entries.forEach(entry => { console.log(entry) console.log(entry.isIntersecting) // returns true if the target intersects the root element }) }, { // default options } ); let target = document.querySelector('#targetId'); intObserver.observe(target); // start observation

entries is a list of IntersectionObserverEntry objects. The IntersectionObserverEntry object describes an intersection change for one observed target element. Note that the callback should not handle any time-consuming task as it runs on the main thread.

The Intersection Observer API currently enjoys broad browser support, as shown on caniuse.

Intersection Observer browser support. (Large preview)

You can read more about the API in the links provided in the resources section.

Let us now look at how to make use of this API in a real React app. The final version of our app will be a page of pictures that scrolls infinitely and will have each image loaded lazily.

Making API Calls With The useEffect Hook

To get started, clone the starter project from this URL. It has minimal setup and a few styles defined. I’ve also added a link to Bootstrap’s CSS in the public/index.html file as I’ll be using its classes for styling.

Feel free to create a new project if you like. Make sure you have yarn package manager installed if you want to follow with the repo. You can find the installation instructions for your specific operating system here.

For this tutorial, we’re going to be grabbing pictures from a public API and displaying them on the page. We will be using the Lorem Picsum APIs.

For this tutorial, we’ll be using the endpoint, https://picsum.photos/v2/list?page=0&limit=10, which returns an array of picture objects. To get the next ten pictures, we change the value of page to 1, then 2, and so on.

We will now build the App component piece by piece.

Open up src/App.js and enter the following code.

import React, { useEffect, useReducer } from 'react'; import './index.css'; function App() { const imgReducer = (state, action) => { switch (action.type) { case 'STACK_IMAGES': return { ...state, images: state.images.concat(action.images) } case 'FETCHING_IMAGES': return { ...state, fetching: action.fetching } default: return state; } } const [imgData, imgDispatch] = useReducer(imgReducer,{ images:[], fetching: true}) // next code block goes here }

Firstly, we define a reducer function, imgReducer. This reducer handles two actions.

  1. The STACK_IMAGES action concatenates the images array.
  2. FETCHING_IMAGES action toggles the value of the fetching variable between true and false.

The next step is to wire up this reducer to a useReducer hook. Once that is done, we get back two things:

  1. imgData, which contains two variables: images is the array of picture objects. fetching is a boolean which tells us if the API call is in progress or not.
  2. imgDispatch, which is a function for updating the reducer object.

You can learn more about the useReducer hook in the React documentation.

The next part of the code is where we make the API call. Paste the following code below the previous code block in App.js.

// make API calls useEffect(() => { imgDispatch({ type: 'FETCHING_IMAGES', fetching: true }) fetch('https://picsum.photos/v2/list?page=0&limit=10') .then(data => data.json()) .then(images => { imgDispatch({ type: 'STACK_IMAGES', images }) imgDispatch({ type: 'FETCHING_IMAGES', fetching: false }) }) .catch(e => { // handle error imgDispatch({ type: 'FETCHING_IMAGES', fetching: false }) return e }) }, [ imgDispatch ]) // next code block goes here

Inside the useEffect hook, we make a call to the API endpoint with fetch API. We then update the images array with the result of the API call by dispatching the STACK_IMAGES action. We also dispatch the FETCHING_IMAGES action once the API call completes.

The next block of code defines the return value of the function. Enter the following code after the useEffect hook.

return ( <div className=""> <nav className="navbar bg-light"> <div className="container"> <a className="navbar-brand" href="/#"> <h2>Infinite scroll + image lazy loading</h2> </a> </div> </navv <div id='images' className="container"> <div className="row"> {imgData.images.map((image, index) => { const { author, download_url } = image return ( <div key={index} className="card"> <div className="card-body "> <img alt={author} className="card-img-top" src={download_url} /> </div> <div className="card-footer"> <p className="card-text text-center text-capitalize text-primary">Shot by: {author}</p> </div> </div> ) })} </div> </div> </div> );

To display the images, we map over the images array in the imgData object.

Now start the app and view the page in the browser. You should see the images nicely displayed in a responsive grid.

The last bit is to export the App component.

export default App; Pictures in responsive grid. (Large preview)

The corresponding branch at this point is 01-make-api-calls.

Let’s now extend this by displaying more pictures as the page scrolls.

Implementing Infinite Scroll

We aim to present more pictures as the page scrolls. From the URL of the API endpoint, https://picsum.photos/v2/list?page=0&limit=10, we know that to get a new set of photos, we only need to increment the value of page. We also need to do this when we have run out of pictures to show. For our purpose here, we’ll know we have run out of images when we hit the bottom of the page. It’s time to see how the Intersection Observer API helps us achieve that.

Open up src/App.js and create a new reducer, pageReducer, below imgReducer.

// App.js const imgReducer = (state, action) => { ... } const pageReducer = (state, action) => { switch (action.type) { case 'ADVANCE_PAGE': return { ...state, page: state.page + 1 } default: return state; } } const [ pager, pagerDispatch ] = useReducer(pageReducer, { page: 0 })

We define only one action type. Each time the ADVANCE_PAGE action is triggered, the value of page is incremented by 1.

Update the URL in the fetch function to accept page numbers dynamically as shown below.

fetch(`https://picsum.photos/v2/list?page=${pager.page}&limit=10`)

Add pager.page to the dependency array alongside imgData. Doing this ensures that the API call will run whenever pager.page changes.

useEffect(() => { ... }, [ imgDispatch, pager.page ])

After the useEffect hook for the API call, enter the below code. Update your import line as well.

// App.js import React, { useEffect, useReducer, useCallback, useRef } from 'react'; useEffect(() => { ... }, [ imgDispatch, pager.page ]) // implement infinite scrolling with intersection observer let bottomBoundaryRef = useRef(null); const scrollObserver = useCallback( node => { new IntersectionObserver(entries => { entries.forEach(en => { if (en.intersectionRatio > 0) { pagerDispatch({ type: 'ADVANCE_PAGE' }); } }); }).observe(node); }, [pagerDispatch] ); useEffect(() => { if (bottomBoundaryRef.current) { scrollObserver(bottomBoundaryRef.current); } }, [scrollObserver, bottomBoundaryRef]);

We define a variable bottomBoundaryRef and set its value to useRef(null). useRef lets variables preserve their values across component renders, i.e. the current value of the variable persists when the containing component re-renders. The only way to change its value is by re-assigning the .current property on that variable.

In our case, bottomBoundaryRef.current starts with a value of null. As the page rendering cycle proceeds, we set its current property to be the node <div id='page-bottom-boundary'>.

We use the assignment statement ref={bottomBoundaryRef} to tell React to set bottomBoundaryRef.current to be the div where this assignment is declared.

Thus,

bottomBoundaryRef.current = null

at the end of the rendering cycle, becomes:

bottomBoundaryRef.current = <div id="page-bottom-boundary" style="border: 1px solid red;"></div>

We shall see where this assignment is done in a minute.

Next, we define a scrollObserver function, in which to set the observer. This function accepts a DOM node to observe. The main point to note here is that whenever we hit the intersection under observation, we dispatch the ADVANCE_PAGE action. The effect is to increment the value of pager.page by 1. Once this happens, the useEffect hook that has it as a dependency is re-run. This re-run, in turn, invokes the fetch call with the new page number.

The event procession looks like this.

Hit intersection under observation → call ADVANCE_PAGE action → increment value of pager.page by 1 → useEffect hook for fetch call runs → fetch call is run → returned images are concatenated to the images array.

We invoke scrollObserver in a useEffect hook so that the function will run only when any of the hook’s dependencies change. If we didn’t call the function inside a useEffect hook, the function would run on every page render.

Recall that bottomBoundaryRef.current refers to <div id="page-bottom-boundary" style="border: 1px solid red;"></div>. We check that its value is not null before passing it to scrollObserver. Otherwise, the IntersectionObserver constructor would return an error.

Because we used scrollObserver in a useEffect hook, we have to wrap it in a useCallback hook to prevent un-ending component re-renders. You can learn more about useCallback in the React docs.

Enter the below code after the <div id='images'> div.

// App.js <div id='image'> ... </div> {imgData.fetching && ( <div className="text-center bg-secondary m-auto p-3"> <p className="m-0 text-white">Getting images</p> </div> )} <div id='page-bottom-boundary' style={{ border: '1px solid red' }} ref={bottomBoundaryRef}></div>

When the API call starts, we set fetching to true, and the text Getting images becomes visible. As soon as it finishes, we set fetching to false, and the text gets hidden. We could also trigger the API call before hitting the boundary exactly by setting a different threshold in the constructor options object. The red line at the end lets us see exactly when we hit the page boundary.

The corresponding branch at this point is 02-infinite-scroll.

We will now implement image lazy loading.

Implementing Image Lazy Loading

If you inspect the network tab as you scroll down, you’ll see that as soon as you hit the red line (the bottom boundary), the API call happens, and all the images start loading even when you haven’t gotten to viewing them. There are a variety of reasons why this might not be desirable behavior. We may want to save network calls until the user wants to see an image. In such a case, we could opt for loading the images lazily, i.e., we won’t load an image until it scrolls into view.

Open up src/App.js. Just below the infinite scrolling functions, enter the following code.

// App.js // lazy loads images with intersection observer // only swap out the image source if the new url exists const imagesRef = useRef(null); const imgObserver = useCallback(node => { const intObs = new IntersectionObserver(entries => { entries.forEach(en => { if (en.intersectionRatio > 0) { const currentImg = en.target; const newImgSrc = currentImg.dataset.src; // only swap out the image source if the new url exists if (!newImgSrc) { console.error('Image source is invalid'); } else { currentImg.src = newImgSrc; } intObs.unobserve(node); // detach the observer when done } }); }) intObs.observe(node); }, []); useEffect(() => { imagesRef.current = document.querySelectorAll('.card-img-top'); if (imagesRef.current) { imagesRef.current.forEach(img => imgObserver(img)); } }, [imgObserver, imagesRef, imgData.images]);

As with scrollObserver, we define a function, imgObserver, which accepts a node to observe. When the page hits an intersection, as determined by en.intersectionRatio > 0, we swap the image source on the element. Notice that we first check if the new image source exists before doing the swap. As with the scrollObserver function, we wrap imgObserver in a useCallback hook to prevent un-ending component re-render.

Also note that we stop observer an img element once we’re done with the substitution. We do this with the unobserve method.

In the following useEffect hook, we grab all the images with a class of .card-img-top on the page with document.querySelectorAll. Then we iterate over each image and set an observer on it.

Note that we added imgData.images as a dependency of the useEffect hook. When this changes it triggers the useEffect hook and in turn imgObserver get called with each <img className='card-img-top'> element.

Update the <img className='card-img-top'/> element as shown below.

<img alt={author} data-src={download_url} className="card-img-top" src={'https://picsum.photos/id/870/300/300?grayscale&blur=2'} />

We set a default source for every <img className='card-img-top'/> element and store the image we want to show on the data-src property. The default image usually has a small size so that we’re downloading as little as possible. When the <img/> element comes into view, the value on the data-src property replaces the default image.

In the picture below, we see the default lighthouse image still showing in some of the spaces.

Images being lazily loaded. (Large preview)

The corresponding branch at this point is 03-lazy-loading.

Let’s now see how we can abstract all these functions so that they’re re-usable.

Abstracting Fetch, Infinite Scroll And Lazy Loading Into Custom Hooks

We have successfully implemented fetch, infinite scroll, and image lazy loading. We might have another component in our application that needs similar functionality. In that case, we could abstract and reuse these functions. All we have to do is move them inside a separate file and import them where we need them. We want to turn them into Custom Hooks.

The React documentation defines a Custom Hook as a JavaScript function whose name starts with "use" and that may call other hooks. In our case, we want to create three hooks, useFetch, useInfiniteScroll, useLazyLoading.

Create a file inside the src/ folder. Name it customHooks.js and paste the code below inside.

// customHooks.js import { useEffect, useCallback, useRef } from 'react'; // make API calls and pass the returned data via dispatch export const useFetch = (data, dispatch) => { useEffect(() => { dispatch({ type: 'FETCHING_IMAGES', fetching: true }); fetch(`https://picsum.photos/v2/list?page=${data.page}&limit=10`) .then(data => data.json()) .then(images => { dispatch({ type: 'STACK_IMAGES', images }); dispatch({ type: 'FETCHING_IMAGES', fetching: false }); }) .catch(e => { dispatch({ type: 'FETCHING_IMAGES', fetching: false }); return e; }) }, [dispatch, data.page]) } // next code block here

The useFetch hook accepts a dispatch function and a data object. The dispatch function passes the data from the API call to the App component, while the data object lets us update the API endpoint URL.

// infinite scrolling with intersection observer export const useInfiniteScroll = (scrollRef, dispatch) => { const scrollObserver = useCallback( node => { new IntersectionObserver(entries => { entries.forEach(en => { if (en.intersectionRatio > 0) { dispatch({ type: 'ADVANCE_PAGE' }); } }); }).observe(node); }, [dispatch] ); useEffect(() => { if (scrollRef.current) { scrollObserver(scrollRef.current); } }, [scrollObserver, scrollRef]); } // next code block here

The useInfiniteScroll hook accepts a scrollRef and a dispatch function. The scrollRef helps us set up the observer, as already discussed in the section where we implemented it. The dispatch function gives a way to trigger an action that updates the page number in the API endpoint URL.

// lazy load images with intersection observer export const useLazyLoading = (imgSelector, items) => { const imgObserver = useCallback(node => { const intObs = new IntersectionObserver(entries => { entries.forEach(en => { if (en.intersectionRatio > 0) { const currentImg = en.target; const newImgSrc = currentImg.dataset.src; // only swap out the image source if the new url exists if (!newImgSrc) { console.error('Image source is invalid'); } else { currentImg.src = newImgSrc; } intObs.unobserve(node); // detach the observer when done } }); }) intObs.observe(node); }, []); const imagesRef = useRef(null); useEffect(() => { imagesRef.current = document.querySelectorAll(imgSelector); if (imagesRef.current) { imagesRef.current.forEach(img => imgObserver(img)); } }, [imgObserver, imagesRef, imgSelector, items]) }

The useLazyLoading hook receives a selector and an array. The selector is used to find the images. Any change in the array triggers the useEffect hook that sets up the observer on each image.

We can see that it is the same functions we have in src/App.js that we have extracted to a new file. The good thing now is that we can pass arguments dynamically. Let’s now use these custom hooks in the App component.

Open src/App.js. Import the custom hooks and delete the functions we defined for fetching data, infinite scroll, and image lazy loading. Leave the reducers and the sections where we make use of useReducer. Paste in the below code.

// App.js // import custom hooks import { useFetch, useInfiniteScroll, useLazyLoading } from './customHooks' const imgReducer = (state, action) => { ... } // retain this const pageReducer = (state, action) => { ... } // retain this const [pager, pagerDispatch] = useReducer(pageReducer, { page: 0 }) // retain this const [imgData, imgDispatch] = useReducer(imgReducer,{ images:[], fetching: true }) // retain this let bottomBoundaryRef = useRef(null); useFetch(pager, imgDispatch); useLazyLoading('.card-img-top', imgData.images) useInfiniteScroll(bottomBoundaryRef, pagerDispatch); // retain the return block return ( ... )

We have already talked about bottomBoundaryRef in the section on infinite scroll. We pass the pager object and the imgDispatch function to useFetch. useLazyLoading accepts the class name .card-img-top. Note the . included in the class name. By doing this, we don’t need to specify it document.querySelectorAll. useInfiniteScroll accepts both a ref and the dispatch function for incrementing the value of page.

The corresponding branch at this point is 04-custom-hooks.

Conclusion

HTML is getting better at providing nice APIs for implementing cool features. In this post, we’ve seen how easy it is to use the intersection observer in a React functional component. In the process, we learned how to use some of React’s hooks and how to write our own hooks.

Resources Smashing Editorial (ks, ra, yk, il)
Catégories: Programmation

Stay Calm And Read Smashing

ven, 03/13/2020 - 13:30
Stay Calm And Read Smashing Stay Calm And Read Smashing Iris Lješnjanin 2020-03-13T12:30:00+00:00 2020-03-13T13:41:14+00:00

For all the times we asked folks about Smashing, most still seem to believe that we’re some sort of large publishing company situated somewhere in the United States — both of which are wrong. It all started in Freiburg, Germany, and the team consists of folks scattered all over the world — with most of us not working fulltime for Smashing.

That’s right, working remotely is quite familiar to us, and so with the current situation going on with COVID-19 that is making everyone uneasy, we’d like to make the best of things and help our friends who are having to work or lead teams remotely for the first time. Our editor-in-chief, Rachel Andrew, has prepared a nice post to help you stay connected and keep learning while we go through this together.

You may have already heard that SmashingConf SF has been postponed to November due to the unfortunate travel restrictions and many other reasons. It was truly a difficult decision for the team to make, but we believe it is the best way forward — safety and health always come first.

Without further ado, here’s a short update of things going on at Smashing and some super creative work shared from and to the community!

Happy reading — from my computer to yours!

Designing With Ethics In Mind ...After months of hard work, the “The Ethical Design Handbook” is finally here — and it’s shipping! The response has already been overwhelmingly positive, and we’re excited to share reviews with you soon. There is still quite a bit of work to do on the web, but our hope is that with this book, you will be equipped with enough tooling to slowly move a company towards a more sustainable and healthy digital footprint!

Of course, you can jump to the table of contents right away, or download a free PDF excerpt to get a first impression of the book — we’re sure you won’t be disappointed! Read our official release post with all the details →

Always Learning New Things From One Another Smashing PodcastWe all have busy schedules, but there’s always time to pop in those earplugs and listen to some music or podcasts that make you happy! We’re moving on to our 12th episode of the Smashing Podcast — with folks from different backgrounds and so much to share! You’re always welcome to tune in and share your questions and thoughts with us anytime!

Apart from the heart-breaking news about our postponed SmashingConf SF, our SmashingConfs are known to be friendly, inclusive events where front-end developers and designers come together to attend live sessions and hands-on workshops. From live designing to live debugging, all of our speakers like to go into detail and show useful examples from their own projects on the big screen.

Here are some talks you may like to watch and learn from:

Talk Title Speaker’s Name Thinking With Grids Jen Simmons Building Accessible Interfaces: Patterns And Techniques Sara Soueidan Dynamic CSS Miriam Suzanne Dynamic Web Typography Jason Pamental Making A Difference With Differential Serving Jeremy Wagner Slam Dunk Your Javascript Fundamentals Wes Bos Think Like An Email Geek Rémi Parmentier Effortless Performance Debugging Anna Migas Move Fast & Don’t Break Things Scott Jehl Designer vs Developer! Dan Mall, Brad Frost and Ian Frost

The first SmashingConf took place in Freiburg back in 2012, so there are so many more talks you can watch. See all SmashingConf videos →

Shining The Spotlight On React, Redux And Electron

Advent calendarsMark your calendars! Next week on March 19, we’ll be hosting a Smashing TV webinar with Cassidy Williams who’ll be explaining how to organize a modern React application and build an Electron application (with React). Join us at 17:00 London time — we’d love to hear your thoughts and experiences you’ve had with React in your projects!

Smashing TV is a series of webinars and live streams packed with practical tips for designers and developers. They’re not just talks, but more like conversations and “here-is-how-I-work”-sessions. Smashing Members can download recordings, and also receive discounts and lots of goodies to make their membership worthwhile. Tell me more →

Trending Topics On SmashingMag

We publish a new article every day on various topics that are current in the web industry. Here are some that our readers seemed to enjoy the most and have recommended further:

  • Why Are We Talking About CSS4?
    by Rachel Andrew
    Around the web and within the CSS Working Group, there has been some discussion about whether we should specify a version of CSS — perhaps naming it CSS4. In this article, Rachel Andrew rounds up some of the pros and cons of doing so, and asks for your feedback on the suggestion.
  • Setting Height And Width On Images Is Important Again
    by Barry Pollard
    Thanks to some recent changes in browsers, it’s now well worth setting width and height attributes on your images to prevent layout shifts and improve the experience of your site visitors.
  • Setting Up Tailwind CSS In A React Project
    by Blessing Krofegha
    This article introduces Tailwind CSS, a CSS library that gives you all of the building blocks you need to build bespoke designs without opinionated styles. You’ll also learn how to seamlessly set up Tailwind CSS in a React project.
  • Introducing Alpine.js: A Tiny JavaScript Framework
    by Phil Smith
    Ever built a website and reached for jQuery, Bootstrap, Vue.js or React to acheive some basic user interaction? Alpine.js is a fraction of the size of these frameworks because it involves no build steps and provides all of the tools you need to build a basic user interface.
  • How To Design Mobile Apps For One-Hand Usage
    by Maitrik Kataria
    90% of the smartphones sold today have >5-inch displays. Bigger screen real estate presents newer challenges and opportunities for app makers and designers. Let’s look at how designing apps for one-handed usage can solve those challenges.
Best Picks From Our Newsletter

We’ll be honest: Every second week, we struggle with keeping the Smashing Newsletter issues at a moderate length — there are just so many talented folks out there working on brilliant projects! So, without wanting to make this monthly update too long either, we’re shining the spotlight on the following projects:

P.S.: A huge thank you to Cosima Mielke for writing and preparing these posts!

Find And Fix Errors In Your Designs

We all know those moments when we are so immersed in a project that we lose the distance we need to be able to catch little inconsistencies: an incorrect border-radius around an image or missing styles or text, for example. If you’re designing in Figma, the free and open-source plugin Design Lint makes finding and fixing errors like these easy so that no bug makes it into production.

Design LintA free and open-source plugin for Figma built to help you find and fix errors in your designs.: Design Lint.

Design Lint checks for missing text, fill, stroke, and effects styles, and catches incorrect border-radius values on all your layers. To not interrupt your workflow, the plugin automatically updates as you fix errors. The repo is available on GitHub, so feel free to write specific rules to tailor the plugin to your needs.

Learn CSS Positioning With… Cats!

Could there be a better way to learn CSS positioning as with a bunch of friendly cats? That’s probably what Ahmad Shadeed thought, too, when he created his interactive guide to how CSS positioning works.

Learn CSS Positioning Meow! Ahmad Shadeed has prepared a great guide for you to learn everything about CSS positioning!

The guide teaches you to use CSS to position three cartoon cats and their blanket inside a box, and once you’ve grasped the concept, you can start tinkering with the interactive demo that visualizes how the result changes as you edit the values. Now who said learning can’t be fun?

Intimacy, An Interactive Short Poem

An inspiring experiment comes from the French graphic and interaction design student Thibaud Giffon: “Intimacy”. The interactive short poem uses abstract images, sound, and text to explore intimacy from different angles.

Intimacy The “Mixed Up” musical poem is brought to life (sound ON) by just moving your cursor across the cords. Try it out!

Compassion, distance, confusion, touch — these are four of the eight chapters that make up the poem; and each one of them reflects the topic in its own, unique way: with warm and harmonious waves or circles that melt into each other but also with dissonant strings or colorful bubbles that burst as they make space for themselves. Beautiful!

All Your SVG Icons In One Place

Having one central place to organize all your assets is always a good thing, not only for teams — to keep track of what you have and to quickly find what you’re looking for. The free cross-platform app Iconset is such a place: it helps you collect, customize, share, and manage all your SVG icon sets.

Iconset Organizing SVG icons all in one place with Iconset.

To make it easier to find the icon you’re looking for, you can organize your icons in sets or with tags, and, once you’ve found the icon you need, you can drag it directly into your favorite tool. A real timesaver. Iconset supports cloud services like Dropbox or OneDrive so that all your icons are always in sync between team members. The app is available for Mac and Windows.

An Ancient Hero’s WebGL Adventure

A reluctant hero on a quest he never asked for — that’s the story behind the browser-based adventure video game Heraclos. Set in ancient Greece, the young Heraclos stumbles across an amphora that belongs to one of the gods. He is declared to be the chosen one and gets sent off to climb the secret mountain and return the amphora to his owner.

Heraclos Heraclos, an adventure video game made in WebGL.

What makes the game so noteworthy is the fun twist in the interaction between the hero and the god (a parody of common heroic stories) but also the technical background: Heraclos was designed in only three months by a group of students at the Gobelins school of images in Paris — with WebGL and Cannon.js. A great example of what’s possible on the web.

An Open-Source Screen Recorder Built With Web Technology

Have you heard of Kap, yet? The open-source screen recorder is one that is definitely worth checking out if you’re frequently doing screen recordings.

Kap Kap, an open-source screen recorder built with web technology.

Built with web technologies, Kap produces high-quality recordings in GIF, MP4, WebM, or APNG formats. You can include audio (even from your microphone), highlight clicks, and trim the recordings. As a bonus goodie, there are also options to share your recorded GIFs on Giphy, deploy them with ZEIT now, or upload them to Streamable. Perfect for technical demos.

Open Peeps, A Free Hand-Drawn Illustration Library

584,688 possible combinations. That’s the number of different characters you could create with Pablo Stanley’s hand-drawn illustration library Open Peeps.

Open Peeps “Open Peeps,” a hand-drawn illustration library created by Pablo Stanley.

Open Peeps lets you mix and match different vector elements to create diverse personalities: combine clothing and hairstyles, change emotion with facial expressions, set the scene with different poses — the possibilities are sheer endless. And if you’re in a hurry, Pablo also prepared some ready-to-download Peeps that you can use right away. Open Peeps is released under a CC0 license, so you are free to use the illustrations in both personal and commercial projects. A great way to add a handmade touch to your design.

How To Make Inputs More Accessible

In 2019, WebAim analyzed the accessibility of the top one million websites, with a shocking conclusion: the percentage of error-free pages was estimated to be under one percent. To make our sites inclusive and usable for people who rely on assistive technology, we need to get the basics of semantic HTML right. With its credo of starting small, sharing, and working together, Oscar Braunert’s article on inclusive inputs is a great starting point to do so.

Starting off with the basics of WAI, ARIA, and WCAG, the article explores how to make inputs more accessible. The tips can be implemented without changing the user interface, and, as Oscar puts it: “If in doubt, just do it. Nobody will notice. Except some of your users. And they will thank you for it.”

An Open-Source Font For Developers

High readability, quick text scanning, no distraction — these are just some of the demands developers have on a typeface. Well, the free and open-source typeface JetBrains Mono meets all of them beautifully.

JetBrains Mono JetBrains Mono’s typeface forms are simple and free from unnecessary details. Rendered in small sizes, the text looks crisper.

To do so, Jet Brains Mono takes advantage of some small but mighty details: Compared to other monospace fonts, the height of JetBrains Mono is increased while the characters remain standard in width to keep code lines to the length developers expect. To improve readability even further, 138 code-specific ligatures reduce noise so that your eyes need to process less and whitespace becomes more balanced. Clever! JetBrains Mono comes in four weights and supports 145 languages.

The Ultimate Guide To iframes

With a lot of articles advising against them, iframes don’t have the best reputation. JavaScript developer Nada Rifki sees things differently: She suggests not to let their reputation prevent you from relying on iframes. After all, they have many legitimate use cases.

The Ultimate Guide To iframes The ultimate guide to iframes written by Nada Rifki.

To help you form your own opinion on this controversial element, Nada wrote an ultimate guide to iframes which explores iframe features and how to use them; tricky situations where iframes might come in handy; last but not least, how you can secure your iframe against potential vulnerabilities. A great opportunity to see things from a different perspective.

A Guide To Console Commands

The capabilities of the developer’s debugging console have evolved significantly in the past years — from a means to report errors to automatically logging information like network requests and security errors or warnings. There’s also a way for a website’s JavaScript to trigger various commands that output to the console for debugging purposes. And while these features are mostly consistent between browsers, there are also some functional differences.

A Guide To Console Commands “A Guide to Console Commands” by Travis Almand

If you’re looking for an overview of what console commands are capable of, Travis Almand put together a helpful guide. It covers Firefox and Chrome and examines various commands that can be used in the browser’s console output or with JavaScript. A handy summary.

A postcat. Sign up for our Smashing Newsletter. Smashing Newsletter

Upgrade your inbox and get our editors’ picks 2× a month — delivered right into your inbox. Earlier issues.

Your (smashing) email Subscribe → Useful tips for web designers. Sent 2× a month.
You can unsubscribe any time — obviously. Smashing Editorial (cm, vf, ra, il)
Catégories: Programmation

Rescheduling SmashingConf SF And Looking Out For Each Other

jeu, 03/12/2020 - 21:00
Rescheduling SmashingConf SF And Looking Out For Each Other Rescheduling SmashingConf SF And Looking Out For Each Other Rachel Andrew 2020-03-12T20:00:00+00:00 2020-03-12T22:37:01+00:00

We have all been looking forward to our SmashingConf in San Francisco, and are so sad to have to announce that the conference is being postponed until 10th–11th November 2020. If you have tickets for the event, you should already have received an email. If not, then please see the detailed information on this page, get in touch with us, and we will help you out. The team is on standby to try and help you as quickly as possible.

As you can imagine, it was a very tough decision for our team to make. We have been working hard to plan this event and were looking very much forward to it for the last few months, however, we believe it is the right decision for the conference and for everyone we hoped to meet there.

We are all faced with a difficult few weeks ahead, but we still need to do our jobs, keep learning, and also stay connected with our friends. We hope that even though we can’t all meet in person, we can help a little bit as we all get through this together.

Topple the Cat holding a guitar, excited for SmashingConf taking place in San Francisco this year Topple the Cat agrees that this is the best way forward for the safety and health of you, our dearest Smashing Family! (Read our full statement here.) Stay Connected

We know that many of you are working from home for the first time to help prevent the spread of COVID-19, and the events and meetups that we all love to attend are being cancelled. We’re working on some ideas for the coming weeks that can be attended virtually — with no need for awkward elbow bumps and footshakes. Our online communities are going to become even more important than usual.

Lot's of us will be stuck at home for weeks if not months. Let's help each other. What are your best coping tips? How do you take care of your mental health?

— Christoph Nakazawa (@cpojer) March 12, 2020

The entire Smashing team are remote, and the conferences are one place that many of us get to meet and spend time in person, so we know how hard it can be to lose those opportunities. The community have been sharing some great resources online, however, for those of you who are new to working from home, we went ahead and asked Twitter for tips and got some great replies — as well as links to resources.

The Smashing Team are all remote, but many of our friends are having to work or lead teams remotely for the first time.

What are your top tips, or useful websites and apps for remote working, or remote team leading?

— Smashing Magazine (@smashingmag) March 12, 2020

Some of you might be having to manage a remote team for the first time, with little time to prepare. In “You’ve Found Yourself Leading A Remote Design Team,” Mark Boulton shares some tips from his own experience having led remote teams for many years. On Twitter, Linda Eliasen wrote a thread with all her tips on leading a team remotely. Also, Holloway have released a section from their upcoming guide which covers morale, mental health, and burnout in remote teams.

Laurie wrote some tips on “Remote Work For Teams” while Zsolt exlained how we can switch from in person to remote UX Research in the time of coronavirus.

For people new to remote work, there are some useful tips in “The Leapers Little Guide To… Working Well From Home Under Self-Quarantine For Coronavirus,” and also in Carie Fisher’s post, “Top 10 Pro-Tips For Working Remotely.” Benedikt Lehnert wrote a great guide with lots of practical suggestions, “I’m Working Remotely, Now What?!Vice.com have some information which they claim will help us not to feel like a “lonely garbage slug”. (Wait, what is a garbage slug?)

As someone who usually has a smarter shirt to hand to throw on over my gym clothes when I need to do a video call, I liked this tip:

Wear pants! Otherwise you’ll forget and go grab a snack. I don’t know that from experience…

— Emma Bostian 🐞 (@EmmaBostian) March 12, 2020

Keep Learning

We have a whole back catalog of video from previous conferences, which you can enjoy from the comfort of your sofa. The talks from last year alone should keep you occupied for a while.

SmashingConf NYC 2019

SmashingConf NYC 2019Watch videos featuring Dan Mall, Brad Frost and Ian Frost, Marcy Sutton, Denys Mishunov, Trine Falbe, Maggie Wachs, Wes Bos, dina Amin, Harry Roberts, Sara Soueidan, Remy Sharp, Scott Jehl, and Miriam Suzanne.

SmashingConf Freiburg 2019

SmashingConf Freiburg 2019Watch talks from Guillaume Kurkdjian, Joe Leech, Heather Burns, Uri Shaked and Benjamin Gruenbaum, Anna Migas, Val Head, Rémi Parmentier, Sara Soueidan, Robyn Larsen, Benjamin Hersh, and Philip Walton.

SmashingConf Toronto 2019

Smashing Toronto 2019Listen to talks from Brad Frost, Sarah Drasner, Phil Hawksworth, Jenny Shen, Kristina Podnar, Steven Hoober, Phil Nash, Dan Rose, Diana Mounter, Scott Jehl, and Chris Gannon.

SmashingConf SF 2019

SmashingConf SF 2019Watch and learn from Jen Simmons, Jason Pamental, Jeremy Wagner, Katie Sylor-Miller, Miriam Suzanne, Chris Coyier, Darin Senneff, Anna Migas, Sara Soueidan, and Brad Frost.

Last But Not Least, Smashing Podcast

If you haven’t found our Smashing Podcast yet, we’re already up to episode 11. Check out the episodes and subscribe here. Of course, we will also be bringing you an article every day here on Smashing Magazine, and perhaps if you find yourself with some extra time, you might like to join our authors and write for us.

Keep In Touch

We are obviously dealing with a fast changing situation, and can only take each day or week as it comes. Take every chance to keep in touch with your friends and peers via phone, text and video chat. Check in on people who might be having a hard time. Your outgoing extrovert friend may be the person who finds the isolation of the next few weeks the hardest. Look after yourselves, each other, and please wash your hands!

Smashing Editorial (il)
Catégories: Programmation

Accessible SVGs: Inclusiveness Beyond Patterns

jeu, 03/12/2020 - 12:30
Accessible SVGs: Inclusiveness Beyond Patterns Accessible SVGs: Inclusiveness Beyond Patterns Carie Fisher 2020-03-12T11:30:00+00:00 2020-03-12T13:35:15+00:00

Scalable Vector Graphics (SVGs) became a W3C open standard in 1999 — back when the new tech hotness was the Blackberry phone, Napster first invaded college dorms, and the Y2K bug sparked fear in us all. Fast forward to our modern digital world and you’ll notice that while the other tech trends have waned, SVGs are still around and thriving. This is partly due to SVGs having a small footprint for such high visual fidelity, in a world where bandwidth and performance matter more than ever — especially on mobile devices and situations/locations where data is at a premium. But also because SVGs are so flexible with their integrated styles, interactivity, and animation options. What we can do with SVGs today goes way beyond the basic shapes of yesteryear.

If we focus on the accessibility aspect of SVGs, we have come a long way as well. Today, we have many robust patterns and techniques to help us optimize inclusiveness. This is true regardless if you are creating icons, simple images, or more complex images. While the specific pattern you decide to use might vary depending on your particular situation and targeted WCAG conformance level — the reality is, most people stop there, focusing on code compliance and not actual end-users and their needs. If true inclusiveness lies beyond patterns — what other factors should we consider when designing and developing accessible SVGs?

Styling And Animating SVGs With CSS

Why is it so important to optimize your SVGs? Also, why even put in the effort to make them accessible? Sara Soueidan explais why and also how to style and animate with CSS. Read article →

SVG Color And Contrast

The primary focus of accessible SVGs is screen readers compliance — which is only part of the issue and part of the solution. Globally, people with low-vision and color blindness outnumber the people who are blind 14:1. We are talking a staggering 546 million in total (246 million low-vision users plus 300 million colorblind users) vs. 39 million users who are legally blind. Many people with low-vision and colorblindness do not rely on screen readers, but may instead use tools like browser resizing, customized stylesheets, or magnification software to help them see what is on the screen. To these 546 million people, screen reader output is probably not as important to them as making sure the color and contrast is great enough that they can see the SVG on the screen — but how do we go about checking for this?

Tools And Checks

The very first step you should take when designing your SVG color palette is to review the WCAG color contrast ratio guidelines. While SVGs and other icons were exempt from color contrast ratio requirements not too long ago (when targeting WCAG AA compliance), the recent update to the WCAG 2.1 guidelines have made it so all essential non-text imagery must adhere to a contrast ratio of at least 3:1 against adjacent colors. By essential, it means if your SVG was to vanish, would it fundamentally change the information or functionality of the content? If you can answer “no,” then you are likely exempt from this guideline. If you can answer “yes” or “maybe,” then you need to make sure your SVG color contrast ratios are in check.

House icon used in demo with light outline vs dark outline House icon used in demo with light outline vs dark outline — which is more accessible? (Large preview)

One example of an essential non-text image is an SVG icon used as a CTA button or link — such as we see in this home button. In this SVG, we see a line drawing of a house with no visual text. When we look into the code, we see the text “Home” in a span with a class called "sr-only" (screen reader only) on it. This class, along with the related CSS, hides the span text from sighted users, but not from AT users (this is just one example of an accessible image/graphic pattern).

This is a good first step, but choosing the correct SVG pattern is one piece of the puzzle — another piece is the color contrast between the icon and its background. Going back to the example, at first glance it seems like both SVGs could be accessible. Yet, when using a color contrast tool and testing the house icon against its background, we see the first SVG fails compliance with a color contrast ratio of 2:1 between the stroke (#8f8f8f) and the background (#cccccc), while the second SVG passes with a color contrast ratio of 3:1 between the stroke (#717171) and the background (#cccccc). By using the same accessible pattern, but taking an extra step and changing the stroke color to something a bit darker, we made our SVG more inclusive to a wider range of abilities.

To check for accessible color contrast ratios, there are many tools available for use. For a quick color contrast spot check, you could use the Contrast Checker in Chrome DevTools. For checking color contrast on non-coded designs, check out the Colour Contrast Analyser tool. And for a full-color palette review, A11y Color Palette is a great way to help you see which color combinations are the most accessible. Of course, make sure you try out a few of the tools and pick whatever works best for you and your team — the best tool is the one you actually use.

Light/Dark Mode

Beyond checking for color contrast ratios, you should also consider the increasingly popular and supported media query called @prefers-color-scheme that allows a user to choose a light or dark themed version of the website or app they are visiting. While this media query does not replace checking for color contrast ratios, it can give your users more choice when it comes to the overall experience of your website or app.

Allowing your users to choose their experience is always better than assuming you know what they want.

As with other media queries, to see the light/dark theme changes, the website or app developer must add additional code targeting the query. Going back to the house icon example from earlier, you can see in the following code that the SVG’s stroke, fill, and background colors are controlled by the CSS. Since these style elements are externally controlled and not hard-coded in the SVG markup, we can add a few extra lines of CSS to make the SVG work in a dark theme.

Light/default mode: House icon used in demo with a light background House icon used in demo with a light background (Large preview) body { background: #cccccc; } .nav-home1 { stroke: #8f8f8f; } .nav-home2 { stroke: #717171; } #home-svg1, #home-svg2 { fill: #64b700; } #home-door-svg1, #home-door-svg2 { fill: #b426ff; } Dark mode: House icon used in demo with a dark background House icon used in demo with a dark background (Large preview) @media (prefers-color-scheme: dark) { body { background: #333333; } .nav-home1 { stroke: #606060; } .nav-home2 { stroke: #7C7C7C; } }

See the Pen Light/Dark mode with SVGs by Carie Fisher.

See the Pen Light/Dark mode with SVGs by Carie Fisher.

As this example shows, setting up your designs to use CSS to control style elements means that creating a dark theme version of your SVG can be relatively simple. Conversely, if you have hard-coded styles into the SVG markup, you may need to reimagine your SVG in a way that allows CSS to have more control over the design. Or you may want to consider creating a completely new dark version of your SVG and swap out the light version when the theme preferences change. Just remember, if you do plan to show/hide different images based on the user mode, you also need to hide the nonvisible SVG from AT users!

Note: in this particular example, the default theme was already light so it made sense to also make that the default experience and build a dark theme for an alternate experience. Otherwise, if we started with a dark theme, we could have done the opposite making the dark theme the default experience and using @media (prefers-color-scheme: light) to create a light theme.

In the next example, we are looking at a more complex SVG with both light and dark mode versions via the @prefers-color-scheme media query. Our friend Karma Chameleon (in SVG form) has both a dark theme and a light/default theme. By changing your light/dark preference settings (Mac OS + Win OS dark mode settings) and navigating to a browser that supports @prefers-color-scheme media query, you can see the environment change. In the light/default mode, Karma Chameleon is sitting on a branch in a green forest surrounded by a fluttering red butterfly. In dark mode, she is sitting on a branch in space with a blue rocket zooming past. In both environments, her colors automatically change and her eyes move around.

See the Pen [Light/Dark mode + reduced motion with SVGs (Karma Chameleon)](https://codepen.io/smashingmag/pen/rNVJyoj) by Carie Fisher.

See the Pen Light/Dark mode + reduced motion with SVGs (Karma Chameleon) by Carie Fisher. In the light/default mode, Karma Chameleon is sitting on a branch in a green forest surrounded by a fluttering red butterfly. In both environments, her colors automatically change and her eyes move around. Karma Chameleon in light mode. (Large preview) In dark mode, she is sitting on a branch in space with a blue rocket zooming past. In both environments, her colors automatically change and her eyes move around. Karma Chameleon in dark mode. (Large preview) Color And Contrast Accessibility

While the above examples are fun ways to show what you can do with color and contrast and the @prefers-color-scheme media query, there are some really great real-world reasons to consider adding a dark theme including:

  • Dark themes are helpful to people with photophobia, or light sensitivity. People with photophobia can trigger headaches and migraines when they view a website or app that is too bright.
  • Some people find the text on a website or app easier to read in dark mode while others might find lighter themes are easier to read — it essentially comes down to giving your user a choice and allowing them to set their preference.
  • Unlike some other color or contrast based media queries like @inverted-colors (currently only supported by Safari) and @forced-colors (developed by Edge/IE engineers with Chromium support coming soon), the browser support is pretty universal for @prefers-color-scheme — so this media query is useful out of the box today and it should be sticking around for awhile. Plus with the recent changes to MS Edge using Chromium under the hood, there is even more support for this media query going forward (R.I.P. -ms-high-contrast-mode).
 prefers-color-scheme media feature - IE and Opera mobile being the only major non-supporting browsers at this time. Graph showing which browsers utilize the CSS at-rule: @media: prefers-color-scheme media feature. (Large preview) SVG Animation

In conjunction with color and contrast, how your SVG moves on the screen is another aspect to consider when designing and developing with inclusiveness in mind. The WCAG motion guidelines are clear: non-essential moving, blinking, or scrolling information that starts automatically, lasts more than five seconds, and is part of other page elements must allow the user to pause, stop, or hide it. But why do we need this rule?

For some users, moving, blinking, or scrolling content can be very distracting. People with ADHD and other attention deficit disorders might be so distracted by your animated SVGs they forget why they even went to your website/app in the first place. While for other people, motion can trigger physical reactions. For example, people with vestibular issues can become nauseous and dizzy when viewing movement. While others can be triggered to have a seizure when viewing content that flashes or is bright — a situation you obviously want to avoid.

While we all like being “delighted” with interesting website and app features — we need to strike a balance between being creative versus distracting (or harming) our users during their interaction with moving content.

“ Manual/Auto Stop

Since SVG animations, like other moving content, must not auto-play for more than five seconds, you must create a way for users to pause or stop the animation. One way to do this is to create a JS toggle button to play/pause the animation.

If your SVG is large or is the main feature of your website (e.g. animations that pop in and out as you scroll down a page) a pause/play button at the top of the screen might be a realistic option to control the entire experience of the page. If your SVGs are smaller in scale or related to user input (e.g. an animation happens when a user submits a form), a pause/play button might not be realistic for each individual image, so an alternative option is to code the animation to stop at five seconds vs. playing it on an infinite loop. Reduced Motion

In addition to using a pause/play option or creating a finite animation loop, you may also consider adding @prefers-reduced-motion media query to address the animation in your SVGs. Similar to the light/dark theme example, the @prefers-reduced-motion media query checks the user’s settings for motion restrictions and then implements a visual experience based on their preference. In the case of @prefers-reduced-motion, a user can choose to minimize the amount of animation or motion they see.

In the following example, the animated SVG “writes out” a word as the page loads — this is its default animation. In the reduced motion version, the SVG is stationary and the word loads without the animation. Depending on the complexity of your SVG animation and how you want the reduced motion experience to look, the amount of extra code involved can vary.

See the Pen [Reduced motion with SVGs](https://codepen.io/smashingmag/pen/dyodvqm) by Carie Fisher.

See the Pen Reduced motion with SVGs by Carie Fisher. Default motion: Movie depicting text being written out via code not adhering to WCAG best practices on movementThe default motion version of the text script (Large preview) .svg-color { stroke: #ff4b00; } #a11y-svg { stroke-linecap: round; padding: 0.25rem; stroke-dasharray: 1000; stroke-dashoffset: 0; -webkit-animation: dash 5s linear forwards; animation: dash 5s linear forwards; overflow: visible; font-size: 100px; height: 0; margin: 10rem 0 5rem; position: relative; } #a11y-svg-design { cursor: pointer; stroke-width: 2px; } @-webkit-keyframes dash { from { stroke-dashoffset: 1000; fill: transparent; } to { stroke-dashoffset: 0; fill: #ff4b00; } } Reduced motion: Still screenshot of the word accessibility in orange with no movement. The reduced motion version of the text script. (Large preview) @media (prefers-reduced-motion: reduce) { #a11y-svg { animation: none; fill: #ff4b00; } }

Keep in mind, having @prefers-reduced-motion code in place is one step in making your SVGs more accessible, but you also need to consider the way the motion is reduced. For example, let’s say you create a slowed-down version of your SVG animation using @prefers-reduced-motion. However, the slower version is on an infinite loop so the animation lasts more than five seconds, which violates one part of the WCAG rules on motion. If you instead create a reduced motion version of your animated SVG that stops the animation at five seconds, then it would pass that part of the rule. This subtle code change equals two completely different user experiences.

In the next example, Karma Chameleon is back with a @prefers-reduced-motion media query and related code. By changing your motion settings (Mac, Win, Android, and iOS settings) and using a browser that supports @prefers-reduced-motion media query, you can see the animation change. In the light mode with reduced motion, Karma Chameleon in a forest with a stationary red butterfly. In dark mode with reduced motion, she is in space with a stationary blue rocket in the background. In both environments, her colors and eyes are also stationary, as the original SVG animation is completely removed.

See the Pen [Light/Dark mode + reduced motion with SVGs (Karma Chameleon)](https://codepen.io/smashingmag/pen/rNVJyoj) by Carie Fisher.

See the Pen Light/Dark mode + reduced motion with SVGs (Karma Chameleon) by Carie Fisher. In light mode + reduced motion, Karma Chameleon is in a forest with a stationary red butterfly. In both environments, her colors and eyes are also stationary, as the original SVG animation is completely removed. Karma Chameleon in light mode + no movement. (Large preview) In dark mode + reduced motion, Karma Chameleon is in space with a stationary blue rocket in the background. In both environments, her colors and eyes are also stationary, as the original SVG animation is completely removed Karma Chameleon in dark mode + no movement. (Large preview) Animation Accessibility

From an accessibility standpoint, there are some great reasons to consider limiting the movement on your screen or providing alternative animations in your SVGs including:

  • Less is more! Keeping your SVG animations simple for people with cognitive and attention disorders can help with your overall user experience. This is especially true for SVGs critical to the content or functionality of your website or app — such as navigation, buttons, links, or any animation triggered by user input.
  • Don’t make people sick! Some people with seizure, vestibular, and vision disorders can trigger physical reaction by motion in your SVGs, so please be responsible with your designs and code. Note: you should double-check any animated SVGs that could be problematic in the flashing/blinking area, by using the free Photosensitive Epilepsy Analysis Tool (PEAT) to ensure you don’t trigger seizures with your content.
  • Most major browsers now support @prefers-reduced-motion media query both on desktop and mobile devices — meaning that more people can limit their exposure to unwanted movement on their screens. Unlike the media query @prefers-color-scheme which has a lot of competitors, there is currently no other motion reducing media query available.
 prefers-reduced-motion media feature - IE and Opera mobile being the only major non-supporting browsers at this time; globally accepted 82.47% Graph showing which browsers utilize the CSS at-rule: @media: prefers-reduced-motion media feature (Large preview) Wrapping Up

Color, contrast, and animation is at the heart of every SVG. Studies report that these visual elements hold intrinsic meaning, contribute to brand recognition, and are tied to a company’s perceived value — making SVGs a very large area where designers and developers can have a direct and immediate impact on our users.

But it is also important that we don’t just think of SVG accessibility as something to help “other people” — because who hasn’t found themselves in a situation where they have to battle glare on a device screen? Or you have a migraine and SVGs keep floating on and off the screen making you sick instead of “delighted”. Or maybe you visit a website in a low-light setting and the text is hard to read due to the gray-on-gray color scheme?

With the use of accessibility tools, WCAG guidelines, and the continued addition and support of new CSS media queries to allow for more choice, we can impact all people in a more responsible and inclusive way.

For true digital inclusivity is understanding that every single one of us can benefit from more accessible designs and code.

Smashing Editorial (dm, yk, il)
Catégories: Programmation

Creating Secure Password Flows With NodeJS And MySQL

mer, 03/11/2020 - 12:30
Creating Secure Password Flows With NodeJS And MySQL Creating Secure Password Flows With NodeJS And MySQL Darshan Somashekar 2020-03-11T11:30:00+00:00 2020-03-11T13:35:50+00:00

If you’re anything like me, you’ve forgotten your password more than once, especially on sites you haven’t visited in a while. You’ve probably also seen, and/or been mortified by, reset password emails that contain your password in plain text.

Unfortunately, the reset password workflow gets short shrift and limited attention during application development. This not only can lead to a frustrating user experience, but can also leave your application with gaping security holes.

We’re going to cover how to build a secure reset password workflow. We’ll be using NodeJS and MySQL as our base components. If you’re writing using a different language, framework, or database, you can still benefit from following the general "Security Tips" outlined in each section.

A reset password flow consists of the following components:

  • A link to send the user to the start of the workflow.
  • A form that lets the user submit their email.
  • A lookup that validates the email and sends an email to the address.
  • An email that contains the reset token with an expiry that allows the user to reset their password.
  • A form that let’s the user generate a new password.
  • Saving the new password and letting the user log in again with the new password.

Besides Node, Express & MySQL, we'll be using the following libraries:

  • Sequelize ORM
  • Nodemailer

Sequelize is a NodeJS database ORM that makes it easier to run database migrations as well as security create queries. Nodemailer is a popular NodeJS email library that we’ll use to send password reset emails.

Security Tip #1

Some articles suggest secure password flows can be designed using JSON Web Tokens (JWT), which eliminate the need for database storage (and thus are easier to implement). We don’t use this approach on our site, because JWT token secrets are usually stored right in code. We want to avoid having ‘one secret’ to rule them all (for the same reason you don’t salt passwords with the same value), and therefore need to move this information into a database.

Installation

First, install Sequelize, Nodemailer, and other associated libraries:

$ npm install --save sequelize sequelize-cli mysql crypto nodemailer

In the route where you want to include your reset workflows, add the required modules. If you need a refresher on Express and routes, check out their guide.

const nodemailer = require('nodemailer');

And configure it with your email SMTP credentials.

const transport = nodemailer.createTransport({ host: process.env.EMAIL_HOST, port: process.env.EMAIL_PORT, secure: true, auth: { user: process.env.EMAIL_USER, pass: process.env.EMAIL_PASS } });

The email solution I'm using is AWS's Simple Email Service, but you can use anything (Mailgun, etc).

If this is your first time setting up your email sending service, you'll need to spend some time configuring the appropriate Domain Keys and setting up authorizations. If you use Route 53 along with SES, this is super simple and done virtually automatically, which is why I picked it. AWS has some tutorials on how SES works with Route53.

Security tip #2

To store the credentials away from my code, I use dotenv, which lets me create a local .env file with my environment variables. That way, when I deploy to production, I can use different production keys that aren’t visible in code, and therefore lets me restrict permissions of my configuration to only certain members of my team.

Database Setup

Since we're going to be sending reset tokens to users, we need to store those tokens in a database.

I am assuming you have a functioning users table in your database. If you’re using Sequelize already, great! If not, you may want to brush up on Sequelize and the Sequelize CLI.

If you haven’t used Sequelize yet in your app, you can set it up by running the command below in your app’s root folder:

$ sequelize init

This will create a number of new folders in your setup, including migrations and models.

This will also create a config file. In your config file, update the development block with the credentials to your local mysql database server.

Let's use Sequelize's CLI tool to generate the database table for us.

$ sequelize model:create --name ResetToken --attributes email:string,token:string,expiration:date,used:integer $ sequelize db:migrate

This table has the following columns:

  • Email address of user,
  • Token that has been generated,
  • Expiration of that token,
  • Whether the token has been used or not.

In the background, sequelize-cli is running the following SQL query:

CREATE TABLE `ResetTokens` ( `id` int(11) NOT NULL AUTO_INCREMENT, `email` varchar(255) DEFAULT NULL, `token` varchar(255) DEFAULT NULL, `expiration` datetime DEFAULT NULL, `createdAt` datetime NOT NULL, `updatedAt` datetime NOT NULL, `used` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Verify this worked properly using your SQL client or the command line:

mysql> describe ResetTokens; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | email | varchar(255) | YES | | NULL | | | token | varchar(255) | YES | | NULL | | | expiration | datetime | YES | | NULL | | | createdAt | datetime | NO | | NULL | | | updatedAt | datetime | NO | | NULL | | | used | int(11) | NO | | 0 | | +------------+--------------+------+-----+---------+----------------+ 7 rows in set (0.00 sec) Security Tip #3

If you're not currently using an ORM, you should consider doing so. An ORM automates the writing and proper escaping of SQL queries, making your code more readable and more secure by default. They’ll help you avoid SQL injection attacks by properly escaping your SQL queries.

Set Up Reset Password Route

Create the get route in user.js:

router.get('/forgot-password', function(req, res, next) { res.render('user/forgot-password', { }); });

Then create the POST route, which is the route that is hit when the reset password form is posted. In the code below, I’ve included a couple of important security features.

Security Tips #4-6
  1. Even if we don’t find an email address, we return 'ok' as our status. We don’t want untoward bots figuring out what emails are real vs not real in our database.
  2. The more random bytes you use in a token, the less likely it can be hacked. We are using 64 random bytes in our token generator (do not use less than 8).
  3. Expire the token in 1 hour. This limits the window of time the reset token works.
router.post('/forgot-password', async function(req, res, next) { //ensure that you have a user with this email var email = await User.findOne({where: { email: req.body.email }}); if (email == null) { /** * we don't want to tell attackers that an * email doesn't exist, because that will let * them use this form to find ones that do * exist. **/ return res.json({status: 'ok'}); } /** * Expire any tokens that were previously * set for this user. That prevents old tokens * from being used. **/ await ResetToken.update({ used: 1 }, { where: { email: req.body.email } }); //Create a random reset token var fpSalt = crypto.randomBytes(64).toString('base64'); //token expires after one hour var expireDate = new Date(); expireDate.setDate(expireDate.getDate() + 1/24); //insert token data into DB await ResetToken.create({ email: req.body.email, expiration: expireDate, token: token, used: 0 }); //create email const message = { from: process.env.SENDER_ADDRESS, to: req.body.email, replyTo: process.env.REPLYTO_ADDRESS, subject: process.env.FORGOT_PASS_SUBJECT_LINE, text: 'To reset your password, please click the link below.\n\nhttps://'+process.env.DOMAIN+'/user/reset-password?token='+encodeURIComponent(token)+'&email='+req.body.email }; //send email transport.sendMail(message, function (err, info) { if(err) { console.log(err)} else { console.log(info); } }); return res.json({status: 'ok'}); });

You’ll see a User variable referenced above — what is this? For the purposes of this tutorial, we’re assuming you have a User model that connects to your database to retrieve values. The code above is based on Sequelize, but you can modify as needed if you query the database directly (but I recommend Sequelize!).

We now need to generate the view. Using Bootstrap CSS, jQuery, and the pug framework built into the Node Express framework, the view looks like the following:

extends ../layout block content div.container div.row div.col h1 Forgot password p Enter your email address below. If we have it on file, we will send you a reset email. div.forgot-message.alert.alert-success(style="display:none;") Email address received. If you have an email on file we will send you a reset email. Please wait a few minutes and check your spam folder if you don't see it. form#forgotPasswordForm.form-inline(onsubmit="return false;") div.form-group label.sr-only(for="email") Email address: input.form-control.mr-2#emailFp(type='email', name='email', placeholder="Email address") div.form-group.mt-1.text-center button#fpButton.btn.btn-success.mb-2(type='submit') Send email script. $('#fpButton').on('click', function() { $.post('/user/forgot-password', { email: $('#emailFp').val(), }, function(resp) { $('.forgot-message').show(); $('#forgotPasswordForm').remove(); }); });

Here's the form on the page:

reset password field for your secure reset password workflow Your reset password form. (Large preview)

At this point, you should be able to fill out the form with an email address that's in your database, and then receive a reset password email at that address. Clicking the reset link won't do anything yet.

Set Up “Reset Password” Route

Now let's go ahead and set up the rest of the workflow.

Add the Sequelize.Op module to your route:

const Sequelize = require('sequelize'); const Op = Sequelize.Op;

Now let's build the GET route for users that have clicked on that reset password link. As you’ll see below, we want to make sure we’re validating the reset token appropriately.

Security Tip #7:

Ensure you’re only looking up reset tokens that have not expired and have not been used.

For demonstration purposes, I also clear up all expired tokens on load here to keep the table small. If you have a large website, move this to a cronjob.

router.get('/reset-password', async function(req, res, next) { /** * This code clears all expired tokens. You * should move this to a cronjob if you have a * big site. We just include this in here as a * demonstration. **/ await ResetToken.destroy({ where: { expiration: { [Op.lt]: Sequelize.fn('CURDATE')}, } }); //find the token var record = await ResetToken.findOne({ where: { email: req.query.email, expiration: { [Op.gt]: Sequelize.fn('CURDATE')}, token: req.query.token, used: 0 } }); if (record == null) { return res.render('user/reset-password', { message: 'Token has expired. Please try password reset again.', showForm: false }); } res.render('user/reset-password', { showForm: true, record: record }); });

Now let's create the POST route which is what is hit once the user fills out their new password details.

Security tip #8 through 11:
  • Make sure that the passwords match and meet your minimum requirements.
  • Check the reset token again to make sure it has not been used and has not expired. We need to check it again because the token is being sent by a user via the form.
  • Before resetting the password, mark the token as used. That way, if something unforeseen happens (server crash, for example), the password won’t be reset while the token is still valid.
  • Use a cryptographically secure random salt (in this case, we use 64 random bytes).
router.post('/reset-password', async function(req, res, next) { //compare passwords if (req.body.password1 !== req.body.password2) { return res.json({status: 'error', message: 'Passwords do not match. Please try again.'}); } /** * Ensure password is valid (isValidPassword * function checks if password is >= 8 chars, alphanumeric, * has special chars, etc) **/ if (!isValidPassword(req.body.password1)) { return res.json({status: 'error', message: 'Password does not meet minimum requirements. Please try again.'}); } var record = await ResetToken.findOne({ where: { email: req.body.email, expiration: { [Op.gt]: Sequelize.fn('CURDATE')}, token: req.body.token, used: 0 } }); if (record == null) { return res.json({status: 'error', message: 'Token not found. Please try the reset password process again.'}); } var upd = await ResetToken.update({ used: 1 }, { where: { email: req.body.email } }); var newSalt = crypto.randomBytes(64).toString('hex'); var newPassword = crypto.pbkdf2Sync(req.body.password1, newSalt, 10000, 64, 'sha512').toString('base64'); await User.update({ password: newPassword, salt: newSalt }, { where: { email: req.body.email } }); return res.json({status: 'ok', message: 'Password reset. Please login with your new password.'}); }); And again, the view: extends ../layout block content div.container div.row div.col h1 Reset password p Enter your new password below. if message div.reset-message.alert.alert-warning #{message} else div.reset-message.alert(style='display:none;') if showForm form#resetPasswordForm(onsubmit="return false;") div.form-group label(for="password1") New password: input.form-control#password1(type='password', name='password1') small.form-text.text-muted Password must be 8 characters or more. div.form-group label(for="password2") Confirm new password input.form-control#password2(type='password', name='password2') small.form-text.text-muted Both passwords must match. input#emailRp(type='hidden', name='email', value=record.email) input#tokenRp(type='hidden', name='token', value=record.token) div.form-group button#rpButton.btn.btn-success(type='submit') Reset password script. $('#rpButton').on('click', function() { $.post('/user/reset-password', { password1: $('#password1').val(), password2: $('#password2').val(), email: $('#emailRp').val(), token: $('#tokenRp').val() }, function(resp) { if (resp.status == 'ok') { $('.reset-message').removeClass('alert-danger').addClass('alert-success').show().text(resp.message); $('#resetPasswordForm').remove(); } else { $('.reset-message').removeClass('alert-success').addClass('alert-danger').show().text(resp.message); } }); });

This is what it should look like:

reset password form for your secure reset password workflow Your reset password form. (Large preview) Add The Link To Your Login Page

Lastly, don’t forget to add a link to this flow from your login page! Once you do this, you should have a working reset password flow. Be sure to test thoroughly at each stage of the process to confirm everything works and your tokens have a short expiration and are marked with the correct status as the workflow progresses.

Next Steps

Hopefully this helped you on your way to coding a secure, user-friendly reset password feature.

  • If you are interested in learning more about cryptographic security, I recommend Wikipedia’s summary (warning, it’s dense!).
  • If you want to add even more security to your app’s authentication, look into 2FA. There are a lot of different options out there.
  • If I’ve scared you off from building your own reset password flow, you can rely on third-party login systems like Google and Facebook. PassportJS is a middleware you can use for NodeJS that implements these strategies.
Smashing Editorial (dm, yk, il)
Catégories: Programmation

Make Honest Design Work For Digital Business, With “Ethical Design Handbook”

mar, 03/10/2020 - 13:17
Make Honest Design Work For Digital Business, With “Ethical Design Handbook” Make Honest Design Work For Digital Business, With “Ethical Design Handbook” Vitaly Friedman 2020-03-10T12:17:00+00:00 2020-03-10T13:36:44+00:00

Many business models thrive on ingeniously deceptive and manipulative digital products. Not because they have to; mostly because dark patterns have become such an accepted norm. But what happens when ad-blockers, cross-browser tracking protection and data regulation (e.g. GDPR & CCPA) become a norm, too? That's when an honest, ethical design could be a competitive advantage.

To grow a sustainable business, we need to learn how to leave dark patterns behind. We also need to figure out how to make honest digital products financially viable. Products that enable and respect customer choices and are built and designed with ethics in mind. That's exactly why we created a new book. Jump to the table of contents ↓

Meet Ethical Design Handbook, our new book with practical techniques and blueprints on how companies ridden with questionable practices can shift towards better, sustainable design. Download a free PDF excerpt (5 MB).

Print + eBook { "sku": "ethical-design-handbook", "type": "Book", "price": "39.00", "prices": [{ "amount": "39.00", "currency": "USD", "items": [ {"amount": "29.00", "type": "Book"}, {"amount": "10.00", "type": "E-Book"} ] }, { "amount": "39.00", "currency": "EUR", "items": [ {"amount": "29.00", "type": "Book"}, {"amount": "10.00", "type": "E-Book"} ] } ] } $ 39.00 Get Print + eBook

Quality hardcover. Free worldwide shipping. 100 days money-back-guarantee.

eBook { "sku": "ethical-design-handbook", "type": "E-Book", "price": "19.00", "prices": [{ "amount": "19.00", "currency": "USD" }, { "amount": "19.00", "currency": "EUR" } ] } $ 19.00 Free! Get the eBook

DRM-free, of course. ePUB, Kindle, PDF.
Included with Smashing Membership.

Get the eBook

Download PDF, ePUB, Kindle.
Thanks for being smashing! ❤️

About The Book

When we set out to write this book, we wanted to develop a new type of working framework to empower people to practice ethical design in their business, in their teams, and with their products. The reason was simple: too many products we use today have become machines for tricking customers into decisions they never intended to make. That’s not quite the web we want to see around us.

The cover of the Ethical Design Handbook

It's not just the poor state of the web that brings us here though. It's the lack of alternatives that companies can rely on. In light of new data regulation and tracking protection, there are some critical questions that only few companies have addressed yet:

  • What happens if you can’t get access to personal data that’s been feeding the machine all this time?
  • What if your competitors discover an alternative business model way before you do?
  • What if you can’t track and target customers wandering from one website to another?
  • What happens when ad-blocking becomes mainstream and your advertising scripts are dismissed by crafty blockers?
  • How should the work of marketing teams change with new regulations, such as GDPR and CCPA?
  • What competitive advantages can your business gain by focusing on privacy and transparency?

Ethical Design Handbook explores alternative, sustainable business models and shows how businesses can move towards ethical design and become more profitable as a result. It’s a very practical and tactical guide for designers, developers and management, with case studies and techniques applicable to every digital product.

The book features interface design examples that take ethical design principles into the account. Large preview. Table Of Contents

In the book, you’ll learn how to:

  1. Help companies understand ethical design,
  2. Justify and prove a business case,
  3. Grow a sustainable business based on transparency and honesty,
  4. Balance data collection and privacy,
  5. Work within new legislation (GDPR/CCPA),
  6. Evaluate and improve design decisions,
  7. Embed ethical design into your workflow,
  8. Gradually transform your organization.

368 pages. Free shipping worldwide. The eBook is available as PDF, ePUB, and Amazon Kindle. Written by Trine Falbe, Martin Michael Frederiksen and Kim Andersen. Get the book now.

Print + eBook { "sku": "ethical-design-handbook", "type": "Book", "price": "39.00", "prices": [{ "amount": "39.00", "currency": "USD", "items": [ {"amount": "29.00", "type": "Book"}, {"amount": "10.00", "type": "E-Book"} ] }, { "amount": "39.00", "currency": "EUR", "items": [ {"amount": "29.00", "type": "Book"}, {"amount": "10.00", "type": "E-Book"} ] } ] } $ 39.00 Get Print + eBook

Quality hardcover. Free worldwide shipping. 100 days money-back-guarantee.

eBook { "sku": "ethical-design-handbook", "type": "E-Book", "price": "19.00", "prices": [{ "amount": "19.00", "currency": "USD" }, { "amount": "19.00", "currency": "EUR" } ] } $ 19.00 Free! Get the eBook

DRM-free, of course. ePUB, Kindle, PDF.
Included with Smashing Membership.

Get the eBook

Download PDF, ePUB, Kindle.
Thanks for being smashing! ❤️

About The Authors

Trine FalbeTrine Falbe is a human-centered UX strategist, designer and teacher who works in the intersection between people and business. Trine is deeply passionate about ethical design and designing for children, and she is also a keynote speaker at conferences and a UX advisor in strategic projects.

Martin Michael FrederiksenAs a serial entrepreneur since the very first browser, Martin Michael Frederiksen was born with a practical appreciation for the crossroads between business and digital development. He has published the books Cross Channel and the CEO’s Guide to IT Projects That Cannot Fail. He works as an independent consultant for businesses that need a devil’s advocate when trying out new strategies and ideas.

Kim AndersenAfter training at an international advertising agency, Kim Andersen quickly left print media for digital design. Owing to his amazing memory he always leaves design meetings with an empty notebook, only to attend the following meeting armed with drawings where nothing has been forgotten and everything is drawn in great detail. He owns the digital design studio Onkel Kim, and he prefers difficult and complex design tasks where the brain is working overtime.

Technical Details
  • ISBN: 978-3-945749-83-8 (print)
  • Quality hardcover, stitched binding, ribbon page marker.
  • Free shipping worldwide, airmail from Germany.
    (Check your delivery times.)
  • 100-days-money-back-guarantee: no ifs or buts.
  • The eBook is available as PDF, ePUB, and Amazon Kindle.
  • Get the book right away.
A quality hardcover, with a dark ribbon, thick paper and a glossy effect on the cover. Photo by Drew McLellan. Large view. Testimonials Helle Martens“This is the book designers have all been missing: A practical reference book on how to work ethically in design. Starting with the why - what does "Ethical Design" mean, and why is this book even necessary or important, the book easily morphs into the business value of ethical design, best practices in ethical design, and how you can influence positive change.”

Helle Martens, UX consultant Heather Burns“It’s easy to feel like we’ve lost the web we used to love. The Ethical Design Handbook is an essential guide to reclaiming it. Packed with practical resources and guidance for designers, developers, and project managers, it will help you to integrate a higher standard of professionalism into your work on the web. Refreshingly, this book contains no inspirational waffle, public shaming, or lectures on morality. What it does contain is proven techniques, standards, and strategies for getting the job done while protecting your users.

That matters more than you think. As policymakers seek to crack down on the tech giants who have diminished the web for us all, adopting the techniques in this book can be an essential way of defending our craft from heavy-handed regulation.”

Heather Burns, Tech policy consultant Per Axbom“I’ve just finished reading The Ethical Design Handbook and am both brimming with new ideas and am more hopeful about the future. The authors bring new tools to the table, and also do a good job of reminding designers how many of our current tools already help us contribute to positive impact. The trick is that we have to make sure to actually put in the effort, and have some cake to keep us going.”

Per Axbom, Commmunication theorist Stephen HayThe Ethical Design Handbook is exactly what its title implies: a gentle, persuasive, perspective-giving guide to how you can become a better designer without selling your soul.”

Stephen Hay, Creative Director, Rabobank Bruce LawsonThe Ethical Design Handbook should probably be compulsory reading for all tech workers.”

Bruce Lawson, Web standards advocate The book features scorecards and blueprints (Excel spreadsheets), applicable to your work right away. Large view. Community Matters ❤️

With The Ethical Design Handbook, we’ve tried to create a very focused handbook with applicable, long-living solutions to introduce a positive change in companies ridden with dark patterns and questionable practices.

There is quite a bit of work to do on the web, but our hope is that with this book, you will be equipped with enough tooling to slowly move a company towards a more sustainable and healthy digital footprint.

Producing a book takes quite a bit of time, and we couldn’t pull it off without the support of our wonderful community. A huge shout-out to Smashing Members for their ongoing support in our adventures. As a result, the eBook is and always will be free for Smashing Members. Plus, Members get a friendly discount when purchasing their printed copy.

Stay smashing, and thank you for your ongoing support, everyone!

Smashing Cat on a bicycle with The Ethical Design Handbook in its bike basket. Print + eBook { "sku": "ethical-design-handbook", "type": "Book", "price": "39.00", "prices": [{ "amount": "39.00", "currency": "USD", "items": [ {"amount": "29.00", "type": "Book"}, {"amount": "10.00", "type": "E-Book"} ] }, { "amount": "39.00", "currency": "EUR", "items": [ {"amount": "29.00", "type": "Book"}, {"amount": "10.00", "type": "E-Book"} ] } ] } $ 39.00 Get Print + eBook

Quality hardcover. Free worldwide shipping. 100 days money-back-guarantee.

eBook { "sku": "ethical-design-handbook", "type": "E-Book", "price": "19.00", "prices": [{ "amount": "19.00", "currency": "USD" }, { "amount": "19.00", "currency": "EUR" } ] } $ 19.00 Free! Get the eBook

DRM-free, of course. ePUB, Kindle, PDF.
Included with Smashing Membership.

Get the eBook

Download PDF, ePUB, Kindle.
Thanks for being smashing! ❤️

More Smashing Books

Promoting best practices and providing you with practical tips to master your daily coding and design challenges has always been (and will be) at the core of everything we do at Smashing. In the past few years, we were very lucky to have worked together with some talented, caring people from the web community to publish their wealth of experience as printed books that stand the test of time. Alla, Adam and Heydon are some of these people. Have you checked out their books already?

Design SystemsDesign Systems

Add to cart $39

Inclusive ComponentsInclusive Components

Add to cart $39

Form Design PatternsForm Design Patterns

Add to cart $39

The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook. The Ethical Design Handbook.
Catégories: Programmation

Smashing Podcast Episode 11 With Eduardo Bouças: What Is Sourcebit?

mar, 03/10/2020 - 12:30
Smashing Podcast Episode 11 With Eduardo Bouças: What Is Sourcebit? Smashing Podcast Episode 11 With Eduardo Bouças: What Is Sourcebit? Drew McLellan 2020-03-10T11:30:00+00:00 2020-03-10T13:36:44+00:00

Eduardo Bouças In this episode of the Smashing Podcast, we’re talking about an interesting open-source tool called Sourcebit. How can it help our content workflow with JAMstack sites? I spoke to developer Eduardo Bouças to find out.

Show Notes Weekly Update Transcript

Drew McLellan: He’s a web developer, technologist, writer and occasional public speaker with a strong track record of working on open source projects. He works as a software engineer on the JAMstack site management platform, Stackbit, and develops open source tools such as Staticman, Speedtracker, and Sourcebit. So we know he’s an expert in the modern web platform. But did you know he’s deathly allergic to Wednesday? My Smashing friends please welcome Eduardo Boucas. Hi, Eduardo, how are you?

Eduardo Bouças: I’m Smashing.

Drew: I wanted to talk to you today about a tool that I know you’ve been working on called Sourcebit. I know you do a lot of work both at the day job Stackbit, and personally in your own time, around sort of tooling with sort of what we now call JAMstack sites. So before we talk about what Sourcebit does itself, perhaps you can tell us a bit about the sort of scenario with the JAMstack site that might lead to somebody needing a tool like Sourcebit.

Eduardo: Sure. So to go back in time a little bit when I started using a static site generator. My first encounter with a JAMstack was with Jekyll, as I’m sure many people are as well. And when I started using Jekyll for my site, the authoring experience was a bit cumbersome. So it involved manually editing Markdown files on my local machine and then pushing them to get repo and then the thing would get integrated and built. And that’s still a workflow that exists today and that many people use and it makes sense for a lot of people in a lot of organizations. But, first of all, it doesn’t scale very well if you have like a larger team and especially if you have people from less technical backgrounds who may not be comfortable with Markdown or with using Git or with that whole pushing to a GitHub repo workflow.

Eduardo: And so it makes a lot of sense, in my opinion to couple a static site generator with what is now these days called a headless or a decoupled CMS. So if you come from a more traditional web development background where you might use something like WordPress, a headless CMS is something that behaves in a very similar way. So you still have this interface where you can author your content, and you have a nice WYSIWYG editor and media management and everything.

Eduardo: But the output of such a platform is not a fully formatted HTML page. And instead, the content is exported in a way in a format that is agnostic of any technology or any tech stack. And so that content is, it’s possible to integrate that content with your static site generator. And that’s why I think it makes a lot of sense to couple a headless CMS with a static site generator because you kind of get the best of both worlds in the sense that you get the performance, the security and the simplicity of using a static site generator, but at the same time, you still get kind of a rich authoring experience by using a nice editorial interface.

Eduardo: And even though it makes a lot of sense to couple those two tools together, it’s not particularly straightforward to integrate them. Especially if you’re using a more traditional file based static site generator, such as Jekyll or Hugo, where everything has to live as a file. So how do you take that content that lives in this headless CMS? And how do you translate that into files that your static site generator can understand and process?

Eduardo: As you said, I’m super passionate about creating tools for developers and particularly creating tools that allows developers to use the JAMstack paradigm with as little friction as possible. And that’s where source that comes in. That’s why I’m super passionate about this project in particular. So the idea is, that Sourcebit allows you to connect to any API based data source such as a headless CMS, you sort of tell it where your content lives, you help it make some sense of the structure of your content. And then Sourcebit takes care of sucking all that content down and writing it into the files with the formats into location static site generator is expecting. So that’s kind of the idea behind Sourcebit.

Drew: So rather than having authors work directly with markdown files, that your static site generator turns to a site, you’ve got your authors working with another tool, a headless CMS, maybe something like Contentful or even WordPress, and then Sourcebit is the bit in between that gets that content from where it’s been authored, and translates it in a way into a format that the static site generator can turn into a static site?

Eduardo: Exactly, yeah. And the way that it could, kind of see two different ways of using the tool that can help developers. One is making Sourcebit part of your deployment routine. So if you’re using a hosting platform like Netlify, for example, and you configure your deploy commands to be a Hugo build, is it the build command for Hugo or something said, so the command that generates the static files for Hugo, you would also have another command as part of that routine. That would be something like Sourcebit fetch. And so at build time, Sourcebit will go pull all the other data, generate all the files that Hugo needs. And then the whole deployment will already use those files and deploy all the content that is coming from the CMS. So that’s kind of one possible use case for Sourcebit.

Eduardo: The other one is to use Sourcebit in a local development workflow. So you can run Sourcebit with something that we call the watch mode. And so Sourcebit keeps looking for changes in the remote data source, so in this case, headless CMS. And so whenever you publish an article or you change an entry into CMS Sourcebit will acknowledge that and it will regenerate all the files for you locally. And so what that means for a developer working locally is that you can have your CMS window next to your Jekyll or Hugo site, running locally, and then you can see changes happening in real time. You change something on the CMS and then you can see that change being reflected on the local side, which I find super useful. So those are kind of the two ways that you could get use Sourcebit.

Drew: So I guess for all that to work Sourcebit has to know about both the system that the content’s stored in and the way that the static site generator needs the files organized in the file system. How do those two things work?

Eduardo: Sourcebit is a plugin-based architecture. So the idea is that you’re going to have different types of plugins that will accomplish different tasks. We have something that we call the source plugins, which are solely responsible for connecting to a data source like Contentful, for example, and they will connect to that data source, they will pull content and they will normalize that content into a format that is kind of agnostic of data source such that if you want to connect multiple data sources, so you’re using WordPress and Contentful, and Sanity, for example, all the content from those data sources will be normalized into a format that is kind of standardized across the board. So the responsibility of the source plugins will be to just that, to connect to a data source, normalize the content and put them into a bucket of data.

Eduardo: And then you have another type of plugin which we call a target plugin. And the target plugin has no knowledge whatsoever about where the data is coming from, but it knows about a particular piece of software that is expecting that data for example, you might have a target plugin for Hugo a target plugin for Jekyll. So the target plug in will be responsible for writing that data into specific format and the specific locations that the static site generated is expecting.

Eduardo: And then you might have other types of plugins that don’t know about the source and don’t know about destination. They’re just responsible for kind of massaging the data and doing all sorts of transformations in between. So that’s kind of the way that the tool is organized. And I think the benefit of that approach is that each plugin is only concerned about a specific area. So if you are, let’s say that you’re maintaining the source plugin for Contentful, you don’t ever need to worry about what static site generators will be supported. You just worry about maintaining that specific plugin that we take care of making sure that it can be plugged in into any combination of static site generators or different outputs that you want to use.

Drew: So is it possible to have multiple sources running at once and use a Sourcebit more like a content aggregator to pull them from lots of different sources at once?

Eduardo: Yes, yes, it’s totally possible. And that’s why we kind of use that principle of normalizing the data, because you might have as many data sources as you want. And then when a plugin comes in to kind of transform that data, it doesn’t really care where the data comes from, everything is treated the same. So it’s totally possible to do that. You can configure as many source plugins as you want. And so it’ll pull data from as many places as you want.

Drew: Yeah, that could be quite interesting. Could you think of a corporate website might have a blog in there, it might have copy from marketing, it might have job openings coming from an HR system. And you could potentially configure Sourcebit to pull that into one location before generating the site, which is quite an exciting prospect, I think.

Eduardo: Yeah, yeah. And CMS is are just one possible data source that you might use this tool with. For example, one of my colleagues that started was creating a source plugin that pulls data from Reddit, for example. And that’s just one very simple example of one possible data source. So as you say, it could get quite interesting because you might be pulling data from a CMS, might be pulling data from Reddit, Twitter or an HR platform and it just all comes down together nicely. So, yeah, it’s a possible use case for it for sure.

Drew: What sort of plugins exist at the moment for different sources?

Eduardo: So we launched the first kind of public version of the tool last week. And we launched with a two source plugins and two target plugins. So the source plugins are for Contentful and Sanity. And the target plugins are for Jacqueline and Hugo. We will keep working on your plugins internally at Stackbit. But our goal is for the community to eventually take ownership of the tool as well like this is a fully open source MIT license project. And so we would love to see people creating their plugins and building stuff with Sourcebit that we haven’t even thought of. So, that’s the ultimate goal. We’ve been in touch with people from different CMS companies who are interested in building their plugins as well. So we’re in constant contact with them. So hopefully we’ll see a nice ecosystem of plugins somewhat soon.

Drew: How complex is it to develop a plugin if you’ve got a completely custom system that you know that you need to integrate with? Is it a very involved difficult task to develop plugin or is it easier than that?

Eduardo: I’m a bit biased to answer that. I like to think that it’s simple and I’ve tried my best to make the process simple and also very well documented. So we have one of the repositories that we make available is kind of a sample plugin, where we have a fully annotated source code for a plugin. So we have comments on every possible function that you might implement outlining the arguments that it receives, how you can use this function to get data from this etc. So hopefully that’ll be a very useful resource. We also have documentation pages where we kind of outline the anatomy of a plugin, like how it pulls data where it’s supposed to push that into. So hopefully, it’s a fairly straightforward process.

Eduardo: But different systems will present different challenges. So I’m sure there will be suggestions and feature requests from someone in the community saying, “I want to integrate with this system. So I kind of need a way of doing this.” And we’ll be more than happy to kind of accommodate those requests and kind of work with the community to make the plugin architecture better over time.

Drew: And it’s all written in, I presume is JavaScript node?

Eduardo: It is. It is.

Drew: I noticed that you mentioned earlier briefly that you can run Sourcebit with a watch flag, and it will help you to have a sort of live updating workflow. Is that something that needs to be implemented by the source plugin, or is that general system? Is it a polling mechanism or are you listening for sort of hooks and things from the source system?

Eduardo: The core application is very lean, and it’s not opinionated at all. So it’s up to each Source plugin to kind of implement that functionality. All the core application does on that front is it tells the plugin what are the kind of the options that the user asked for. So in the two plugins that we launched with, so we have one for Contentful, and one for Sanity, the way that the watch mode is implemented in each of them is very different. For example, in Contentful we have, as I mentioned, a polling mechanism in a regular interval of time, like poll for changes whereas for Sanity, we have like a running web socket that is constantly listening for changes and respond to the changes. But basically, the idea is that the source plugin implements its own listening mechanism and it’s responsible for telling the core application that I have new content please update yourself. That’s kind of the domain idea.

Drew: That sounds like quite a flexible system then that should cope with lots of different sources and different types of system.

Eduardo: Yes. I was just going to say like still on that topic of flexibility, one thing that I wanted to mention as well is Sourcebit is configured using a JavaScript file. So if something similar to what you would do with some like web pack, for example, although a bit simpler. And so you have the option to configure each of the plugins on that file manually. But we also offer this commandline interface, where basically each plugin is able to tell the core application the set of questions that it needs to ask the user in order to configure itself. So basically, when you run npx create-sourcebit, it can create everything from scratch for you.

Eduardo: So it pulls a list of all the available plugins to have the option to sit on a source plugin for Contentful and the target plugin for Jekyll, for example. And then based on the plugins that you choose, it then asks you a series of questions that will ultimately lead to a fully configured JavaScript file. So for example, for Contentful it’ll ask you for your credentials, like how do I access your Contentful account? And then it will actually pull all the content types from Contentful. And it’ll ask you okay, I found this content type called blog posts. What is this? Is this like a page? Is this a data object? And if it’s a page, where should I store this? What kind of fields should I use for the layout for the content?

Eduardo: I think it’s a very user friendly way of configuring the whole project. So hopefully, by the end of this configuration process, you can just run a command and you can pull the content straight away without having to mess around with JavaScript files.

Drew: So that configuration process answering those questions, then writes the JavaScript configuration file for you, which you can then presumably just commit into your source control and distribute to other developers on your project or into your build process for running live. You mentioned a third type of plugin distinct from the source and the target that works on data in this agnostic format in the middle. What sort of scenarios do you imagine that being used for?

Eduardo: We created a plugin that is responsible for transforming assets. So to give you an example, let’s say that I’m using Contentful, and you have images embedded as part of a blog post. And by default, if you just pull that data from Contentful, the images will be using a live URL from like Contentful CDN which is a totally viable option if that’s what you want to use. But you might want to instead, serve the images alongside the content. So have them in your repo and served from whatever service you’re using to serve to site as well. And so that plugin in specific, it will look for any assets that are using, it will pull those assets down, download them basically to your repo or to your local file system which it can then push.

Eduardo: And it will replace any URLs in your files that reference that remote URL, it’ll replace those with references to the local files instead. So basically, when you push the site, you push the content and the assets and everything will just work seamlessly. So, that’s one example of kind of a transformation plugin that is not pulling. It’s not specific to a data source and it’s not specific to a static site generator. It just transforms things in between.

Drew: You mentioned that there are target plugins for Jekyll and Hugo, are there any that you’re expecting to see in the near future?

Eduardo: Well, I’m a big fan of Eleventy. So I’m really hoping to see an Eleventy plugin coming out fairly soon. And then I guess there are some static site generators that already have their own kind of plugin ecosystem. So I’m curious to see if people will still find a need to have a source plugin for those types of static site generators. Like another possible way that you can use Sourcebit by the way, is if you’re using something like Next.js, so like any node based static site generator. You don’t necessarily need a target plugin, you can just require Sourcebit as an NPM module, and you can run the all the mechanisms for fetching data. You can just run those as in memory functions and get your content available as part of your Next.js pages. To answer your question, I guess for those we won’t see target plugins specifically, but we can already use Sourcebit in that way. In terms of next source plugins, I would expect to see Eleventy and maybe a few other kind of file based static site generators in the near future.

Drew: This is all quite exciting stuff, I think. Is it just you working on it in terms of development or is there a bigger team?

Eduardo: I’ve been kind of the main developer working on it, but it’s a team effort. So it’s something that a bunch of people at Stackbit identified as a problem. And we’ve been working together on kind of specification and the right way to approach this. I just happen to be the guy pressing the keys to make it happen.

Drew: And I guess Sourcebit actually can be very useful for Stackbit customers, which is Stackbits motivation for developing and contributing this but obviously, it’s going to be useful to a much wider audience than just Stackbit customers.

Eduardo: Yeah, we have big plans for Sourcebit internally. It’ll really help us achieve our mission in terms of making JAMstack, accessible to as many people as possible, but we wanted to make sure that we share this particular project with the community because we feel that it’ll help a lot of people regardless of whether they’re interested in using Stackbit or not. So that’s why it’s a fully open source project.

Drew: That’s great. Is there anything else you’d like to tell us about Sourcebit?

Eduardo: No. I would just love people to try it out. I’m sure we can share links to like the repo and stuff like that. There’s a YouTube video in the main repository, that shows how the experience is like when using Sourcebit with a headless CMS and a static site generator. So it kind of gives you an idea of what it’s like to use the CLI and the whole interactive setup process, and I would just love people to try it out. And get in touch if they think it could be improved or it’s terrible, or it’s great, or it’s helping them. So yeah, I would love to hear from people.

Drew: That’s great. We’ll link that all from the show notes, but also Sourcebit be found at github.com/stackbithq/sourcebit. So I’ve been learning all about Sourcebit today, what have you been learning about lately?

Eduardo: I’ve been super interested in learning about Serverless. And I’ve actually been trying to learn as much as possible about it for the past few months. It’s a concept that I’m super interested in. It’s one of those seismic changes in how you approach development. And I’m super interested in kind of the use cases that it has and kind of the different ways of rethinking how you build an application for Serverless. So that’s something that I’ve been trying to read about as much as possible and just playing around and trying, like side projects. Yeah, it’s an area I’m super passionate about.

Drew: It’s very interesting, isn’t it? Quite a shift in how you have to think about projects?

Eduardo: Definitely, definitely. There’s a metaphor, and I don’t want to ramble about Serverless here, which is that a metaphor that I think is really helpful is to think about Serverless as kind of using Uber as opposed to owning a car, like it forces you to, you still have a car, like the term Serverless maybe is a bit misleading because you still have a server, but if you have a car, you might just leave your stuff in the car because you know it’s going to be there the next day, whereas if you’re using at Uber, it forces you to rethink and to acknowledge that every day you’re going to get a new car with different people driving it, and it just have to adapt your way around that fact. So, that metaphor really helped me wrap my head around the whole Serverless paradigm.

Drew: Yes, I had not heard that before, that’s quite an interesting way of looking at it. If you, dear listener, would like to hear more from Eduardo, you can follow him on Twitter, where he’s @Eduardoboucas. And you can find his web development periodical build times at Eduardoboucas.com. Thanks for joining us today. Eduardo. Do you have any parting words?

Eduardo: No, not really. Just first of all, thank you so much for having me. It’s been a pleasure. And by the way that weird pronunciation for my last name, maybe I should say that it’s, if you want to find my Twitter handle and website the surname is B-O-U-C-A-S. Boucas is another weird Portuguese pronunciation if you want to find, it’s Eduardoboucas. So, yeah, thank you so much for having me. It’s been a pleasure.

Drew: Thank you so much.

Smashing Editorial (dm, ra, il)
Catégories: Programmation

Building An E-Commerce Site With October CMS And Shopaholic

mar, 03/10/2020 - 10:30
Building An E-Commerce Site With October CMS And Shopaholic Building An E-Commerce Site With October CMS And Shopaholic Leonardo Losoviz 2020-03-10T09:30:00+00:00 2020-03-10T10:46:55+00:00

October CMS is flourishing: With over 9000 stars in its GitHub repo, 2000 forks and 300 contributors, it is becoming a major force in the CMS space. It won the popular vote as the Best Flat-File CMS from 2018, new plugins are published on its marketplace almost daily (covering most of the developer needs), and its network of partners is expanding worldwide. Let's see what it is all about.

Built in PHP and powered by Laravel (one of the most powerful and developer-friendly PHP frameworks), October CMS is a free open-source Content Management System (CMS). It benefits from Laravel's clean code and sound architecture to provide a great developer experience, over which it adds simple and flexible CMS functionality to provide a great user experience. This combination makes it possible to launch new projects in a matter of minutes, without having to build the project from scratch. Due to all these features, October can minimize the costs of developing and maintaining websites, making it particularly valuable to businesses and digital agencies.

Yet, in spite of its power, October CMS is very easy to use. Since its inception, October has strived to be “as simple as possible, but not simpler”. For this reason, it is based on one of the simplest stacks for the web: PHP to render HTML, plus CSS and JS assets. In the words of its creators, October's mission is to prove that “web development is not rocket science”.

In this article, we will do a tour around October CMS: We will first see how to install it, then check some of its coding and usability features in a bit more detail, and finally get our hands dirty implementing an e-commerce website through one of its most popular plugins, Shopaholic.

Recommended YouTube Channel

Are you looking to learn more about e-commerce development? You can do so with the help of live streams that explain the main aspects of the development process based on the Shopaholic platform for October CMS. Watch →

Installing October CMS

Since October CMS runs on PHP, it requires to have a web server running on the computer (if we don't have one yet, MAMP can provide one for free, allowing to choose between Apache and Nginx, and it works for both Windows and macOS) and a MySQL server to store the database (which can also be provided by MAMP).

The installation through October's wizard doesn't take more than a few minutes: We create a new MySQL database, download and unpack the installer files to our target directory for the website (which must be granted writing permission, and which must be set as document root in the web server for the chosen domain, such as localhost), and then invoke the script file from the web browser. From that moment on the wizard takes over, guiding us through the installation process. The wizard will:

  1. Validate if the web server satisfies all the requirements (at least PHP 7.0, and others):
     System check System check (Large preview)
  2. Ask for database and site configuration values, and user credentials:
     Configuration Configuration (Large preview)
  3. Ask how to set-up the site: From scratch, already installing a specific theme, or using our own existing project (from which our chosen theme and plugins can be automatically installed):
     Initial set-up Initial setup (Large preview)
  4. Next, we click on "Install!", and in a few seconds (depending on our Internet connection speed) the website will be installed and ready to use:
    October CMS installation is installed Site installed (Large preview)
    In this case, I chose to install it from scratch, under http://localhost. Browsing to this URL on the browser, we can encounter the October starter demo theme:
    Starter demo theme Browsing the starter demo theme (Large preview)
  5. Navigating to http://localhost/backend (unless we changed this URL during the installation process) we can log into the administration panel:
    Admin panel Browsing the admin panel (Large preview)
  6. Finally, we delete the installer files from the folder. And voilà, in just a few minutes we have a fully functioning site (well, we still need to enhance it with plugins... we will do that in a while).

    Alternatively, we can also install October from the command-line interface, by executing:
    $ curl -s https://octobercms.com/api/installer | php
    This method is faster (it can take as little as 10 seconds to install) because it doesn't require to input the database configuration. Hence, it is particularly useful for setting-up October CMS as a flat-file system, i.e. a CMS fully set-up through files stored in the local disk, and without a database.
Installation through the Command-Line Interface Installing October CMS through the CLI takes no time. (Large preview) Templating System

October CMS has a robust templating system to implement layouts, re-use chunks of code and enable dynamic functionality. Its most important elements are the following ones:

Pages are the most basic structure for storing content. These are readily available, since they are shipped as part of the core (blog posts, on the other hand, must be installed through a plugin). Pages are based on Twig, which is a modern template engine for PHP (devised by the creators of Symfony), and compiled to plain optimized PHP code, so they execute very fast.

Partials contain reusable chunks of code that can be used all throughout the website, as to avoid duplicating code on the different pages or layouts. They are particularly useful for navigation menus, testimonials, calls to action, and other common elements.

Layouts define the scaffolding, or structure, of the page. They define the <html> and <body> HTML elements, and are useful for creating the frame of the site, including the header, footer and sidebars. The actual content in the body is injected by the page.

Components are the mechanism to extend functionality in October CMS. Any page, partial or layout can have attached any number of components, which are most commonly provided through plugins, and which are fully configurable. In addition to rendering HTML code on the page, components can also provide services, such as form validation, security check-up, control of user permissions, or others.

Component configuration Configuring a component attached to a page. (Large preview)

These elements are all implemented through files living in the website's folder in the local hard drive. As such, it is possible to edit them not only through October CMS' built-in editor, but also from the developer's preferred text editor (Sublime, VS Code, PHPStorm, etc).

Editing an element through October CMS' built-in editor and in an external text editor We can edit elements either through the October CMS' built-in editor or in an external text editor. (Large preview)

Similarly, the October CMS project can be perfectly managed through any version control system, and it can be easily adapted to any existing workflows. For instance, a project can be set-up through continuous integration, deploying it automatically to the server after new code is pushed to the Git repo.

Git workflow October can be easily managed with Git. (Large preview) October CMS Marketplace

October CMS has a marketplace for themes (which allow to change the site’s look and feel) and plugins (which allow to extend the site’s functionalities), providing both free and paid offerings. By providing themes which can be used to quickly establish and then configure the design of the site, and plugins each of which implements some required functionality for the site, the marketplace ultimately leads to lower costs for creating our projects and reduced time to launch them.

The marketplace has been getting bigger! Following October's growing popularity, its marketplace has received a constant stream of new offerings: It currently boasts 915 plugins, comprising most of the functionalities required for our websites (blogging, SEO, e-commerce, analytics, email, galleries, maps, security, social, user management, and others), and 150+ themes. Both themes and plugins can be submitted to the marketplace by any independent 3rd party developer, company or agency, and they must adhere to quality guidelines, which ensures that they are performant and secure.

Creating An E-Commerce Site Through Shopaholic

Let's get our hands dirty and implement a real-life use case: An e-commerce website! For this, we will install Shopaholic, the most popular plugin to add e-commerce functionality to October CMS, and the free theme Bootstrap theme for Shopaholic to quickly bootstrap the site (which will be made to look like this demo site). Shopaholic is ideal for our needs because it provides a comprehensive e-commerce solution, which includes an ecosystem of extensions (both free and paid ones) to further enhance it. In addition, we can install the core experience for free and only make a one-time payment for the extensions that we need, which will be cheaper than using cloud solutions which have a recurring fee to use. And finally, because we are the full owners of our own on-premise e-commerce website, we can customize it as much as we need to and we own all the data, which is not possible with cloud solutions.

Because of the October marketplace dependency management system, we need only install the theme (the Shopaholic plugin is added as a dependency). Let's proceed to install the theme then: Inside the October CMS admin, we click in the "Front-end theme" section in the Settings, and then click on "Find more themes":

Front-end theme manager Front-end theme manager. (Large preview)

Then, we search for theme "Bootstrap theme for Shopaholic" and, upon clicking on the result in the dropdown, it will install the theme and all its dependencies. Once installed, we go back to the Front-end theme manager page and click on the Activate button on the new theme:

Activating the new theme Activating the new theme. (Large preview)

After installing the theme and plugins, we will notice a new element "Catalog" on the top menu bar. Clicking on it, we can manage the items in our e-commerce catalog, namely products, categories and brands (these are the core elements; other elements, such as coupons, can be added through extensions). Initially, our catalog will be empty:

Catalog Catalog comprising products, categories and brands. (Large preview)

Let's fill it up with some data. We can either create the items one by one or, quite conveniently, import data through CSV and XML files (which allows us to manage a large set of records with Excel or other tools). In our case, since we are creating a demo site for testing purposes, let's install plugin Fake Data for Shopaholic which provides large sets of mock data and an easy way to import these records to the system. To do this, follow these steps:

  1. Head to Settings => Updates & Plugins in October CMS backend, and install plugin "Fake Data for Shopaholic".
  2. Head to Dashboard, and click on Manage widgets and then Add widget.
  3. Select widget "Fake data for Shopaholic", and click on Add.
  4. In the newly added widget, clicking on Generate under section "Generate fake data " will run the process to import the fake data.

The last step will ask how many times should the insertion be repeated (as to create bulk and be able to test the performance of the site when loading many records) and which data set (clothes or sneakers):

Generating fake data through Laravel's artisan command Generating fake data through Laravel's artisan command. (Large preview)

After running this process, our catalog will look better stocked:

Catalog with some mock data Catalog with some mock data. (Large preview)

The next step is to create some promotions. To do this, we click on Promotions on the top menu, then on the Create button, and fill the required information. Once each promotion is created, we must edit it again to add products to it. After creating a few of them, our promotion list will look like this:

Promotion list Creating some promotions. (Large preview)

Now that we have some data, we can finish customizing how our front page will look like. For that, we go to section Settings => Front-end theme => Customize and we complete the information for all tabs (Header, Footer, Social, Main slider, Index page). Once this is ready, our e-commerce site will now be ready:

Demo e-commerce site Our e-commerce site is ready! (Large preview)

Clicking on a product, we can see how its page looks like:

Product page Product page. (Large preview) Auditing The Speed And Reliability Of The E-Commerce Solution

Because we want to sell our products, speed and a good SEO are mandatory, so let's make an audit using Google Chrome's Lighthouse on the product page to make sure it runs fast and that it will score high with search engines. Running the audit against the live demo site, it returns the following report:

Lighthouse report of the product page Lighthouse report of the product page. (Large preview)

Equally important is that the site can withstand heavy load, so that if our product becomes successful and attracts plenty of traffic the server doesn't crash. For this, we can use the Load Impact tool to run a load test. Running the test using 50 virtual users for 12 minutes against the live demo site (which is hosted on DigitalOcean with a droplet configuration of Standard 2CPU/4 GB RAM) produced the following results:

LoadImpact report LoadImpact report of a test load using 50 virtual users during 12 minutes. (Large preview)

As can be seen, the website was able to sustain an acceptable response time throughout the load test, giving us the confidence that we can trust the e-commerce plugin when we need it the most: When it's time to sell the product.

Finally, we can also feel confident of the reliability of the software, since it is covered by unit tests.

Adding Extensions To Shopaholic

So far so good. However, as it can be seen on the screenshots from our website, there is still no way for the visitor to buy a product. Let's add this functionality by installing the following free extensions for Shopaholic: Orders, to allow to add products to a cart and make orders, and Omnipay, to process the payment. (For the other Shopaholic extensions, if they are not free and authored by LOVATA, you can use coupon "WELCOME" to get a 50% discount the first time you buy them.) To install these extensions, we head to Settings => Updates & Plugins, search for the plugin names, and click on the results to have them installed.

Plugin installation Searching for 'Shopaholic' displays its plugins. (Large preview)

Once installed, we will see a new item Orders in the top navigation, where all orders will be stored, and items Payment methods and Shipping types in the Settings page, to configure the payment gateways (card, cash, etc) and how to deliver the product (by post, etc). We configure these and load again the product page. Now it shows an "Add to cart" button, allowing the user to place an order:

Product page with cart enabled Product page with cart enabled. (Large preview)

After adding several items to the cart, we can proceed to the check-out and complete the order:

Cart Completing the order. (Large preview)

Once the user submits the order, the inventory will be automatically taken care of, updating the number of items for each product in stock, and we will receive an email informing us of the new order (if configured to do so). In section Orders on the admin panel, we can find all the information for the order (products sold, buyer information, method of payment and total, and others), and we can complete the transaction.

Orders page All the information from the order is here. (Large preview)

The basic work is done: In barely a few hours we managed to have a fully functional e-commerce sith with October CMS and Shopaholic.

Creating Our Own Extension

If none of the several extensions to Shopaholic on the October marketplace provides the functionality needed, we can also create our own extensions.

To do this, if you are comfortable with Object-Oriented Programming and PHP and, more specifically, with Laravel, then you are ready to do it. The documentation explains how to add an extension, step by step. For instance, following this tutorial, with barely a few lines of code we can add a custom field "rating" to our products:

Editing a product Adding a custom field to the product. (Large preview)

We can then retrieve the new "rating" field from the product and display it in the product template:

Product page Displaying a custom field in the product page. (Large preview)

Extending Shopaholic is not difficult and enables us to fully implement our own e-commerce requirements, and personalize the site to suit our brand.

Conclusion

October CMS is a great candidate for building powerful sites in a very simple manner (showing that “web development is not rocket science”). It delivers the great developer experience granted by Laravel, and its marketplace (which is growing daily) provides a large number of ready-to-use themes and plugins, allowing us to build websites very quickly. One such plugin is Shopaholic, which converts the site into a full-fledged e-commerce platform.

Because of these reasons, building a site with October can be very cost-effective. As a result, it has gained some reputation (by winning the popular vote as best flat-file CMS from 2018) and has increasingly become a tool of choice for businesses and digital agencies crafting sites for their clients.

To find out more from the October community, be welcome to join the October CMS Slack workspace, which is where the creators of themes and plugins published in the marketplace hang out, so you can conveniently chat with them to get their help and advice.

Give October a try (it's free!), and let us know how it goes.

Smashing Editorial (ra, yk, il)
Catégories: Programmation

Setting Height And Width On Images Is Important Again

lun, 03/09/2020 - 12:30
Setting Height And Width On Images Is Important Again Setting Height And Width On Images Is Important Again Barry Pollard 2020-03-09T11:30:00+00:00 2020-03-09T13:41:43+00:00

Web performance advocates have often advised to add dimensions to your images for best performance to allow the page to be laid out with the appropriate space for the image, before the image itself has been downloaded. This avoids a layout shift as the image is downloaded — something Chrome has recently started measuring in the new Cumulative Layout Shift metric.

Well, a dirty, little, secret — not that well-known outside the hard-core web performance advocates — is that, until recently, this actually didn’t make a difference in a lot of cases, as we’ll see below. However, adding width and height attributes to your <img> markup have become useful again after some recent changes in the CSS world, and the quick adoption of these changes by the most popular web browsers.

Recommended Reading

The CSS contain property gives you a way to explain your layout to the browser, so performance optimizations can be made. However, it does come with some side effects in terms of your layout. Read more →

Why Adding Width And Height Were Good Advice

Take for example this simple page:

<h1>Your title</h1> <p>Introductory paragraph.</p> <img src="hero_image.jpg" alt="" width="400" height="400"> <p>Lorem ipsum dolor sit amet, consectetur…</p>

This might render in two stages, first as the HTML is downloaded, and then second once the image is downloaded. With the above code, this would cause the main content to jump down after the image is downloaded and the space needed to display it can be calculated:

An example layout with a title and two paragraphs, where the second paragraph has to shift down to make space for an image. Layout shift after image loads. (Large preview)

Layout shifts are very disrupting to the user, especially if you have already started reading the article and suddenly you are thrown off by a jolt of movement, and you have to find your place again. This also puts extra work on the browser to recalculate the page layout as each image arrives across the internet. On a complex page with a lot of images this can place a considerable load on the device at a time when it’s probably got a lot of better things to deal with!

The traditional way to avoid this was to provide width and height attributes in the <img> markup so even when the browser has just the HTML, it is still able to allocate the appropriate amount of space. So, if we change above example to the following:

<h1>Your title</h1> <p>Introductory paragraph.</p> <img src="hero_image.jpg" alt="" width="400" height="400"> <p>Lorem ipsum dolor sit amet, consectetur…</p>

Then the render happens like below, where the appropriate amount of space is set aside for the image when it arrives, and there is no jarring shift of the text as the image is downloaded:

An example layout mockup with a title, a paragraph, space for an image and then a second paragraph, where the text does not shift when the image loads. Text should not shift if image dimensions are provided so appropriate space can be allocated. (Large preview)

Even ignoring the annoying impact to the user in content jumping around (which you shouldn’t!), the impact on the CPU can also be quite substantial. The below screenshot shows the performance calculations performed by Chrome on a site I work on which has a gallery of about 100 images. The left-hand side shows the calculations when width and height are provided, and on the right when they are not.

Two screenshots from Chrome Dev tools showing various layout timings of 75ms to 450ms on the left, and 124ms to 2709ms on the right. Performance calculations with and without dimensions. (Large preview)

As you can see, the impact is considerable — especially on lower-end devices and slow network speed, where images are coming in separately. This increases load time by a noticeable amount.

How CSS Interacts With Element Widths And Heights

Widths and heights on an image can cause issues when you try to alter them using CSS. For example, if you want to limit your images to a certain width you might use the following CSS:

img { max-width: 100%; }

This will override the width of the image and constrain it when necessary, but if you have explicitly set the height on the image tag, then we are not overriding that (only the width) and you will end up with a stretched or squashed image, as we have no longer maintained the aspect ratio of the image:

An example layout mockup with a really stretched image. Image dimensions clashes between HTML and CSS can create stretched (or squashed!) images. (Large preview)

This is actually very easily fixed by adding a height: auto line to the CSS so the height attribute from the HTML is overridden too:

img { max-width: 100%; height: auto; }

However, I find it still catches people by surprise and sometimes leads to them not specifying image dimensions in the HTML instead. With no image dimensions, you can get away with just specifying max-width: 200px in the CSS without having to specify height: auto and the browser will automatically figure out the height itself — once it has the image.

So, once we add the dimensions and that the height: auto trick, we get the best of both worlds, right? No layout shifts, but also the ability to resize images using CSS? Well until very recently you might have been surprised to find out the answer was in fact: no (I was — hence why I decided to write this article).

For example, take the code below:

<style> img { max-width: 100%; height: auto; } </style> <h1>Your title</h1> <p>Introductory paragraph.</p> <img src="hero_image.jpg" alt="" height="500" width="500"> <p>Lorem ipsum dolor sit amet, consectetur…</p>

This would have resulted in this load:

Another example layout mockup with a title and two paragraphs, where the second paragraph has to shift down to make space for an image. Layout shifts happen when height: auto is used in CSS. (Large preview)

Wait, what’s going on here? We’re back to the first problem. I thought I said that by specifying the image dimensions in the HTML you could avoid this layout shift problem? Well, this is where it gets interesting and will lead on to the main point of this article.

The problem is that, unless you were giving explicit width and height CSS values to your images — and who wants to limit themselves like that in a responsive world where you want the image to expand or shrink to fill up the available space — then CSS will need the dimensions from the image file itself to figure out the auto part of the dimensions. It ignored any width and height attributes set in the HTML.

The implication of all this is that specifying width and height attributes on images often wasn’t actually that useful in a lot of cases. Yes, when an image is being shown at full size, without any CSS changing any dimensions, it is useful to resolve the layout shifting problem. However, when you use CSS like below to ensure images do not overflow their available space, then you run into problems as soon as the available width becomes smaller than the actual image size.

img { max-width: 100%; height: auto; }

This affects any page where we constrain the image size in a responsive manner — i.e. small screen mobile devices. These are likely to be the very users suffering with network constraints and limited processing power that will suffer most from layout shifts! Of course, we ideally should be delivering appropriately sized images for the screen size, but you cannot cover every device size, so often images will need some resizing by the browser, particularly on mobile.

Many websites may not bother to specify widths and heights on their <img> tags. That could be because they weren’t aware this was useful, or because they were all too aware of what we talked about here and knew it actually wasn’t that useful in a lot of cases. Whatever the reason is beside the point, they are frequently not provided. (How can we even evangelize putting the effort into using them given what I’ve just described?) Even the popular Lighthouse auditing tool doesn’t flag when you don’t do this (though in light of some of the things we’re about to talk about, that is under discussion again).

Working Around The Problem

The limitations for responsive images have been known for a long time and many workarounds, including the so-called padding-bottom hack, have been created to work around the issue. This uses the fact that padding percentages (including padding-bottom ) are always based on the container width (to ensure a consistent padding even if height and width differ). This fact can therefore be used to create a container with where the height is set based on a ratio of the width. For example for, let’s say we have an image with an aspect-ratio of 16:9, then the following CSS code will create the appropriately sized space for the image:

.img-container { position: relative; padding-bottom: 56.25%; /* 16:9 ratio */ height: 0; overflow: hidden; } .img-container img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }

The three main downsides of this technique are the following:

  1. It requires a hard-coded ratio to be calculated (56.25% — 9÷16 — in this example), so it potentially requires custom CSS for each different image.
  2. The CSS code is not exactly easy to remember — forgetting or removing a single line of the above CSS code will break the whole thing. Not to mention this technique requires all images to be wrapped in an extra container element.
  3. This is a more advanced technique that not all web developers know about or use.

And, let’s be honest — it’s a bit of a hack! So, we really should fix this properly, shouldn’t we?

Fixing The Resizing Problem

The issue has been tackled from a few different directions by a number of different standards organizations.

The CSS Working Group (CSS WG) proposed the aspect-ratio property that Rachel wrote about previously. This would tackle the complexity problem (issue 2) once it becomes available, and simplify the above code to just this:

img { width: 100%; height: auto; aspect-ratio: 16/9; }

Much nicer! This is particularly useful for video where we usually have a set number of commonly used aspect-ratios, so we could create a few classes like above for each size. It’s perhaps less useful for images where dimensions are much less standardized, as it doesn’t solve issue 1 (custom CSS code required per image), nor issue 3 (website developers will need to remember to set this). So, it’s a step forward, but not a full solution.

Separate to this, the Web Incubator Community Group (WICG) — a group of browser developers and other interested parties that can experiment on technologies to see if they work before formal standardisation — also created a proposal to fix this. They proposed the intrinsicsize attribute, that would look like this:

<img intrinsicsize="400x400" style="width: 100%">

As this is an HTML attribute, it can be set per image (solving issue 1), and is relatively easy to code (solving issue 2), but was still likely to suffer from adoption issues (issue 3) unless it became very well-known with a big push from the whole community.

We already have a common, well-known method of setting the width and height on <img> elements (even if they are not used as much as they should be!) so anything new, other than that, is going to suffer from the adoption issue. And that is where the (now seemingly obvious!) answer presented itself.

Jen Simmons proposed this elegant, and simple solution, that she had come up with, along with fantasai:

<style> img { width: 100%; height: auto; aspect-ratio: attr(width) / attr(height); } </style> <img src="hero_image.jpg" alt="" width="500" height="500">

Rather than hard-coding the aspect-ratio, this uses the attr CSS function to create the appropriate aspect-ratio based on the image width and height attributes provided by the HTML. The attr function has been around for a while, but has been very limited in scope — it’s supported for content by all browsers, but not for the wider use case of any other attribute like width and height, which is what is needed here.

If attr was able to be used for the well-known width and height attributes from img elements, then it could use be used to automatically calculate the aspect-ratio as per above. This would solve issue 1 (no hard-coded aspect ratio needs to be set in the HTML nor the CSS), issue 2 (very simple to add) and, as we shall see, there is a very simple answer to issue 3 (adoption).

Basically, this solution means if the following four conditions are true, then the correct image dimensions could be calculated without needing to wait for the images to download, and so without the need of a content layout shift:

  • height is set on the element in HTML
  • width is set on the element in HTML
  • height (or width) is set in the CSS — including using percentage values like max-width: 100%;
  • width (or height) is set to auto in the CSS.

If any one of these were not set, then the calculation would not be possible, and so would fail and be ignored and have to wait for the image to be downloaded.

So once browsers support using the HTML width and height to calculate the aspect-ratio we can solve our problem very simply with no change in practice to HTML and one line of CSS code! As mentioned above, this is also something many web developers may have already assumed was happening anyway.

Driving Adoption Of This Solution

Because this is just a CSS attribute, the proposal contained a further twist — it could be added to the user-agent stylesheet used by browsers so would not even require any changes from web developers to benefit from this.

The user-agent stylesheet is where default CSS definitions are set (e.g. what font-size the h1 element uses), which can be overridden by your own CSS if you want. By adding the above aspect-ratio one-liner to this we don’t need to drive adoption — we basically turn it on automatically for all sites that meet the above four conditions!

However, this does depend on the attr function having access to the width and height HTML attributes, and also the upcoming aspect-ratio CSS property to be completed — neither of which has happened yet. So instead, as an easier fix, the browsers could implement the equivalent logic deep in rendering code rather than exposing it via the user-agent stylesheet, but the effect is the same. This alternative implementation approach was even suggested as part of the proposal.

Firefox went ahead and did this as an experiment and then turned it on by default for Firefox 71. Once that was released, then your site may well have just got faster for free — thanks Mozilla! Maybe in future, they will move this to the user-agent stylesheet method, but for now, this is sufficient (and perhaps more performant?).

Backwards Compatibility

When introducing a change in behavior, there is always a concern about backwards compatibility and this feature was no different. In theory, as long as the four attributes were appropriately set, there should be no breakage with this.

However, when Firefox initially experimented with it, they discovered problems for those setting the width and height incorrectly in their HTML. Whereas previously these incorrect values would be ignored if the CSS overrode them, now they were being used when auto was set and the images were not displayed correctly and led to squished or stretched images. Now you could argue that web developers shouldn’t set these values incorrectly, and in some cases, it would be already broken even without this change (the case above when you didn’t set height: auto), but still, breaking sites is never a good thing. That is also something the web tries very hard to avoid — and is mostly very good at avoiding that (it’s one of my favorite things about the web as a platform).

The solution to that problem, however, was relatively simple: have the actual image aspect-ratio of the image override any CSS calculated aspect-ratio. This way the (incorrectly) calculated aspect-ratio can be used for initial layout, but then can be recalculated when the image is downloaded, so the image is displayed as it was before. This does cause a layout shift (since the incorrect space was allocated initially) but that was happening before anyway, so it’s no worse. In fact, it’s often a lot better as an incorrect aspect ratio will often be closer to the truth than a zero aspect-ratio.

Rollout To Other Browsers

After Firefox’s successful experimentation, Chrome also decided to implement this (again using the layout coded method for now rather than default user-agent stylesheet), and rolled it out by default in Chrome 79. This also took care of the other chromium-based browsers (Edge, Opera and Brave, for example). More recently, in January 2020, Apple added it to their Tech Preview edition of Safari, meaning it should hopefully be coming to the production version of Safari soon, and with that, the last of the major browsers will have implemented this and the web will become better and less jolty for a huge number of sites.

Limitations

There are a few limitations to be aware of with this feature, including issues with:

  • Art Direction
  • Lazy Loading
  • Non-Images
Art Direction

The fix works great to calculate the aspect-ratio based on a fixed width and height, but what about when those change? This is known as art direction and an example is shown below:

Two example page layout mockups with the first being a desktop layout using a wide banner-style image, and the second, mobile, layout using a square image. 'Art direction' uses different photographs depending on the available space. (Large preview)

In this case we are using a wide image for desktop, and then a square, cropped image for mobile. Responsive images can be implemented using srcset attributes on an <img> element:

<img srcset="hero_800x400.jpg 800w, hero_400x400.jpg 400w" sizes="(min-width: 327px)" 800px 400px src="hero_800x400.jpg" alt="" width="800" height="400">

or with the <picture> element like this:

<picture> <source media="(min-width: 327px)" type="image/jpeg" srcset="hero_800x400.jpg"> <source type="image/jpeg" srcset="hero_400x400.jpg"> <img src="hero_800x400.jpg" alt="" width="800" height="400"> </picture>

Currently, both these elements only allow the width and height to be set once on the main, fallback <img> element and not on the individual <srcset> alternatives. Adding these has been proposed but until then, this is currently a limitation of the solution, and using images with different dimensions will still experience a layout shift.

Lazy Loading

This feature would be perfectly suited for use with lazy-loading. Ideally, all lazy-loaded images are loaded off-screen as you scroll down the page before the lazy-loaded image enters the viewport, but often this is not the case depending on how fast the user scrolls and the network, so having the image area correctly set would at least avoid the layout shift after loading does occur. Additionally, even when loading is happening off-screen, layout shifts can be costly in terms of CPU time, as we have shown above.

However, lazy loading techniques may involve not using an <img> element, or at least one without a src (to prevent the browser from downloading the image by default). Therefore, it may not be able to benefit from this recent change depending on how your browser handles the element used or src-less <img> elements. Though if the CSS version of this solution becomes available, then website developers will have greater control over specifying aspect-ratio themselves.

Native lazy loading was recently released by the Chrome team and it has since been added to the HTML spec. Other browsers are also looking to support this with Firefox also getting this soon, and Safari hopefully not too much later. That does make use of the <img> element with a src with syntax like the following (including when used as part of the <picture> element):

<img src="hero_800x400.jpg" alt="" width="800" height="400" loading="lazy">

Perfect! Well, unfortunately, I discovered this height and width solution is not compatible with the recently released native lazy-loading functionality as can be seen on this test page. I’ve raised a bug for this issue and hopefully the Chrome team will fix this soon.

Non-Images

Currently, the browsers that have implemented this, have only done for the <img> element, but it would also be useful for <video>, <iframe> and <object> elements to name a few, and this under discussion. Again, if the CSS version of this technique becomes available through the attr functions and aspect-ratio property, then that puts the power in the website developer to implement this for whatever elements they want!

Conclusion

I love improvements that just work without any effort required of website owners. That is not to ignore the hard work required by the browser developers and standardization teams, of course, but it’s often rolling out to websites that is the real difficulty. The less friction we can add to introduce these improvements, the more likely they will be adopted, and there’s no better friction than none at all! Fixing the impact of layout shifts on users for responsive images seems to be one such improvement and the web is all the better for it.

The one change that is required of us web developers is to ensure we are providing width and height attributes in our markup. It’s a habit we shouldn’t really have gotten out of, and many CMS and publishing tools make this relatively easy. I queried the HTTPArchive and it looks like 62% of <img> tags have width or heights, which is way higher than I expected to be honest — but let’s try to increase that statistic even more now we have a reason to again. So, I implore you to check that you are doing this on your sites and, if not, start to. It will improve the experience for your users and ultimately make them happier, and who doesn’t want that?

Smashing Editorial (jw, yk, il)
Catégories: Programmation

Pages