1

Need to hover a div then action on another div, but the action DIVs is on top of the Hover Div, any idea to make this happen?

Thank you

Here is my code

a {
  display: block;
  padding: 8px 10px;
  border: 1px solid red;
  max-width: 20%;
}

.hover:hover ~ .action{
  background: yellow;
}


.hover1:hover ~ .action1{
  background: yellow;
}
<!--This one can -->
<a href="#" class="hover1">Hover</a>
<a href="#" class="action1">Action</a>

<br>
<br>

<!-- But this one cannot, i need this-->
<a href="#" class="action">Need This to be action</a>
<a href="#" class="hover">When Hover This</a>

<br><br>

Codepen link: https://codepen.io/YSLee/pen/OQNadN

Jared Chu
  • 2,757
  • 4
  • 27
  • 38
CanDiceYap
  • 29
  • 1
  • 8

5 Answers5

2

Just wrap them up and use flexbox's order (you need to let them in normal order - CSS can't go backwards - but invert them from CSS):

a {
  display: block;
  padding: 8px 10px;
  border: 1px solid red;
  max-width: 20%;
}

.hover:hover~.action {
  background: yellow;
}

.hover1:hover~.action1 {
  background: yellow;
}
.inverter {
  display: flex;
  flex-direction: column;
}
.inverter>*:last-child {
  order: -1;
}
<!--This one can -->
<a href="#" class="hover1">Hover</a>
<a href="#" class="action1">Action</a>

<br>
<br>

<!-- But this one cannot, i need this-->
<div class="inverter">
  <a href="#" class="hover">When Hover This</a>
  <a href="#" class="action">Need This to be action</a>
</div>
tao
  • 82,996
  • 16
  • 114
  • 150
  • you change html code. – Ehsan Feb 05 '18 at 04:51
  • 1
    @Ehsan, yes I did. But for the sake of exercise, let's take what you're suggesting to absurd and consider the following exercise: "*Turn the following code into a cool website without changing the markup: ``. Thanks in advance!"*. Let's not forget the role of markup and simply stick to best practices. – tao Feb 05 '18 at 05:03
2

If you can add a wrapper div to your HTML, you can use the hover on the wrapper to target the .action element, then disable pointer-events on the wrapper and reset it on the .hover element, so it doesn't work when hovering the other part.

a {
  display: block;
  padding: 8px 10px;
  border: 1px solid red;
  max-width: 20%;
}

.wrapper:hover > .action{
    background: yellow;
}

.wrapper{pointer-events:none;}

.hover{pointer-events:auto;}
<div class="wrapper">
        <a href="#" class="action">Need This to be action</a>
        <a href="#" class="hover">When Hover This</a>
</div><br/><br/>

<div class="wrapper">
        <a href="#" class="hover">regular Hover</a>
        <a href="#" class="action">Action</a>
</div><br/><br/>

<div class="wrapper">
        <a href="#" class="hover">Hover sandwich</a>
        <a href="#" class="action">Action</a>
        <a href="#" class="hover">Hover sandwich</a>
</div><br/><br/>

<div class="wrapper">
        <a href="#" class="action">multiple Action!</a>
        <a href="#" class="hover">Hover</a>
        <a href="#" class="action">multiple Action!</a>

</div>

Best part of this approach is that you can set simple, scalable rules that will apply correctly whatever the .hover and .action elements are positioned, even if using multiples :)

A noticeable limitation though, is that you'll loose pointer-events on the target element, so if you need to hover / click or whatever on them, this might not be the best approach.

So it all depends on your use case.

Another approach would be to set the :hover on the container, then reset the initial values on the target's :hover.

a {
  display: block;
  padding: 8px 10px;
  border: 1px solid red;
}

.wrapper{
  display:inline-block;
  width: 20%;
}

.wrapper:hover > .action{
    background: yellow;
}

.action:hover{
  background:initial !important;
  }
<div class="wrapper">
        <a href="#" class="action">Need This to be action</a>
        <a href="#" class="hover">When Hover This</a>
