Why default button overrides outline on focus event? - html

I do not know if it is a bug or not, but it seems to be.
When you have a default button and you click it when you have a :focus pseudo class it does not seem to have an outline.
#buttontag:focus {
}
<button id="buttontag" type="button">Focus me</button>
It shows the outline when you use tab key, though.
Nevertheless, it shows the outline both when clicking or using tab key on the button if you change the background-color to it.
#buttontag:focus {
background-color: #dde;
}
<button id="buttontag" type="button">Focus me</button>
But it does not work for all types of background-color. For example, it does not work for background-color: #ddd. In this case it is only shows when you use tab key.
#buttontag:focus {
background-color: #ddd;
}
<button id="buttontag" type="button">Focus me</button>
Here an screenshot when the button is focused, nothing changes.
I know that the background-color: #ddd is the same colour as the default border of the button (both on focus or not focused). I have created the following code to be sure of it.
var buttontag = document.getElementById('buttontag');
buttontag.onfocus = function(){
var border = window.getComputedStyle(buttontag).getPropertyValue("border");
alert(border);
}
var border = window.getComputedStyle(buttontag).getPropertyValue("border");
alert(border);
#buttontag:focus {
background-color: #ddd;
}
<button id="buttontag" type="button">Focus me</button>
I know that rgb(221, 221, 221) is the same as #DDDDDD on hex and that is the same as #ddd. I do not know if it has to be something related about contrast between both colours (there is no contrast because they are the same colour) and outline but it is very strange that in this background-color the outline does not appear.
More and more strange
If you inspect the default button and you force it to be focussed (I am trying on Google Chrome debugger) , it has an outline and shows it on the button. It is the default outline that appears in the rest of buttons with another background-color.
:focus {
outline: -webkit-focus-ring-color auto 5px;
}
And I also wanted to know if it was something related about forcing the button to be in focus state so I created a Javascript snippet to see what outline the button has in focus state.
var buttonFocus = document.getElementById('buttontag');
buttonFocus.onfocus = function(){
var outline = window.getComputedStyle(buttonFocus).getPropertyValue("outline");
alert(outline);
}
#buttontag:focus {
background-color: #ddd;
}
<button id="buttontag" type="button">Focus me</button>
It retrieves the default outline, but does not show it. It seems that it only shows the outline if you force the button to be focussed (on the debugger).
I have searched on the official documentation but could not find anything related about a special behaviour for default buttons or specific background-color.
So here I have some questions:
Why is the outline not displayed on the default button when you click on it?
Why with background: #ddd it is not shown also?
Why is the outline shown when you use tab and not when you click on the button (on the two cases above)?
Why the button has the outline in his CSS but it does not display it? Is it a bug?

Might be wrong.
The default button (in Google Chrome at least) uses appearance
style attribute:
button {
-webkit-appearance: button;
}
The appearance property allows you to make elements look like a
standard user interface element from your operating system. Talking about OS X, standard interface buttons do not have outline
by default.
Very easy way to check how the standard os buttons looks:
alert('I am standard button')
When you've created a button:focus pseudo-class that contained
background or border rule (example #2), you have overridden the
standard appearance by default browser style for button + your
rules.
In example #1, the button:focus is empty, and apparently it is
just ignored by the browser, hence os interface style is applied.
If you will create a style:
button { -webkit-appearance: initial; }
you will get default browser button that has outline.
Chrome's default style for button has a rule:
background-color: buttonface;
Safari and Google Chrome support custom color names that are
references to the currently used colors of user interface elements.
It might be the case, that buttonface is '#dddddd' in your system. Interesting though, as I can see the blue outline in OS X Chrome.
For the questions 3 and 4, I am afraid I cannot replicate it, as I do get outline.
Will update the answer after some research. Cheers! :)

