Skip to content(if available)orjump to list(if available)

Just use a button

Just use a button

146 comments

·October 31, 2025

lyricaljoke

My very similar pet peeve is about websites that use `onclick` handlers and similar to implement navigation. Just use a damn anchor tag, which gets you correct link behavior for free:

* works with middle click for new tab

* integrates with accessibility devices

* works with right click + open in new window or similar options

* etc. etc. etc.

If it's notionally navigation, don't use javascript soup: use a link.

Zak

I've seen an increase in people doing this sort of thing over the past few years. I imagine it has something to do with frameworks and ignorance or apathy, but the old fashioned way almost always provides the best UX.

To anyone reading who has tried to get fancy with a substitute for the <a> tag, I wish you mild discomfort and inconvenience.

philistine

Could it be that the devs who write that code are not allowed to touch the CSS so they implement the visual functionality they want in their framework instead of telling the design team their intent?

Zak

There could be any number of weird constraints that would lead a developer who knows better to do such a thing in a specific situation, but someone designed (or failed to intentionally design) the system in question.

That person should sit alone in a room with no distractions and think about what they did.

zahlman

We've reached the point, years ago even, where image hosting sites will not show you an image without JavaScript, even. Just use a damn img tag.

psygn89

Yup. I think a lot of the devs that started with React jumped straight into the "fun" stuff without learning some of the "boring" fundamentals.

And those devs set the wrong patterns and standards for others following hot behind them. The only time I can remember needing to dress a div up like a button was when an accordion trigger was just a giant button and anything passed in would be rendered inside, but I needed an action to the right of the trigger title. But those happen super rarely. You can't just pass in a button as it was invalid html to have nested buttons obviously. Yes, I know I could probably use css to absolutely position it or something but that takes it out of the flow and starts hacking about it in another way.

derefr

I wonder why browsers don't intercept JS-triggered navigation (or history.push) events that happen with a click handler on the stack — where it can be determined from the event data of that click handler that the user additionally used the middle mouse button or was holding cmd/ctrl at the time — and rewrite them into navigation-in-new-tab. (Ideally, without making the caller aware that anything different happened than what it was expecting.)

It might not be what the developer of the site/app intended; but it's exactly the semantics the user is expressing their desire to trigger. So why not do what the user wants? Browsers are user agents, not developer agents, after all.

(Before you say "that sounds like a layering violation" — well, yes it is, but that particular layering violation already exists to support most browsers' JS engines' "suppress popup-window / new-tab navigation if the stack of the navigating call doesn't contain a click event" logic. The code ugliness was already bought and paid for; we may as well reap as much benefit from it as we can!)

yakshaving_jgt

> it's exactly the semantics the user is expressing their desire to trigger.

That’s not necessarily true. You could imagine writing perhaps a video game or something where this control is intended to have a different meaning. For this reason, I don’t think this is a liberty that browser developers can take.

derefr

Keep in mind that this check+logic would only come into play within the call to `history.push` or the `window.location.href` setter.

It's not "add a browser-default click event listener that shims in special behavior" (which wouldn't be able to catch the JS navigation in the first place, since that would be occurring in its own, separate click event listener.)

It's instead "when I-the-browser have been called by page JS to do something navigation-like through the native `location` or `history` APIs, first check if the current call stack has a event-listener call triggered by a browser-delivered click event in its ancestry. If it does, check further whether the click was a "special" [middle-mouse-button / shift / ctrl-or-cmd / alt] click. If it was, then cause some other side-effect depending on the "special" modifier [i.e. open the target URL in a new tab, or new window, or download it] while silently failing to actually navigate this tab. Otherwise, proceed with the original semantics of the native `location` / `history` API call that was made."

If your game isn't specifically trying to have middle-clicking / ctrl/cmd-clicking navigate the tab, then this check+logic would never fire.

---

That being said, in theory, if you bound a listener to `auxclick` and told it to `e.preventDefault()`, that should maybe tell the browser you're doing something special and different where the middle-mouse button isn't just "the left mouse button with extra flags set", and therefore that navigation triggered via the middle mouse button shouldn't be seen as "navigation triggered via the left mouse button with extra flags set."

I say in theory because web developers would probably use that to prevent people from opening their site/app in multiple tabs at once. And the whole point here is that people should be able to do this whether web developers like it or not.

--

Also, a tangent:

Web developers may have what are, to them, good reasons for preventing the user from opening their page/app in multiple tabs.

