htmlcssreactjscss-animationspseudo-class

Can I use the :not pseudoclass to swap animations of an HTML element depending on whether the cursor is covering it?


I am trying to learn CSS fundamentals before diving into use of front end frameworks like Tailwind. I've made a small project for myself of making a webpage, and my first task is to make a sidebar which is made visible by hovering the side of the page. The body of my HTML output looks like this:

<div id="root">
   <div class="layout">
      <div class="bio">
         <img>
         <p flex="4">Hello, World!</p>
      </div>
      <div class="container">
         <div class="content"></div>
      </div>
   </div>
</div>

I know it may be a little div-happy, but I'm learning here. My issue is with my css file which correctly arranges the elements so that the left side of the screen is the "bio" where some text and an image reside and the right side of the screen is the "container" representing the sidepanel. When I hover the container, it correctly runs the animation of growing the menu's width from 0% to 100% of its width. I am struggling with making the sidebar initially display with a width of 0%, and I am struggling with triggering the render of the animation for the sidebar to collapse from 100% to 0% of its width. Here is my css file:

.layout {
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: row;
    justify-content: space-between;
}

.bio {
    margin: 0 auto;
    padding: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}


.container {
    flex: 1;
    margin: 0;
    padding: 0;
    min-width: 200px;
    max-width: 500px;
    height: 100%;
    display: inline-block;
}

.content {
    padding-left: 5px;
    min-width: 0px;
    max-width: 500px;
    height: 100%;
    border-left-width: 1px;
    border-left-style: solid;
    border-left-color: black;
    background: grey;
    transform-origin: bottom right
}

.container:hover .content {
    animation: show-menu 0.5s ease-in normal; 
}

.bio:hover ~ .container.content {
    animation: show-menu 0.5s ease-out reverse; 
}

@keyframes show-menu {
    0% {
        transform: scaleX(0);
    }

    100% {
        transform: scaleX(1);
    }
}

Currently, I am trying to capture the not hovering of my sidebar container by attaching a CSS rule for when the "bio" class is hovered, which essentially covers every portion of the screen that isn't covered by the "container" class. This is proving to be difficult, and using selectors like "~" to refer to sibling elements is not working. I initially tried using the ":not" pseudoclass to apply a rule for when "container" is not being hovered in a more intuitive manner, but that did not work for me (I tried .container:not(:hover) .content as the rule header).

I feel this would be a simple task for any experienced web dev, but I'm having a hard time overcoming this hurdle or finding posts about it specifically. Any advice is greatly appreciated!

** last note, I am running React as my UI server for this application, if that is relevant.


Solution

  • Looks like you'll be in business with a couple small tweaks to your CSS. We can simplify a bit by avoiding animations altogether for a much simpler solution in the transition property.

    Include a couple new lines to your inner div content rule:

    .content {
      padding-left: 5px;
      // we want width to be 0 before hovering anything
      width: 0;
      height: 100%;
      border-left-width: 1px;
      border-left-style: solid;
      border-left-color: black;
      background: grey;
      // essentially "watching" width changes and applying a transition to it
      transition: width .5s ease-in;
    }
    

    But this change has content expanding from left to right within its parent, container... Here we style the container, to align its child correctly on render:

    .container {
      width: 500px;
      height: 100%;
      display: flex;
      justify-content: right;
    }
    

    This gives us the perfect setup to do away with animations entirely. All we have to do whenever container is hovered is manually set the width of content.

    .container:hover .content {
      width: 100%;
    }
    

    Everything below the .container:hover .content rule in your CSS example can be deleted with this arrangement. When you're no longer hovering container, the style will disappear and the width of content will naturally reset to 0.