Perform action when focused - html

I have 3 divs. 2 of them change their color when focused. Can also an action be performed on another div when 2 of them get focused?
div {
border: 1px solid;
margin: 5px;
width: 300px;
height: 50px;
padding: 2px;
}
.myClass:focus {
background-color: yellow;
outline: none;
}
<div class="myClass" tabindex="-1">
Focus me!
</div>
<div class="myClass" tabindex="-1">
You can focus me too!
</div>
<hr />
<div class="anotherClass">
I cannot be focused, but want to change my color, when one of the other divs above me get focused.
</div>
So when 1 of the 2 upper divs get focused I want the 3rd div at the bottom to change its color.
Here you can have a look: https://jsfiddle.net/ogpvvwtg/

Sure, you can use the general sibling selector ~
.myClass:focus ~ .anotherClass {
background-color: red;
outline: none;
}
div {
border: 1px solid;
margin: 5px;
width: 300px;
height: 50px;
padding: 2px;
}
.myClass:focus {
background-color: yellow;
outline: none;
}
.myClass:focus ~ .anotherClass {
background-color: red;
outline: none;
}
<div class="myClass" tabindex="-1">
Focus me!
</div>
<div class="myClass" tabindex="-1">
You can focus me too!
</div>
<hr />
<div class="anotherClass">
I cannot be focused, but want to change my color, when one of the other divs above me get focused.
</div>

you can do this with a little bit of javascript which might give you more control of the things you want to color.
colorDiv3 = function() {
window.document.getElementById("div3").style.backgroundColor = "lightGreen";
}
div {
border: 1px solid;
margin: 5px;
width: 300px;
height: 50px;
padding: 2px;
}
.myClass:focus {
background-color: yellow;
outline: none;
}
<div class="myClass" tabindex="-1" onFocus="colorDiv3()">
Focus me!
</div>
<div class="myClass" tabindex="-1" onFocus="colorDiv3()">
You can focus me too!
</div>
<hr />
<div id="div3" class="anotherClass">
I cannot be focused, but want to change my color, when one of the other divs above me get focused.
</div>

You can also accomplish this using JavaScript:
First give the divs IDs:
<div id="topDiv" class="myClass" tabindex="-1">
etc...
Then you can find them with:
var top_div = document.getElementById('top_div');
var middle_div = document.getElementById('middle_div');
var bottom_div = document.getElementById('bottom_div');
Assign an event listener to the objects. This allows you to call a function when an element is focused:
top_div.addEventListener("focus", changeBottomDivColor);
middle_div.addEventListener("focus", changeBottomDivColor);
And finally, the function to actually change the color:
function changeBottomDivColor() {
bottom_div.style.backgroundColor = "red";
}

Related

How to not execute parent's :hover on child :hover