For instance, each instance of a page/app on their site might open its own persistent websocket connection to their backend, and so having O(N) tabs open to their site means O(N) websocket connections. And if many users do that, their backend falls over.

Or each instance of the page/app thinks it has exclusive ownership of a local IndexedDB, and so might try to migrate the data in a non-atomic way at any time; where if other instances of the page/app are also running and accessing the same DB, they might blow up, or do the same thing and corrupt the DB.

(I've seen both of these in practice. In fact, I believe Reddit [in its new design] does the former; at around ~100 open Reddit tabs, they all crash! [I think it has something to do with their chat system.])

IMHO, any webpage that can't stand being open multiple times simultaneously is badly architected. Such pages have been "coddled" too long by browser vendors, by allowing devs to mostly disable the user's ability to easily open links as tabs. We should stop coddling these pages.

If we give users back the ability to easily open tabs on modern websites, we'll see the owners of these sites finally [probably begrudgingly] fix the problems that cause them to want to disable opening things in tabs in the first place.

Akronymus

Also, get rid of JS based scrolling. I scroll a lot with pressing the middle mouse button. Too many sites break that.

OptionOfT

This reminds me of Microsoft's website checker in Office 365.

Click a link with left-mouse, and it'll intercept the page with their safety checker (that doesn't work half of the time) before forwarding you.

But middle click? No safety for you.

weaksauce

when i was doing .net programming way back in the day asp.net handled each navigation with a javascript event and it broke all that stuff. this was right before ruby on rails existed so maybe it’s better now.

epidemian

oh, 100% yes! The job project i joined somewhat recently is a moderately-complex React web app, and none of the navigation elements are actual links. Everything is done by onClick handling, even thought many things are, conceptually, just links. I have no idea why this kind of thing is so widespread on the web front-end world.

pverheggen

A good addition to this article is that most buttons should have type="button" on them. By default, buttons are type="submit", which if contained inside a form will submit that form.

I'm sure there are some devs who reach for a div because they're unaware of the proper way to disable submit behavior.

mixmastamyk

Believe that default is for <input type="submit">, not <button>.

cferdinandi

It's the default for buttons inside forms, but it's SO trivial to add type="button" than any argument that div's are a better choice because of this should be dismissed as unserious trolling out-of-hand.

pverheggen

Nope, it's the default:

https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/...

Maybe you’re thinking of <input type=“button”>, which doesn’t submit?

tomkarho

I seem to recall that once upon a time the default type for a button was in fact "button" but at some point (somewhere in the region of html 5 / es6) it was switched into "submit".

sam_lowry_

Indeed this long rant by OP misses the critical info.

A button of default type will do weird things, IIRC it will skip the JS handler onCick, for instance.

efilife

I don't think it skips the handler behavior on default but can't check now

Shog9

It does not. What it does do is submit the form, so if you trigger some fast change to the page or async behavior from the click event, you may never see it because the submission happens and the page reloads (or a different page loads if form action is set to a different URL). If you're relying on event bubbling, the click handler may run after the form is submitted, which is even less likely to do what you intend.

If you aren't expecting this (and don't know how to discover it e.g. by examining browser dev tools, server logs, etc.) then you'll assume the button is broken and... probably try something else.

Even if you do discover it, you may try something that won't quite have the same reliability - at one point it was common to see folks putting preventDefault() or return false in their click handlers to squelch the (correct) behavior, rather than changing the type of button.

rado

Right. I learned it the hard way lol

galaxyLogic

> they're unaware of the proper way to disable submit behavior.

That is an issue in favor of DIV, you don't accidentally set type="submit" because you don't know about that. There are many things many people don't know.

Using a DIV means you start from empty plate and explicitly add the features you want to add, which makes it easy to later remove or change those features when you want to.

Of course if your knowledge of HTML standards is great and Button exactly fits your current use-case you probably will use it, but designs and requirements change all the time.

Using DIV makes your design more transparent, you see there are certain features you have set to it by adding the attributes.

Using a Button means you (and other people reading your code) probably want to consult documentation to understand what it exactly does. With a DIV + attributes that is explicitly "spelled out".

Just some pros and cons.

MrJohz

You always want all the accessibility features. If your button is a button, then you want the whole lot: the correct role, tabability, keyboards shortcuts, everything. There is no situation where you only want some of those features.

