Search code examples
jquerycssflexboxhoverexpand

CSS: Expanding a <div> from right to left to reveal text


I'd like to set up a fixed <div>, containing an icon, which expands from right to left when being hovered over (the <div> expands, not the icon), revealing a piece of text on the left side of the icon. The icon's position stays unchanged. Here's a sketch to help illustrate what I'd like to do:

enter image description here

Changing the size of the <div> on hover is no issue, I simply add a class with a larger width (including a transition to animate the expansion). But I struggle with the positioning of the elements. I placed both the icon and the text (inside a <span>) in separate <div> and tried arranging everything using flex. In the expanded/hover state things look the way they should, but once the <div> shrinks down again, the two divs containing the icon and the text try sharing the little space that is left and hence the icon gets cut off and the text gets squished.

Would appreciate if someone could help me figure out how set this up the way I'd like it to be.

Here's a jsFiddle of what I got so far: Button-GrowOnHover

Plus the code itself:

$(document).ready(function() {
  var button = $("#myButton");

  button.mouseenter(function() {
    $(this).addClass("grow");
  });
  button.mouseleave(function() {
    $(this).removeClass("grow");
  });
});
.button-container {
  position: fixed;
  top: 5%;
  right: 5%;
  width: 100px;
  padding: 5px;
  background-color: tomato;
  display: flex;
  justify-content: space-between;
  overflow: hidden;
  transition: width 1s;
}

.button-container.grow {
  width: 300px
}

.button-text-container {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: lightblue;
}

.button-icon-container {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="button-container" id="myButton">

  <div class="button-text-container">
    <span>Here comes some text.</span>
  </div>

  <div class="button-icon-container">
    <img src="https://placeholder.pics/svg/100x100/7AFFA6/000000/ICON">
  </div>

</div>


Solution

  • You can do this with only CSS if you rely on flexbox order and you can move the width changes to the text instead of the parent container:

    .button-container {
      position: fixed;
      top: 5%;
      right: 5%;
      padding: 5px;
      background-color: tomato;
      display: flex;
      justify-content: space-between;
      overflow: hidden;
    }
    
    
    .button-text-container {
      order:-1;
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: lightblue;
      white-space:nowrap; /*Keep text always one line*/
      overflow:hidden;
      width:0;
      transition: width 1s;
    }
    
    .button-icon-container {
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .button-icon-container:hover + .button-text-container {
      width:200px;
    }
    <div class="button-container" id="myButton">
      <div class="button-icon-container">
        <img src="https://placeholder.pics/svg/100x100/7AFFA6/000000/ICON">
      </div>
      
      <div class="button-text-container">
        <span>Here comes some text.</span>
      </div>
    </div>