Grid layout and accessibility

Those of us who have been doing web development for more years than we care to remember might consider that CSS grid is a little bit like using "tables for layout". Back in the early days of web design, the way we constructed page layout was to use HTML tables, then fragment our design into the cells of those tables in order to create a layout. This had some advantages over the "CSS Positioning" that came afterwards, in that we could take advantage of the alignment and full height columns offered by table display. The biggest downside however was that it tied our design to the markup, often creating accessibility issues as it did so. In order to lay the design out in the table we often broke up the content in ways that made no sense at all when read out by a screen reader for example.

In moving to CSS we often spoke about CSS for layout enabling a separation of content and markup and presentation. The ultimate aim being that we could create a semantic and well structured document, then apply CSS to create the layout we desired. Sites such as the CSS Zen Garden showcased this ability. The CSS Zen Garden challenged us to take identical markup and create a unique design using CSS.

CSS grid layout does not have the same issues that tables did, our grid structure is defined in CSS rather than in the markup. If we need to add an element we can use something with no semantic meaning. On paper grid helps us properly fulfill that promise of content separated from markup, however is it possible to go too far with this idea? Is it possible that we could create an accessibility issue through our use of grids?

Re-ordering content in CSS grid layout

We've already seen in these guides that grid gives us power to re-order the content of our page in various ways. We can use the order property, which will change how items auto-place. We can use grid-auto-flow: dense which will take items visually out of DOM order. We can also position items using line-based placement of grid template areas, without considering their location in the source.

The specification includes a section that covers Reordering and Accessibility. In the introduction to that section are details of what the specification expects browsers to do when the content is visually reordered using grid layout.

Grid layout gives authors great powers of rearrangement over the document. However, these are not a substitute for correct ordering of the document source. The order property and grid placement do not affect ordering in non-visual media (such as speech). Likewise, rearranging grid items visually does not affect the default traversal order of sequential navigation modes (such as cycling through links, see e.g. tabindex HTML5).

If you reorder things visually using grid layout, this will not change how the items are ordered if the content is being read out by a screen reader, or other text to speech user agent. In addition, the reordering will not change tab order. This means that someone navigating using the keyboard could be tabbing through links on your site and suddenly find themselves jumping from the top to the bottom of the document due to a reordered item being next in line.

The specification warns authors (the CSSWG term for web developers) not to do this reordering.

Authors must use order and the grid-placement properties only for visual, not logical, reordering of content. Style sheets that use these features to perform logical reordering are non-conforming.

What does this mean for designing with grid layout in practice?

Visual not logical re-ordering

Any time you reorder things with grid layout – or with flexbox – you only perform visual reordering. The underlying source is what controls things like text to speech, and the tab order of the document. You can see how this works with a very simple example.

In this example I have used grid to lay out a set of boxes that contain links. I have used the line-based placement properties to position box 1 on the second row of the grid. Visually it now appears as the fourth item in the list. However, if I tab from link to link the tab order still begins with box 1, as it comes first in the source.

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
}

.box1 {
  grid-column: 1;
  grid-row: 2;
}
html
<div class="wrapper">
  <div class="box box1"><a href="">One</a></div>
  <div class="box box2"><a href="">Two</a></div>
  <div class="box box3"><a href="">Three</a></div>
  <div class="box box4"><a href="">Four</a></div>
  <div class="box box5"><a href="">Five</a></div>
</div>

The specification says that in this scenario, if box 1 really makes sense logically in that position, we should go back to our source and make the change there rather than reordering using grid layout. This is what is meant by visual versus logical reordering, logical ordering is important for the meaning and structure of our document, and we should make sure that we preserve that structure.

How should we approach accessibility for grid layout?

From the specification we know that we need to ensure our document maintains the logical order of our content. How should we approach our development to make sure that we maintain accessibility for the different users and the ways that they interact with our pages?

Start with a structured and accessible document

A grid layout should mean we do not need to change our document source in order to get the layout that we want. Therefore the starting point of your page should be a well structured and accessible source document. As is noted in the CSS grid layout specification, this is quite often going to give you a good structure for your smallest screen devices too. If a user is scrolling through a long document on mobile, the priorities for that user quite often map to what should be a priority in the source.

Create a responsive, and responsible grid

With a solid document you can begin to add your layout, it is likely you will be using media queries to create additional columns and make changes for different screen sizes and devices. Grid can be really very useful here, elements deprioritized in the mobile source order can be moved into a sidebar in a desktop layout, for example. The key here is to keep testing, a very simple test is to tab around the document. Does that order still make sense? Check that you do not end up leaping from the top to the bottom of the layout in a peculiar way. If so that would be a sign that you need to address something about the layout.

Returning to the source

If at any time in the design process you find yourself using grid to relocate the position of an element, consider whether you should return to your document and make a change to the logical order too. The nice thing about using CSS grid layout is that you should be able to move an item in the source to match the logical order, without needing to make big changes to your layout. This is a huge improvement over a float-based layout for example, where document source matters a lot in order to get layouts at different breakpoints. However the onus is on us as developers to remember to go back to our source and update it to maintain logical order.

Grid and the danger of markup flattening

Another issue to be aware of in CSS grid layout and to a lesser extent in CSS flexbox, is the temptation to flatten markup. As we have discovered, for an item to become a grid item it needs to be a direct child of the grid container. Therefore, where you have a <ul> element inside a grid container, that ul becomes a grid item – the child <li> elements do not.

The subgrid value of grid-template-columns and grid-template-rows will solve this problem once widely implemented. It will allow the grid to be inherited by grid items and passed down the tree.

Given that interoperable support for subgrid is limited, there is a definite temptation when developing a site using CSS grid layout to flatten out the markup, to remove semantic elements in order to make it simpler to create a layout. An example would be where some content was semantically marked up as a list but you decide to use a set of <div> elements instead as then you can have the element to be a direct child of a container set to display: grid. Be aware of this temptation and find ways to develop your design without stripping out the markup. Starting out with a well-structured document is a very good way to avoid the problem, as you will be aware that you are removing semantic elements in order to make the layout work if you actually have to go into the document and do so!

Further reading

There is not a lot of existing material regarding accessibility and CSS grid layout. Many of the issues are similar to those raised regarding CSS flexbox, which also gives methods of reordering content with flex-direction and the order property.

The concept of visual display following document source order is detailed in the WCAG Techniques for Success Criteria – Technique C27.

As a way to start thinking about these issues, as you use CSS grid layout I would suggest reading Flexbox & the Keyboard Navigation Disconnect from Léonie Watson. Also the video of Léonie's presentation from ffconf is helpful to understand more about how screen readers work with the visual representation of things in CSS. Adrian Roselli has also posted regarding tab order in various browsers – although this was prior to grid support being fully implemented in Firefox.