FireFox keyboard active button

44
June 20, 2019, at 05:30 AM

Having a UI that is meant to be keyboard friendly. It has various controls in the for of buttons etc.

Problem is that when one click a button by keyboard, the button does not get the :active status. I have a strong style to show it gets :focus - but the active status is only triggered when one use mouse and click with main button.

This makes things very user-unfriendly. It looks as if the button is not activated. The page has frozen or the like. One risk users clicking multiple times as they expect a visual feedback.

From what I read at MDN it looks as this is a feature in the CSS3 specification:

Note: On systems with multi-button mice, CSS3 specifies that the :active pseudo-class must only apply to the primary button; on right-handed mice, this is typically the leftmost button.

https://developer.mozilla.org/en-US/docs/Web/CSS/:active

As this is a JavaScript based UI, I have tried to solve this by JS on the click event:

Add, and remove a .activated class.

This does not work as the page is not re-rendered. To fix this without using a setTimeout() I have tried things like these:

https://css-tricks.com/restart-css-animation/#article-header-id-0

element.classList.add('activated');
void element.offsetWidth;                // Trigger reflow
element.classList.remove('activated');

No effect.

I have tried to add class, remove element, insert a new with the class, and remove the class. No effect.

Used dataset-active=1 and CSS by that. No effect. Same issue as with adding and removing class.

And some other things.

I have also tried to use setTimeout(), but this is somewhat buggy. Especially if one use Enter key (to trigger multiple clicks.)

In the end I also tried to listen for keydown, keyup etc. setting statuses if it was enter, space or mouse click etc. But that quickly got very messy.

Is there a neat trick for this that I am missing? A solution that is not overly complex.

Sample code

button:focus { 
  outline: 1px solid blue; 
} 
button:active { 
  outline: 4px solid red; 
}
<button onclick="counter.value = ++counter.value;">Button</button> 
<input id="counter" value="0">

Answer 1

How about that: Adding a data-attribute containing the related keycode to the button. While pressing the key down an active class is assigned and click() and focus() are triggert. When the key is released the active class will be unassigned.

  
document.onkeydown = function (evt) 
{ 
    let btn = document.querySelector ('[data-key=' + CSS.escape (evt.keyCode) + ']'); 
    if (btn) 
    { 
        btn.classList.add ('active'); 
        btn.click(); 
        btn.focus(); 
    } 
} 
 
document.onkeyup = function (evt) 
{ 
    let btn = document.querySelector ('[data-key=' + CSS.escape (evt.keyCode) + ']'); 
    if (btn) 
    { 
        btn.classList.remove ('active'); 
    } 
}
    button:focus { 
  outline: 1px solid blue; 
} 
 
button.active, button:active { 
  outline: 4px solid red; 
}
<button data-key="32" onclick="console.log(1);">Button 1 [space]</button> 
<button data-key="16" onclick="console.log(2);">Button 2 [shift]</button> 
<button data-key="13" onclick="console.log(3);">Button 3 [enter]</button>

Alternatively you can take a look at accesskey attribute.

READ ALSO
Get JavaScript alert in case of specific words on web page

Get JavaScript alert in case of specific words on web page

Is it possible to get a JavaScript alert when there is a given word (or words) on a currently visited web page? I have searched in all the Google extensions, but I haven't found it unfortunately

68
How to pass a form data to a client side function (google.scripts.run) and return result to HTML?

How to pass a form data to a client side function (google.scripts.run) and return result to HTML?

I'm trying to take an ID from a form and run that ID against a function in CODEgs that checks the spreadsheet for that ID and returns the name back in the HTML

66
Apexcharts xaxis formatting fails when using datetime type

Apexcharts xaxis formatting fails when using datetime type

I use vue-apexcharts to plot charts in a dashboardI created a generic file that contains the base options for all charts (to uniformize styling and code reusability) and I extend/override this object with a mergeDeep() function when necessary

49
Configure webpack to generate separate vendor js files for each entry

Configure webpack to generate separate vendor js files for each entry

I have multiple js apps in one applicationEach js app has different dependency on js libraries and each js app is an entry for webpack

71