When the .post-item <div> is hovered I want to execute some specific styles (change background-color and cursor) but I don't want this to happen if the .rating-wrapper <div> is hovered too. This happens because I want the .rating-wrapper to do something different than the hover of its parent. Basic question: How to do only child's hover, ignoring the parent's hover
HTML:
<div class="post-item">
<div class="rating-wrapper">
<div class="upvote">
<img src="/images/upvote_arrow.png" alt="upvote" />
</div>
<div class="rating"></div>
<div class="downvote">
<img src="/images/downvote_arrow.png" alt="downvote" />
</div>
</div>
<span class="owner-data">
<img src="" alt="" class="owner-avatar" />
<span class="owner-username"></span>
</span>
<span class="creation-date"></span>
<div class="title"></div>
</div>
Since you want to change the style of the parent element based on a pseudo-class of the child element, this isn't really possible with CSS alone today.
You can do it with the :has() pseudo-class but that is currently only supported in Safari (with support for Chrome a few months away and no sign of it in Firefox, Edge, Opera or elsewhere).
#parent {
background: white;
border: solid black 1px;
padding: 2em;
max-width: 50%;
margin: auto;
}
#parent:hover:not(:has(#child:hover)) {
background: orange;
}
#child {
background: #aaa;
border: solid black 1px;
padding: 2em;
}
#child:hover {
background: green;
}
<div id="parent">
<div id="child"></div>
</div>
For a more reliable approach, you should probably look at adding a splash of JavaScript to the mix.
Use mouseenter and mouseleave events to modify the classes of the parent element, then reference the class in your stylesheet.
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
const enter = event => parent.classList.add('child-hover');
const leave = event => parent.classList.remove('child-hover');
child.addEventListener('mouseenter', enter);
child.addEventListener('mouseleave', leave);
#parent {
background: white;
border: solid black 1px;
padding: 2em;
max-width: 50%;
margin: auto;
}
#parent:hover:not(.child-hover) {
background: orange;
}
#child {
background: #aaa;
border: solid black 1px;
padding: 2em;
}
#child:hover {
background: green;
}
<div id="parent">
<div id="child"></div>
</div>
You can use this CSS Selector,
.post-item>:not(.rating-wrapper):hover {
background-color: white;
}
This will select all immediate children of .post-item which are not .rating-wrapper.
To change the block of the remaining items background color, you can enclose them in another div.
There is a css property called not property.The syntax is like:
:not(element) {
// CSS Property}
If you want to learn more, please visit this link:
https://www.geeksforgeeks.org/how-to-exclude-particular-class-name-from-css-selector/
The pointer-events CSS property sets under what circumstances (if any) a particular graphic element can become the target of pointer events.
try:
pointer-events: none
you can read more here: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events

How do I highlight proper border boxes applying focus on stacked input fields?

I have an application with "stacked" input fields like so:
As you can see from the image, when a field is receiving focus, I only want the borders of that particular input element to be highlighted. I also want to avoid a particularly thick border by having both a top and bottom border that corresponds to the same middle lines.
Here is a Fiddle: https://jsfiddle.net/3nL426uy/
Creating the stacked input fields and applying borders is not a problem. I simply remove the bottom border on all the input fields and on the last field, I apply a bottom border.
The issue comes in when I want to apply the focus styles. As it stands currently, simply applying a different border color (used red in the example to clearly show the contrast) results in a red bottom border and a gray top border of the input field below it. Now, I may be able to use an Id selector on that particular field and apply a full border, however, how do I remove the top border of the input field below it?
const inputWrappers = document.querySelectorAll(".input-wrapper")
const wrappers = [...inputWrappers]
wrappers.forEach(wrapper => {
wrapper.addEventListener('focusin', (event) => {
event.target.classList.add('selected');
});
wrapper.addEventListener('focusout', (event) => {
event.target.classList.remove('selected');
});
})
.wrapper {
display: flex;
flex-direction: column;
}
.item {
width: 300px;
height: 30px;
padding: 5px 15px;
border: 1px solid gray;
border-radius: 0;
border-bottom: 0;
}
/* Remove the default input focus-visible outline */
.item:focus-visible {
outline: 0;
}
.input-wrapper:last-child .item {
border-bottom: 1px solid gray;
}
.selected {
border: 1px solid red;
}
<div class="container">
<div class="input-wrapper" >
<input class="item" placeholder="Enter item..." />
</div>
<div class="input-wrapper">
<input class="item" placeholder="Enter item..." />
</div>
<div class="input-wrapper">
<input class="item" placeholder="Enter item..." />
</div>
<div class="input-wrapper">
<input class="item" placeholder="Enter item..." />
</div>
</div>
I'm not sure why you've used any JavaScript here? You can just set a new focus style in the :focus-visible CSS rule, you don't need to add and remove a class when the inputs receive and lose keyboard focus.
To collapse the margins, I'd recommend applying margin-top: -1px; to each of the siblings with borders. Then, to make sure the current one has its borders on top, you can give it a z-index above its siblings. I've also added a couple of lines here to ensure that z-index won't escape the .wrapper element by creating its own stacking context.
.wrapper {
display: flex;
flex-direction: column;
/* Create a new stacking context to contain z-index */
isolation: isolate;
transform: scale(1);
}
.item {
width: 300px;
height: 30px;
padding: 5px 15px;
border: 1px solid gray;
border-radius: 0;
}
/* Remove the default input focus-visible outline */
.item:focus-visible {
outline: 0;
border-color: red;
/* Setting a z-index on the focused element ensures its borders are on top */
position: relative;
z-index: 1;
}
.input-wrapper {
/* A negative top margin lets the borders collapse */
margin-top: -1px;
}
.container {
/* Offset the negative top margin of the items */
margin-top: 1px;
}
<div class="container">
<div class="input-wrapper">
<input class="item" placeholder="Enter item..." />
</div>
<div class="input-wrapper">
<input class="item" placeholder="Enter item..." />
</div>
<div class="input-wrapper">
<input class="item" placeholder="Enter item..." />
</div>
<div class="input-wrapper">
<input class="item" placeholder="Enter item..." />
</div>
</div>
you can add 'selected' class to the div element;
wrappers.forEach(wrapper => {
wrapper.addEventListener('focusin', (event) => {
event.target.parentNode.classList.add('selected');
});
wrapper.addEventListener('focusout', (event) => {
event.target.parentNode.classList.remove('selected');
});
})
and then use sibling selector x + y to select below div, remove the top boarder.
.selected .item{
border: 1px solid red;
}
/* remove below div top border */
.selected+.input-wrapper .item{
border-top: 0;
}
.input-wrapper:last-child.selected .item{
border-bottom: 1px solid red;
}
here is the whole example
https://jsfiddle.net/2tuzi/koqrcxaw/

CSS overflow not obeying padding

I have a set of HTML elements that I need to style, which I can't change the structure of in any way (yeah, I know).
The HTML has a div that contains two nested spans. The div has padding and the overflow is hidden. The width of the div is set programatically and applied as an inline style.
I would like the text contained within the inner span to be clipped, but still retain the right hand padding as specified on the containing div.
After some research, it appears that the standard approach to this is to use a second nested div but, as I mentioned, I can't change the structure of the HTML.
Currently I have:
<!-- This is what I have to work with (I can't change the structure of this HTML!) -->
<div class="c1" style="width: 100px;">
<span class="c1-inner">
<span class="c1-inner-2">
122333444455555666666777777788888888999999999
</span>
</span>
</div>
<!-- This is how I want the HTML above to display -->
<div class="c2" style="width: 100px;">
<div class="c2-inner">
122333444455555666666777777788888888999999999
</div>
</div>
Styled by the following CSS:
.c1 {
border: 1px solid red;
border-radius: 4px;
background-color: #c0c0c0;
padding: 0 13px 0 13px;
overflow: hidden;
}
.c1-inner {
// No relevant styles here yet
}
.c1-inner-2 {
// No relevant styles here yet
}
.c2 {
border: 1px solid red;
border-radius: 4px;
background-color: #c0c0c0;
padding: 0 13px 0 13px;
}
.c2-inner {
overflow: hidden;
}
A jsFiddle is available here
I need to style the top "button" so that it looks like the second one only using CSS. I have reached the limits of my CSS skills and any help would be very much appreciated.
A simple fix. Most important bit: you can make a span have a display value of block rather than inline, which is its default.
Here's the relevant CSS you need and a working example:
.c1 {
border: 1px solid red;
background-color: #c0c0c0;
padding: 0 13px 0 13px;
}
.c1-inner {
overflow: hidden;
display: block;
}
.c2 {
border: 1px solid red;
background-color: #c0c0c0;
padding: 0 13px 0 13px;
}
.c2-inner {
overflow: hidden;
}
We want this<br>
<!-- This is what i Have to work with -->
<div class="c1" style="width: 100px;">
<span class="c1-inner">
<span class="c1-inner-2">
122333444455555666666777777788888888999999999
</span>
</span>
</div>
<!-- This displays how i want the html above to display -->
<br>
to look like this<br>
<div class="c2" style="width: 100px;">
<div class="c2-inner">
122333444455555666666777777788888888999999999
</div>
</div>
<br>
but cannot change the structure of the html!

CSS selector :active not working on child element click in IE8

I have the following HTML structure:
<div id="ctr__Wrapper" class="wrapper">
<div id="ctr" class="control clickable">
<img src="logo.png">
</div>
</div>
And the following CSS for this:
.control
{
border: 1px solid #000;
background-color: #666;
padding: 20px;
}
.control:active
{
background-color: #bbb;
}
When I click on the element "ctr", I see the background color changing, but when I click on the image itself, it doesn't. This works fine in Firefox, but not in IE8. Is there something I can do to solve this in CSS.
The working example can be seen here:
http://jsfiddle.net/miljenko/DNMPd/
You could use a background image instead of a real image.
html:
<div id="ctr__Wrapper" class="wrapper">
<div id="ctr" class="control clickable">
</div>
</div>
css:
.control
{
border: 1px solid #000;
background-color: #666;
height: 40+height-of-logopx;
background-image:url(logo.png); background-repeat:no-repeat;
background-position:20px 20px;
}
.control:active
{
background-color: #bbb;
}
because < ie9 don't support :active on anything other than anchor elements. here's your fiddle, that should work in ie8 http://jsfiddle.net/jalbertbowdenii/DNMPd/12/

Remove ':hover' CSS behavior from element

I have CSS that changes formatting when you hover over an element.
.test:hover { border: 1px solid red; }
<div class="test">blah</div>
In some cases, I don't want to apply CSS on hover. One way would be to just remove the CSS class from the div using jQuery, but that would break other things since I am also using that class to format its child elements.
Is there a way to remove 'hover' css styling from an element?
One method to do this is to add:
pointer-events: none;
to the element, you want to disable hover on.
(Note: this also disables javascript events on that element too, click events will actually fall through to the element behind ).
Browser Support ( 98.12% as of Jan 1, 2021 )
This seems to be much cleaner
/**
* This allows you to disable hover events for any elements
*/
.disabled {
pointer-events: none; /* <----------- */
opacity: 0.2;
}
.button {
border-radius: 30px;
padding: 10px 15px;
border: 2px solid #000;
color: #FFF;
background: #2D2D2D;
text-shadow: 1px 1px 0px #000;
cursor: pointer;
display: inline-block;
margin: 10px;
}
.button-red:hover {
background: red;
}
.button-green:hover {
background:green;
}
<div class="button button-red">I'm a red button hover over me</div>
<br />
<div class="button button-green">I'm a green button hover over me</div>
<br />
<div class="button button-red disabled">I'm a disabled red button</div>
<br />
<div class="button button-green disabled">I'm a disabled green button</div>
Use the :not pseudo-class to exclude the classes you don't want the hover to apply to:
FIDDLE
<div class="test"> blah </div>
<div class="test"> blah </div>
<div class="test nohover"> blah </div>
.test:not(.nohover):hover {
border: 1px solid red;
}
This does what you want in one css rule!
I would use two classes. Keep your test class and add a second class called testhover which you only add to those you want to hover - alongside the test class. This isn't directly what you asked but without more context it feels like the best solution and is possibly the cleanest and simplest way of doing it.
Example:
.test { border: 0px; }
.testhover:hover { border: 1px solid red; }
<div class="test"> blah </div>
<div class="test"> blah </div>
<div class="test testhover"> blah </div>
add a new .css class:
#test.nohover:hover { border: 0 }
and
<div id="test" class="nohover">blah</div>
The more "specific" css rule wins, so this border:0 version will override the generic one specified elsewhere.
I also had this problem, my solution was to have an element above the element i dont want a hover effect on:
.no-hover {
position: relative;
opacity: 0.65 !important;
display: inline-block;
}
.no-hover::before {
content: '';
background-color: transparent;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 60;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<button class="btn btn-primary">hover</button>
<span class="no-hover">
<button class="btn btn-primary ">no hover</button>
</span>
You want to keep the selector, so adding/removing it won't work. Instead of writing a hard and fast CSS selectors (or two), perhaps you can just use the original selector to apply new CSS rule to that element based on some criterion:
$(".test").hover(
if(some evaluation) {
$(this).css('border':0);
}
);