DEV Community

Cover image for Accessible, Resizable Table-Columns
Mads Stoumann
Mads Stoumann

Posted on

Accessible, Resizable Table-Columns

I love using the <input type="range">. It's an interactive control with touch-support, and you get accessibility baked-in for free!

After I finished the Accessible Image Compare a while ago, I thought about other use-cases.

One obvious candidate is resizable table columns. You'll find plenty of examples and libraries out there — but they often lack accessibility. None of the ones I found supported resizing with arrow-keys (they must be out there, I just couldn't find any).

This is a bit more complex than the Accessible Image Compare; you need an <input type="range"> for all columns except the last.

Without styling, it looks like this:

a11yTableUnstyled

Each <input type="range"> will update two custom properties, holding the widths of the cells to the left and the right of the input.

In CSS, we need to stack them all on top, using position: absolute, the range-height must be set to the lowest value possible (1px), while the draggable thumb must be the full height of the table. This is to avoid "collisions" between the ranges.

It now looks like this:

a11yTableColor

The draggable thumb should be invisible, so we'll set that to transparent, and the cursor should change to ew-resize when hovering:

a11yTableResize

Then, when using keyboard-navigation, :focus-visible is used to show the thumb, styled like this:

a11yTable

And because it's <input type="range">, you can use arrow-keys to de/increase the column widths! The widths are stored as CSS Custom Properties on the table:

--c0:23; --c1:26; --c2:25; --c3:26;
Enter fullscreen mode Exit fullscreen mode

These are then used on the thead th-cells:

<th style="width: calc(1% * var(--c0));">ID</th>
Enter fullscreen mode Exit fullscreen mode

I've made a JavaScript, you can add to any table — but beware(!) : I haven't used it in production yet - it might need tweaks and fixes.

You can grab both CSS and JS from this Pen.

NOTE: This is a proof-of-concept. It's to show how we get a lot "out-of-the-box" when using native HTML-controls vs. writing loads of JavaScript. If you refine the code / come up with ways to make it better, please fork the Pen, and paste the link in the comments below.

Thanks for reading!

UPDATE 02/05/2021: I've added styling for Firefox, as well as a small JavaScript-hack to run an event, that'll position the sliders correctly (only an issue in Firefox).

Top comments (22)

Collapse
 
stephanieleary profile image
Stephanie Leary

There is a typo in the ARIA attributes on the inputs: "aria-hideen"

Collapse
 
grahamthedev profile image
GrahamTheDev

Interesting concept and I like the principle, however from an accessibility standpoint this will cause issues with screen readers.

Your inputs will be read out as range sliders with no context. As you can't use aria-hidden on them (as it will both be ignored on an active element and also it appears to crash the browser when I was fiddling with your example) this means there are now 3 random tab stops for inputs that make no sense.

Giving the sliders a label is a minimum step to at least inform screen reader users what they are interacting with. It is still not ideal but at least that gives them an idea that they can ignore this control.

I would also say that if you implement this a "skip this table" link should be provided if there are more than 3 columns as otherwise the tab stops could be frustrating.

The other issue is that on a mobile if you stack the columns too close to each other it is impossible to release them again due to tap target size. As you should have a minimum tap target size of 44 by 44 CSS pixels I am sure this can be fixed by just making the minimum number on the slider larger and the tap target area larger. However at that point we then run into the issue of needing a minimum of 132px just for column stacking and this solution becomes less useful as we lose over a quarter of the effective screen width.

To be fair it doesn't work well for mobile anyway as to view the columns requires moving several columns at a time and would be much easier just scrolling the whole table left and right so perhaps this could be desktop only?

Anyway keep fiddling with the concept as you might be on to something, but I think you might run into issues accessibility wise trying to do this with inputs.

Collapse
 
madsstoumann profile image
Mads Stoumann • Edited

