Search code examples
htmlcsstwitter-bootstrapbootstrap-4bootstrap-icons

Bootstrap Icon Fading


I'm wondering how to display the filled version of a bootstrap icon when I hover over it.

I have this code:

<svg
  width="80px"
  height="80px"
  viewBox="0 0 16 16"
  class="bi bi-cloud-plus"
  fill="#5cb85c"
  xmlns="http://www.w3.org/2000/svg"
>
  <path
    fill-rule="evenodd"
    d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"
  />
  <path
    fill-rule="evenodd"
    d="M8 5.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V10a.5.5 0 0 1-1 0V8.5H6a.5.5 0 0 1 0-1h1.5V6a.5.5 0 0 1 .5-.5z"
  />
</svg>

(cloud plus icon) and I'm wondering how to merge it to it's filled partner (cloud plus fill icon). How?


Solution

  • Generally the way this is accomplished is to:

    1. Include both elements in your markup (in this case, both the filled and non-filled version), with a common parent.
    2. Hide the fill version with CSS
    3. On :hover of the parent, swap the CSS to hide the non-filled version and show the filled version.

    See below:

    .icon-wrapper .bi-cloud-plus-fill {
      display: none;
    }
    
    .icon-wrapper:hover .bi-cloud-plus-fill {
      display: inline;
    }
    
    .icon-wrapper:hover .bi-cloud-plus {
      display: none;
    }
    <div class="icon-wrapper">
      <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-plus" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
      <path fill-rule="evenodd" d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"/>
        <path fill-rule="evenodd" d="M8 5.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V10a.5.5 0 0 1-1 0V8.5H6a.5.5 0 0 1 0-1h1.5V6a.5.5 0 0 1 .5-.5z"/>
      </svg>
      
      <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-plus-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
        <path fill-rule="evenodd" d="M8 2a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13h8.906C14.502 13 16 11.57 16 9.773c0-1.636-1.242-2.969-2.834-3.194C12.923 3.999 10.69 2 8 2zm.5 4a.5.5 0 0 0-1 0v1.5H6a.5.5 0 0 0 0 1h1.5V10a.5.5 0 0 0 1 0V8.5H10a.5.5 0 0 0 0-1H8.5V6z"/>
      </svg>
    </div>

    To do a transition between them is possible but a bit more difficult, in that it requires some positioning tricks. We have to make the parent position: relative; so that the children can be position: absolute to sit on top of each other. Then, instead of leveraging display we leverage opacity for showing/hiding, and put a transition for the opacity property:

    .icon-wrapper {
      position: relative
      display: inline-block;
      height: 1em;
      width: 1em;
      font-size: 36px;
    }
    
    .icon-wrapper .bi {
      position: absolute;
      top: 0;
      left: 0;
      transition: opacity 1s;
    }
    
    .icon-wrapper .bi-cloud-plus-fill {
      opacity: 0;
    }
    
    .icon-wrapper .bi-cloud-plus {
      opacity: 1;
    }
    
    .icon-wrapper:hover .bi-cloud-plus-fill {
      opacity: 1
    }
    
    .icon-wrapper:hover .bi-cloud-plus {
      opacity: 0;
    }
    <div class="icon-wrapper">
      <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-plus" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
      <path fill-rule="evenodd" d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"/>
        <path fill-rule="evenodd" d="M8 5.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V10a.5.5 0 0 1-1 0V8.5H6a.5.5 0 0 1 0-1h1.5V6a.5.5 0 0 1 .5-.5z"/>
      </svg>
      
      <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-plus-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
        <path fill-rule="evenodd" d="M8 2a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13h8.906C14.502 13 16 11.57 16 9.773c0-1.636-1.242-2.969-2.834-3.194C12.923 3.999 10.69 2 8 2zm.5 4a.5.5 0 0 0-1 0v1.5H6a.5.5 0 0 0 0 1h1.5V10a.5.5 0 0 0 1 0V8.5H10a.5.5 0 0 0 0-1H8.5V6z"/>
      </svg>
    </div>

    One last thing-- these SVG are not particularly accessible by themselves. Consider leveraging Bootstrap screen reader utilities to add some accessible text for users who may not be looking at your site to navigate it.