{"id":7464,"date":"2017-01-28T16:19:43","date_gmt":"2017-01-28T20:19:43","guid":{"rendered":"http:\/\/www.useragentman.com\/blog\/?p=7464"},"modified":"2017-01-30T15:50:47","modified_gmt":"2017-01-30T19:50:47","slug":"flex-layout-fail-fixing-firefox-keyboard-accessibility-with-the-css-order-property","status":"publish","type":"post","link":"https:\/\/www.useragentman.com\/blog\/2017\/01\/28\/flex-layout-fail-fixing-firefox-keyboard-accessibility-with-the-css-order-property\/","title":{"rendered":"Flex Layout Fail: Fixing Firefox&#8217;s Keyboard Accessibility Bug With The CSS <code>order<\/code> Property"},"content":{"rendered":"<p>While fixing accessibility issues on a project, I noticed a huge problem with a page that relied on <a href=\"https:\/\/css-tricks.com\/snippets\/css\/a-guide-to-flexbox\/\">CSS Flex Layout<\/a>, specifically with <a href=\"https:\/\/developer.mozilla.org\/en\/docs\/Web\/CSS\/order\">the <code>order<\/code> property<\/a>.  If you are not familiar with CSS <code>order<\/code>, it allows developers to make the visual order of elements on the page different than their DOM order.  For example, you can have this code:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n&lt;div class=\"flex-example shuffled\"&gt;\r\n  &lt;button class=\"btn\"&gt;\r\n    &lt;strong&gt;1&lt;\/strong&gt;\r\n    &lt;br&gt; This appears first in source order.\r\n  &lt;\/button&gt;\r\n  &lt;button class=\"btn\"&gt;\r\n    &lt;strong&gt;2&lt;\/strong&gt;\r\n    &lt;br&gt; This appears second in source order.\r\n  &lt;\/button&gt;\r\n  &lt;button class=\"btn\"&gt;\r\n    &lt;strong&gt;3&lt;\/strong&gt;\r\n    &lt;br&gt; This appears third in source order.\r\n  &lt;\/button&gt;\r\n  &lt;button class=\"btn\"&gt;\r\n    &lt;strong&gt;4&lt;\/strong&gt;\r\n    &lt;br&gt; This appears fourth in source order.\r\n  &lt;\/button&gt;\r\n&lt;\/div&gt;\r\n<\/pre>\n<\/blockquote>\n<p>with CSS like this:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n.flex-example {\r\n  display: inline-flex;\r\n  justify-content: space-around;\r\n  width: 100%;\r\n}\r\n\r\n.example-main > div .btn {\r\n  width: 23%;\r\n}\r\n\r\ndiv.shuffled .btn:nth-child(1) {\r\n  order: 2;\r\n}\r\n\r\ndiv.shuffled .btn:nth-child(2) {\r\n  order: 4;\r\n}\r\n\r\ndiv.shuffled .btn:nth-child(3) {\r\n  order: 1;\r\n}\r\n\r\ndiv.shuffled .btn:nth-child(4) {\r\n  order: 3;\r\n}\r\n<\/pre>\n<\/blockquote>\n<p>look like this:<\/p>\n\r\n<div class=\"example-main\">\r\n  <div class=\"flex-example shuffled\">\r\n\t<button class=\"btn\">\r\n\t\t<strong>1<\/strong>\r\n\t\t<br> This is 1st in source order.\r\n\t<\/button>\r\n\t<button class=\"btn\">\r\n\t\t<strong>2<\/strong>\r\n\t\t<br> This is 2nd in source order.\r\n\t<\/button>\r\n\t<button class=\"btn\">\r\n\t\t<strong>3<\/strong>\r\n\t\t<br> This is 3rd in source order.\r\n\t<\/button>\r\n\t<button class=\"btn\">\r\n\t\t<strong>4<\/strong>\r\n\t\t<br> This is 4th in source order.\r\n\t<\/button>\r\n  <\/div>\r\n<\/div>\r\n<p>Note that the <code>order<\/code> property changes the how the order of the elements appear visually in the design.  Neat, huh?<\/p>\n<p>Among it&#8217;s other use-cases, I have found the <code>order<\/code> property is extremely useful when the order of elements change from breakpoint to breakpoint.  However, it opens up a huge accessibility issue in the desktop version of Firefox.  <a href=\"http:\/\/webaim.org\/techniques\/keyboard\/\">When a user employs a keyboard to navigate the page<\/a>, all other browsers have the tabbing order to be the same as the DOM order, as shown in this animation:<\/p>\n<p><div id=\"attachment_7471\" style=\"width: 525px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-7471\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2017\/01\/flex_chrome_515.gif\" alt=\"Animation showing tabbing order of previous example in Chrome.  Note the tabbing order is the DOM order, not visual order.\" width=\"515\" height=\"356\" class=\"size-full wp-image-7471\" \/><p id=\"caption-attachment-7471\" class=\"wp-caption-text\">Animated GIF showing the tabbing order of elements with flex-layout&#8217;s <code>order<\/code> CSS property (bottom) and without (top).  Note the tabbing order is the DOM order, not visual order.<\/p><\/div><\/p>\n<p>Unfortunately, the desktop version of Firefox is different &mdash; it makes the tabbing order the same as the visual order, as seen here:<\/p>\n<p><div id=\"attachment_7472\" style=\"width: 525px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-7472\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2017\/01\/flex_ff_515.gif\" alt=\"Animation showing tabbing order of the same example in Firefox. Note the tabbing order is the visual order, not the DOM order.\" width=\"515\" height=\"356\" class=\"size-full wp-image-7472\" \/><p id=\"caption-attachment-7472\" class=\"wp-caption-text\">Animation showing tabbing order of the same example in Firefox. Note the tabbing order is the visual order, not the DOM order.<\/p><\/div><\/p>\n<p>These examples were originally made for the excellent article <a href=\"http:\/\/adrianroselli.com\/2015\/10\/html-source-order-vs-css-display-order.html\">HTML Source Order vs CSS Display Order<\/a> by <a href=\"http:\/\/adrianroselli.com\/\">Adrian Roselli<\/a>.  In it, he mentions that this will likely be fixed due to <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=812687\">this bug report asking to fix the issue<\/a>.  It is unclear, however, if\/when it will be fixed (the bug was reported in 2012!), so I implemented a fix using JavaScript to fix this issue.  Note that this bug only appears in the desktop version of Firefox, <strong>the Android version of Firefox 50 doesn&#8217;t have this bug when using <a href=\"https:\/\/support.google.com\/accessibility\/android\/answer\/6151827?hl=en\">Talkback gestures<\/a>.<\/strong><\/p>\n<p><a class=\"exampleLink\" href=\"http:\/\/useragentman.com\/examples\/a11y-examples\/2.4.3-tab-order-flex-layout-firefox-bug.html\">Load the above example with the Firefox Flex Layout Keyboard Navigation Fix<\/a>.<\/p>\n<h2>How Does This Fix Work?<\/h2>\n<p>This fix uses <a href=\"http:\/\/www.quirksmode.org\/blog\/archives\/2008\/04\/delegating_the.html\">event delegation<\/a> to listen to all <code>focus<\/code> and <code>blur<\/code> events on the page.  When a tabbable element gains focus, we set the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Global_attributes\/tabindex\"><code>tabindex<\/code><\/a> property of it and the tabbable DOM elements before and after it so that tabbing order repects DOM order.  The <code>tabindex<\/code> values used are the highest three that the can be used, in order to ensure we are not interfering with the <code>tabindex<\/code> of any other element.  When a tabbable element is blurred (and on <code>keypress<\/code> when the TAB key is pressed), the <code>tabindex<\/code> of these three elements are set back to what they were before they the focus event.<\/p>\n<p>This fix will only be executed in Firefox, since it is the only browser that has this issue (at the moment).<\/p>\n<h2>How Can I Implement This Fix Myself?<\/h2>\n<ol>\n<li>Have your application load <a href=\"https:\/\/raw.githubusercontent.com\/zoltan-dulac\/a11y-examples\/master\/js\/fixFirefoxFlexbox.js\">the fixFirefoxFlexbox.js<\/a> script (it&#8217;s from my <a href=\"https:\/\/github.com\/zoltan-dulac\/a11y-examples\">a11y-examples<\/a> GitHub repo, which is where I am putting examples for all my accessibility fixes going forward).<\/li>\n<li>Add the <code>a11y-fix-firefox-flexbox<\/code> class to the <code>&lt;body&gt;<\/code> of your document.<\/li>\n<li>That&#8217;s it.<\/li>\n<\/ol>\n<h2>But Doesn&#8217;t Visual Order Would Make More Sense Than DOM Order?<\/h2>\n<p>There is quite a bit of debate on this right now.  If you look at the comments on the <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=812687\">Firefox bug on the issue<\/a>, quite a few people understandably think visual order makes sense.  However, this is <a href=\"https:\/\/www.w3.org\/TR\/css-flexbox-1\/#order-accessibility\">contrary to what the official Flexbox spec says<\/a> (which states &#8220;The order property does not affect ordering in non-visual media (such as speech). Likewise, <strong>order does not affect the default traversal order of sequential navigation modes (such as cycling through links, see e.g. tabindex [HTML5])<\/strong>.<\/p>\n<p>Regardless of your stance on which is right, I am frustrated with Mozilla&#8217;s decision on keeping this bug active for such a long time &mdash; <a href=\"https:\/\/www.ontario.ca\/page\/how-make-websites-accessible\">in the Canadian Province of Ontario, web accessibility is a legal requirement<\/a> and companies and other organizations of a certain size must implement accessible websites that follow <a href=\"http:\/\/useragentman.com\/examples\/progressive-pushstate\/examples\/example03-wcag.php?section=&#038;level[]=level-A\">WCAG level A<\/a>.  <a href=\"http:\/\/www.lflegal.com\/2013\/05\/gaad-legal\/\">Making web sites accessible is also a legal requirement is other parts of the world as well.<\/a>  While probably having good intentions, <strong>Mozilla has made it impossible for developers to create designs using the CSS <code>order<\/code> property that are truly accessible across all browsers without JavaScript.<\/strong>  As a developer who cares about accessibility (as well as the legal well-being of his clients) I hope someone from Mozilla reads this article and helps developers out by fixing this bug.<\/p>\n<p>I am not saying visual order should or shouldn&#8217;t affect tabbing order &mdash; I have seen some great arguments for the &#8220;Tabbing order should be the same as visual order&#8221; argument.  I just think that Mozilla should try to change the standard instead of making a decision that breaks cross-browser accessibility.<\/p>\n<h2>Acknowledgments<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.flickr.com\/photos\/hendry\/1953702631\">The title photo<\/a> used in the link to article on the homepage is by <a href=\"https:\/\/www.flickr.com\/photos\/hendry\/\">Kai Hendry<\/a><\/li>\n<li>The example page used to show the script in action (as well as the animated screen captures in the article) were from the article <a href=\"http:\/\/adrianroselli.com\/2015\/10\/html-source-order-vs-css-display-order.html\">HTML Source Order vs CSS Display Order<\/a> and are used with kind permission from <a href=\"http:\/\/adrianroselli.com\/\">Adrian Roselli<\/a>.<br \/>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2017\/01\/tab-order.jpg\" \/> Firefox, unlike every other browser on the planet, changes the way that keyboard navigation works in designs that use the CSS <code>order<\/code> property.  Since a lot of developers use flexbox, this can create a lot of cross-browser accessibility issues.  This article shows a fix for this problem using a small amount of Javascript.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[191,9,210,209,1],"tags":[192,228,218,230,211,212,199,195,196,197],"class_list":["post-7464","post","type-post","status-publish","format-standard","hentry","category-accessibility","category-css","category-flex-layout","category-order","category-uncategorized","tag-a11y","tag-accessibility","tag-css","tag-flex-layout","tag-keyboard-accessibility","tag-keyboard-tabbing","tag-section-508","tag-skip-navigation","tag-wcag","tag-wcag-level-a"],"_links":{"self":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/7464","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/comments?post=7464"}],"version-history":[{"count":39,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/7464\/revisions"}],"predecessor-version":[{"id":7498,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/7464\/revisions\/7498"}],"wp:attachment":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/media?parent=7464"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/categories?post=7464"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/tags?post=7464"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}