css3 pointer-event NOT on child? - css

I have the folowwing structure
<div class='offline'>some text <button class='delete'>Delete</button></div>
Is it possible to disable the div with pointer-events: none but KEEP the button active ?
I tried with
div.offline:not(.delete) {
pointer-events: none;
}
No success. Any idea ?

You can disable events on the parent and reenable them on the child.
.parent {
pointer-events: none;
}
.child {
pointer-events: auto;
}
<div class='parent'>
foo
<button class='child'>bar</button>
</div>

Given this:
div.offline:not(.delete) {
pointer-events: none;
}
You are targeting divs with class offline, which don't have class delete.
Since your sole div doesn't have a delete class, it is targeted.
To target all descendant elements of div.offline that don't have the delete class, you would do this:
div.offline :not(.delete) { //note the space before ":not"
pointer-events: none;
}
However, that excludes text nodes. So both "some text" and the delete button would still receive pointer events.
Your only option is to create a default style for the parent, which is overridden by the child:
div.offline {
pointer-events: none;
}
div.offline .delete {
pointer-events: auto;
}

The documentation for the pointer-events: none;:
none
The element is never the target of mouse events; however, mouse events may target its descendant elements if those descendants
have pointer-events set to some other value. In these circumstances,
mouse events will trigger event listeners on this parent element as
appropriate on their way to/from the descendant during the event
capture/bubble phases.
https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
Note the emphasis added above.
So basically descendants should still have those events if you set them:
.offline .delete {
pointer-events: auto;
}

Related

Hover state on an element when mouse is over its container DIV

I'd need to recreate the following effect: hovering onto .card container, should trigger :hover also on .btn inside it.
Please, consider this example code: https://codepen.io/ldetomi/pen/ZEoNprQ
Ok, could be possible to use JS and trigger an 'hover' css class onto inner .btn, but this will force me to duplicate code for hover state of .btn, for :hover pseudo-state and .hover class. Or, in another way, I'd need to duplicate state of hover buttons, in case that is child of a DIV that has an 'hover' state.
Due to the thing that i have a complex style for hover state of buttons, I'd like to be able to trigger the same hover effect on it, also if hover is made onto father DIV in a smart way.
If, possible, I'd like to avoid something like this:
.btn {
&:hover {
background: red;
}
}
.card {
&:hover {
.btn {
background: red;
}
}
}
You can just add the below rule.
.card:hover > .btn {
background: red;
}
Edit :
You can club both hover rules together to prevent code duplication
.card:hover > .btn, .btn:hover
{
background:red;
}

can't drag element that has css property unset: all

It seems I'm not able to drag an element that has unset: all css property.
.my-component {
all: initial;
* {
all: unset;
}
}
I use these rules inside a chrome extension, on elements that are being injected in the user browser page (to prevent local style affecting my component). Unfortunately, elements are not draggable anymore.
Those elements have the draggable property on in html.
I tried pointer-events: auto;, -webkit-user-drag: auto;, user-select: all; but I still can't manage to make elements draggable.
There must be some properties I have to set back to normal.
If someone had an idea, I would highly appreciate any help on this topic.
Edit : see this codepen - https://codepen.io/thomaslh/pen/OgQNMz
Looks like you need to add 2 CSS properties. user-select and -webkit-user-drag
.el {
all: unset;
-webkit-user-drag: element;
user-select: none;
}
<div class="el" draggable="true">
drag
</div>

CSS div disappears before I'm able to execute the click event