So if you use a div, you _always_ need to add _all_ of the features. Whereas if you use a button, you usually need to remember to add the correct "type" attribute (although if you're building a form, you might not even need that).

You also mention transparency. A button makes your design transparent: it is a standard element, and web developers should know what it does. A div is not transparent - firstly, if I'm a developer reading that code, I need to look at context clues to understand what the authors' intent was (a tabbable element with a keydown handler and a click handler could be all sorts of elements, not just a button, so now I need to inspect event handlers and see what they do), and secondly, many people do not implement this stuff correctly, so what you're usually looking at is something that looks like it might have been intended as a button, but is missing a bunch of features. Was that intentional or did the author just forget some stuff?

This isn't really a "pros and cons" type of thing. Just use a button. It's doing all the work that you'd have to do manually, but automatically. Just use it.

serial_dev

So some developers cannot be trusted to figure out that they, in some cases, need to add a single attribute to the button, but they can reimplement a button with all its behavior, feel, look, and accessibility settings starting with a div?

Levitz

No, but they can reimplement it in a good enough state for the vast majority of users without getting bothered by default behaviour or styling that might vary per browser.

Which, don't get me wrong, is still a problem, accessibility matters, but if there's a reason as to why something happens, the way to fix it is to actually look at that reason.

brazukadev

React in a nutshell

thyristan

DIV isn't a button with features disabled. DIV is something else entirely, and you have to emulate most of the features in Javascript, badly. As the original article explains...

jmull

How is it harder to learn “want normal button” => <button type=“button”…> than “want normal button” => <div role=“button” tabindex=“0”…>, plus the javascript for keyboard access (plus css for at least the cursor), etc.?

culi

Agreed. It's not hard and it's definitely not unreasonable to expect front-end developers to know the very basics of semantic HTML and accessibility standards. It's literally their jobs

Mawr

> Using a DIV means you start from empty plate and explicitly add the features you want to add,

Yep, which guarantees you will not add everything that's required for e.g. accessibility. It's not realistic for every single dev to be aware of every single important property of a button. This approach just doesn't scale.

cferdinandi

No. Objectively no.

It is INFINITELY easier to add type="button" than all of the other shit I mentioned in my article.

marcosdumay

Every input should have a type. It's a good thing to put in a linter and run before you consider your code complete.

Yes, the default is bad, but you should be overriding every one of those anyway.

Sohcahtoa82

> Using a DIV means you start from empty plate

When comparing to a Button, that's a bug, not a feature.

donatj

I would love to see this expanded into "Just use the HTML element that was built for that explicit purpose". I feel like your average SPA developer doesn't understand what even a quarter of the HTML elements are meant for and just reinvent the wheel every time.

alberth

> doesn't understand what even a quarter of the HTML elements

I’d welcome people knowing a quarter of the html elements.

Because in my experience, it seems like people only know 1 html element, which is DIV and it’s used for everything.

christophilus

I wish the elements were just stylable, then. For example, the date picker sucks. I’d love to use it and eschew a JS based one, but my clients complain that it’s ugly.

culi

Yes it's called "just use the platform" and it's become a common refrain in the front-end world at least since HTML5 came out around 2014. Unfortunately it hasn't caught on in all parts of web dev but it's definitely seen as the "correct" way to do things

serial_dev

I heard it almost a decade ago in Polymer and Web components circles https://www.polymer-project.org/blog/2016-05-26-IO-2016-Reca...

It’s strange to look back and see that most spa projects still just bundle it all up into a gigantic js file…

jay_kyburz

I vaguely remember, back in 2010, when I wrote my app, you couldn't style a button consistently across all browsers. They were grey boxes in firebox, or used other OS standard styling.

We had to invent our own buttons if we wanted it to look the same everywhere. I could be wrong though.

array_key_first

The great thing about using a platform as big as the web, which runs on a million different types of devices, is you can say "not my problem" and offload it to someone else.

When you're building a webpage or webapp, you're really building, like, 5% of an app. The other 95% is taken care of for you. You can always just say "fuck it, who cares if the button is gray in Firefox". Because you know what? Firefox might just fix it. And boom, you get the same result with no effort and no maintenance burden. And even if you don't, who cares? Maybe Firefox users like that and that's why they're on Firefox. All you need to know, as a web developer, is that the button does clicky things and is a button. That is a super power. We should use it!

zahlman

As an end user: I chose my web browser. I know how things tend to look in it. I know that this is not the same as how they look by default in other browsers. I do not care. I actively want it the widgets to look familiar, because that means I can readily parse the UI, and don't have to think about your design.

I actively do not want you to even try to "make it look the same everywhere", because the way you want it to look will in general be a way that degrades functionality for me. When you try, you send the message that you know better than me about how I want the GUI on my computer to work; and that makes me less inclined to use your site, and thus your product.

tomwheeler

> I vaguely remember, back in 2010, when I wrote my app, you couldn't style a button consistently across all browsers. They were grey boxes in firebox, or used other OS standard styling.

I'm sure I'll trigger a lot of designers by saying this, but I'm probably not alone in valuing basic usability FAR above styling. I much rather have an ugly button that looks like 90's era Tcl/TK than something pretty that doesn't behave like I expect it to.

HocusLocus

A whole generation of people who click all over to find places that do something. People have this problem where they feel 'proudly vested' in learning things that just weren't designed well.

10 years ago someone decided that dragging links is so much more important than selecting text, selecting text is scarcely possible. I'm going to have to fork a browser to give link-dragging the demotion it deserves. It was probably those DIV guys.

ajmurmann

Almost as bad as copying a phone number on iOS instead of calling it (no idea if this is better on Android). The eagerness of iOS to call phone numbers which almost never is the thing I want to happen, is a source of much anxiety.

Shog9

Android works great - lets you select the # and then gives you a context menu with the option to call (or copy, or search).

...unless someone made the phone # a tel: protocol link, in which case it has the selection behavior of any other link. Which is mostly fine, since "copy" is a context menu option for tel: links... unless some jerk put a tel: URL in that isn't the same number as what is shown in the text of the link, in which case it's time for some crazy hoop-jumping to either copy OR call the number.

ForLoveOfCats

I might be a weirdo but I drag links all the time as it's how I open links as background tabs even though there is a right-click context menu entry for it

Unless the site is _really_ messing with events, holding alt on PC (Windows/Linux/ect) or Option on macOS lets you select text in links without triggering the link to navigate.

ivanche

Holy fsck! 30 years on the web and today I learn about this Alt/Option trick. Thank you!

tomwheeler

> selecting text is scarcely possible

I find non-selectable text maddening, but I recently found an macOS app called TextSniper that restores my control. It lets you select an area with the mouse (as you would when taking a screenshot) and it then OCRs the text and puts it into your clipboard. It almost makes Google Analytics usable again.

culi

This is a great point that I don't see brought up enough. I don't know if I've ever purposely wanted to drag a link but I struggle to highlight/select some in a link every other day

ratijas

There are browser extensions for selecting links. It used to be called Select Like A Boss, now it's Drag-Select Link Text. tl;dr: drag horizontally to select text, drag vertically to drag-and-drop as usual, press and hold to select the whole link text.

steve_adams_86

This is a good example of cases where LLMs can tend to write 'bad' code, because these patterns (i.e. reinventing wheels in the browser) are quite common in the wild, and LLMs tend to choose them over just using native features (such as buttons). I find myself telling Claude to revisit implementations and simplify them in these kinds of ways.

Another good example is bizarre error handling conventions when working in TypeScript. Claude will come up with tons of weird ways of doing this, using different approaches all over the place, but rarely consider simple patterns like 'return an expected value or an error'.

zahlman

> and LLMs tend to choose them over just using native features (such as buttons).

Of course course the LLMs do that. The pattern contains a lot more tokens that naturally follow on from each other.

turtletontine

These are great examples of how LLMs are great at writing code, but pretty bad at software engineering

serial_dev

Search engines were also only good at looking up things, not software engineering. I find it a blessing that a human is still valuable in this process we call software engineering. And meanwhile you can use search engines just like LLMs to learn and discover much faster than without them.

boothby

Only nowadays LLMs are embedded in search engines so if you're looking for something that doesn't exist the top of the page is liable to hallucinate its existence.

SmartHypercube

I got bitten by this: user agent stylesheet contains "button {align-items: flex-start}" (at least in Chrome). The default behavior is "stretch". Spent an hour debugging why my flexboxs' sizes are wrong. I still want to use correct HTML elements as much as possible, but I do think using <div>s everywhere makes my small side projects so much easier, since I don't have to remember all the non-default behaviors.

cferdinandi

I probably should have included "if you're building for the frontend you should probably know CSS". Good follow-up piece. Thanks for mentioning it!

crisnoble

`appearance: none` goes a long way to resetting button styles. I usually make a .unbuttonify class to use or extend for things I want to behave like buttons (free focus, accessibility, and interactivity) but look like, say, a hamburger menu toggle.

culi

are css resets not in vogue any more? I still use them for all my side projects. As well as a normalize.css[0] that smooths over any additional browser inconsistencies. The original Meyer reset is definitely overkill, but there are a couple newer more minimal ones out there[2][3]

[0] https://necolas.github.io/normalize.css/

[1] https://meyerweb.com/eric/tools/css/reset/

[2] https://www.joshwcomeau.com/css/custom-css-reset/

[3] https://piccalil.li/blog/a-more-modern-css-reset/

notatoad

did everybody else get to the end of this article, and right-click inspect the button on the newsletter sign-up to confirm that it was actually a <button>?

tarwich

100%

Use elements as close to their original intention as possible

giancarlostoro

Weird, I always use buttons when I can, unless what I need is not actually a button, but something that performs and on-click sort of like a button, like a hyperlink that navigates you through the web app.

ervine

I guess if it doesn't update the url, it's a button.

If it changes the url, it should be a link. At least that's how I've always done it.

cassepipe

Is is not okay to wrap a link inside a button ? I guess not

Which elements are allowed to wrap which is unclear to me

Shog9

FWIW, you can generally figure out what's allowed fairly quickly by checking the content model for a given element[1]. Some browsers might be more or less restrictive, but for normal usage this'll be more than enough to avoid unexpected behavior.

[1]: https://html.spec.whatwg.org/#the-button-element:concept-ele...

stevula

What is the use case? It’s hard for me to think of a reason you’d want to wrap a link in a button. If you want to navigate, use an anchor. If you want to trigger JS logic, use a button with onclick handler. If you want to navigate while doing some side effect like an API call, use an anchor with onclick handler (and don’t prevent default).

cferdinandi

Literally absolutely never ever do this.

Zak

> like a hyperlink that navigates you through the web app

You mean an <a> tag?

array_key_first

Well it might be a SPA so it's not a real link but rather just a function call + pushing some stuff to history and updating the URL (if you're lucky!)

