Manuel Matuzovi ć Frontend Developer from Vienna HTML, CSS, Accessibility twitter: @mmatuzo
bit.ly/react-tips @mmatuzo
12 Tips For More Accessible React Apps @mmatuzo
8 12 Tips For More Accessible React Apps @mmatuzo
a11y tip #1 Create a sound document outline. @mmatuzo
a11y tip #1 <h1>Yo! I'm the title of your page. �<0 h1> <h2>I'm very important. �<0 h2> <h3>My parent is very important. �<0 h3> <h3>My parent is very important. �<0 h3> <h4>I exist. �<0 h4> <h2>I'm very important. �<0 h2> <h3>My parent is very important. �<0 h3> @mmatuzo
a11y tip #1 <Heading.H>I will be an h1 �<0 Heading.H> <Heading.LevelBoundary> <Heading.H>I will be an h2 �<0 Heading.H> <Heading.LevelBoundary> <Heading.H>I will be an h3 �<0 Heading.H> �<0 Heading.LevelBoundary> <Heading.H>I will be an h2 �<0 Heading.H> �<0 Heading.LevelBoundary> @mmatuzo
a11y tip #1 <h1>I will be an h1 �<0 h1> <h2>I will be an h2 �<0 h2> <h3>I will be an h3 �<0 h3> <h2>I will be an h2 �<0 h2> @mmatuzo
a11y tip #1 Create a sound document <h1>React Finland. �<0 h1> outline. <h2>MCs �<0 h2> • It gives your document structure. <h2>Speakers �<0 h2> • Helps screen reader users with navigation. <h2>Sponsors �<0 h2> • Important for SEO. <h3>Gold Sponsors �<0 h3> • Check out Tenon UI's headings <h3>Silver Sponsors �<0 h3> component. <h3>Bronze Sponsors �<0 h3> • Test your document outline with tota11y or wave. @mmatuzo @mmatuzo
a11y tip #2 Hide content correctly @mmatuzo
display: none; visibility: hidden; hidden attribute @mmatuzo
display: none; visibility: hidden; hidden attribute @mmatuzo
a11y tip #2 .visually - hidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; white - space: nowrap; } @mmatuzo
<h1>React Finland. �<0 h1> <h2>MCs �<0 h2> <h2>Speakers �<0 h2> <h2 className="visually - hidden"> Sponsors �<0 h2> <h3>Gold Sponsors �<0 h3> <h3>Silver Sponsors �<0 h3> <h3>Bronze Sponsors �<0 h3> @mmatuzo @mmatuzo
a11y tip #2 <button> <span class="visually - hidden">Save �<0 span> <svg aria - hidden="true" width="32" height="32"> <path …> �<0 path> �<0 svg> �<0 button> @mmatuzo
a11y tip #2 <button> <VisuallyHidden>Save �<0 VisuallyHidden> <svg aria - hidden="true" width="32" height="32"> <path …> �<0 path> �<0 svg> �<0 button> https://github.com/reach/reach-ui/tree/master/packages/visually-hidden @mmatuzo
a11y tip #2 .visually - hidden { Hide content correctly border: 0; clip: rect(0 0 0 0); • display: none; visibility: height: 1px; hidden; and the hidden attribute margin: -1px; remove content from the accessibility overflow: hidden; tree. padding: 0; • Every item needs a textual position: absolute; representation, even if it isn't visible. width: 1px; • Check out Reach UI's VisuallyHidden white - space: nowrap; component. } @mmatuzo @mmatuzo
a11y tip #3 Use <button> if you need a button @mmatuzo
<button className="btn" onClick={this.handleClick}> I'm a real button �<0 button> @mmatuzo @mmatuzo
<div className="btn" onClick={this.handleClick}> I'm a wannabe �<0 div> @mmatuzo @mmatuzo
a11y tip #3 Use <button> if you need a button <button> • < button> s are focusable by default. ❤ • They come with keyevents for free. • <button> s are semantic. A <div> is �<0 button> just generic text. • Check out Just use button by Rob Dodson and The Links vs. Buttons Showdown by Marcy Sutton on YouTube. @mmatuzo @mmatuzo
a11y tip #4 Use fragments to avoid invalid HTML @mmatuzo
a11y tip #4 const Table = props �=? { return ( <table> <tr> <Columns �/? �<0 tr> �<0 table> ); } @mmatuzo
a11y tip #4 const Columns = props �=? { return ( <div> <td>Hello �<0 td> <td>World �<0 td> �<0 div> ); } @mmatuzo
a11y tip #4 <table> <tr> <div> ☠ 🚩 <td>Hello �<0 td> <td>World �<0 td> �<0 div> �<0 tr> �<0 table> @mmatuzo
a11y tip #4 const Columns = props �=? { return ( <React.Fragment> <td>Hello �<0 td> <td>World �<0 td> �<0 React.Fragment> ); } @mmatuzo
a11y tip #4 <table> <tr> 🥱 🎊 <td>Hello �<0 td> <td>World �<0 td> �<0 tr> �<0 table> @mmatuzo
a11y tip #4 Use fragments to avoid function Columns() { invalid HTML return ( �<? • Fragments help you write valid HTML. <td>Hello �<0 td> • They reduce bloat. <td>World �<0 td> • There's also a shorter syntax (see code ��</? example ➡ ) ); • Check out the Fragments docs for more } details and examples. @mmatuzo @mmatuzo
a11y tip #5 Take care of focus management. @mmatuzo
class Button2 extends React.Component { a11y tip #5 constructor(props) { super(props); this.btn = React.createRef(); } setFocus(){ this.btn.current.focus(); } render() { return ( <button className="btn" ref={ this.btn }> { this.props.children } �<0 button> ) } @mmatuzo }
a11y tip #5 class CustomTextInput extends React.Component { constructor(props) { super(props); Take care of focus �/0 Create a ref to store the textInput DOM element management. this.textInput = React.createRef(); } • Focus management is important render() { �/0 Use the `ref` callback to store a because it's essential for keyboard and reference to the text input DOM screen reader users. �/0 element in an instance field (for example, this.textInput). • Take advantage of refs in React to return ( manage focus. <input type="text" ref={this.textInput} • Check out the A11y dialog on Github �/? ); and the accessibility docs on } reactjs.org. } @mmatuzo @mmatuzo
a11y tip #6 Make notifications accessible to everyone @mmatuzo
a11y tip #5 <div className="alert" role="alert"> Saved successfully �<0 div> @mmatuzo
a11y tip #6 <div className="alert" role="alert"> Saved successfully �<0 div> Make notifications �/0 alert will interrupt the screen reader if it's in the course of announcing something accessible to everyone else. • Use role="alert" or role="status" <div className="alert" role="status"> Saved successfully to create live regions. �<0 div> �/0 status will wait until the screen reader has • Use live regions only for important finished announcing. information. <div className="alert" role="alert" aria - • Check out Reach UI's alert component. atomic="true"> Saved successfully • Check out react-aria-live on Github. <span>I will be announced as well �<0 span> • Read ARIA live regions in React on �<0 div> �/0 aria - atomic="true" - annouces everything not Almero Steyns blog. just the content that has changed. @mmatuzo @mmatuzo
a11y tip #7 Announce page changes @mmatuzo
a11y tip #7 class About extends React.Component { constructor(props) { super(props); this.section = React.createRef(); } componentDidMount(){ this.section.current.focus(); document.title = "About"; } render() { return ( <section tabIndex="-1" ref={ this.section }> <h2>About �<0 h2><p>We are… �<0 p><p>Lorem ipsum… �<0 p> �<0 section> ) } } @mmatuzo
a11y tip #7 render() { return ( <section aria - labelledby="pageTitle" tabIndex="-1" ref= { this.section }> <h2 id="pageTitle">About �<0 h2> <p>We are… �<0 p><p>Lorem ipsum… �<0 p> �<0 section> ) } @mmatuzo
a11y tip #7 Reach Router • Keyboard accessible. • Assistive devices announce changes. • Cmd/Ctrl click opens in a new tab. • Right click “open in new window” opens in a new window. • Out-of-the-box focus management. https://reach.tech/router @mmatuzo @mmatuzo
Recommend
More recommend