DEV Community

Shane Duffy
Shane Duffy

Posted on • Updated on • Originally published at shaneduffy.io

Dear Web Devs, Please Use Anchors Instead of Divs for Buttons

I get it, you're using React or Angular, and you don't need to use <a> for your web app's buttons. But do it for us, the keyboard purists.

Since I'd like to eventually do the "digital nomad" thing for awhile, I made it a point to become accustomed to working on a laptop. In other words, becoming a "keyboard purist".

As far as development tools go, there is plenty of keyboard support, naturally. But desktop apps? No such luck. And web apps are even worse.

Enter Vimium, the amazing Chrome extension that makes it possible to traverse the web with nothing but your keyboard! Assuming the website you're on uses anchors for buttons...

My First Userscript

Standard Notes is an awesome open source, cross platform app for note taking. I love the simplicity of it. And I'm constantly switching to it to edit and lookup notes while I'm developing. However, they recently changed some of the buttons to be divs instead of anchors, and thus I have been quickly developing carpal tunnel from having to constantly switch to my mousepad to click around. It is terribly frustrating. I spent some time searching around, and posted on the subreddit about it, but it looks like the devs don't intend to implement keyboard support anytime soon.

Normally, I'd just avoid apps that don't have good keyboard shortcut (or Vimium) support, but in this case I was already a bit too invested into Standard Notes. So, I decided to write a Userscript to change the elements in question to be anchors again:

Vimium Standard

// ==UserScript==
// @name         Vimium Standard
// @namespace    https://shaneduffy.io
// @version      0.1
// @description  Standard Notes changed their UI, and now it doesn't work with Vimium. This makes things work with Vimium again.
// @author       Shane Duffy
// @match        https://app.standardnotes.com
// @icon         https://shaneduffy.io/assets/img/logo-circle-64.png
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const observer = new MutationObserver(mutationList => {
        var applyChanges = true;

        for (const mutation of mutationList) {
            switch (mutation.type) {
                case 'childList':
                    for (const node of mutation.addedNodes) {
                        var classString;
                        if (node instanceof Element) {
                            classString = node.getAttribute("class");
                            if (classString?.includes("name") || classString?.includes("tag-icon")) {
                                if (node.tagName == "DIV") {
                                    node.remove();
                                }
                            }

                            if (classString.includes("standard-vimium")) {
                                applyChanges = false;
                            }
                        }
                    }
                    for (const node of mutation.removedNodes) {
                        if (node instanceof Element) {
                            classString = node.getAttribute("class");
                            if (classString?.includes("standard-vimium")) {
                                applyChanges = false;
                            }
                        }
                    }
                    break;
                case 'attributes':
                    break;
            }
        }

        if (applyChanges) {
            var notes = document.getElementsByClassName("name");
            for (const note of notes) {
                if (note != undefined && note.tagName != "a") {
                    var newNote = document.createElement("a");
                    newNote.setAttribute("class", "name standard-vimium");
                    newNote.innerHTML = note.innerHTML;

                    if (note.parentNode != undefined) {
                        note.parentNode.replaceChild(newNote, note);
                    }
                }
            }

            var tags = document.getElementsByClassName("tag-icon");
            for (const tag of tags) {
                if (tag != undefined && tag.tagName != "a") {
                    var newTag = document.createElement("a");
                    newTag.setAttribute("class", "tag-icon standard-vimium");
                    newTag.innerHTML = tag.innerHTML;

                    if (tag.parentNode != undefined) {
                        tag.parentNode.replaceChild(newTag, tag);
                    }
                }
            }
        }
    });

    observer.observe(document.body, {
        childList: true,
        attributes: true,
        subtree: true,
        characterData: true
    });
})();
Enter fullscreen mode Exit fullscreen mode

In hindsight, Standard Notes is open source, so I probably could have just done a PR. Oops.

Discussion (6)

Collapse
jonrandy profile image
Jon Randy • Edited on

If a site or web app is well made - it should already be possible to navigate with the keyboard - without an extension. The fact that you even need one is a sad indictment of the state of modern web development.

In general, buttons that just do something on the page should probably be <button> or <input type="button/submit/etc.">. If they actually 'take' you somewhere - like another page or part of the app, they should be anchor tags (possibly styled to look like a button if the design requires it) - this way, all normal stuff like opening a link in a new tab works as expected.

I've seen at least 5 documentation sites for APIs recently where every single 'link' on the page is JS framework 'powered' - obliterating any hope of easily copying link URLs, opening doc links in new tabs etc. Seriously, WTF?

Sadly, in recent times - a lot of developers don't seem to to care about this kind of stuff whatsoever... and websites/apps have gotten crappier and crappier with respect to basic expected navigation features.

Collapse
cppshane profile image
Shane Duffy Author • Edited on

Yeah Vimium supports <button> as well. But you're right, web devs just don't care about this stuff. They seem to be more concerned with fancy animations and such.

And I didn't even think about the accessibility aspect of it, as mentioned by @andrewbaisden. I just prefer pure keyboard access for ease of use, but it's probably a necessity for a lot of people with disabilities.

smh web devs

Collapse
blindfish3 profile image
Ben Calder

I think it's less the case that developers don't care, and more the case that they're simply unaware of the problem. Modern frameworks make it far too easy to create inaccessible content and it seems there just isn't enough awareness of these issues.
It also points to poor QA processes. I usually pick this up in code review, and it definitely shouldn't get past a QA tester.

Collapse
jonrandy profile image
Jon Randy

The fact that they're unaware of the problem is a problem in itself

Collapse
andrewbaisden profile image
Andrew Baisden

It's definitely important for accessibility.

Collapse
toddpress profile image
Todd Pressley

Neat article. Love the ending… or is that a beginning πŸ€”