Thanks for your reply! It is indeed work-in-progress, and I haven't added any aria-labels or anything yet. My main goal was to make it keyboard-navigable without a load of JS, and that's accomplished with this code. I have a condition, so I cannot use a mouse and prefer to navigate by (digitizer-) pen or keyboard - so my personal goal is always "keyboard first". Regarding Screen Reader-issues: wouldn't it be enough to hide the sliders for SR's with aria-hidden? There's no point in resizing a table-column from a SR IMO. From a performance point-of-view this will hopefully also perform better, as it only updates two CSS Custom props, instead of updating all widths of all TD's.

Collapse
 
grahamthedev profile image
GrahamTheDev

Then the touch target size thing is probably beneficial to you too as I assume your accuracy may not be perfect using the pen and large tap areas make life easier there.

They are just observations and suggestions, it is a concept I haven't seen before and so I am interested in what you can achieve with this idea as it is very clever.

The concept is much better suited to your image before and after post that is the inspiration for this article, as that is much easier to clean up with only one slider. I think that idea really does have merit as a mini library in itself!

Thread Thread
 
madsstoumann profile image
Mads Stoumann

The touch-target is only 32px, but I just tried it on my iPad, where it works quite well, although the draggable thumbs need some styling. I'll try with larger sizes - and you're probably right about mobile, where dragging columns might be too tiny!

Collapse
 
saip12 profile image
Sai P • Edited

This is excellent work.
I'm running into css issues and not able to get hold of input attributes. I'm using chrome. Is there an updated version of this? TIA

Collapse
 
madsstoumann profile image
Mads Stoumann

Thank you! Sounds like you're navigating with keyboard? You should get this visual clue:
screenshot
This is from Chrome on Mac.
When I get some more time, I'll continue working on this, creating a better a11y-experience!

Collapse
 
saip12 profile image
Sai P • Edited

Yes, I'm actually navigating with keyboard. Not able to make it look as shown in your screenshot. Input element css are not binding and the sliders sit below the table. Functionality seems to work fine.

Thread Thread
 
madsstoumann profile image
Mads Stoumann

That is weird. Are you using the Codepen-example - in Chrome for Windows?

Thread Thread
 
saip12 profile image
Sai P

I'm using a Mac. I implemented the code in my storybook.

Thread Thread
 
madsstoumann profile image
Mads Stoumann

OK, but does the Codepen example work for you, in Chrome?

Thread Thread
 
saip12 profile image
Sai P

Yes. It works fine within Codepen.

Thread Thread
 
madsstoumann profile image
Mads Stoumann

Sorry, dont know much about Storybook - check the generated CSS/markup and see if you can spot the differences - or if some JavaScript fails in the console.

Thread Thread
 
saip12 profile image
Sai P

Sure, I definitely don’t see the js errors in console. Its only the css that's missing. Thanks.

Collapse
 
stereobooster profile image
stereobooster

Interesting idea. Looks a bit buggy in Firefox.

Collapse
 
madsstoumann profile image
Mads Stoumann

Thanks! I mention Firefox at the end of the article - I haven't added -moz prefixes to style the ranges (yet!)

Collapse
 
stereobooster profile image
stereobooster

I have missed this note. Firefox is my default browser, so I just opened codepen... I wasn't nitpicking, just wanted to let you know

Thread Thread
 
madsstoumann profile image
Mads Stoumann

I just checked an older Pen I did with range-sliders - it works well in Firefox, so it should be easy to update the styles: codepen.io/stoumann/pen/oNzgWMo
However, there was a mis-calculation for the table column-widths in Firefox, that I need to look into.

Collapse
 
ben profile image
Ben Halpern

This is really interesting. As the others have commented it seems like there might be more to flesh out to get this just right, but I really do like this.

Collapse
 
madsstoumann profile image
Mads Stoumann

Thanks! Yes, it's in "early stages", but I like the simplicity of it.

Collapse
 
crystalzenyth profile image
Crystal Scott

The CodePen is broken! How disappointing!

Collapse
 
madsstoumann profile image
Mads Stoumann