Search code examples
angularsasshoverbackground-imageopacity

Change background image opacity on hover in angular and scss


i have angular component with dynamic background-image fetched from server:

  <div
    class="picture"
    [style.background-image]="'url(' + this.category.photo + ')'"
  >
    <div class="seeDetails">
        join group
      <button>see details</button>
    </div>
  </div>

After putting mouse over .picture class .seeDetails appear with text and button inside it, in CSS it looks like this:

.picture {
  width: 400px;
  height: 300px;
}

.seeDetails {
  display: none;
}

.picture:hover {
opacity:0.2;
  .seeDetails {
    display: block;
    animation-name: fadeIn;
    animation-duration: 0.5s;
  }

@keyframes fadeIn {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

i want to set background image opacity to 0.2 after hover, but it also set text and button opacity to 0.2.

I have read about solution with pseudoelement ::before https://coder-coder.com/background-image-opacity/ but i can't figure out how to use it in this case with :hover.


Solution

  • (There is a little bit simpler solution with ::before/::after, but you would have to move the dynamic background url to css to make it work.)

    You should have:

    <div class="container">
        <div class="background" [style.background-image]="'url(' + this.category.photo + ')'">
        </div>
        <div class="seeDetails">
            join group
          <button>see details</button>
        </div>
    </div>
    
    div.container {
      position: relative;
    
      > div.background {
        position: absolute;
        inset: 0;
        background-size: cover;
      }
    
      &:hover > div.background {
         opacity: 0.2;
      }
    
      > div.seeDetails {
        display: block;
        animation-name: fadeIn;
        animation-duration: 0.5s;
      }
    }
    

    Note: inset does not work everywhere. You should create a mixin:

    @mixin inset($size: 0) {
        inset: $size;
        top: $size;
        left: $size;
        right: $size;
        bottom: $size;
    }
    

    And use it as:

    div.container {
      // ...
    
      > div.background {
        position: absolute;
        @include inset(0 !important);
        background-size: cover;
      }
    
      // ...
    }