flemhans

Why is the <div> option proposed by anyone in the first place?

wrs

Based on what I see in the world, I suspect one reason is that a <div> makes it easier to apply some bizarro appearance to the button, so it not only doesn’t act like a button, it doesn’t even look like a button.

mcny

This comes from either business or the UX people who want stuff to look pixel perfect to their stupid wireframe.

Why does a website that sells to a pretty much captive audience who cares more about functionality than looks obsess so much about every single button looking pixel perfect to some arbitrary wireframe, I will never know.

Joker_vD

Well, have you been on, I don't know, TV Tropes? They have those long lists, that are separated into "folders" on a single page. You can click on those "folders" to expand/collapse them, and it's implemented as a <div> with "onclick" property and <ul> inside it (well, used to IIRC; nowadays this <ul> is a child of a sibling <div>).

zahlman

> You can click on those "folders" to expand/collapse them, and it's implemented as a <div> with

... Isn't that what <details> and <summary> are for?

1-more

what's annoying about that example is that all of those <div>s could be buttons with no other changes. The only content inside the button <div> is the title and folder icon, not the list of examples associated with that title. That's just fine for a button!

The other thing I'd do is add `aria-controls=folder0` to the button that toggles visibility of the list with `id=folder0`

no_wizard

I'll do you one better and argue they could `<details>` elements. This is a perfect use case for that.

