Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a custom web component focusable?

I'm writing a custom web component that is meant to be interactive. How can I tell the browser that this custom component should receive focus?

I wish that my custom element…

  • could be focused (by tab-navigation);
  • could receive keypresses when focused;
  • could be matched by :focus pseudo-selector.

I'm not using any external library, just plain HTML5 APIs.

like image 818
Denilson Sá Maia Avatar asked Sep 05 '15 20:09

Denilson Sá Maia


People also ask

How do you make a component focusable?

You can make it focusable by adding a tabindex=0 attribute value to it. That will add the element to the list of elements that can be focused by pressing the Tab key, in the sequence of such elements as defined in the HTML document.

Can custom elements be self closing?

Custom elements cannot be self-closing because HTML only allows a few elements to be self-closing.


1 Answers

@Denilson, I would like to provide you with some more information.

As you said, this.tabIndex = 0 works when your webcomponent contains no focusable elements. If it does, it gets more complicated.

For example, if your component contains one or more inputs, then first the "whole" component gets focus, and only later, when tabbing, each inner inputs get focus, one by one. This is usually not what you want. Usually, when the component gets focus this should mean its first input gets focus immediately.

Also, there is a reverse tabbing problem. If your first input has focus and you press SHIFT-TAB, then the "whole" component gets focus, and you are forced to press SHIFT-TAB twice to move to the previous element.

I found this to solve all focus and tabbing problems:

// At first, the component may get focus and accept tabbing.
createdCallback = function () { this.tabIndex = 0; }

// When the component gets focus, pass focus to the first inner element.
// Then make tabindex -1 so that the component may still get focus, but does NOT accept tabbing.
focus = function (e) { firstFocusableInnerElement.focus(); this.tabIndex = -1; }

// When we completely left the component, then component may accept tabbing again.
blur = function (e) { this.tabIndex = 0; }

Note: As of now (Sep 2015) if an inner element gets focus, then the "whole" element is not matched by the :focus pseudo-selector (tested only in Chrome). If find this behavior to be just plain wrong. The focus event was fired, and the blur event was not. So the element should have focus, right? I hope they change this in the future.

like image 160
MarcG Avatar answered Oct 16 '22 21:10

MarcG