Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a selector to only affect the innermost :hover match with CSS only?

Tags:

html

css

hover

For a feature to manage custom layouts, I've created a little wizard with zone indication, to offer a chance on seeing which zone you're editing.

Since it's a nested layout, all containers have the same CSS class values. In order to only issue the innermost element I've written a short piece of JavaScript code. To be precise, it's this:

$outermostContainer.on("mousemove", function(event) {
    var $t = $(event.target).closest("table.dashboardLayoutOutline");
    $layoutWizardTables.removeClass("hovering");
    $t.addClass("hovering");
});

Sample case:

http://jsfiddle.net/w0sw9510/ (The solution is correct if you hover one of the child elements and the parent element does not have a yellow border, while if you hover the outer element only that will receive a yellow border)

Is this really a case where I can't do something with CSS only?

I somehow can't imagine I'm the only one who has a use for this.

I've looked into W3C + mozilladocs for CSS 2/3 selectors and no selector I've seen appeared to handle the case I need.

These days I mainly do backend, so I hope there's one of you who knows a trick for me.

Duplicate questions: While this problem is similar to my issue, I did not find it while searching because of its title. I am just going to leave it here so others will find their answer too in case they use the same search words.

like image 470
Dbl Avatar asked Aug 30 '25 16:08

Dbl


2 Answers

It doesn't seem possible with just CSS, because when a child element is hovered the parent element is hovered too (and pointer-events: none doesn't help). However JavaScript makes it pretty simple:

$('.zone').on('mouseover mouseout', function(e) {
    $(this).toggleClass('hovering', e.type === 'mouseover');
    e.stopPropagation();
});
.zone {
    margin: 10px;
    box-sizing: border-box;
    border: 5px solid transparent;
}

.zone.hovering {
    border: 5px solid yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="zone" id="parent" style='background-color: orange;'>
    <div class="zone" id="child1" style='background-color: red;'>a</div>
    <div class="zone" id="child2" style='background-color: blue;'>b</div>
</div>

Well, it's actually possible to do this in just CSS, but the solutions are not very flexible and generic, because it depends on the background color of the parent container:

.zone {
    margin: 10px;
    box-sizing: border-box;
    border: 5px solid transparent;
    position: relative;
}

.zone:hover {
    border: 5px solid yellow;
}

.zone > .parent-border {
    position: absolute;
    top: -5px; left: -5px; bottom: -5px; right: -5px;
    display: none;
    z-index: 1;
}

.zone > .zone {
    z-index: 2;
}

.zone > .zone:hover ~ .parent-border {
    border: 5px orange solid;
    display: block;
}
<div class="zone" id="parent" style='background-color: orange;'>
    <div class="zone" id="child1" style='background-color: red;'>a</div>
    <div class="zone" id="child2" style='background-color: blue;'>b</div>
    <div class="parent-border"></div>
</div>
like image 148
dfsq Avatar answered Sep 02 '25 05:09

dfsq


Now that the :has() pseudo-class is a thing, you can do something like this:

.item {
    margin-left: 12px;
    background-color: white;
}

.item:hover{
    background-color:blue;
}

.item:has(.item:hover) {
    background-color: white;
}
<div class="item">
    <p>Item 1</p>
    <div class="item">
        <p>Item 2</p>
        <div class="item">
            <p>Item 3</p>
            <div class="item">
                <p>Item 4</p>
            </div>
        </div>
    </div>
</div>
like image 38
JMather Avatar answered Sep 02 '25 06:09

JMather