Styling input field focused by keyboard - html

I am trying to set different styling on input field which is focused by keyboard (not by mouse).
I know that it's possible to distinct focus by mouse and keyboard on other elements by using pseudo-class :focus-visible but it's not working on input due the spec:
The :focus-visible pseudo-class applies while an element matches the :focus pseudo-class and the UA determines via heuristics that the focus should be made evident on the element.
For example, UAs typically display focus indicators on text fields any time they’re focused, to draw attention to the fact that keyboard input will affect their contents.
On the other hand, UAs typically only display focus indicators on buttons when they were focused by a keyboard interaction (such as tabbing through the document)—because it’s not always immediately obvious where the focus has gone after such an interaction, but is sufficiently self-evident when the button was focused by more obviously-targetted interactions, like clicking on the button with a mouse pointer.
Is there any solution to distinct styling when input field is focused by mouse or keyboard?

You could add additional styles for :hover in addition to :focus-visible or :focus if that works for you. The example is here (https://codepen.io/alekskorovin/pen/OJxJaQB):
input {
outline: 4px dashed transparent;
}
input:focus-visible {
outline: 4px dashed darkorange;
}
input:hover:focus-visible {
outline: 4px dashed darkgreen;
}
input:hover {
outline: 4px dashed transparent;
}
<input type="text" />

Related

What is this CSS checkbox state called, and how can I remove its effects?

Consider this checkbox:
<input type="checkbox" />
When pressing a keyboard button when this checkbox is focused, a solid black outline appears around it. I can get rid of by removing the outline:
input {
outline: none;
}
<input type="checkbox" />
However, I wish to apply an outline to the actual element, and this method would invalidate it. I was wondering if there was a pseudoclass that could be used to select this checkbox state. If so, what is it called and how do I access it? If not, is there any other viable way (CSS only) to do achieve this? I thought the :focused pseudoclass would work, but this selects the focused state of the checkbox and not whatever this state is, when the checkbox is focused and a key is pressed.
P.S. when I add an outline to the checkbox, the problem appears in a different format. The outline is somehow "extended", almost as if a padding or border was added to the element (try focusing on the following checkbox and pressing a key):
input {
outline: solid red 3px;
}
<input type="checkbox" />
I think outline-offset: 0px; under the element state focus-visible is what you're looking for:
input {
outline: solid red 3px;
}
input:focus-visible
{
outline-offset: 0px;
}
<input type="checkbox" />
The checkbox is an HTML element used to take input from the user. This HTML element is generally used on every website, but without styling them, they look similar on every website.

Why does the internal css style of black outline on in-focus focusable elements, not apply on click+hold?

If you run the following demo, and click+hold(hold for 1sec before releasing the click) on the third link, you will see they get the same styles of :focus pseudo selector from the css(red outline).
.ext:focus {
outline: 1px dotted red;
}
1. Get me in focus with tab to see black outline -- Browser default
<br><br>
<a class="ext" href="#">2. Get me in focus with tab to see red outline -- ext css </a>
<br><br>
<a class="ext" href="#">3. Click+hold to see red outline -- supposody gets me in focus </a>
<br><br>
4. Click+hold to see black outline -- doesnt work as expected!
My gut feeling is that when you click+hold on any focusable element, it gets that element in focus, thats why you see a red dotted outline on #3 link.
Now, then why in the fourth link when you click+hold you don't see a black outline?
It is true that when you click on a focusable element it gets infocus as well, but your misconception is that the browsers internally apply the following css:
a:focus {
outline: 2px solid black;
}
In reality the browsers use the focus-visible css property like this:
a:focus-visible {
outline: 2px solid black;
}
focus-visible is a css4 level property recently introduced by most browsers(except safari). It has been designed specifically for what have you observed. This behaviour gets even more apparent in case of input fields(check out MDN's example), where you don't have to hold the click to see the result. In the case of anchor tags focus-visible applies style to only those elements who've been focused through the keyboard not the mouse. It should be noted that the button element behaves similar to a element, but the input element treats focus-visible identical to focus, that is even on click it gets the styles mention in input:focus-visible{...}.
Example:
input:focus-visible, button:focus-visible {
outline: 2px dotted black;
}
<input type="text" value="Click/tab shows outline">
<button>Only tab shows outline</button>
Moreover, you can inspect element in your browser and toggle element's state to focus-visible. You will see the following styles being applied by the user-agent(chrome):
a:-webkit-any-link:focus-visible {
outline-offset: 1px;
}
user agent stylesheet
a:-webkit-any-link {
color: -webkit-link;
cursor: pointer;
text-decoration: underline;
}
user agent stylesheet
:focus-visible {
outline: -webkit-focus-ring-color auto 1px;
}

How to style focus outline for accessibility purposes

I'm trying to style the outline of the field when in focus because my current outline is very hard to see. I know that some html elements are focusable by default, so I'm not quite sure to what element to attach the outline style.
Do I need to target all the potentially focusable elements? Like
a:focus, button:focus {outline: 1px solid white; }
(including all the other elements)? This does not seem like the right method.
I have tried searching for the answer and all I can find is that outline must not be none but other than then, I haven't found anything else.
Just go
:focus { outline: 1px solid white; }
to target all focussable elements. No need to specify those elements explicitly.
Btw, this is short for
*:focus { outline: 1px solid white; }

CSS: How to toggle switch action on the <a> link?

I know that press signal in css is :active, but i still can't find a proper way to make a toggle switch for the link.
For example, <a> has the color blue, when <a> will be pressed first time, it's color should be red, when it is pressed second time, it's color should blue again. So basically first press is a toggle switch from blue to red, and second is vice versa.
I have used :target action which didn't seem to work out:
a {
color: blue;
}
a:active {
color: red;
}
a:target {
color: red;
}
How could this be possible without use of JS? So i could toggle switch the link color to red on the first click, and then blue again at the second.
You can do it via checkboxes and labels.
HTML:
<input type="checkbox" id="t1" class="toggle">
<label for="t1">Link with toggling color</label>
CSS:
.toggle {
position: absolute;
left: -99em;
}
.toggle:not(:checked) + a {
color: blue;
}
.toggle:checked + a {
color: red;
}
Working example here.
This is not possible to achieve without JS. Links are not designed to be toggle elements, and CSS has nothing to track multiple clicks on an element (it is either being clicked or is not).
If you want to represent a toggle, then look at checkbox inputs instead. They have a :checked pseudo-class.
There is one way you could (sort of) achieve this purely with CSS but it would mean that, in its initial state the link would actually be unclickable, which probably wouldn't be desirable.
The trick is to set the pointer-events of the anchor tag to none, wrap it in another element with a tabindex attribute (to allow it to gain focus) and then, when the wrapping element receives focus, change the colour of the anchor and reset its pointer-events. On the next click, the link will receive focus but this will remove the focus from the wrapping element, which will revert the anchor's styles back to their initial state.
*{color:#000;font-family:sans-serif;outline:0;}
a{
color:#00f;
pointer-events:none;
}
span:focus>a{
color:#f00;
pointer-events:initial;
}
<span tabindex="-1">link</span>

Tabindex Focus Styles

I have made a div tabbable with the tabindex attribute to make hidden content accessible.
Currently when clicked with the mouse the div gets browser :focus styling.
Is there a way to have that tabbable element to only have focus styling when accessed via the keyboard? An anchor element has this by default.
Div with tabindex='0' gets browser focus styles on mouse and keyboard
interaction
Anchor gets browser focus styles on keyboard interaction
only
I would like the div to emulate the anchor. Making it an anchor is not an option though unfortunately.
Any help would be great, I'm genuinely at a loss.
Edit -> Here is an example: http://jsfiddle.net/LvXyL/2/
Sure just add the :focus pseudo-class to the div, and style. I recommend using outline vs border. I updated the fiddle.
div:focus {outline: blue solid 2px;}
Kub suggested a JS solution, but why use js if you don't actually need to?
I've had great success using javascript to add/remove a class to the body that indicates if the user is using a mouse or a keyboard. Use those classes to style your focus states as you desire.
document.addEventListener("mousedown", () => {
document.body.classList.add("using-mouse")
document.body.classList.remove("using-keyboard")
})
document.addEventListener("keydown", () => {
document.body.classList.add("using-keyboard")
document.body.classList.remove("using-mouse")
})
The in the css you can do something like:
.using-mouse :focus {
outline: none;
}
.using-keyboard :focus {
outline: auto 5px blue;
}
I would suggest to don't be specific on tags like div, p, span
let's write one common selector to achieve this functionality for all the elements.
*:focus {
outline: blue solid 2px;
}
If you want to be specific then I would suggest this one.
*[tabindex]:focus {
outline: 2px green solid;
}
I have used the focus-visible css selector to apply different styles for keyboard focus and mouse click.
The way I implemented it is like this:
.your-element's-classname:focus:not(:focus-visible) { outline: none; }
When you focus it with the keyboard you will see the browser's focus styling or the custom styling you have made for your element, and when you click it you will see no styling because I have applied outline:none which removes the outline created by the browser's focus styling.
You can find more information in Mozilla's focus-visible docs and Chromium's browser focus article.
For those who are looking to override the tabindex focus style and preserve the original functionality of tabindex ie. show outline only when tab key is pressed and not on mouse click like if
:focus {
outline: 2px solid lime;
}
is used it will show outline on every element that is getting focus, but I found out that if I use
Change Tabindex Style - for all elements:
:focus-visible {
outline: 2px solid lime;
}
this will override the outline style of the tabindex on focus and preserve the tab outline functionality but with the new outline style.
https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible
If you can use javascript, try use onclick attribute.
onclick="this.blur()" for lost focus
onclick="this.focus()" for set focus
Example where DIV on click lost focus and A is set focus http://jsfiddle.net/LvXyL/6/
Disadvantage is visible focus style if you hold mouse key for a longer time.