webkit Chrome and Safari behave differently, in that they do not trigger :focus on a click event, but do on tab keyboard event.
That :focus behavior is present, especially on the button element.
So you might have to add tabindex attribute on your button element to let the browser know that this element can receive focus.
tabindex="0"
Since without that tabindex attribute, the browser sees that focus flag as being false, hence no :focus.
See W3C spec:
https://drafts.csswg.org/selectors-3/#the-user-action-pseudo-classes-hover-act
There may be document language or implementation specific limits on which elements can become :active or acquire :focus.
Also see the following regarding focused browsing context
https://html.spec.whatwg.org/multipage/interaction.html#currently-focused-area-of-a-top-level-browsing-context
If the attribute is omitted or parsing the value returns an error.
The user agent should follow platform conventions to determine if the element's tabindex focus flag is set and, if so, whether the element and any focusable areas that have the element as their DOM anchor can be reached using sequential focus navigation, and if so, what their relative position in the sequential focus navigation order is to be.
Modulo platform conventions, it is suggested that for the following elements, the tabindex focus flag be set:
a elements that have an href attribute
link elements that have an href attribute
button elements
You can also see this related StackOverflow question:
css focus not working in safari and chrome

button has a default style define by each browser. it might (and often is) different from browser to browser. But we can overwrite the default values to suit our needs.
Why is the outline not displayed on the default button when you click on it?
The button doesn't enter in focus state when you click. It enters the active state.
Why with background: #ddd it is not shown also?
It does show in my browser, but only when in focus. I your examples you use #ddd and #dde which are 2 very similar grays to the default gray, but once I changed the value I could see the difference.
Why is the outline shown when you use tab and not when you click on the button (on the two cases above)?
The focus state is meant to allow the user to hit the Enter/Return key to activate the button. However, the button doesn't enter the focus state one it is clicked
Why the button has the outline in his CSS but it does not display it? Is it a bug?
It is not a bug. It only displays when in focus state, which can be forced through the code inspector, via javascript or by tabbing through form elements. I used my own example declaring:
outline: 2px solid #ccc;
The focus state is very useful when trying t make the application/website accessible to screen readers for people who are visually impaired. It allows us to add more functions that can be triggered in those situations, and to guide the user through the page when looking at it isn't possible.

The default browser behavior is to show an outline only on focus (by using tab f.e.), not on click. Each browser also may have it's default outline color and width.
To avoid any funny behavior you can overwrite the outline, and also add it to a click:
#buttontag:focus, #buttontag:active {
outline: #ddd solid 2px;
}

Related

Make HTML form elements 'display only' - non-interactive