I have the following CSS code:
#searchbar-wrapper input#header-searchbar:focus +
#search-dropdown-wrapper { display: block; }
The purpose is that a dropdown becomes visible when the user puts focus on a textbox.
The dropdown should by default be invisible though:
#searchbar-wrapper #search-dropdown-wrapper{ display: none; }
Now the problem is that when I try to select an item from the dropdown list (anchor href), the dropdown wrapper disappears before I'm actually able to execute the click event. This happens because there is no focus on the textbox anymore.
Is there an easy solution for my problem without requiring to change the entire code?
Thanks!
Edit: I've added the resulting HTML in an image, because it is being dynamically generated.
Edit2: Fiddle based on the fiddle made by #anpsmn: http://jsfiddle.net/thh9z99c/2/
I need a list with anchors because they represent a list with urls.
Use the CSS pseudo selector [:focus] and then extend it to the child element.
//CSS BLOCK
#searchbar-wrapper input#header-searchbar{
}
a{
display: none;
}
#searchbar-wrapper input#header-searchbar:focus>a { // use [:focus>a]
display: flex;
display: -webkit-flex;
}
It works with the pseudo-class active instead of focus:
#searchbar-wrapper input#header-searchbar:focus +
#search-dropdown-wrapper, #searchbar-wrapper input#header-searchbar +
#search-dropdown-wrapper:active { display: block; }
#searchbar-wrapper #search-dropdown-wrapper{ display: none; }
Fiddle: http://jsfiddle.net/thh9z99c/3/

Clicking a child doesn't trigger the parent's :active state in IE

I have found an irritating bug in IE 8-10 that prevents a parent's active state being triggered. It appears that if a child of the parent element is the target of the click event the active state on the parent element is not triggered.
Here is a working example. If you click the text inside the <li> the element wont change colour. If you click inside an <li> anywhere other than on the <p> child the element will turn blue.
This is a problem as it pretty much renders the css :active pseudo state useless in IE if the element has any children.
Has anyone encountered this problem before, and even better found a way round it?
Here's an easy workaround: add a css rule to the paragraph.
Working example
CSS
ul { list-style: none; }
li { height: 50px; margin-bottom: 4px; background: red; }
li:active { background: blue; }
p:active { background: blue; height: 100%;}
I have fixed the issue by preventing pointer-events on the child element. This way the :active state is triggered directly on the parent and doesn't need to be propagated. The only downside of this solution is you cannot attach an event listener (not even a css `:hover selector) to the child anymore. So you have to move all your event listeners to the parent.
.child { pointer-events: none; }
Here is jsFiddle https://jsbin.com/govelabuca/1/edit?css,output
Just uncomment the last line in css and compare the result in IE and other modern browser
You could add another CSS selector for the <p> tag so your
li:active { background: blue; }
will become
li:active, li p:active { background: blue; }
I would suggest you would use javascript or jquery for that when you click a child element, perform the active state of of the parent.
I've stumbled upon this on IE11. I was writing a drag-n-drop styling logic using this approach suggested by Martin.
In my case I have a row with td cell elements and using :active for the parent tr does the job for other browsers. For IE, I've added a CSS rule to target the cells (tr.myRowClass > td:active) and modified the if condition in my custom JS logic executed during the mousemove event handler of the cells:
if (style.getPropertyValue('cursor') == 'auto' || document.querySelectorAll(":active").length > 0) {
The remaining task is to find the target element:
Determine which element the mouse pointer is on top of in Javascript

css change style of an element on click

I have a list of elements, and i want to change a style of an element when one clicks on the list element(and that specific style to stay the same until the user presses another list item).
I tried using the 'active' style, but no success.
My code:
#product_types
{
background-color: #B0B0B0;
position: relative; /*overflow: hidden;*/
}
#product_types a:active
{
background-color:yellow;
}
but the element is 'yellow' only a millisecond, while i actually click on it...
Use the :focus pseudo class
#product_types a:focus
{
background-color:yellow;
}
See this example -> http://jsfiddle.net/7RASJ/
The focus pseudo class works on elements like form fields, links etc.
The reason it doesn't work in other browsers is related to the css focus specification. It states:
The :focus pseudo-class applies while an element has the focus
(accepts keyboard events or other forms of text input).
So it seems to work perfectly fine with text input fields or when you focus using the tab key. To make the above compatible with other browsers add the tabindex attribute to each element and this appears to fix the problem.
HTML:
<ul>
<li id = 'product_types'>First</li>
<li id = 'product_types'>Second</li>
</ul>
CSS:
#product_types {
background-color: #B0B0B0;
position: relative;
}
#product_types a:focus {
background-color:yellow;
}
JSFiddle Example

Resources