using :focus pseudo class on li or other element else than a,input,button, etc
That's simple: just add a tabindex
attribute to the elements which normally don't receive focus.
Make :focus change css of another class
Using pseudo-classes (such as :hover
or :focus
) to modify other elements can only be done if the other elements are siblings or children of the element which has the pseudo-class. That's because CSS child/sibling selectors are fairly restrictive.
You can use the >
selector to select a direct child, and the +
selector to select a direct sibling. For example, if you have the following HTML:
<form>
<input type="text" />
<input type="submit" />
</form>
<p class="arbitrary">
This is an arbitrary element. It is neither a child nor sibling of
the text field. It cannot be selected as a result of a pseudo-class
action on the textfield using CSS, but can be selected using
client-side scripting such as JavaScript.
</p>
You could style the button when the text field has focus (because it is a direct sibling of the text field), but there is no possible way to style the arbitrary paragraph as a result of the text field receiving focus (because it is neither a child nor sibling, it is the sibling of a parent) without using client-side scripting (JavaScript, jQuery, etc.).
This CSS would style the submit button, and can be altered to select any direct or indirect child or sibling:
input[type="text"]:focus + input[type="submit"] {
/* some sweet CSS */
background-color:green;
}
Using Javascript, of course, you have much greater flexibility. The focusin
and focusout
events can be used to toggle CSS classes. Here's an example that demonstrates both the CSS and JavaScript techniques of achieving this.
function setFocused() {
document.querySelectorAll('.arbitrary').forEach((result) => {
result.classList.add('focused');
});
}
function unsetFocused() {
document.querySelectorAll('.arbitrary').forEach((result) => {
result.classList.remove('focused');
});
}
document.querySelectorAll('input[type="text"]').forEach((result) => {
result.addEventListener("focusin", setFocused);
result.addEventListener("focusout", unsetFocused);
});
input[type="text"]:focus + input[type="submit"] {
/* some sweet CSS */
background-color: green;
}
.arbitrary.focused {
/* even more sweet CSS */
color: red;
}
<form>
<input type="text" />
<input type="submit" />
</form>
<p class="arbitrary">
This is an arbitrary element. It is neither a child nor sibling of
the text field. It cannot be selected as a result of a pseudo-class
action on the textfield using CSS, but can be selected using
client-side scripting such as JavaScript.
</p>
List item is not getting focus even though I am using focus()
It looks like adding a tabindex might work. Add this to the attributes.
lItem.setAttribute('tabindex', index);
Got the idea from here. Worked for some people not all.
Apply same effect to all elements with the same tabindex on focus of one of them
This selector does the trick:
li[tabindex='1']:focus ~ li[tabindex='1'], li[tabindex='1']:focus {
background: black;
color: white;
}
Here's an example.
It only selects both when you focus on the first one though.
This only works in CSS3 since we're using the general sibling selector.
When the first one is focused, it selects the second one with the same tabindex
and adds the background. The second li[tabindex='1']:focus
is to apply the background to the currently focused one too.
The general sibling selector can only select succeeding elements with the same parent. CSS can't travel up the DOM, unfortunately. For this reason, the only way to have it work backwards too would be to use Javascript.
Can I use a :before or :after pseudo-element on an input field?
:after
and :before
are not supported in Internet Explorer 7 and under, on any elements.
It's also not meant to be used on replaced elements such as form elements (inputs) and image elements.
In other words it's impossible with pure CSS.
However if using jquery you can use
$(".mystyle").after("add your smiley here");
API docs on .after
To append your content with javascript. This will work across all browsers.
How to remove focus around buttons on click
I found this Q and A on another page, and overriding the button focus style worked for me. This problem may be specific to MacOS with Chrome.
.btn:focus {
outline: none;
box-shadow: none;
}
Note though that this has implications for accessibility and isn't advised until you have a good consistent focus state for your buttons and inputs. As per the comments below, there are users out there who cannot use mice.
Using :focus to style outer div?
While this can't be achieved with CSS/HTML alone, it can be achieved with JavaScript (without need of a library):
var textareas = document.getElementsByTagName('textarea');
for (i=0;i<textareas.length;i++){
// you can omit the 'if' if you want to style the parent node regardless of its
// element type
if (textareas[i].parentNode.tagName.toString().toLowerCase() == 'div') {
textareas[i].onfocus = function(){
this.parentNode.style.borderStyle = 'solid';
}
textareas[i].onblur = function(){
this.parentNode.style.borderStyle = 'dashed';
}
}
}
JS Fiddle demo.
Incidentally, with a library, such as jQuery, the above could be condensed down to:
$('textarea').focus(
function(){
$(this).parent('div').css('border-style','solid');
}).blur(
function(){
$(this).parent('div').css('border-style','dashed');
});
JS Fiddle demo.
References:
getElementsByTagName()
.onfocus
.onblur
.parentNode
.tagName
.toString()
.toLowerCase()
.style
.focus()
.blur()
.parent()
.css()
.
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
You could also pass the content to the pseudo element with a data attribute and then use jQuery to manipulate that:
In HTML:
<span>foo</span>
In jQuery:
$('span').hover(function(){
$(this).attr('data-content','bar');
});
In CSS:
span:after {
content: attr(data-content) ' any other text you may want';
}
If you want to prevent the 'other text' from showing up, you could combine this with seucolega's solution like this:
In HTML:
<span>foo</span>
In jQuery:
$('span').hover(function(){
$(this).addClass('change').attr('data-content','bar');
});
In CSS:
span.change:after {
content: attr(data-content) ' any other text you may want';
}
Related Topics
Set Textfield Height Material-Ui
How to Solve the Table Row Background Image Problem, in Chrome, in Multi Celled Tables
Css: How Is Height of Block-Elements Calculated
What Is That Thing Between CSS "Selectors" Called
Why Does Box-Sizing: Border-Box Still Show the Border with a Width of 0Px
Reading Documents CSS in Chrome Extension
Remove 3D Press Effect Internet Explorer Button
Is There a SASS Rule for Outputting a Descendant to the Root
Conditional CSS Rule Targeting Firefox Quantum
How to Build a String in a Loop for a Dynamic Gradient
Hide All Elements Except One Div for Print View
Clamping Lines Without '-Webkit-Line-Clamp'
Clip-Path on Chrome Leaves a Strange Line on the Edge
Input[Type=Number] Placeholder Color in Ff29+
How to Change a Background Image Opacity Without Changing on Div Content
How to Get Rid of Unwanted Space Between Inline-Block Columns
Javafx: Cannot Set Font Size Programmatically After Font Being Set by CSS