I'm working on a dynamic form builder, where the user can add different blocks of content to a page (buttons, text inputs, paragraphs of text, images etc), which they can later publish and it will be a simple HTML form they can use.
For the 'preview' section of this application (where they are adding different blocks of content and modifying the content and look of it), it occurs to me that the simplest way to do this, is to just display the end product HTML itself and that way I'm more or less guaranteed that what is displayed in the preview matches what is displayed in the actual form.
Where this is important is with obscure styling quirks, such as the behaviour of buttons with display:block.
However, I don't want the the preview to be actually interactive like the real form would. That is, I don't want the following behaviours:
Inputs receiving focus and being able to insert content
Buttons having click animations
Clicking links navigating
Default hover styles occuring.
Also, in terms of accessibility, it might be very confusing if there are a bunch of input that don't do anything appearing on the screen.
Is there a browser native/standard way to do this?
My fallback will likely be to disable all of the elements. But this won't work for links for example.
An alternative might be to put an invisible div on top of the form, which captures all of the click events. But I don't like this from an accessibility POV.
Is using the role="presentation" intended for this?
Code Example
As an example here, see some sample code here: https://codepen.io/dwjohnston/pen/qBrGPmr?editors=1111
Now for this, I have the divs with role="button" - These buttons are intended to be clickable, - when you click them the side panel will show content configuration eg, the default value of the input, label, etc.
Already, there is a problem - interactive content is not permitted inside a button.
But also, I shouldn't be able to tab to those controls, (now I can manually add tabindex = "-1", but that's not the complete picture). I don't want to confuse screen readers etc.
INFO
There is an edit to this question that addresses the specific issues OP has with their current implementation. I have left this first part here as my original answer.
I don't want the the preview to be actually interactive like the real form would.
Why? Having the form be interactive would be great for all users (taking into account that some functionality needs to not work fully in a preview).
Let people see what default hover styles look like, what clicking links would do (i.e. click the link and alert says "would navigate to xxx page") etc.
I understand not wanting to be able to navigate to new pages and submit the form (any "save" or "update" actions plus any "navigation" actions) but everything else I believe should be able to work in a preview.
Also, in terms of accessibility, it might be very confusing if there are a bunch of input that don't do anything appearing on the screen.
It would be far more confusing if a preview appeared on screen but then I couldn't navigate to the buttons, links etc.
How would that behave for a screen reader user? i.e. would you hide all elements using aria-hidden="true" (in which case how would they test the page?).
My fallback will likely be to disable all of the elements. But this won't work for links for example.
This is really one of the worst ways you could handle it, disabled inputs generally can't receive focus so keyboard users would suffer when testing.
Plus if some elements in the final production form are disabled until a certain field is filled in (for example) then how could a user test that in your end form?
Also if you intercept the navigation for a link without explaining why the link doesn't work that could also cause confusion. (and yet again could that link open in a new window in "preview" mode if you explain that to end users? Obviously depends if it is a static link etc. but just a thought on a way users can check any custom links point to the right place).
Proposed Solution
I would say you need two versions of the finished form. The "real world" one and the "preview" one.
The HTML can be (read "should be") identical but you need to implement JavaScript handlers to disable the functionality you don't want to be active.
There is nothing wrong with having an editing tool only work with JavaScript if that is one of your concerns, as long as you provide a warning to end users that the tool requires JavaScript to work. (The difference between a publishing tool and an end user experience is you can be much more reliant on JavaScript.)
For example: Let's say you have a <button> that when clicked should add a new row to the form (in the production version of the form) and for whatever reason you do not want this functionality to be active in the preview version.
In that case in the preview / demo version of the form when you click this button an alert could be shown that says "will add a new row to the form".
That way screen reader users and keyboard only users can test the form without you needing to do too much extra work (and can also see if the form has usability issues for keyboard users while they are at it!)
I think this would be the most clear for everybody and a much better user experience.
You just need to think of navigating in and out of preview mode (Esc to close for example) and quick edits (when you preview the form give the option to focus the previously focused element if the forms are particularly long, keyboard only users will thank you for this! The same for when you go back to the edit, put focus back on the last edited item).
Further reading
From an accessibility perspective WCAG isn't what you are looking for in this scenario, Authoring Tool Accessibility Guidelines (ATAG) is.
This is a little known set of guidance on how to create editors, WYSIWYGS etc. etc.
As with all W3C guidance it is a heavy read but if you understand the core principles it will guide you to good decisions and you can always ask here if you need clarity on some of the individual points that aren't clear :-).
EDIT: How could you achieve an accessible interface with the current design
The issues that you have within the codepen you linked and their solutions are as follows:
Stop interactive items receiving focus
As you wrap each element you have correctly diagnosed your biggest issue which is nested interactive elements.
The solution to this is quite straight forward: Give every interactive element a tabindex="-1" as you said. This makes sure they cannot be focused incorrectly.
Make sure the actual wrapper item can be focused and activated
Then we just need to make sure that the wrapper .content-item has tabindex="0" so it is added to the focus order.
We also need to capture the Enter and the Space keys and ensure our panel is activated with them also.
Visual focus indicator
I also added an outline to the wrapper "button" so that visual focus indicators are available.
So that essentially fixes normal keyboard navigation issues, the next issue is how a screen reader will interpret nested buttons, inputs etc.
Screen reader corrections
Here I would also go simple, hide the button, input etc. entirely from a screen reader and instead explain what element is inside.
Effectively we make the button invisible and instead describe the contents of the .content-item.
To hide the element we use aria-hidden="true"
To announce something meaningful we can use some visually-hidden (screen reader only) text inside a <span>. This will be far more robust that using aria-label with such a complex application.
make the application behave well with a mouse
Final challenge - stop mouse events.
Luckily pointer-events: none has really good support and even on the few browsers that don't support it being able to click into an input isn't the end of the world (we have fixed it for keyboard users)
Example with all issues resolved:
This solves all of the issues with your selection method.
Please note it doesn't take into account accessibility errors of the components themselves (for example the <input> having no <label> etc.) but I assume that is just because it is an example.
The only thing you need to work out is how to generate the visually hidden text describing the item and the .content-info "button" action.
document.addEventListener("DOMContentLoaded", function () {
const items = document.getElementsByClassName("content-item");
const rightPanel = document.getElementById('right-panel');
for (let i = 0; i< items.length; i++) {
const item = items[i];
item.addEventListener("click", (e) => {
console.log(e.target);
const id = e.target.dataset.id;
rightPanel.innerHTML = id;
});
// ADDED this to capture the Enter and Space presses on our wrapper button
item.addEventListener("keydown", function(e){
if(e.keyCode == "32" || e.keyCode == "13"){
console.log(e.target);
const id = e.target.dataset.id;
rightPanel.innerHTML = id;
}
});
}
});
.main {
display: flex;
flex-flow: row nowrap;
}
.left {
flex: 1 1 auto;
}
.right {
flex: 1 1 auto;
}
.content-item {
margin-top: 20px;
width: 600;
border: solid 2px blue;
cursor: pointer;
}
/* ADDED a focus indicator so keyboard users know where they are */
.content-item:focus{
outline: 4px solid #333;
}
/* ADDED to stop pointer events reaching the input, button etc. */
input, button{
pointer-events: none;
}
/* ADDED the visually hidden class so we can provide meaningful text to screen reader users */
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
<div class ="main">
<div class ="left">
<!-- Added `tabindex="0"` so the wrapper is focusable by keyboard -->
<div class="content-item" role="button" data-id="item-1" tabindex="0">
<!-- added `aria-hidden="true"` and `tabindex="-1"` to hide the input from screen readers and make sure it cannot be focused by keyboard, I also added `role="presentation"` just for good measure, although it shouldn't be needed. -->
<input type="text" aria-hidden="true" tabindex="-1" role="presentation">
<!-- Added this span that explains the action that the "content-item button" would perform if clicked. You need to come up with something meaningful for the contents of this -->
<span class="visually-hidden">Edit input [input identifier]</span>
</div>
<div class="content-item" role="button" data-id="item-2" tabindex="0">
<button aria-hidden="true" tabindex="-1" `role="presentation"`> I am a button</button>
<span class="visually-hidden">Edit button [button identifier]</span>
</div>
</div>
<div class ="right" >
<h2> Right panel</h2>
<div id ="right-panel">
</div>
</div>
</div>
You might want to look into the inert attribute. It is not supported by any browser at the moment, but there are polyfill libraries.
The idea is that marking this on any element will make it and all its children non-interactive and invisible for accessibility purposes.
You can read some background and download the library here:
https://github.com/WICG/inert
Try this
$(document).ready(function(){
var demoPage = $('div.demoPage');
demoPage.find('a').attr('href','#');
demoPage.find('button').attr("disabled", true)
})
div {
padding: 20px;
margin: 20px;
background: #eee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="no-copy">
<p>You can't click me.</p>
</div>
<div class="demoPage">
<a href="www.google.com" readonly="" class="no-copy">
It is a link
</a>
<button> It is a button</button>
</div>
<!--you can do this-->
<input type="text" id="input" disabled>
<script>
document.getElementById('input').disabled = true;
</script>
You can do that very simple by adding some css classes:
<div class="content-item disable-control" role="button" data-id="item-1">
<input type="text" />
</div>
<div class="content-item disable-control" role="button" data-id="item-2">
<button> I am a button</button>
</div>
^^ I added an additional "disable-control" class
.content-item.disable-control * {
pointer-events: none;
cursor: inherit;
user-select: none;
}
.content-item.disable-control *::selection {
background: transparent;
}
Make sure to add some browser-specifix css if needed, e.g.
*::-moz-selection
.. and of course, you can modify my code to apply the class only once (for the whole left pane) and not for each control seperately
Add the disabled attribute to all form elements that you want to disable.

keyboard TAB selection is not visible

I have an angular application, when I use keyboard TAB to move around the elements, current focused element is not highlighting.
This is how it looks like when I TAB to an element
This is when I then click on space to expand the accordionTab
I then added the following CSS but it's working only on mouse hover BUT not on tab selection.
::ng-deep {
.ui-accordion-header:hover, .ui-accordion-header:active, .ui-accordion-header:focus {
border: solid #00a1cf 1px !important;
}
}
I had been testing, it is working when I force select focus in chrome developer tools but not when I keyboard tab select.
I am unable to figure out why its not highlighting when focused using keyboard TAB. Can anyone help me out? Thanks in advance :)
What does the markup look like? Normally when tabbing to focus the elements that have focus by default are:
a (anchors)
buttons
inputs
textareas
If you have a different type of element such as a div, you can try and give it focus by adding tabindex to your markup.

