Friday, 13 March 2020

Stay Calm And Read Smashing

Stay Calm And Read Smashing

Iris Lješnjanin

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 →

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 Lint
A 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.

Smashing Editorial(cm, vf, ra, il)

from Tumblr https://ift.tt/2TKNYh3

Thursday, 12 March 2020

Rescheduling SmashingConf SF And Looking Out For Each Other

Rescheduling SmashingConf SF And Looking Out For Each Other

Rachel Andrew

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.

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.

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:

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)

from Tumblr https://ift.tt/2Q8WpjW

Accessible SVGs: Inclusiveness Beyond Patterns

Accessible SVGs: Inclusiveness Beyond Patterns

Carie Fisher

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://ift.tt/2Q7ymCf) 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).
Graph showing which browsers utilize the CSS at-rule: @media: 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://ift.tt/2W79bDF) 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 movement
The 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://ift.tt/2Q7ymCf) 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.
Graph showing which browsers utilize the CSS at-rule: @media: 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)

from Tumblr https://ift.tt/38LuXzt

Wednesday, 11 March 2020

Creating Secure Password Flows With NodeJS And MySQL

Creating Secure Password Flows With NodeJS And MySQL

Darshan Somashekar

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)

from Tumblr https://ift.tt/2W3thhP