</div><br/><br/>

<div class="wrapper">
        <a href="#" class="hover">regular Hover</a>
        <a href="#" class="action">Action</a>
</div><br/><br/>

<div class="wrapper">
        <a href="#" class="hover">Hover sandwich</a>
        <a href="#" class="action">Action</a>
        <a href="#" class="hover">Hover sandwich</a>
</div><br/><br/>

<div class="wrapper">
        <a href="#" class="action">multiple Action!</a>
        <a href="#" class="hover">Hover</a>
        <a href="#" class="action">multiple Action!</a>
</div>

Notice with this alternative method you don't loose pointer-events on your .action, but you can't really have the 1 .hover, multiple .action as in the first method

Facundo Corradini
  • 3,825
  • 9
  • 24
  • Smart idea, I'll be using that in the future, – Hastig Zusammenstellen Feb 05 '18 at 05:16
  • @HastigZusammenstellen thanks! :) – Facundo Corradini Feb 05 '18 at 05:17
  • Cool. I think this would work well. – davecar21 Feb 05 '18 at 05:30
  • I like the idea. But you're losing all `pointer:events` in `.action`. So your solution is limited to anything that doesn't have links or other type of `pointer:events`. – tao Feb 05 '18 at 05:55
  • @AndreiGheorghiu of course, every technique has some limitations. For the intended use case (as far as I can tell) this might be valid, as he speaks of divs (although given anchors as example). Most of the times those links are gonna be on li items or something like that, so you can always reset pointer-events on the actual links as well. – Facundo Corradini Feb 05 '18 at 06:00
  • I think you're not really clear about what you're doing here. The moment you take the `pointer-event` from the parent, you lost the hover effect. So no, it won't work with anything that needs any `pointer-event`, because it's consumed. Which, by all standards, is a major limitation and you should clearly specify it in your solution. Other than that, congrats for thinking out of the box. – tao Feb 05 '18 at 06:07
  • @AndreiGheorghiu thanks for the input. I've added the warning to the answer, and provided an alternative, similar approach that won't break the pointer-events on the .action, but also has some limitations such as not supporting one .hover, multiple .actions as the previous one did. Flex is also an option, but it requires specific markup to set the orders / flex direction, which might be a luxury dynamic environments won't have, besides having to change the order in the actual html, so not the best for accessibility. So as I said, every technique has some limitations. Cheers and thanks again! – Facundo Corradini Feb 05 '18 at 06:29
0

This is impossible in pure css,because css can't get backward,so you must change html code or you must get help of jquery,like this:

$(document).ready(function(){

    $('.hover').hover(function(){

        $('.action').css('background','yellow');

    },function(){$('.action').css('background','none');})

})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<a href="#" class="action">Need This to be action</a>

<a href="#" class="hover">When Hover This</a>
Ehsan
  • 12,655
  • 3
  • 25
  • 44
0

Don't know the reason as well but Here is a work around : )

    <!--This one can -->
    <a href="#" class="hover1">Hover</a>
    <a href="#" class="action1">Action</a>

    <br>
    <br>

    <!-- But this one cannot, i need this-->
    <div>
    <a href="#" class="hover2" style="position: relative; 
            bottom:0; width:100%">When Hover This</a>
    <a href="#" class="action2" style="position: relative;bottom:72px;width:100%"> Need This to be action</a>
    </div>
Chris Chen
  • 1,228
  • 9
  • 14
0

Another flex option using flex-direction: column-reverse;

.flex-wrapper {
  display: flex;
  flex-direction: column-reverse;
}
a {
  display: block;
  padding: 8px 10px;
  border: 1px solid red;
  max-width: 20%;
}
.hover:hover ~ .action{
  background: yellow;
}
<div class="flex-wrapper">
  <a href="#" class="hover">When Hover This</a>
  <a href="#" class="action">Need This to be action</a>
</div>
Hastig Zusammenstellen
  • 4,286
  • 3
  • 32
  • 45