Setting a button border-radius makes for focus on click

I'm seeing some odd behaviour concerning standard HTML buttons on Chrome. A standard button does not add an outline when clicked; only on focus through keyboard.
<button type="button">Works as expects</button>
As soon as I add styling with border-radius, the button will get an outline when clicked.
<button type="button" style="border-radius: 5px;">Focus on click</button>
Does anyone know what makes the button behave this way? And how can I make sure that the outline only gets added on keyboard navigation using the border-radius?
In response to the first part of the question:
If you right click on the round button, click inspect, and click the computed tab you can see that by adding styling it has overridden the platform-native styling:
-webkit-appearance: button;
has changed to:
-webkit-appearance: none;
the button's background-color change (when you hold down click) is also lost.

Blue highlight when hovering in drop down menu

Is there a way to change the blue highlight color when hovering in a drop down menu? I'm using the drop-down list on my page. I have a drop down menu that allows you to choose the topic.
I would greatly appreciate any help or feedback on this topic.
That blue colour is called an outline, and is used for accessibility reasons.
For example, when you press the tab key to move between form elements, an outline is commonly used so the user knows what element is currently selected.
You can remove this outline with the following CSS:
select:focus {
outline: none;
}
However, It is not recommended to remove this. If you must, you should provide an alternative style by using a background colour, changing the text colour, or provide a custom outline instead of the browser default.
ex:
select:focus {
outline: 2px solid red;
}
.dropdown-item.active, .dropdown-item:active {
background-color: red;
}
These are the Bootstrap classes that need to be overwritten if you wish to change the highlighted background colour when you hover over the dropdown item (i.e. when it is "active").
The classes can be discovered by opening up the Elements section within Google Dev Tools (F12) and then highlighting the element that you wish to restyle. Finding the active states of classes can be a little more tricky and may require a little more digging into the HTML.

