Using :Focus Pseudo Class on Li or Other Element Else Than A,Input,Button, etc

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



Leave a reply



Submit