Input Effect on Keyboard Tab -> Focus, But Not on Click

Enable :focus only on keyboard use (or tab press)

Update: This issue may no longer be relevant

Some other posters have mentioned the :focus-visible pseudo class - which now has decent browser support...

I would like to add, that based on the spec which covers the :focus-visible pseudo class, browsers should now only indicate focus when it is helpful to the user - such as in cases where the user interacts with the page via a keyboard or some other non-pointing device

This basically means that the original issue is no longer relevant, because now, when a user clicks/taps a button (or another focusable element), the User Agent won't show the focus ring anymore - even though the button is focused - because in this case the focus ring isn't helpful to the user.

From the spec:

While the :focus pseudo-class always matches the currently-focused
element, UAs only sometimes visibly indicate focus (such as by
drawing a “focus ring”), instead using a variety of heuristics to
visibly indicate the focus only when it would be most helpful to the
user. The :focus-visible pseudo-class matches a focused element in
these situations only...

Indeed, as of version 90, Chromium’s User Agent stylesheet switched from :focus to :focus-visible, and as a result of this change, button clicks and taps no longer invoke focus rings

Also, as of version 87, Firefox also uses :focus-visible on their User Agent style.

All that being said, if custom focus styles are needed, since focus styles have now shifted from :focus to :focus-visible, when overriding the default styles with custom focus styles - the :focus-visible pseudo class should be used.

Something like this:

button:focus-visible {
/* remove default focus style */
outline: none;
/* custom focus styles */
box-shadow: 0 0 2px 2px #51a7e8;
color: lime;
}

Backwards Compatibility:

The possible problem with using :focus-visible like this, is that browsers which don't support :focus-visible, will show the default focus ring, which may not be clear or visible - depending on the design.

Šime Vidas, in this article, describes a viable strategy to currently use the :focus-visible pseudo class - which would work even in browsers which don't yet support :focus-visible -

A good way to start using :focus-visible today is to define the focus
styles in a :focus rule and then immediately undo these same styles in
a :focus:not(:focus-visible) rule. This is admittedly not the most
elegant and intuitive pattern, but it works well in all browsers:

Browsers that don’t support :focus-visible use the focus styles
defined in the :focus rule and ignore the second style rule completely
(because :focus-visible is unknown to them).

In browsers that do support :focus-visible, the second style rule
reverts the focus styles defined in the :focus rule if the
:focus-visible state isn’t active as well. In other words, the focus
styles defined in the :focus rule are only in effect when
:focus-visible is also active.

button:focus {
outline: none;
background: #ffdd00; /* gold */
}

button:focus:not(:focus-visible) {
background: white; /* undo gold */
}

Original Answer:

This excellent article by Roman Komarov poses a viable solution for achieving keyboard-only focus styles for buttons, links and other container elements such as spans or divs (which are artificially made focusable with the tabindex attribute)

The Solution:

button {
-moz-appearance: none;
-webkit-appearance: none;
background: none;
border: none;
outline: none;
font-size: inherit;
}

.btn {
all: initial;
margin: 1em;
display: inline-block;
}

.btn__content {
background: orange;
padding: 1em;
cursor: pointer;
display: inline-block;
}

/* Fixing the Safari bug for `<button>`s overflow */
.btn__content {
position: relative;
}

/* All the states on the inner element */
.btn:hover > .btn__content {
background: salmon;
}

.btn:active > .btn__content {
background: darkorange;
}

.btn:focus > .btn__content {
box-shadow: 0 0 2px 2px #51a7e8;
color: lime;
}

/* Removing default outline only after we've added our custom one */
.btn:focus,
.btn__content:focus {
outline: none;
}
<h2>Keyboard-only focus styles</h2>

<button id="btn" class="btn" type="button">
<span class="btn__content" tabindex="-1">
I'm a button!
</span>
</button>

<a class="btn" href="#x">
<span class="btn__content" tabindex="-1">
I'm a link!
</span>
</a>

<span class="btn" tabindex="0">
<span class="btn__content" tabindex="-1">
I'm a span!
</span>
</span>

<p>Try clicking any of the the 3 focusable elements above - no focus styles will show</p>
<p>Now try tabbing - behold - focus styles</p>

Why pressing TAB key (:focus effect) causes positioned off-the-screen div element with input field inside it to appear on the screen?

Set a tabIndex of -1 to prevent tab focusability to elements that you don't want to gain focus with the tab key.

Label that wraps an input - how to make focus style visible only when focused using the keyboard, not mouse click?

Update the styles of the input inside it so it can style get the focus while being visually hidden:

label {
position:relative;
}
.visually-hidden {
position: absolute;
inset: 0;
margin: 0;
padding: 0;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
overflow: hidden;
}

button:focus-visible,
input:focus-visible{
outline: 4px solid red;
}

body {
margin: 40px;
}

div {
display: flex;
gap: 20px;
}
<div>
<input type="text" />
<button>Submit</button>
<label>
<input class="visually-hidden" type="checkbox" />
Label
</label>
</div>

tabIndex doesn't make a label focusable using Tab key

Why doesn't tabindex make the label focusable?

Short Answer:

  1. Label is focusable.
  2. TabIndex won't make any difference.
  3. Welcome to the world of browser/agent inconsistencies.

tl;dr;

The label (Ref) element is very much focusable. Its DOM Interface is HTMLLabelElement which derives from HTMLElement (Ref) which in turn implements GlobalEventHandlers (Ref) and hence exposes the focus() method and onfocus event handler.

The reason you are unable to get hold of proper specification / reference document for labels focus behaviour, is because you might have been looking at HTML5 Specs. Interestingly, HTML5 refs do not state anything relating to that, which adds to the confusion.