cferdinandi

The most common reason I've seen is whining about having to override default button styles.

no_wizard

I too have encountered this reasoning.

Then I write some basic CSS and show them they have nothing to fear.

Yet, I still remain irritated beyond belief that its such a common thing. In 2025. Hell, in 2017!

I don't know what to do about it, other than constantly remind people about things, but it gets tiring.

Though, its a great interview question. Its a quick way to understand if someone knows the fundamentals or not.

Kinda like how people got ".bind" wrong on functions for years.

Brendinooo

Related, because I don't always get to talk about buttons:

In my day job's shared library, we made a Clickable component that basically exists to abstract away the decision to use a button or an anchor tag, and resets the styles so both elements act the same way (both by default and when we apply styles to each).

We'd have a lot of confusion on the design side about button-as-design vs button-as-function and now we don't have to deal with that at all anymore.

And since the styling's been reset in a predictable way, it takes away one of the bigger reasons why people go to divs in the first place.

Sharlin

How does style reset make the elements work the same way? Links have vastly more features built into browsers than buttons

bugsliker

- tabindex=0 doesn’t affect ordering, does it?

- why do you need to listen for events at the document level?

not that i disagree with the article, but some arguments didn’t seem right.

thyristan

> - tabindex=0 doesn’t affect ordering, does it?

