Search code examples
csscss-selectorsselector

css - selecting nearby element on hover not working


.circle-container {
    width: 200px;
    height: 200px;
    position: fixed;
    display: flex;
    left: 20%;
    top: 30%;
    margin-left: -100px;
    margin-top: -100px;
    transition: top, left 1s;
}
.circle-container-button {
    width: 200px;
    height: 200px;
    position: fixed;
    left: 20%;
    top: 30%;
    margin-left: -100px;
    margin-top: -100px;
}
.circle {
    position: absolute;
    width: 100%;
    height: 100%;
    display: flex;
    transition: transform 1s;
    opacity: 0.5;
}
.circle-container-button:hover {
    top: 0;
    left: 0;
    margin: 0;
    width: 100%;
    height: 100%;
}
.circle-container-button:hover ~ .circle-container {
    top: 50%;
    left: 50%;
}
.circle-container-button:hover ~ .circle-container .a {
    transform: rotate(220deg) scale(6);
}
.circle-container-button:hover ~ .circle-container .b {
    transform: rotate(-280deg) scale(6);
}
.circle-container-button:hover ~ .circle-container .c {
    transform: rotate(180deg) scale(6);
}
.circle-container-button:hover ~ .circle-container .d {
    transform: rotate(-50deg) scale(6);
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>

<div class="base-container"> 
    <div class = "circle-container">
        <div class = "circle a">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16.933 16.933" height="64" width="64"><path d="M8.467 0A8.467 8.467 0 00.745 5.01 8.287 8.287 0 017.27 1.817a8.287 8.287 0 018.288 8.288 8.287 8.287 0 01-1.423 4.639 8.467 8.467 0 002.798-6.276A8.467 8.467 0 008.467 0z" fill="#00f" fill-rule="evenodd"/></svg>
        </div>
        <div class = "circle b">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16.933 16.933" height="64" width="64"><path d="M.842 6.284a7.937 7.937 0 00-.313 2.183 7.937 7.937 0 007.938 7.937 7.937 7.937 0 005.624-2.345 9.355 9.355 0 01-3.923.874A9.355 9.355 0 01.842 6.284z" fill="#0ff" fill-rule="evenodd"/></svg>
        </div>
        <div class = "circle c">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16.933 16.933" height="64" width="64"><path d="M5.596 2.156a6.941 6.941 0 00-4.07 6.31 6.941 6.941 0 006.94 6.942 6.941 6.941 0 006.208-3.853 6.61 6.61 0 01-5.218 2.565 6.61 6.61 0 01-6.609-6.61 6.61 6.61 0 012.749-5.354z" fill="#ff0" fill-rule="evenodd"/></svg>
        </div>
        <div class = "circle d">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16.933 16.933" height="64" width="64"><path d="M13.341 5.227a6.253 6.253 0 01.217 1.623 6.253 6.253 0 01-6.254 6.253 6.253 6.253 0 01-3.465-1.052 5.857 5.857 0 004.628 2.273 5.857 5.857 0 005.857-5.857 5.857 5.857 0 00-.983-3.24z" fill="purple" fill-rule="evenodd"/></svg>
        </div>  
    </div>
    <div class = "circle-container-button"></div>  
</div> 

</body>
</html>

I need to modify the circle elements inside the circle-container when hovering over the circle container button, ewerithing seems ok, but it is still not working. below is the full code.

I understand that the ~ selector is for selecting nearby elements, just as in the code below.

I tried to place the circle-container inside circle-container-button and use just .circle it is working that way. but I need to have the button outside, near the container.

<html>
<body>
<style>
.circle-container {
    width: 200px;
    height: 200px;
    position: fixed;
    display: flex;
    left: 20%;
    top: 30%;
    margin-left: -100px;
    margin-top: -100px;
    transition: top, left 1s;
}
.circle-container-button {
    width: 200px;
    height: 200px;
    position: fixed;
    left: 20%;
    top: 30%;
    margin-left: -100px;
    margin-top: -100px;
}
.circle {
    position: absolute;
    width: 100%;
    height: 100%;
    display: flex;
    transition: transform 1s;
    opacity: 0.5;
}
.circle-container-button:hover {
    top: 0;
    left: 0;
    margin: 0;
    width: 100%;
    height: 100%;
}
.circle-container-button:hover ~ .circle-container {
    top: 50%;
    left: 50%;
}
.circle-container-button:hover ~ .circle-container .a {
    transform: rotate(220deg) scale(6);
}
.circle-container-button:hover ~ .circle-container .b {
    transform: rotate(-280deg) scale(6);
}
.circle-container-button:hover ~ .circle-container .c {
    transform: rotate(180deg) scale(6);
}
.circle-container-button:hover ~ .circle-container .d {
    transform: rotate(-50deg) scale(6);
}
</style>


<div class="base-container"> 
    <div class = "circle-container">
        <div class = "circle a">
            <img src="circle1.svg">
        </div>
        <div class = "circle b">
            <img src="circle2.svg">
        </div>
        <div class = "circle c">
            <img src="circle3.svg">
        </div>
        <div class = "circle d">
            <img src="circle4.svg">  
        </div>  
    </div>
    <div class = "circle-container-button"></div>  
</div> 

Solution

  • I understand that the ~ selector is for selecting nearby elements

    Well, more specifically, it is for selecting subsequent siblings. Your .circle-containers are in fact siblings of circle-container-button, but they are previous siblings.

    This may not be the best news you wanted to year, but there's really no previous sibling selector. So you have the option of either placing the button before the images, or of using css to display the elements out of their order.

    I simplified your code to demonstrate the effect I'm talking about.

    .button:hover ~ .container .element {
        color: red;
    }
    <div class = "container">
      <div class = "element">
        previous container: element a
      </div>
      <div class = "element">
        previous container: element b
      </div>
    </div>
    <div class = "button">button</div>           
    <div class = "container">
      <div class = "element">
        subsequent container: element c
      </div>
      <div class = "element">
        subsequent container: element d
      </div>
    </div>

    Extending the simplified code, here's the ugly solution:

    .button:hover ~ .container .element {
        color: red;
    }
    
    /* Makes the button appear after everything */
    /* Even though in the markup it comes before */
    .button {
      position: absolute;
      top: 100px;
    }
    <div class = "outer">
      <div class = "button">technically previous button</div>           
      <div class = "container">
        <div class = "element">
          subsequent container: element a
        </div>
        <div class = "element">
          subsequent container: element b
        </div>
        <div class = "element">
          subsequent container: element c
        </div>
        <div class = "element">
          subsequent container: element d
        </div>
      </div>
    </div>