This is mentioned in the HTML 4.01 Ref here: http://www.w3.org/TR/html401/interact/forms.html#h-17.9.1

Specifically near the end of section 17.9.1 and just before 17.10:

When a LABEL element receives focus, it passes the focus on to its
associated control.

Also, elsewhere (I am unable to get hold of that part of the ref) I have read that it depends on the implementing agent. (Don't take my word for that, am not too sure).

However, what it means is that when you focus a label (or a label received a focus), that focus is passed on to its associated labeleable control. This will not result in two different focuses, but one focus on the input (in your case a checkbox). Because of this behaviour, tabindex property cannot play a role.

There is also a test suite by W3C for website accessibility (WAAG) here: http://www.w3.org/WAI/UA/TS/html401/cp0102/0102-ONFOCUS-ONBLUR-LABEL.html which, discusses the implementation of onfocus and onblur for a label. Ideally a keyboard or an assistive technology that emulates the keyboard should implement this. But...

This is where the browser inconsistencies play their role.

This can be demonstrated by this example. Check the following snippet in different browsers. (I have tested it against IE-11, GC-39 and FF-34. All of them behave differently.)

  1. Click the button "Focus Label"
  2. It should focus the label, then pass the focus and highlight its associated checkbox outline in blue.
  3. Chrome-v39 works. IE-v11 it doesn't (somehow html and body do respond to :focus). FF-v34 it works.

Talking about browser inconsistencies, try using the "access key" L. Some browsers will focus the checkbox whereas some will click it i.e. pass the action to it.

Here is a fiddle to test it: http://jsfiddle.net/abhitalks/ff0xds4z/2/

Here is a snippet:

label = $("label").first();$("#btn").on("click", function() {    label.focus();});
* { margin: 8px; }.highlight { background-color: yellow; }:focus {    outline: 2px solid blue;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><input id="txt" type="text" value="input" /><br /><label for="chk" accesskey="L">Checkbox: </label><input id="chk" type="checkbox" /><br /><input id="btn" type="button" value="Focus Label" />

Add Focus To Pop Up / Modal On Click For Tabbing / Accessibility - JavaScript

You have to add focus to the pop-up right after this appears, when you do it simultaneously with closeButton.focus() only it won't work that's why I'm using setTimeout(() => closeButton.focus(), 1), this will added it focus after a 1 millisecond.

At first, focus on a button isn't visible, it become visible when arrow keys are pressed, so I make it visible styling it:

      .close:focus {
border: 2px solid black;
border-radius: 5px;
}

The whole code:

      let clickMe = document.querySelector("#click-me"),
modal = document.querySelector(".modal"),
closeButton = document.querySelector(".close");

clickMe.addEventListener("click", () => {
setTimeout(() => closeButton.focus(), 1);
modal.style.display = "flex";
});

closeButton.addEventListener("click", () => {
modal.style.display = "none";
});
      body {
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}

input,
button {
margin: 1rem;
padding: 0.5rem;
}
.click-me {
display: block;
}

.modal {
display: none;
flex-direction: column;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
background: gray;
position: absolute;
}

form {
display: flex;
}
.close:focus {
border: 2px solid black;
border-radius: 5px;
}
    <button id="click-me">Click Me</button>
<form action="">
<input type="text" placeholder="An Input" />
<input type="text" placeholder="An Input" />
<input type="text" placeholder="An Input" />
<input type="text" placeholder="An Input" />
</form>

<div class="modal">
<button class="close">Close x</button>
<button>More Buttons</button>
<button>More Buttons</button>
</div>

Input Verifier effect not work by click, just work by tab button

The purpose of InputVerifier class is to help clients support smooth focus navigation through GUIs with text fields. Before focus is transfered to another Swing component that requests it, the input verifier's shouldYieldFocus method is called(which ask the verify function to validate data). Focus is transfered only if that method returns true.

Please Try to fix the issues about using InutVerifier, verify and shouldYieldFunction as mentioned in your previous post. If you are not going to change your practice, you will be danger in future. Remove you components enabling and disabling code from verify function.

Your Problem in this post: In this case, what really happening is that, when your data is invalid and you try to lose your input text field focus by clicking another component, your JRadioButtons get disabled. A disabled cant be focused until it is re-enabled. As input-verifier responds with focus-lose event, clicking on the disabled RadioButton isn't resulting in focus navigation, and thus ShouldYieldFocus(which calls verify) is not being called to re-enable your components.

Pressing the tab works, because it is sending the Focus to your second text input field according to swing's focus traversal policy. Hence a focus lose event occur on first input text field and this time InputVerifier's verify function get called which eventually enables your component. To understand the problem better, try rewriting your own example with one JRadioButton and one JTextFeild.


Try using a DocumentListener with your text Field. upon data insertion and removal event, check your data validity using InputVerifier and then, enable/disable related components.

I am writing a sample code snippets to demonstrate, how adding DocumentListener to your fNameTF and lNameTF text fields will resolve your problem:

fNameTF.getDocument().addDocumentListener(new DocumentListener() {

@Override
public void insertUpdate(DocumentEvent e) {
doOnDataValidity(verifier.verify(fNameTF));
}

@Override
public void removeUpdate(DocumentEvent e) {
doOnDataValidity(verifier.verify(fNameTF));
}

@Override
public void changedUpdate(DocumentEvent e) {}
});

doOnValidity(boolean isValid) function is as follows:

public void doOnDataValidity(boolean isDataValid)
{
if(isDataValid)
{
//enable your components
}else
{
//disable your components
}
}

Add a DocumentListener to your lNameTf.getDocument() the same way.

Tutorial Resources: How to use DocumentListener.



Related Topics



Leave a reply



Submit