-1

This is my full code. When you press the buttons the div class is changed with a different background and it should fade in smoothly instead it just appears. This doesnt happen if the background is a solid color (if transition set to ALL). Why is that?

function changit(color) {
 document.getElementById('cont').classList = color;
}
#cont {position:relative;width:100px;height:100px;display:block;}

#cont::before {
 opacity:0;
 width: 93%;
    height: 100%;
    position: sticky;
    content: "";
    display: block;
 transition: opacity 2s ease;
}

.red::before { opacity:1!important;background:url(https://cdn.sstatic.net/Img/teams/teams-illo-free-sidebar-promo.svg) no-repeat; }
.blue::before { opacity:1!important;background:url(https://www.gravatar.com/avatar/24780fb6df85a943c7aea0402c843737?s=64&d=identicon&r=PG) no-repeat; }
.black::before { opacity:1!important;background: black; }
<div id="cont">

</div>
<button onclick="changit('red');">make red</button>
<button onclick="changit('blue');">make blue</button>
<button onclick="changit('black');">make black</button>

is there any alternative to this?

gobler
  • 95
  • 1
  • 6
  • Have you checked: https://stackoverflow.com/q/18353274/5468463, https://stackoverflow.com/q/30457239/5468463, https://stackoverflow.com/q/55309310/5468463, etc? – Vega Jun 25 '22 at 19:19
  • thats for background color. Im using images. – gobler Jun 25 '22 at 19:23
  • The question is absolutely unclear. There is no sense in classe names neither in aims. I voted to close – Vega Jun 28 '22 at 05:14

1 Answers1

0

There's 2 things that you would want to do when you set the new image.

  • reset the opacity to 0
  • change the actual image and transition opacity back to 1.

you're setting the image just fine. You're not resetting the opacity. You can achieve this by

  • removing the class
  • triggering a reflow, and render the element with opacity:0
  • applying a new class

I've added logic to your changeit function to remove the class and trigger the reflow.
I've also moved the 'transition' css rule to the other classes. so that when we remove a class, it will immediately snap to 0 opacity

function changit(color) {
  // remove the old classs
  document.getElementById('cont').classList = ""
  // trigger a 'reflow' so the dom is updated
  document.getElementById('cont').offsetWidth;
  // apply the new class.
  document.getElementById('cont').classList = color;
}
#cont {
  position: relative;
  width: 100px;
  height: 100px;
  display: block;
}

#cont::before {
  opacity: 0;
  width: 93%;
  height: 100%;
  position: sticky;
  content: "";
  display: block;
}

.red::before {
  opacity: 1!important;
  transition: opacity 2s ease;
  background: url(https://cdn.sstatic.net/Img/teams/teams-illo-free-sidebar-promo.svg) no-repeat;
}

.blue::before {
  opacity: 1!important;
  transition: opacity 2s ease;
  background: url(https://www.gravatar.com/avatar/24780fb6df85a943c7aea0402c843737?s=64&d=identicon&r=PG) no-repeat;
}

.black::before {
  opacity: 1!important;
  transition: opacity 2s ease;
  background: black;
}
<div id="cont">

</div>
<button onclick="changit('red');">make red</button>
<button onclick="changit('blue');">make blue</button>
<button onclick="changit('black');">make black</button>

using an animation:

if your animation has a single name, it will not automatically reset the animation when changing a class.
you can work around this by defining separate animation names in css.

function changit(color) {
  document.getElementById('cont').classList = color;
}
#cont {
  position: relative;
  width: 100px;
  height: 100px;
  display: block;
}

#cont::before {
  width: 93%;
  height: 100%;
  position: sticky;
  content: "";
  display: block;
}

.red::before {
  animation: appear-red 1s;
  background: url(https://cdn.sstatic.net/Img/teams/teams-illo-free-sidebar-promo.svg) no-repeat;
}

.blue::before {
  animation: appear-blue 1s;
  background: url(https://www.gravatar.com/avatar/24780fb6df85a943c7aea0402c843737?s=64&d=identicon&r=PG) no-repeat;
}

.black::before {
  animation: appear-black 1s;
  background: black;
}

@keyframes appear-red {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes appear-blue {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes appear-black {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
<div id="cont">

</div>
<button onclick="changit('red');">make red</button>
<button onclick="changit('blue');">make blue</button>
<button onclick="changit('black');">make black</button>
Lars
  • 3,022
  • 1
  • 16
  • 28
  • Thats great but I wouldnt like to change the javascript code. Is there any css alternative? I tried with animation like this `@keyframes appear { 0% {opacity(0);} 100% {opacity(0.6);} }` but it doesnt work either. – gobler Jun 25 '22 at 20:50
  • Sure, an animation can also be used, you would then have to restart the animation instead. [that has a similar approach.](https://stackoverflow.com/questions/6268508/restart-animation-in-css3-any-better-way-than-removing-the-element) – Lars Jun 25 '22 at 21:26
  • If you really don't want to touch the JS, you would have to define separate animations names in css. – Lars Jun 25 '22 at 21:43
  • one animation for each class name? – gobler Jun 25 '22 at 23:39
  • It is clear that the question is unclear. The OP should first clarify before expecting your time and efforts to write back and forth – Vega Jun 28 '22 at 05:15