How to remove CSS mousedown effects

I have this problem in Safari and Chrome but not in IE.
When I click a button the mousedown event triggers some kind of CSS rule which makes it slightly wider.
Because of this it drops down onto the next row and the click event is not triggered.
It stays on the next row until the mouse button is released.
I'm working on a large existing site and it's difficult to isolate all the CSS, but I think this could be due to an effect inherent in the browser(s).
Is there a CSS way to stop any effects occuring when the button is clicked?
Thanks for your help.
This is the CSS I have found for :active / :hover.
I don't think this could cause it!
a:hover, a:active
{
text-decoration: none;
}
(The button is an image inside an anchor)
Open your page with Chrome. Right click on the element and select inspect element. On the right handside corner of the inspect element handler, you will see few icons.
Click on the middle one(Which is having a arrow. When you hover it a label will display as "Toggle element State").
Change the element state to active (and to focus if it didn't change anything), and now you will be able to see what css rules are used to apply those changes to your button(It can be a padding or width).
Since now you know what the rule is, you can undo it using another rule (Or using javascript). It's hard to say how to remove the effects without knowing what the effects are.
you can declare a class in css name it for exemple abortmousedowncss :
.abortmousedowncss{
width:yourwidth; !important /* this dont allow any css to overide it ;)*/
}
and you can apply it after with jquery like this :
$('#yourbutton').addClass("abortmousedowncss");