Of course it does. tabindex=0 doesn't sort naturally into the automatic tabindex order, it sorts AFTER everything. So you are jumping through all the other tabindex elements, then you are jumping back to all tabindex=0.

bugsliker

I'm saying tabindex=0 is naturally sorted wrt other naturally focusable elements. That matches the behavior of the <button> you're trying to emulate. I don't know what tabindex>0 has to do with this.

See this fiddle https://jsfiddle.net/483uqjnp/

(again, I do not condone building your own <button>, just pointing this out)

pverheggen

That's the same behavior as a <button> without tabindex, like the author is proposing.

It's generally advised not to set tabindex to anything but 0 or -1 and let the document order dictate tab order.

thyristan

> That's the same behavior as a <button> without tabindex, like the author is proposing.

Yes, but often you have elements with taborder > 0.

> It's generally advised not to set tabindex to anything but 0 or -1 and let the document order dictate tab order.

Only if document order is sane. Usually with modern websites it isn't, document order is a broken notion if you can position elements at will and e.g. put navigation at the bottom of a document but move it to the top by CSS. Which is actually a recommendation that some people make for acessibility...

What you usually want to do is assign a sensible taborder > 0 to the one form element that the user is probably currently using. Otherwise, he will pointlessly tab through search, menus, cookie bars and a ton of other pointless stuff first.

minitech

tabindex=0 does sort naturally into the automatic tabindex order.

> So you are jumping through all the other tabindex elements

This part is correct (for elements with an explicit positive tabindex), which is why specifying an explicit positive tabindex is considered a code smell. If you don’t specify a tabindex on an element that’s focusable by default, it behaves like tabindex=0.

Try it:

  data:text/html,<button>foo</button><i tabindex=0>bar</i><button>baz</button>

brandonhorst

thyristan

That is correct. From your link: "tabindex="0" means that the element should be focusable in sequential keyboard navigation, after any positive tabindex values. The focus navigation order of these elements is defined by their order in the document source. "

Ma8ee

Your link actually supports the comment you replied to.

cferdinandi

Hey, it's me, the original author!

The issue isn't with tabindex=0 specifically, but fucking with tabindex in general. People go down that path, and start putting that shit on everything, like it's Frank's Red Hot.

And in my experience, the same folks who use div's instead of button's are the ones who don't know better and start throwing tabindex around.

"why do you need to listen for events at the document level?"

Not events generally, keydown events specifically, which do not fire on child elements of the document.

kyle-rb

Hi, good premise overall, but there are just a lot of little things that are off.

- It only counts as "fucking with tabindex" if you give it a value that's not 0 or -1. You should give that specific disclaimer, because there are uses for tabindex=0 other than reimplementing <button>.

- Divs can definitely receive keydown events. If I go to an arbitrary web page, pick a div and run `div.tabIndex = 0;` + `div.addEventListener('keydown', console.log);`, I see those events coming through when I have the div keyboard-focused.

- "Run your code, somehow..." I think just calling `notRealBtn.click()` is the best option.

- Stupid but semi-interesting nitpick: 'keydown' is good for enter, but you should be listening to 'keyup' for the space bar. That's how real <button>s work anyway.

- The 'keyup' listener should call event.preventDefault() to prevent the default behavior of the space bar scrolling the page.

pverheggen

Not sure about that, MDN's example shows keydown being attached to an element.

https://developer.mozilla.org/en-US/docs/Web/API/Element/key...

susam

> Not events generally, keydown events specifically, which do not fire on child elements of the document.

Are you sure? I have a 17 year old HTML tool written using plain, vanilla JavaScript where keydown on a child element seems to have been working as expected.

https://susam.net/quickqwerty.html

https://github.com/susam/quickqwerty/blob/1.2.0/quickqwerty....

Nice article, by the way!

skrebbel

I think that’s because it’s an input and not a div, so it can get focus. Im not sure whether tabindex is enough to make a div do that too, article suggests no