Scroll bouncing (also sometimes referred to as scroll ‘rubber-banding’, or ‘elastic scrolling’) is often used to refer to the effect you see when you scroll to the very top of a page or HTML element, or to the bottom of a page or element, on a device using a touchscreen or a trackpad, and empty space can be seen for a moment before the element or page springs back and aligns itself back to its top/bottom (when you release your touch/fingers). You can see a similar effect happen in CSS scroll-snapping between elements.
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 article →
A good understanding of scroll bouncing is very useful as it will help you to decide how you build your websites and how you want the page to scroll.
Scroll bouncing is undesirable if you don’t want to see fixed elements on a page move. Some examples include: when you want a header or footer to be fixed in a certain position, or if you want any other element such as a menu to be fixed, or if you want the page to scroll-snap at certain positions on scroll and you do not want any additional scrolling to occur at the very top or bottom of the page which will confuse visitors to your website. This article will propose some solutions to the problems faced when dealing with scroll bouncing at the very top or bottom of a web page.
My First Encounter With The Effect
I first noticed this effect when I was updating a website that I built a long time ago. You can view the website here. The footer at the bottom of the page was supposed to be fixed in its position at the bottom of the page and not move at all. At the same time, you were supposed to be able to scroll up and down through the main contents of the page. Ideally, it would work like this:
It currently works this way in Firefox or on any browser on a device without a touchscreen or trackpad. However, at that time, I was using Chrome on a MacBook. I was scrolling to the bottom of the page using a trackpad when I discovered that my website was not working correctly. You can see what happened here:
Oh no! This was not what was supposed to happen! I had set the footer’s position to be at the bottom of the page by setting its CSS position property to have a value of fixed. This is also a good time to revisit what position: fixed; is. According to the CSS 2.1 Specification, when a “box” (in this case, the dark blue footer) is fixed, it is “fixed with respect to the viewport and does not move when scrolled.” What this means is that the footer was not supposed to move when you scroll up and down the page. This was what worried me when I saw what was happening on Chrome.
To make this article more complete, I’ll show you how the page scrolls on both Mobile Edge, Mobile Safari and Desktop Safari below. This is different to what happens in scrolling on Firefox and Chrome. I hope this gives you a better understanding of how the exact same code currently works in different ways. It is currently a challenge to develop scrolling that works in the same way across different web browsers.
Searching For A Solution
HTML And CSS Only Solutions
Absolute And Relative Positioning
One of the first things I tried, was to use absolute and relative positioning to position the footer because I was used to building footers like this. The idea would be to set my web page to 100% height so that the footer is always at the bottom of the page with a fixed height, whilst the content takes up 100% minus the height of the footer and you can scroll through that. Alternatively, you can set a padding-bottom instead of using calc and set the body-container height to 100% so that the contents of the application do not overlap with the footer. The CSS code looked something like this:
This solution works in almost the same way as the original solution (which was just position: fixed;). One advantage of this solution compared to that is that the scroll is not for the entire page, but for just the contents of the page without the footer. The biggest problem with this method is that on Mobile Safari, both the footer and the contents of the application move at the same time. This makes this approach very problematic when scrolling quickly:
Another effect that I did not want was difficult to notice at first, and I only realized that it was happening after trying out more solutions. This was that it was slightly slower to scroll through the contents of my application. Because we are setting our scroll container’s height to 100% of itself, this hinders flick/momentum-based scrolling on iOS. If that 100% height is shorter (for example, when a 100% height of 2000px becomes a 100% height of 900px), the momentum-based scrolling gets worse. Flick/momentum-based scrolling happens when you flick on the surface of a touchscreen with your fingers and the page scrolls by itself. In my case, I wanted momentum-based scrolling to occur so that users could scroll quickly, so I stayed away from solutions that set a height of 100%.
One of the solutions suggested on the web, and that I tried to use on my code, is shown below as an example.
This code works on Chrome and Firefox on macOS the same way as the previous solution. An advantage of this method is that scroll is not restricted to 100% height, so momentum-based scrolling works properly. On Safari, however, the footer disappears:
On iOS Safari, the footer becomes shorter, and there is an extra transparent (or white) gap at the bottom. Also, the ability to scroll through the page is lost after you scroll to the very bottom. You can see the white gap below the footer here:
One interesting line of code you might see a lot is: -webkit-overflow-scrolling: touch;. The idea behind this is that it allows momentum-based scrolling for a given element. This property is described as “non-standard” and as “not on a standard track” in MDN documentation. It shows up as an “Invalid property value” under inspection in Firefox and Chrome, and it doesn’t appear as a property on Desktop Safari. I didn’t use this CSS property in the end.
To show another example of a solution you may encounter and a different outcome I found, I also tried the code below:
This actually works well across the different desktop browsers, momentum-based scrolling still works, and the footer is fixed at the bottom and does not move on desktop web browsers. Perhaps the most problematic part of this solution (and what makes it unique) is that, on iOS Safari the footer always shakes and distorts very slightly and you can see the content below it whenever you scroll.
One approach of solving the issue of scroll bouncing is by preventing the touchmove or touchstart events on the window or document. The idea behind this is that the touch events on the overall window are prevented, whilst the touch events on the content you want to scroll through are allowed. An example of code like this is shown below:
// Prevents window from moving on touch on older browsers.
window.addEventListener('touchmove', function (event)
// Allows content to move on touch.
document.querySelector('.body-container').addEventListener('touchmove', function (event)
I tried many variations of this code to try to get the scroll to work properly. Preventing touchmove on the window made no difference. Using document made no difference. I also tried to use both touchstart and touchmove to control the scrolling, but these two methods also made no difference. I learned that you can no longer call event.preventDefault() this way for performance reasons. You have to set the passive option to false in the event listener:
// Prevents window from moving on touch on newer browsers.
window.addEventListener('touchmove', function (event)
, passive: false)
You may come across a library called “iNoBounce” that was built to “stop your iOS webapp from bouncing around when scrolling.” One thing to note when using this library right now to solve the problem I’ve described in this article is that it needs you to use -webkit-overflow-scrolling. Another thing to note is that the more concise solution I ended up with (which is described later) does a similar thing as it on iOS. You can test this yourself by looking at the examples in its GitHub Repository, and comparing that to the solution I ended up with.
After trying out all of these solutions, I found out about the CSS property overscroll-behavior. The overscroll-behavior CSS property was implemented in Chrome 63 on December 2017, and in Firefox 59 on March 2018. This property, as described in MDN documentation, “allows you to control the browser’s scroll overflow behavior — what happens when the boundary of a scrolling area is reached.” This was the solution that I ended up using.
All I had to do was set overscroll-behavior to none in the body of my website and I could leave the footer’s position as fixed. Even though momentum-based scrolling applied to the whole page, rather than the contents without the footer, this solution was good enough for me and fulfilled all of my requirements at that point in time, and my footer no longer bounced unexpectedly on Chrome. It is perhaps useful to note that Edge has this property flagged as under development now. overscroll-behavior can be seen as an enhancement if browsers do not support it yet.
If you don’t want your fixed headers or footers to bounce around on your web pages, you can now use the overscroll-behavior CSS property.
Despite the fact that this solution works differently in different browsers (bouncing of the page content still happens on Safari and Edge, whereas on Firefox and Chrome it doesn’t), it will keep the header or footer fixed when you scroll to the very top or bottom of a website. It is a concise solution and on all the browsers tested, momentum-based scrolling still works, so you can scroll through a lot of page content very quickly. If you are building a fixed header or footer on your web page, you can begin to use this solution.
The Holy Grail Of Reusable Components: Custom Elements, Shadow DOM, And NPM
For even the simplest of components, the cost in human-labour may have been significant. UX teams do usability testing. An array of stakeholders have to sign off on the design.
Developers conduct AB tests, accessibility audits, unit tests and cross-browser checks. Once you’ve solved a problem, you don’t want to repeat that effort. By building a reusable component library (rather than building everything from scratch), we can continuously utilize past efforts and avoid revisiting already solved design and development challenges.
Building an arsenal of components is particularly useful for companies such as Google that own a considerable portfolio of websites all sharing a common brand. By codifying their UI into composable widgets, larger companies can both speed up development time and achieve consistency of both visual and user-interaction design across projects. There’s been a rise in interest in style guides and pattern libraries over the last several years. Given multiple developers and designers spread over multiple teams, large companies seek to attain consistency. We can do better than simple color swatches. What we need is easily distributable code.
Sharing And Reusing Code
The Markup Problem
“Once they copy that code they are essentially cutting a version which needs to be maintained indefinitely. When they copied the markup for a working component it had an implicit link to a snapshot of the CSS at that point. If you then update the template or refactor the CSS, you need to update all versions of the template scattered around your site.”
A Solution: Web Components
A component-centric approach to front-end development has become ubiquitous, ushered in by Facebook’s React framework. Inevitably, given the pervasiveness of frameworks in modern front-end workflows, a number of companies have built component libraries using their framework of choice. Those components are reusable only within that particular framework.
It’s rare for a sizeable company to have a uniform front-end and replatorming from one framework to another isn’t uncommon. Frameworks come and go. To enable the maximum amount of potential reuse across projects, we need components that are framework agnostic.
“I have built web applications using: Dojo, Mootools, Prototype, jQuery, Backbone, Thorax, and React over the years…I would love to have been able to bring that killer Dojo component that I slaved over with me to my React app of today.”
When we talk about a web component, we are talking about the combination of a custom element with shadow DOM. Custom Elements and shadow DOM are part of both the W3C DOM specification and the WHATWG DOM Standard — meaning web components are a web standard. Custom elements and shadow DOM are finally set to achieve cross-browser support this year. By using a standard part of the native web platform, we ensure that our components can survive the fast-moving cycle of front-end restructuring and architectural rethinks. Web components can be used with any templating language and any front-end framework — they’re truly cross-compatible and interoperable. They can be used everywhere from a WordPress blog to a single page application.
Making A Web Component
Defining A Custom Element
It’s always been possible to make up tag-names and have their content appear on the page.
HTML is designed to be fault tolerant. The above will render, even though it’s not a valid HTML element. There’s never been a good reason to do this — deviating from standardized tags has traditionally been a bad practice. By defining a new tag using the custom element API, however, we can augment HTML with reusable elements that have built-in functionality. Creating a custom element is much like creating a component in React — but here were extending HTMLElement.
class ExpandableBox extends HTMLElement
A parameter-less call to super() must be the first statement in the constructor. The constructor should be used to set up initial state and default values and to set up any event listeners. A new custom element needs to be defined with a name for its HTML tag and the elements corresponding class:
It’s a convention to capitalize class names. The syntax of the HTML tag is, however, more than a convention. What if browsers wanted to implement a new HTML element and they wanted to call it expandable-box? To prevent naming collisions, no new standardized HTML tags will include a dash. By contrast, the names of custom elements have to include a dash.
The API offers four custom element reactions — functions that can be defined within the class that will automatically be called in response to certain events in the lifecycle of a custom element.
connectedCallback is run when the custom element is added to the DOM.
console.log("custom element is on the page!")
document.body.appendChild(document.createElement("expandable-box")) //“custom element is on the page”
as well as simply including the element within the page with a HTML tag:
<expandable-box></expandable-box> // "custom element is on the page"
Any work that involves fetching resources or rendering should be in here.
disconnectedCallback is run when the custom element is removed from the DOM.
console.log("element has been removed")
document.querySelector("expandable-box").remove() //"element has been removed"
adoptedCallback is run when the custom element is adopted into a new document. You probably don’t need to worry about this one too often.
attributeChangedCallback is run when an attribute is added, changed, or removed. It can be used to listen for changes to both standardized native attributes like disabled or src, as well as any custom ones we make up. This is one of the most powerful aspects of custom elements as it enables the creation of a user-friendly API.
Custom Element Attributes
There are a great many HTML attributes. So that the browser doesn’t waste time calling our attributeChangedCallback when any attribute is changed, we need to provide a list of the attribute changes we want to listen for. For this example, we’re only interested in one.
static get observedAttributes()
So now our attributeChangedCallback will only be called when we change the value of the expanded attribute on the custom element, as it’s the only attribute we’ve listed.
HTML attributes can have corresponding values (think href, src, alt, value etc) while others are either true or false (e.g. disabled, selected, required). For an attribute with a corresponding value, we would include the following within the custom element’s class definition.
For our example element, the attribute will either be true or false, so defining the getter and setter is a little different.
// the second argument for setAttribute is mandatory, so we’ll use an empty string
Now that the boilerplate has been dealt with, we can make use of attributeChangedCallback.
attributeChangedCallback(name, oldval, newval)
console.log(`the $name attribute has changed from $oldval to $newval!!`);
// do something every time the attribute changes
Shadow DOM and custom elements can be used separately, and you may find custom elements useful all by themselves. Unlike shadow DOM, they can be polyfilled. However, the two specs work well in conjunction.
Attaching Markup And Styles With Shadow DOM
So far, we’ve handled the behavior of a custom element. In regard to markup and styles, however, our custom element is equivalent to an empty unstyled <span>. To encapsulate HTML and CSS as part of the component, we need to attach a shadow DOM. It’s best to do this within the constructor function.
class FancyComponent extends HTMLElement
var shadowRoot = this.attachShadow(mode: 'open')
shadowRoot.innerHTML = `<h2>hello world!</h2>`
Don’t worry about understanding what the mode means — its boilerplate you have to include, but you’ll pretty much always want open. This simple example component will just render the text “hello world”. Like most other HTML elements, a custom element can have children — but not by default. So far the above custom element we’ve defined won’t render any children to the screen. To display any content between the tags, we need to make use of a slot element.
These styles will only apply to the component, so we are free to make use of element selectors without the styles affecting anything else of the page. This simplifies writing CSS, making naming conventions like BEM unnecessary.
Publishing A Component On NPM
NPM packages are published via the command line. Open a terminal window and move into a directory that you would like to turn into a reusable package. Then type the following commands into the terminal:
If your project doesn’t already have a package.json, npm init will walk you through generating one.
npm adduser links your machine to your NPM account. If you don’t have a preexisting account, it will create a new one for you.
If all’s gone well, you now have a component in the NPM registry, ready to be installed and used in your own projects — and shared with the world.
Although originally announced in 2011, browser support still isn’t universal. Firefox support is due later this year. Nevertheless, some high-profile websites (like Youtube) are already making use of them. Despite their current shortcomings, for universally shareable components they’re the singular option and in the future we can expect exciting additions to what they have to offer.
Full-day workshop • June 28th
This workshop is designed for designers and developers who already have a good working knowledge of HTML and CSS. We will cover a range of CSS methods for achieving layout, from those you are safe to use right now even if you need to support older version of Internet Explorer through to things that while still classed as experimental, are likely to ship in browsers in the coming months.
Let’s suppose Tony Stark would like to redesign the ID cards of the Avengers, and he needs our help to create them in HTML and CSS. So, how can we help? In this tutorial, we’ll be using Flexbox to create the desired layout while diving into nested flexboxes for some advanced layouts. We will also be using rounded as well as transparent borders to create sci-fi arcs in CSS, and then animating them by using CSS animations around the picture of the Avenger. Last but not least, we’ll be using the box-shadow and text-shadow properties to give our ID card a final sci-fi touch.
By the end of the tutorial, we will build a sci-fi animated Avengers ID card, and also learn the basics of Flexbox, nested Flexbox, CSS animations, borders, shadows, and many other frequently used CSS properties.
Here’s how our final Avengers ID card will look like:
We need a div that covers the entire screen. We will use this div as the background to place the ID card:
Let’s make the div cover the entire page and give a dark background:
Why use 100vh and not 100% for height?
If you look closely, you will notice that we used 100% for width, but 100vh for height. The vh unit stands for “viewport height”. It is a viewport unit, some other viewport units are: vw, vmin, and vmax.
So, why should we use 100vh instead of 100% for the height? Well, a % based dimension is relative to its parent element. So, if we set the height of the id-card-wrapper to 100%, that would mean it will make the height of id-card-wrapper cover 100% of the height of its parent element (which is the body element).
The problem is — by default — the body element doesn’t cover entire screen’s height. The width of the body element is by default 100% that’s why we can use width: 100% on id-card-wrapper, but since the height is not 100% by default the same won’t work for height.
Since a viewport unit is relative to the viewport, not the parent element, setting the height to 100vh will make the element cover entire height of the visible area (viewport), regardless of the parent’s dimensions.
Note: If you want to dive deeper into the viewport units, checkout this Fun with Viewport Units article on CSS-Tricks. One more thing, there are many ways to create a full page background, Chris Coyier lists them well in this post.
Why margin: 0px On Body?
The browsers by default display some margin around the body. If we don’t set this margin to 0, we will get a white gap around the id-card-wrapper div.
Centering Using Flexbox
There are many ways to center. Now that our full-page background is ready, let’s create the div that will contain our ID Card. We will put only “Test” as content, and build the layout first:
“The em is simply the font size. In an element with a 2in font, 1em thus means 2in.”
This means that if your browser has a default font size of 14px, then 30em will be equal to 30×14 = 420px.
But, why use em unit instead of px?
Look, the em unit is relative to the font size. Let’s suppose you are using a browser with 14px default font size. Now if someone views your project from another browser that has 16px as default font size, then guess what would happen?
The content inside will need more space, but your div has a fixed width, i.e. the content will either spill out or break the layout.
It’s always a good idea to have dimensions that scale along with the content, instead of fixing it to arbitrary pixels.
Why Doesn’t margin: auto Center The div Vertically?**
We already know that we can center a block element horizontally using margin: auto, but it doesn’t work for vertical centering.
What if I told you that margin: auto works vertically, too? Actually, in normal layout mode, it doesn’t. But in new layout modes like Flexbox, the margin: auto works for vertical centering, too. Go ahead and make the id-card-wrapper a flexbox to see it yourself:
As you can see, our id-card div is now centered horizontally and vertically. We simply set display: flex on the id-card-wrapper div. When you set display: flex to an element, that element becomes a flex-container and its child elements become flex-items. Check out “Basic Concepts Of Flexbox” on MDN.
Okay, this did center our element, but why did it lose its width? The id-card div is a block element, and since block elements are by default 100% wide, why did the div lose this block level behavior when it became a flex-item?
Actually, it hasn’t lost its block behavior. What’s happening is, as soon as the div comes into the flexbox context, the flexbox algorithm notes that the div doesn’t have any width property set to it (we are giving it only max-width), and then it sets the initial width to 0.
We can change this behavior by explicitly defining the initial width of the element using the [flex-basis](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis) property, like this:
Now our id-card div is ready for content. Let’s create a profile-row div and two sections in it dp and desc. The dp div will contain the profile photo of the Avenger while the desc div will contain the description of that Avenger:
We know that the id-card div is a flex-item, but the div we just created inside id-card (the profile-row div) isn’t a flex-item. Yes, only the direct decedents of the flex-containers become flex-items, but not the grandchildren.
Therefore, profile-row is a normal div, and we will make it a flex-container by setting display: flex to it. This will make its child elements, dp and desc, flex-items:
Now we can use the flex-basis property to make the dp div 33.3% wide and the desc div 66.6% wide:
We set max-width: 100% for the img element because the img element by default displays the image in its original resolution.
If the image is 500px×500px then it will be displayed in that dimension. But we don’t want that. Instead, we want the image to be only as wide as the dp div, that’s why we set its max-width to 100%.
Also, we set the border-radius property to 50%. We are doing this to display the image as a circle:
Making Arcs In CSS
Eventually, Tony visits us while we’re still working on this ID card, and says that this doesn’t look sci-fi enough. Alright, no problem. Let’s make it more sci-fi. We can make two arcs rotate around the image by inserting the first arc dp-arc-inner inside the dp element:
We want the arc div to overlap on the dp div. The only problem is that elements don’t overlap in HTML. However, if we set the position of an element as absolute then that element is taken out of the normal flow of the document and we can set its position as we desire.
The default positioning of HTML elements is static. We set position: absolute on dp-arc-inner to make it absolutely positioned. Now we can use left, top, bottom, and right properties to set its position.
One caution: The left, top, bottom, and right properties are relative the first parent element in the hierarchy which is “relatively” positioned. That’s why we’ve set position: relative on the dp div. If we don’t do this, the left, top, bottom, and right properties will be set respectively to the screen, not the dp element.
One more thing: we are setting display: block on the img element. Why? Because img elements are inline-block by default, and inline-block elements display a tiny gap on its sides and bottom.
This gap generally doesn’t cause any problem, but a little gap around the image in our case will offset the arc’s position. So we set the img element as block element.
Next, let’s make the dp-arc-inner div look like an arc:
What we are doing is, instead of setting the border for all the sides with #0AE0DF color, we are setting all the sides as transparent, and then giving only the top border the color #0AE0DF. Then we set the border-radius: 50% to make it round:
Calc is a CSS function that calculates the mathematical expression given to it. Look, we had the inner arc with width and height of 100% and a border of 6px, right? That makes the inner arc’s total width 6px + 100% + 6px.
Now if we want the outer arc to be bigger than the inner arc then we need some way to make it 100% + 12px wide. This is where the calc() function comes to the rescue.
Also, notice that we are using border-bottom-color for this arc since we want the arc to display on the bottom.
Animating The Arcs
Now that our arcs are ready, let’s make them rotate around the image. We can do this with the help of CSS animations.
Any animation requires three basic things:
The start state of the animation,
The end state of the animation,
How long it should take to go from start to end state (speed of the animation).
We use @keyframes to define the animation. The from and to keywords are used to set the start and end state of the animation.
In the start state, we are rotating the arc 0-degree using transform: rotate(0deg), and in the end state we are rotating the arc 360-degree using transform: rotate(360deg).
To use this animation on an element, we need to give the name of the animation (rotate-clock in our case) to the animation-name property of that element. That’s what we are doing with animation-name: rotate-clock .
We also need to know how long it should take the animation to complete. We can do this by setting animation-duration property to 2s.
You will notice two problems in the output. One, the arc is rotated only one time, we want it to keep rotating, and two, the animation is not linear. The animation is fast at beginning and end, we want it to rotate with same speed throughout the animation.
To solve these problems, we will use the animation-iteration-count property to keep the animation repate itself infinite times, and animation-timing-function property to get a linear animation:
Wait a sec, why are we setting the margin of h1 to 0?
All the heading elements (h1, h2, h3, h4, and h5) are displayed with some margin around it by the browsers. This is usually not a problem, but we don’t want the top and bottom gaps around the heading elements right now. That’s why we zeroed the margin for h1 element.
What’s happening is, the height of the dp div is increasing.
Normally, if the content in the desc div is of more height than the height of the dp div then nothing happens to the dp div. However, in flexbox layout, the height of the dp div will also increase along with the height of the desc div.
We don’t want the dp div to increase in height with the desc div, and we can do that by using [align-self](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self) sub-property of flexbox:
In the text-shadow property, the first value, 0px, is the x-offset, how much the shadow is away from text in the x-direction. The second value, 0px, is the y-offset, telling us how much the shadow is away from the text in the y-direction. The third value, 4px, is the amount of blur you want to give to the shadow. The fourth value, #12a0a0, is the color of the shadow.
Note, we also added a 1px space between the letters of text using the [letter-spacing](https://developer.mozilla.org/en-US/docs/Web/CSS/letter-spacing) property because the text was looking a bit congested.
Next, let’s add some shadow to the ID card and the image:
The text-shadow property gives shadow to the text, and the [box-shadow](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow) property gives shadow to the elements.
The first three values for box-shadow are the same as text-shadow: x-offset, y-offset, and blur. The fourth value is how much you want the shadow to spread, and the fifth value is the color of the shadow.
Notice how we are giving two shadows, outer and inner, to the id-card div in a single line:
In this tutorial, we learned an effective way of making a full-page background, and centering elements with Flexbox and auto margins. We saw the basic usage of Flexbox and nested Flexboxes to make single dimension layouts.
If you want to dive deeper into Flexbox, check out “A Complete Guide to Flexbox” by Chris Coyier at CSS-Tricks. If you are more of a video learner, then you will enjoy the free 20 video course by Web Bos at Flexbox.io.
We also used CSS animations and the rotate transform to make animated arcs, however, we used a limited number of CSS properties and values. If you want to explore more about CSS animations then you will love this detailed MDN guide.
Finally, the glowing elements gave our ID card a unique sci-fi look. We used the “box-shadow” property to give the glow to our elements. Sometimes manually setting the values of the “box-shadow” property becomes cumbersome. Use CSSmatic’s Box Shadow CSS Generator to easily generate box shadows.
Managing SVG Interaction With The Pointer Events Property
Try clicking or tapping the SVG image below. If you put your pointer in the right place (the shaded path) then you should have Smashing Magazine’s homepage open in a new browser tab. If you tried to click on some white space, you might be really confused instead.
This is the dilemma I faced during a recent project that included links within SVG images. Sometimes when I clicked the image, the link worked. Other times it didn’t. Confusing, right?
I turned to the SVG specification to learn more about what might be happening and whether SVG offers a fix. The answer: pointer-events.
Not to be confused with DOM (Document Object Model) pointer events, pointer-events is both a CSS property and an SVG element attribute. With it, we can manage which parts of an SVG document or element can receive events from a pointing device such as a mouse, trackpad, or finger.
A note about terminology: “pointer events” is also the name of a device-agnostic, web platform feature for user input. However, in this article — and for the purposes of the pointer-events property — the phrase “pointer events” also includes mouse and touch events.
Outside Of The Box: SVG’s “Shape Model”
Using CSS with HTML imposes a box layout model on HTML. In the box layout model, every element generates a rectangle around its contents. That rectangle may be inline, inline-level, atomic inline-level, or block, but it’s still a rectangle with four right angles and four edges. When we add a link or an event listener to an element, the interactive area matches the dimensions of the rectangle.
Note: Adding a clip-path to an interactive element alters its interactive bounds. In other words, if you add a hexagonal clip-path path to an a element, only the points within the clipping path will be clickable. Similarly, adding a skew transformation will turn rectangles into rhomboids.
SVG does not have a box layout model. You see, when an SVG document is contained by an HTML document, within a CSS layout, the root SVG element adheres to the box layout model. Its child elements do not. As a result, most CSS layout-related properties don’t apply to SVG.
So instead, SVG has what I’ll call a ‘shape model’. When we add a link or an event listener to an SVG document or element, the interactive area will not necessarily be a rectangle. SVG elements do have a bounding box. The bounding box is defined as: the tightest fitting rectangle aligned with the axes of that element’s user coordinate system that entirely encloses it and its descendants. But initially, which parts of an SVG document are interactive depends on which parts are visible and/or painted.
Painted vs. Visible Elements
SVG elements can be “filled” but they can also be “stroked”. Fill refers to the interior of a shape. Stroke refers to its outline.
Together, “fill” and “stroke” are painting operations that render elements to the screen or page (also known as the canvas). When we talk about painted elements, we mean that the element has a fill and/or a stroke. Usually, this means the element is also visible.
However, an SVG element can be painted without being visible. This can happen if the visible attribute value or CSS property is hidden or when display is none. The element is there and occupies theoretical space. We just can’t see it (and assistive technology may not detect it).
Perhaps more confusingly, an element can also be visible — that is, have a computed visibility value of visible — without being painted. This happens when elements lack both a stroke and a fill.
Note: Color values with alpha transparency (e.g. rgba(0,0,0,0)) do not affect whether an element is painted or visible. In other words, if an element has an alpha transparent fill or stroke, it’s painted even if it can’t be seen.
Knowing when an element is painted, visible, or neither is crucial to understanding the impact of each pointer-events value.
All Or None Or Something In Between: The Values
pointer-events is both a CSS property and an SVG element attribute. Its initial value is auto, which means that only the painted and visible portions will receive pointer events. Most other values can be split into two groups:
Values that require an element to be visible; and
Values that do not.
painted, fill, stroke, and all fall into the latter category. Their visibility-dependent counterparts — visiblePainted, visibleFill, visibleStroke and visible — fall into the former.
The SVG 2.0 specification also defines a bounding-box value. When the value of pointer-events is bounding-box, the rectangular area around the element can also receive pointer events. As of this writing, only Chrome 65+ supports the bounding-box value.
none is also a valid value. It prevents the element and its children from receiving any pointer events. The pointer-events CSS property can be used with HTML elements too. But when used with HTML, only auto and none are valid values.
Since pointer-events values are better demonstrated than explained, let’s look at some demos.
Here we have a circle with a fill and a stroke applied. It’s both painted and visible. The entire circle can receive pointer events, but the area outside of the circle cannot.
Disable the fill, so that its value is none. Now if you try to hover, click, or tap the interior of the circle, nothing happens. But if you do the same for the stroke area, pointer events are still dispatched. Changing the fill value to none means that this area visible, but not painted.
Let’s make a small change to our markup. We’ll add pointer-events="visible" to our circle element, while keeping fill=none.
Now the unpainted area encircled by the stroke can receive pointer events.
Augmenting The Clickable Area Of An SVG Image
Let’s return to the image from the beginning of this article. Our “amethyst” is a path element, as opposed to a group of polygons each with a stroke and fill. That means we can’t just add pointer-events="all" and call it a day.
Instead, we need to augment the click area. Let’s use what we know about painted and visible elements. In the example below, I’ve added a rectangle to our image markup.
Even though this rectangle is unseen, it’s still technically visible (i.e. visibility: visible). Its lack of a fill, however, means that it is not painted. Our image looks the same. Indeed it still works the same — clicking white space still doesn’t trigger a navigation operation. We still need to add a pointer-events attribute to our a element. Using the visible or all values will work here.
Using bounding-box would eliminate the need for a phantom element. All points within the bounding box would receive pointer events, including the white space enclosed by the path. But again: pointer-events="bounding-box" isn’t widely supported. Until it is, we can use unpainted elements.
Using pointer-events When Mixing SVG And HTML
Another case where pointer-events may be helpful: using SVG inside of an HTML button.
In most browsers — Firefox and Internet Explorer 11 are exceptions here — the value of event.target will be an SVG element instead of our HTML button. Let’s add pointer-events="none" to our opening SVG tag.
Now when users click or tap our button, the event.target will refer to our button.
SVG supports the same kind of interactivity we’re used to with HTML. We can use it to create charts that respond to clicks or taps. We can create linked areas that don’t adhere to the CSS and HTML box model. And with the addition of pointer-events, we can improve the way our SVG documents behave in response to user interaction.
Browser support for SVG pointer-events is robust. Every browser that supports SVG supports the property for SVG documents and elements. When used with HTML elements, support is slightly less robust. It isn’t available in Internet Explorer 10 or its predecessors, or any version of Opera Mini.
We’ve just scratched the surface of pointer-events in this piece. For a more in-depth, technical treatment, read through the SVG Specification. MDN (Mozilla Developer Network) Web Docs offers more web developer-friendly documentation for pointer-events, complete with examples.
MDN Web Docs has been documenting the web platform for over twelve years and is now a cross-platform effort with contributions and an Advisory Board with members from Google, Microsoft and Samsung as well as those representing Firefox. Something that is fundamental to MDN is that it is a huge community effort, with the web community helping to create and maintain the documentation. In this article, I’m going to give you some pointers as to the places where you can help contribute to MDN and exactly how to do so.
If you haven’t contributed to an open source project before, MDN is a brilliant place to start. Skills needed range from copyediting, translating from English to other languages, HTML and CSS skills for creating Interactive Examples, or an interest in browser compatibility for updating Browser Compatibility data. What you don’t need to do is to write a whole lot of code to contribute. It’s very straightforward, and an excellent way to give back to the community if you have ever found these docs useful.
Contributing To The Documentation Pages
To start editing, you need to log in using GitHub. As is usual with a wiki, any editors of a page are listed, and this section will use your GitHub username. If you look at any of the pages on MDN contributors are listed at the bottom of the page, the below image shows the current contributors to the page on CSS Grid Layout.
What Might You Edit?
Things that you might consider as an editor are fixing obvious typos and grammatical errors. If you are a good proofreader and copyeditor, then you may well be able to improve the readability of the docs by fixing any spelling or other errors that you spot.
You might also spot a technical error, or somewhere the specs have changed and where an update or clarification would be useful. With the huge range of web platform features covered by MDN and the rate of change, it is very easy for things to get out of date, if you spot something – fix it!
You may be able to use some specific knowledge you have to add additional information. For example, Eric Bailey has been adding Accessibility Concerns sections to many pages. This is a brilliant effort to highlight the things we should be thinking about when using a certain thing.
Another place you could add to a page is in adding “See also” links. These could be links to other parts of MDN, or to external resources. When adding external resources, these should be highly relevant to the property, element or technique being described by that document. A good candidate would be a tutorial which demonstrates how to use that feature, something which would give a reader searching for information a valuable next step.
How To Edit A Document?
Once you are logged in you will see a link to Edit on pages in MDN, clicking this will take you into a WYSIWYG editor for editing content. Your first few edits are likely to be small changes, in which case you should be able to follow your nose and edit the text. If you are making extensive edits, then it would be worth taking a look at the style guide first. There is also a guide to using the WYSIWYG Editor.
After making your edit, you can Preview and then Publish. Before publishing it is a good idea to explain what you added and why using the Revision Comment field.
Those of us with English as a first language are incredibly fortunate when it comes to information on the web, being able to get pretty much all of the information that we could ever want in our own language. If you are able to translate English language pages into other languages, then you can help to translate MDN Web Docs, making all of this information available to more people.
If you click on the language icon on any page, you can see which languages that information has been translated into, and you can add your own translations following the information on the page Translating MDN Pages.
The Interactive Examples on MDN, are the examples that you will see at the top of many pages of MDN, such as this one for the grid-area property.
The content for these Interactive Examples is held in the Interactive Examples GitHub repository. For example, if you wanted to locate the example for grid-area, you would find it in that repo under live-examples/css-examples/grid. Under that folder, you will find two files for grid-area, an HTML and a CSS file.
An Interactive Example is just a small demo, which uses some standard classes and IDs in order that the framework can pick up the example and make it interactive, where the values can be changed by a visitor to the page who wants to quickly see how it works. To add or edit an Interactive Example, first fork the Interactive Examples repo, clone it to your machine and follow the instructions on the Contributing page to install the required packages from npm and be able to build and test examples locally.
Then create a branch and edit or create your new example. Once you are happy with it, send a Pull Request to the Interactive Examples repo to ask for your example to be reviewed. In order to keep the examples consistent, reviews are fairly nitpicky but should point out the changes you need to make in a clear way, so you can update your example and have it approved, merged and added to an MDN page.
The Interactive Examples are incredibly useful for people exploring the web platform, so adding to the project is an excellent way to contribute. Contributing to CSS or HTML examples requires knowledge of CSS and HTML, plus the ability to think up a clear demonstration. This last point is often the hardest part, I’ve created a lot of CSS Interactive Examples and spent more time thinking up the best example for each property than I do actually writing the code.
Browser Compat Data
Fairly recently the browser compatibility data listed on MDN Pages has begun to be updated through the Browser Compatibility Project. This project is developing browser compat data in JSON format, which can display the compatibility tables on MDN but also be useful data for other purposes.
The Browser Compatibility Data is on GitHub, and if you find a page that has incorrect information or is still using the old tables, you can submit a Pull Request. The repository contains contribution information, however, the simplest way to start is to edit an existing example. I recently updated the information for the CSS shape-outside property. The property already had some data in the new format, but it was incomplete and incorrect.
To edit this data, I first forked the Browser Compat Data so that I had my own fork. I then cloned that to my machine and created a new branch to make my changes in.
Once I had my new branch, I found the JSON file for shape-outside and was able to make my edits. I already had a good idea about browser support for the property; I also used the live example on the shape-outside MDN page to test to see support when I wasn’t sure. Therefore making the edits was a case of working through the file, checking the version numbers listed for support of the property and updating those which were incorrect.
As the file is in JSON format is pretty straightforward to edit in any text editor. The .editorconfig file explains the simple formatting rules for these documents. There are also some helpful tips in this checklist.
Once you have made your edits, you can commit your changes, push your branch to your fork and then make a Pull Request to the Browser Compat Data repository. It’s likely that, as with the live examples, the reviewer will have some changes for you to make. In my PR for the Shapes data I had a few errors in how I had flagged the data and needed to make some changes to links. These were simple to make, and then my PR was merged.
You can get started simply by picking something to add to and starting work on it in many cases. If you have any questions or need some help with any of this, then the MDN Discourse forum is a good place to post. MDN is the place I go to look up information, the place I send new developers and experienced developers alike, and its strength is the fact that we can all work to make it better.
If you have never made a Pull Request on a project before, it is a very friendly place to make that first PR and, as I hope I have shown, there are ways to contribute that don’t require writing any code at all. A very valuable skill for any documentation project is that of writing, editing and translating as these skills can help to make technical documentation easier to read and accessible to more people around the world.
“Accessibility is solved at the design stage.” This is a phrase that Daniel Na and his team heard over and over again while attending a conference. To design for accessibility means to be inclusive to the needs of your users. This includes your target users, users outside of your target demographic, users with disabilities, and even users from different cultures and countries. Understanding those needs is the key to crafting better and more accessible experiences for them.
One of the most common problems when designing for accessibility is knowing what needs you should design for. It’s not that we intentionally design to exclude users, it’s just that “we don’t know what we don’t know.” So, when it comes to accessibility, there’s a lot to know.
How do we go about understanding the myriad of users and their needs? How can we ensure that their needs are met in our design? To answer these questions, I have found that it is helpful to apply a critical analysis technique of viewing a design through different lenses.
“Good [accessible] design happens when you view your [design] from many different perspectives, or lenses.”
A lens is “a narrowed filter through which a topic can be considered or examined.” Often used to examine works of art, literature, or film, lenses ask us to leave behind our worldview and instead view the world through a different context.
For example, viewing art through a lens of history asks us to understand the “social, political, economic, cultural, and/or intellectual climate of the time.” This allows us to better understand what world influences affected the artist and how that shaped the artwork and its message.
Accessibility lenses are a filter that we can use to understand how different aspects of the design affect the needs of the users. Each lens presents a set of questions to ask yourself throughout the design process. By using these lenses, you will become more inclusive to the needs of your users, allowing you to design a more accessible user experience for all.
You should know that not every lens will apply to every design. While some can apply to every design, others are more situational. What works best in one design may not work for another.
The questions provided by each lens are merely a tool to help you understand what problems may arise. As always, you should test your design with users to ensure it’s usable and accessible to them.
Lens Of Animation And Effects
Effective animations can help bring a page and brand to life, guide the users focus, and help orient a user. But animations are a double-edged sword. Not only can misusing animations cause confusion or be distracting, but they can also be potentially deadly for some users.
Fast flashing effects (defined as flashing more than three times a second) or high-intensity effects and patterns can cause seizures, known as ‘photosensitive epilepsy.’ Photosensitivity can also cause headaches, nausea, and dizziness. Users with photosensitive epilepsy have to be very careful when using the web as they never know when something might cause a seizure.
Other effects, such as parallax or motion effects, can cause some users to feel dizzy or experience vertigo due to vestibular sensitivity. The vestibular system controls a person’s balance and sense of motion. When this system doesn’t function as it should, it causes dizziness and nausea.
“Imagine a world where your internal gyroscope is not working properly. Very similar to being intoxicated, things seem to move of their own accord, your feet never quite seem to be stable underneath you, and your senses are moving faster or slower than your body.”
Constant animations or motion can also be distracting to users, especially to users who have difficulty concentrating. GIFs are notably problematic as our eyes are drawn towards movement, making it easy to be distracted by anything that updates or moves constantly.
This isn’t to say that animation is bad and you shouldn’t use it. Instead you should understand why you’re using the animation and how to design safer animations. Generally speaking, you should try to design animations that cover small distances, match direction and speed of other moving objects (including scroll), and are relatively small to the screen size.
To use the Lens of Animation and Effects, ask yourself these questions:
Are there any effects that could cause a seizure?
Are there any animations or effects that could cause dizziness or vertigo through use of motion?
Are there any animations that could be distracting by constantly moving, blinking, or auto-updating?
Is it possible to provide controls or options to stop, pause, hide, or change the frequency of any animations or effects?
Lens Of Audio And Video
Autoplaying videos and audio can be pretty annoying. Not only do they break a users concentration, but they also force the user to hunt down the offending media and mute or stop it. As a general rule, don’t autoplay media.
“Use autoplay sparingly. Autoplay can be a powerful engagement tool, but it can also annoy users if undesired sound is played or they perceive unnecessary resource usage (e.g. data, battery) as the result of unwanted video playback.”
You’re now probably asking, “But what if I autoplay the video in the background but keep it muted?” While using videos as backgrounds may be a growing trend in today’s web design, background videos suffer from the same problems as GIFs and constant moving animations: they can be distracting. As such, you should provide controls or options to pause or disable the video.
Along with controls, videos should have transcripts and/or subtitles so users can consume the content in a way that works best for them. Users who are visually impaired or who would rather read instead of watch the video need a transcript, while users who aren’t able to or don’t want to listen to the video need subtitles.
To use the Lens of Audio and Video, ask yourself these questions:
Are there any audio or video that could be annoying by autoplaying?
Is it possible to provide controls to stop, pause, or hide any audio or videos that autoplay?
Do videos have transcripts and/or subtitles?
Lens Of Color
Color plays an important part in a design. Colors evoke emotions, feelings, and ideas. Colors can also help strengthen a brand’s message and perception. Yet the power of colors is lost when a user can’t see them or perceives them differently.
Because colors and their meanings can be lost either through cultural differences or color blindness, you should always add a non-color identifier. Identifiers such as icons or text descriptions can help bridge cultural differences while patterns work well to distinguish between colors.
Oversaturated colors, high contrasting colors, and even just the color yellow can be uncomfortable and unsettling for some users, prominently those on the autism spectrum. It’s best to avoid high concentrations of these types of colors to help users remain comfortable.
Poor contrast between foreground and background colors make it harder to see for users with low vision, using a low-end monitor, or who are just in direct sunlight. All text, icons, and any focus indicators used for users using a keyboard should meet a minimum contrast ratio of 4.5:1 to the background color.
You should also ensure your design and colors work well in different settings of Windows High Contrast mode. A common pitfall is that text becomes invisible on certain high contrast mode backgrounds.
To use the Lens of Color, ask yourself these questions:
If the color was removed from the design, what meaning would be lost?
How could I provide meaning without using color?
Are any colors oversaturated or have high contrast that could cause users to become overstimulated or uncomfortable?
Does the foreground and background color of all text, icons, and focus indicators meet contrast ratio guidelines of 4.5:1?
Lens Of Controls
Controls, also called ‘interactive content,’ are any UI elements that the user can interact with, be they buttons, links, inputs, or any HTML element with an event listener. Controls that are too small or too close together can cause lots of problems for users.
Small controls are hard to click on for users who are unable to be accurate with a pointer, such as those with tremors, or those who suffer from reduced dexterity due to age. The default size of checkboxes and radio buttons, for example, can pose problems for older users. Even when a label is provided that could be clicked on instead, not all users know they can do so.
Controls that are too close together can cause problems for touch screen users. Fingers are big and difficult to be precise with. Accidentally touching the wrong control can cause frustration, especially if that control navigates you away or makes you lose your context.
Controls that are nested inside another control can also contribute to touch errors. Not only is it not allowed in the HTML spec, it also makes it easy to accidentally select the parent control instead of the one you wanted.
It’s also recommended that controls be placed far enough apart to reduce touch errors. Microsoft recommends at least 8 pixels of spacing while Google recommends controls be spaced at least 32 pixels apart.
Technology today is very different than it was 20 years ago. Today, browsers can be used on any device of any size, from a small watch to a huge 4K screen. We can no longer use fixed font sizes to design our sites. Font sizes must be as responsive as the design itself.
The font itself should be easy to read. You may be wondering if one font is more readable than another. The truth of the matter is that the font doesn’t really make a difference to readability. Instead it’s the font style that plays an important role in a fonts readability.
Decorative or cursive font styles are harder to read for many users, but especially problematic for users with dyslexia. Small font sizes, italicized text, and all uppercase text are also difficult for users. Overall, larger text, shorter line lengths, taller line heights, and increased letter spacing can help all users have a better reading experience.
To use the Lens of Font, ask yourself these questions:
Is the design flexible enough that the font could be modified to a comfortable reading level by the user?
Is the font style easy to read?
Lens Of Images and Icons
They say, “A picture is worth a thousand words.” Still, a picture you can’t see is speechless, right?
Images can be used in a design to convey a specific meaning or feeling. Other times they can be used to simplify complex ideas. Whichever the case for the image, a user who uses a screen reader needs to be told what the meaning of the image is.
As the designer, you understand best the meaning or information the image conveys. As such, you should annotate the design with this information so it’s not left out or misinterpreted later. This will be used to create the alt text for the image.
Since knowing how to describe an image can be difficult, there’s a handy decision tree to help when deciding. Generally speaking, if the image is decorational or there’s surrounding text that already describes the image’s information, no further information is needed. Otherwise you should describe the information of the image. If the image contains text, repeat the text in the description as well.
Descriptions should be succinct. It’s recommended to use no more than two sentences, but aim for one concise sentence when possible. This allows users to quickly understand the image without having to listen to a lengthy description.
As an example, if you were to describe this image for a screen reader, what would you say?
Since we describe the information of the image and not the image itself, the description could be Vincent van Gogh’s The Starry Night since there is no other surrounding context that describes it. What you shouldn’t put is a description of the style of the painting or what the picture looks like.
This way, users can still get the most important information quickly but have the ability to dig in further if they wish. If the image is of a chart, you should repeat the data of the chart just like you would for text in the image.
If the platform you are designing for allows users to upload images, you should provide a way for the user to enter the alt text along with the image. For example, Twitter allows its users to write alt text when they upload an image to a tweet.
To use the Lens of Images and Icons, ask yourself these questions:
Does any image contain information that would be lost if it was not viewable?
How could I provide the information in a non-visual way?
If the image is controlled by the user, is it possible to provide a way for them to enter the alt text description?
Lens Of Keyboard
Keyboard accessibility is among the most important aspects of an accessible design, yet it is also among the most overlooked.
There are many reasons why a user would use a keyboard instead of a mouse. Users who use a screen reader use the keyboard to read the page. A user with tremors may use a keyboard because it provides better accuracy than a mouse. Even power users will use a keyboard because it’s faster and more efficient.
A user using a keyboard typically uses the tab key to navigate to each control in sequence. A logical order for the tab order greatly helps users know where the next key press will take them. In western cultures, this usually means from left to right, top to bottom. Unexpected tab orders results in users becoming lost and having to scan frantically for where the focus went.
Sequential tab order also means that they must tab through all controls that are before the one that they want. If that control is tens or hundreds of keystrokes away, it can be a real pain point for the user.
By making the most important user flows nearer to the top of the tab order, we can help enable our users to be more efficient and effective. However, this isn’t always possible nor practical to do. In these cases, providing a way to quickly jump to a particular flow or content can still allow them to be efficient. This is why “skip to content” links are helpful.
A good example of this is Facebook which provides a keyboard navigation menu that allows users to jump to specific sections of the site. This greatly speeds up the ability for a user to interact with the page and the content they want.
When tabbing through a design, focus styles should always be visible or a user can easily become lost. Just like an unexpected tab order, not having good focus indicators results in users not knowing what is currently focused and having to scan the page.
Changing the look of the default focus indicator can sometimes improve the experience for users. A good focus indicator doesn’t rely on color alone to indicate focus (Lens of Color), and should be distinct enough to easily allow the user to find it. For example, a blue focus ring around a similarly colored blue button may not be visually distinct to discern that it is focused.
Although this lens focuses on keyboard accessibility, it’s important to note that it applies to any way a user could interact with a website without a mouse. Devices such as mouth sticks, switch access buttons, sip and puff buttons, and eye tracking software all require the page to be keyboard accessible.
By improving keyboard accessibility, you allow a wide range of users better access to your site.
To use the Lens of Keyboard, ask yourself these questions:
What keyboard navigation order makes the most sense for the design?
How could a keyboard user get to what they want in the quickest way possible?
Is the focus indicator always visible and visually distinct?
Lens Of Layout
Layout contributes a great deal to the usability of a site. Having a layout that is easy to follow with easy to find content makes all the difference to your users. A layout should have a meaningful and logical sequence for the user.
With the advent of CSS Grid, being able to change the layout to be more meaningful based on the available space is easier than ever. However, changing the visual layout creates problems for users who rely on the structural layout of the page.
The structural layout is what is used by screen readers and users using a keyboard. When the visual layout changes but not the underlying structural layout, these users can become confused as their tab order is no longer logical. If you must change the visual layout, you should do so by changing the structural layout so users using a keyboard maintain a sequential and logical tab order.
The layout should be resizable and flexible to a minimum of 320 pixels with no horizontal scroll bars so that it can be viewed comfortably on a phone. The layout should also be flexible enough to be zoomed in to 400% (also with no horizontal scroll bars) for users who need to increase the font size for a better reading experience.
To use the Lens of Layout, ask yourself these questions:
Does the layout have a meaningful and logical sequence?
What should happen to the layout when it’s viewed on a small screen or zoomed in to 400%?
Is content that is related or changes due to user interaction in close proximity to one another?
Lens Of Material Honesty
Material honesty is an architectural design value that states that a material should be honest to itself and not be used as a substitute for another material. It means that concrete should look like concrete and not be painted or sculpted to look like bricks.
Material honesty values and celebrates the unique properties and characteristics of each material. An architect who follows material honesty knows when each material should be used and how to use it without tarnishing itself.
Material honesty is not a hard and fast rule though. It lies on a continuum. Like all values, you are allowed to break them when you understand them. As the saying goes, they are “more what you’d call “guidelines” than actual rules.”
Links and buttons have different behaviors and affordances. A link is activated with the enter key, typically takes you to a different page, and has a special context menu on right click. Buttons are activated with the space key, used primarily to trigger interactions on the current page, and have no such context menu.
When a link is styled to look like a button or vise versa, a user could become confused as it does not behave and function as it looks. If the “button” navigates the user away unexpectedly, they might become frustrated if they lost data in the process.
“At first glance everything looks fine, but it won’t stand up to scrutiny. As soon as such a website is stress‐tested by actual usage across a range of browsers, the façade crumbles.”
Where this becomes the most problematic is when a link and button are styled the same and are placed next to one another. As there is nothing to differentiate between the two, a user can accidentally navigate when they thought they wouldn’t.
Autocomplete is used to suggest or predict the rest of a word a user is typing. An autocomplete menu allows a user to select from a large list of options when not all options can be shown.
An autocomplete menu is typically attached to an input field and is navigated with the up and down arrow keys, keeping the focus inside the input field. When a user selects an option from the list, that option will override the text in the input field. Autocomplete menus are meant to be lists of just text.
The problem arises when an autocomplete menu starts to gain more behaviors. Not only can you select an option from the list, but you can edit it, delete it, or even expand or collapse sections. The autocomplete menu is no longer just a simple list of selectable text.
The added behaviors no longer mean you can just use the up and down arrows to select an option. Each option now has more than one action, so a user needs to be able to traverse two dimensions instead of just one. This means that a user using a keyboard could become confused on how to operate the component.
Screen readers suffer the most from this change of behavior as there is no easy way to help them understand it. A lot of work will be required to ensure the menu is accessible to a screen reader by using non-standard means. As such, it will might result in a sub-par or inaccessible experience for them.
To avoid these issues, it’s best to be honest to the user and the design. Instead of combining two distinct behaviors (an autocomplete menu and edit and delete functionality), leave them as two separate behaviors. Use an autocomplete menu to just autocomplete the name of a user, and have a different component or page to edit and delete users.
To use the Lens of Material Honesty, ask yourself these questions:
Is the design being honest to the user?
Are there any elements that behave, look, or function as another element?
Are there any components that combine distinct behaviors into a single component? Does doing so make the component materially dishonest?
Lens Of Readability
Have you ever picked up a book only to get a few paragraphs or pages in and want to give up because the text was too hard to read? Hard to read content is mentally taxing and tiring.
Sentence length, paragraph length, and complexity of language all contribute to how readable the text is. Complex language can pose problems for users, especially those with cognitive disabilities or who aren’t fluent in the language.
Along with using plain and simple language, you should ensure each paragraph focuses on a single idea. A paragraph with a single idea is easier to remember and digest. The same is true of a sentence with fewer words.
Another contributor to the readability of content is the length of a line. The ideal line length is often quoted to be between 45 and 75 characters. A line that is too long causes users to lose focus and makes it harder to move to the next line correctly, while a line that is too short causes users to jump too often, causing fatigue on the eyes.
“The subconscious mind is energized when jumping to the next line. At the beginning of every new line the reader is focused, but this focus gradually wears off over the duration of the line”
— Typographie: A Manual of Design
You should also break up the content with headings, lists, or images to give mental breaks to the reader and support different learning styles. Use headings to logically group and summarize the information. Headings, links, controls, and labels should be clear and descriptive to enhance the users ability to comprehend.
To use the Lens of Readability, ask yourself these questions:
Is the language plain and simple?
Does each paragraph focus on a single idea?
Are there any long paragraphs or long blocks of unbroken text?
Are all headings, links, controls, and labels clear and descriptive?
Lens Of Structure
As mentioned in the Lens of Layout, the structural layout is what is used by screen readers and users using a keyboard. While the Lens of Layout focused on the visual layout, the Lens of Structure focuses on the structural layout, or the underlying HTML and semantics of the design.
As a designer, you may not write the structural layout of your designs. This shouldn’t stop you from thinking about how your design will ultimately be structured though. Otherwise, your design may result in an inaccessible experience for a screen reader.
Take for example a design for a single elimination tournament bracket.
How would you know if this design was accessible to a user using a screen reader? Without understanding structure and semantics, you may not. As it stands, the design would probably result in an inaccessible experience for a user using a screen reader.
To understand why that is, we first must understand that a screen reader reads a page and its content in sequential order. This means that every name in the first column of the tournament would be read, followed by all the names in the second column, then third, then the last.
If all you had was a list of seemingly random names, how would you interpret the results of the tournament? Could you say who won the tournament? Or who won game 6?
With nothing more to work with, a user using a screen reader would probably be a bit confused about the results. To be able to understand the visual design, we must provide the user with more information in the structural design.
This means that as a designer you need to know how a screen reader interacts with the HTML elements on a page so you know how to enhance their experience.
Landmark Elements (header, nav, main, and footer)
Allow a screen reader to jump to important sections in the design.
Headings (h1 → h6)
Allow a screen reader to scan the page and get a high level overview. Screen readers can also jump to any heading.
Lists (ul and ol)
Group related items together, and allow a screen reader to easily jump from one item to another.
Trigger interactions on the current page.
Navigate or retrieve information.
Tell screen readers what each form input is.
Knowing this, how might we provide more meaning to a user using a screen reader?
To start, we could group each column of the tournament into rounds and use headings to label each round. This way, a screen reader would understand when a new round takes place.
Next, we could help the user understand which players are playing against each other each game. We can again use headings to label each game, allowing them to find any game they might be interested in.
By just adding headings, the content would read as follows:
This is already a lot more understandable than before.
The information still doesn’t answer who won a game though. To know that, you’d have to understand which game a winner plays next to see who won the previous game. For example, you’d have to know that the winner of game four plays in game six to know who advanced from game four.
We can further enhance the experience by informing the user who won each game so they don’t have to go hunting for it. Putting the text “(winner)” after the person who won the round would suffice.
We should also further group the games and rounds together using lists. Lists provide the structural semantics of the design, essentially informing the user of the connected nodes from the visual design.
If we translate this back into a visual design, the result could look as follows:
“If the end result is visually the same as where we started, why did we go through all this?” You may ask.
The reason is that you should always annotate your design with all the necessary structural design requirements needed for a better screen reader experience. This way, the person who implements the design knows to add them. If you had just handed the first design to the implementer, it would more than likely end up inaccessible.
To use the Lens of Structure, ask yourself these questions:
Can I outline a rough HTML structure of my design?
How can I structure the design to better help a screen reader understand the content or find the content they want?
How can I help the person who will implement the design understand the intended structure?
Lens Of Time
Periodically in a design you may need to limit the amount of time a user can spend on a task. Sometimes it may be for security reasons, such as a session timeout. Other times it could be due to a non-functional requirement, such as a time constrained test.
Whatever the reason, you should understand that some users may need more time in order finish the task. Some users might need more time to understand the content, others might not be able to perform the task quickly, and a lot of the time they could just have been interrupted.
“The designer should assume that people will be interrupted during their activities”
— The Design of Everyday Things
Users who need more time to perform an action should be able to adjust or remove a time limit when possible. For example, with a session timeout you could alert the user when their session is about to expire and allow them to extend it.
To use the Lens of Time, ask yourself this question:
Is it possible to provide controls to adjust or remove time limits?
Bringing It All Together
So now that you’ve learned about the different lenses of accessibility through which you can view your design, what do you do with them?
The lenses can be used at any point in the design process, even after the design has been shipped to your users. Just start with a few of them at hand, and one at a time carefully analyze the design through a lens.
Ask yourself the questions and see if anything should be adjusted to better meet the needs of a user. As you slowly make changes, bring in other lenses and repeat the process.
By looking through your design one lens at a time, you’ll be able to refine the experience to better meet users’ needs. As you are more inclusive to the needs of your users, you will create a more accessible design for all your users.
Using lenses and insightful questions to examine principles of accessibility was heavily influenced by Jesse Schell and his book “The Art of Game Design: A Book of Lenses.”
Many people want to create the best email campaigns possible, and this goal can be realized by following best practices for email design and coding and by implementing advanced techniques correctly. This comprehensive guide, for novices and pros alike, delves deep into the nitty gritty of email marketing.
Here’s what you’ll learn:
best practices for email design, from creating a theme to designing the footer;
how to add images and incorporate rich media (GIFs, cinemagraphs, video) in your emails;
how to design responsive emails for a better user experience;
email client support for responsive mobile emails;
finally, advanced techniques in email design.
Emails have transformed from being an ordinary text-based personal communication tool into a future-proof marketing channel. We have moved into a world of visually attractive HTML emails that have the feel of microsites in the inbox.
Getting acquainted with the best practices of email coding is, therefore, imperative if you want to avoid a broken user experience and instead improve user engagement. Moreover, as the digital world becomes more mobile, creating responsive emails is the need of the hour.
In this article, we shall delve deeper into best practices to follow for all email clients, as well as advanced techniques you can include for email clients that support interactive elements.
Let’s start with the basic structure of an email.
Basic Email Structure
As Leonardo da Vinci said, ”Simplicity is the ultimate sophistication.” Accordingly, keep the design of your email simple.
Check out the email design below by Charity: Water. Simple yet engaging.
Developers have been coding emails using <table> layouts for a long time now. So, it is recommended that you place your email elements in a grid-based layout, rather than arbitrarily placed. Moreover, any element that might overlap needs to be added to a different layer.
The email shown above by Charity: Water looks like this when exported to a tabular layout:
Email design is made up of different subelements. Let’s explore them now.
1. Email Theme
The logo is not the only element that reflects your brand’s personality. The overall theme of your email, including the fonts, color scheme and imagery, should be in sync with branding guidelines.
2. Width And Height Of Email Template
Because your subscribers use diverse email clients and devices, your email should be appropriately visible in the preview pane of all email clients. Keep in mind that the email will be displayed according to the display pane of the email service provider or client. Only certain email clients, such as Thunderbird, Apple Mail and native mobile email clients, will display email at full width.
For other email clients, the display boxes have variable sizes. Many service providers, such as MailChimp, go over the basics of HTML email, by recommending, for example, 600 to 800 pixels as a width, so that the full email gets displayed. Remember, that most subscribers never use the horizontal scroll bar in an email.
The height of your email template should usually be long enough to accommodate your copy within two scroll lengths. You can certainly have a longer email template if you have to convey a huge amount of information. However, if your email template gets too long, it might become boring for subscribers, who will be less likely to scroll to the end to check out all of the offers and promotions included.
The height of the preview pane of most email clients (which contains content commonly referred to as “above the fold”) is generally between 300 and 500 pixels. Make the best use of this space, so that the content included above the fold entices the subscriber to scroll down.
Every email developer knows that if an email’s file size exceeds 102 KB, Gmail’s app will clip the email, and they will not be able to track metrics.
Check out the screenshot below to see what an email looks like in Gmail when it is clipped:
To avoid Gmail’s clip, make sure your email does not have unnecessary code and is not over-formatted. Go for a minimalist email design, without any shortened URLs. Note that images will not be embedded in the email and, so, will not increase the file’s size. That being said, removing unnecessary images will help to reduce the email size.
For marketers who use predesigned templates, the height and width will already be taken care of. If you want to use your own design, consider the ideal width and height of an email template.
3. Body Of Email
Emails usually begin with a hero image at the top, followed by the main copy, a call to action and then the footer.
Because most people read on screens positioned about 2 to 3 feet away, your h1 title should be around 16 pixels; if your title is short, it could even go up to 20 pixels. A good idea would be to render the h1 title as text, along with an attractive hero image.
Your descriptive text should not be smaller than 12 pixels. It should be easily readable across all email clients and devices. Moreover, the alignment of paragraphs and paragraph size also play an important role.
4. Call To Action
The primary objective of email marketing is to persuade customers to take action. To do that, your call to action (CTA) should have engaging, actionable verbs. Use convincing and actionable text, like “Start the free trial,” rather than drab phrases like “Click here.”
Create a sense of urgency in CTAs and get higher click-through rates by adding the word “now.”
Campaign Monitor, in one of its guides, “10 Tips to Optimize Your Calls to Action,” emphasizes that a CTA button should always contrast strongly with the background color, so that it doesn’t blend in and that it grabs the subscriber’s attention. Based on your target audience, your industry and the message to be conveyed, including CTAs at regular intervals can increase email conversions and the desired subscriber action. Its height should be at least 30 pixels, and it should be easily tappable with a thumb on mobile devices.
Check out the email below from Asana. It places a CTA strategically above the first fold and also follows the CTA best practices discussed above.
5. Images And Interactive Elements
If you are putting images or rich media in your email, add relevant alternative (alt) text, so that the purpose of the email is preserved even when the visuals are blocked by the email client. This is also greatly helpful with accessibility, because screen readers will be able to read the alternative text and convey your message.
Most email marketers tend to send emails consisting of a single image, which is first of many common HTML mistakes compiled by MailChimp. It recommends a text-to-image ratio of 80 to 20, to make sure that emails do not get trapped in spam filters. According to a recent study by MailChimp, 200 words per image yield a good click-through rate.
Using linked images in your email ensures an optimum file size. Load images from an external server using <img> tags.
The main advantage of this technique is that you can change images even after sending the email. It makes the email light and reduces the time taken to send the email. The disadvantage is that subscribers will have to download the images from the external server, which will incur download costs for those on metered connections, and the images might also get blocked by some email services.
Rich media elements, such as GIFs, cinemagraphs and video, are becoming popular in email these days.
You can add a GIF or cinemagraph in an email simply by uploading the file to the server that stores your images. Then, copy the URL and use the following HTML:
<pre class="lang:default decode:true" title="Code for adding GIFs or Cinemagraphs in Email"><img src="/wp-content/uploads/thefiletobeinserted.gif">
Test the email to make sure that the GIF works properly.
Embedding video is a very adaptable technique of web development, but unfortunately, it’s not supported in email. Therefore, opt for HTML5 video.
To add a video in email, use the code below:
<pre class="lang:default decode:true" title="Code for including video in email"><video width="400" height="200" controls poster="http://www.art.com/images/blog_images/Imagefiles/2017/html5_video/valentinesday.jpg"><br/><source src="http://www.videofile.com/htmlfiles/movie-14thfeb.mp4" type="video/mp4"><br/><!-- fallback 1 --><br/><a href="http://www.xyz.com" ><br/><img height="200" src=" http://www.art.com/pictures/important/Imagefiles/2017/html5_video/valentinesday.jpg " width="400" /><br/></a><br/></video><br/><br/><br/>
HTML5 primarily supports the MP4, OGG and WebM video formats.
Pro tip: Apple supports the MP4 video format in its email clients and browsers.
Some points to remember:
Make sure that the server configuration you use can output the right MIME type, so that the email client identifies the correct video format when retrieving the video.
If you are using an Apache web server, add this entry to the .htaccess file: Add Type video/mp4.mp4 m4v.
6. Number Of Email Folds
Your email should have just two folds, as mentioned earlier. The first fold should capture your brand and include the h1 title with a relevant CTA. If your email template exceeds two scrolls, then the third scroll should cross-sell your products. The idea is to change up the content and keep subscribers hooked by providing interesting information.
The footer is the most overlooked part of any email. However, it probably has information that subscribers are looking for, such as the company address, social sharing buttons and contact details. In order for your email to be CAN-SPAM compliant, the footer should have some additional elements.
An “Unsubscribe” link should allow subscribers to opt out of your mailing list easily and will reduce spam complaints.
Your contact details should link back to your company website and should include your postal and email address.
Additionally, you can have ancillary links, such as “Forward to a friend” and “View in Browser.”
Explanation of why the recipient got this email
Your subscribers have probably subscribed to numerous mailing lists. Subtly remind recipients of the reason they received the email, to maintain your reputation as an emailer and to minimize spam complaints.
Include the copyright mark, along with the current year and your business name.
Designing The Footer
Cramming information into the footer sounds tempting, but you should determine the most important information for your business and restrict the footer to the minimum. Stuffing it with too much information could lead readers to dismiss it entirely because they will not be able to figure out which links to click.
Check out the footer below by Cotton on Body. Although it is well organized, it could be overwhelming for the subscriber who is scanning the email.
Have a look at the footer below by Alice and Olivia. It is simple, and it maintains a visual hierarchy according to the actions they want subscribers to take.
The footer by HSN below is clean and makes good use of padding and white space. It is not overwhelming, yet it conveys important information that readers might be looking for.
Mobile Responsive Emails
Most subscribers will check email on their phone. Owing to this trend, your emails ought to be responsive. Responsive design includes several elements, such as media queries, fluid grids and fluid images, so that users can view the email as intended, regardless of screen size or device. The basics of responsive email design include the table element, easily stackable sections and full-width CTAs.
If your subscriber list consists of many mobile users, then avoid overlapping layouts. Hide non-primary sections, such as navigation and email advertisements, to cater to mobile subscribers. Mobile-specific email elements such as a navigation menu and image sliders can also be used.
Responsive email design is supported in these email clients:
iOS Mail app
Windows Phone 7.5
Android 4.x Email (OEM) app
iPhone Gmail app
The following email clients do not support responsive email:
To make their emails responsive, developers use a media query that is commonly referred to as @media. It is a special set of CSS styles, included in the header, that work as conditional statements or dynamic rules.
The point of media queries is to identify the screen size of the device being used and to execute various rules according to that screen size. The challenge is that media queries do not work in all email clients and might need detailed planning and testing compared to other design techniques.
Have a look at the media query below:
<pre class="lang:default decode:true" title="Structure of Media Query">@media only screen and (min-width:479px) and (max-width:701px)
width: 100% !important;
display: none !important;
When this email is accessed on a device whose screen is between 479 and 701 pixels wide, the email’s width will be 100%, according to the width: 100% !important; attribute. The !important function forces this attribute in email clients such as Gmail, where it might be ignored.
The styles in the CSS rule block should specify the container or element type that the styles will dictate. Assign these rules in the HTML if you want them to work.
Here is the CSS:
<pre class="lang:default decode:true" title="Code for CSS"> td[class="body-header"] font-size: 18px !important;
And here is the HTML:
<pre class="lang:default decode:true" title="Code for HTML"><td align="left" class="body-header">
It is important that the element (td) and the class (body-header) added in the CSS and HTML match each other.
With the advent of advanced email clients, such as Apple Mail, which is based on Webkit, email developers can even play around with keyframe animation, interactive elements such as carousels, and live feeds.
Conditional coding for different email clients (such as for Outlook and for Samsung and Apple devices) has also become possible.
If you follow these simple tips, you will surely be able to create awesome email marketing campaigns that convert, whether you are a novice or pro at email programming. In the end, aim to create a good user experience and make subscribers look forward to your emails. Happy emailing!
Since its creation in 2011, D3.js has become the de facto standard for building complex data visualizations on the web. React is also quickly maturing as the library of choice for creating component-based user interfaces.
Both React and D3 are two excellent tools designed with goals that sometimes collide. Both take control of user interface elements, and they do so in different ways. How can we make them work together while optimizing for their distinct advantages according to your current project?