Animations have potential to add detail and flair to your user experience, but may introduce some issues for assistive technology and render performance. It’s now common practice to include some animation in web apps to enhance user experience.
We'll go over common accessibility issues with CSS animations, why people may not be aware of the fact that some of their CSS animations are not accessible, and some simple ways this can be resolved with minimal JavaScript. We will also do a quick dive into the performance differences across various animation methods.
8. ⚡ “60 fps” ⚡
Performant, accessible anima6ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce8 |
9. “60 fps”
• Common refresh rate of ~60hz on digital displays
• 60 fps = ~16.66ms each frame
• Browser overhead leaves ~10ms each frame
• Exceed 16.66ms => stuBer, low framerate
Performant, accessible animaFons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce9 |
10. Browser “Render Cycle”
Performant, accessible anima1ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce10 |
hDps://developers.google.com/web/fundamentals/performance/rendering/
11. Browser “Render Cycle” - Layout
• Can be triggered by JS or CSS – e.g. width/height, font sizes, top/le<
• When a layout change occurs, browser has to re-flow, re-paint and re-
composite the rest of the page*
*Only specific secFon of the page which requires updaFng
• Expensive (slow to complete)
Performant, accessible animaFons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce11 |
12. Browser “Render Cycle” - Paint
• background image
• text colour
• shadows
• Expensive (slow to complete)
Performant, accessible anima>ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce12 |
13. Browser “Render Cycle” - Composite
• opacity
• transform (e.g. translate, scale, rota7on)
• Cheap (quick to complete)
Performant, accessible anima=ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce13 |
14. .SlidingBox {
padding: 70px 30px;
background-color: white;
border: 3px solid green;
position: fixed;
opacity: 0;
top: 200px;
transition: top 0.6s, opacity 0.6s;
}
.SlidingBox.active {
opacity: 1;
top: 0;
}
Performant, accessible animaEons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce
“Sliding Box”
14 |
15. One small trick that browser
engines don’t want you to know...
Performant, accessible anima;ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce15 |
19. ”will-change” property
• Hints to the browser that this element…
will change !
• Typically provide a value of another
property
• Use sparingly
.PerformantSlidingBox {
…
will-change: top;
}
.PerformantSlidingBox {
…
transform: translateZ(0); // old hacky way
}
Performant, accessible animaKons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce19 |
20. Why
! High end laptop
vs
" Low spec mobile device
Performant, accessible anima9ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce20 |
21. Why
• Performance gains are universal, regardless of device
• ⬆ Ba5ery life
• " Smoother experience
• # Improved engagement
Performant, accessible anima>ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce21 |
23. .SlidingBox {
padding: 70px 30px;
background-color: white;
border: 3px solid green;
opacity: 0;
posi-on: fixed;
top: 200px;
transi-on: top 0.6s, opacity 0.6s;
}
.SlidingBox.ac@ve {
opacity: 1;
top: 0;
}
Performant, accessible anima@ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce
“Sliding, Fading In Box”
23 |
24. opacity:0 is s,ll in the DOM layout.
Performant, accessible anima,ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce24 |
25. Accessible
• opacity:0 is s,ll in the DOM layout
• Not consistent experience for assis,ve technology - screen readers
will s,ll read these elements
Performant, accessible anima,ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce25 |
27. display:none
• Removes it from the layout / flow completely
• Does not “take up space” in the DOM layout
Performant, accessible anima@ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce27 |
28. visibility:hidden
• Space is s)ll allocated for the element in the DOM as if it was
visiblity:visible
Performant, accessible anima)ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce28 |
29. ARIA a&ribute?
• “aria-hidden”
• Requires JavaScript
Performant, accessible anima=ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce29 |
30. Both break our CSS transition animation.
Performant, accessible anima8ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce30 |
34. “visibility:hidden” property
• “Animate” visibility by adding a delay to this property
Performant, accessible animations with CSS & a dash of JavaScript | Wing Ho | @soyarsauce34 |
35. .SlidingBox {
…
visibility:hidden;
transi'on: transform 0.6s, opacity 0.6s, 0.6s visibility;
}
.SlidingBox.ac9ve {
…
visibility:visible;
}
Performant, accessible anima9ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce
visibility:hidden w/ delay
35 |
37. visibility:hidden - limita0ons
• Only works for visibility, can’t “transi5on” the “display” property.
• Not scalable past simple anima5ons, when you are delaying other
proper5es
Performant, accessible anima5ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce37 |
39. JavaScript
• A dash of JavaScript for maximum accessibility
• Listen for the “transi;onend” or “anima;onend” events
Performant, accessible anima;ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce39 |
40. Ini$al State > Anima$on State > End State
Performant, accessible anima$ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce40 |
41. transi'onend
• Triggered when a transition has ended
• Check your expected property has finished animating
• “Clean up” the animation at this point (e.g. toggle CSS classes / aria
attributes, set display/visibility properties, remove from DOM)
Performant, accessible animaGons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce41 |
42. transi'onend
let element = document.getElementById(“SlidingBox”);
element.addEventListener("transi@onend", () => {
// Toggle class or “display” property directly to remove
}, false);
Performant, accessible anima@ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce42 |
44. Which is best?
• Pick what is required for your par4cular design & use case
• Consider whether the element needs to stay in the flow, or be removed from
the DOM
• S4ll need JavaScript for toggling aria-roles
Performant, accessible anima4ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce44 |
45. Which is best?
Performant, accessible animations with CSS & a dash of JavaScript | Wing Ho | @soyarsauce45 |
46. Which is best?
Performant, accessible anima1ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce46 |
49. Performant, accessible anima1ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce
Performant, accessible sliding boxes?
49 |
• Modals
• Menus
• Docks
• ”Toast no1fica1ons”
50. Accessible Modals
• Modals tend to be fixed/absolute-rela2ve to the document body
• Handle user focus
• document.getElementById(“SlidingBox”).focus()
• aria-roles “dialog, “alertdialog” – include focusable child element
• Make sure user can close the modal
Performant, accessible animations with CSS & a dash of JavaScript | Wing Ho | @soyarsauce50 |
53. Seman&cs
❌ <div onClick=“...” />
✅ <bu4on onClick=“...” />
Performant, accessible anima>ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce53 |
54. Performant, accessible anima1ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce
Give me the React stuff
54 |
• https://github.com/reactjs/react-transition-group
• Great for managing mounting and unmounting with animation at
the forefront
56. Performant, accessible anima1ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce
Performant
56 |
• Restrict transi1ons to transforms or opacity when possible
• Use “will-change”, sparingly, when making final op1misa1ons
57. Performant, accessible anima1ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce
Accessible
57 |
• Ensure elements represented are consistent
• Ensure keyboard users do not get trapped in modals
• Fix opacity anima1ons with (visibility:hidden / display:none) +
aria-hidden=”true”
58. Performant, accessible anima1ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce
Some other resources
58 |
• requestAnima1onFrame
• hGps://csstriggers.com/
• Your browser devtools
• ”FLIP” anima1ons – First Last Invert Play
59. Live demo? !
Performant, accessible anima5ons with CSS & a dash of JavaScript | Wing Ho | @soyarsauce59 |
60. www.csiro.au
Engineering & Design | Data61
Wing Ho
t twi*er.com/soyarsauce
e wing@wingho.io
w wingho.io | research.csiro.au/data61ux
Thank you