Search code examples
csscss-positionopacityfade

position:absolute element messes up fading of another


I'm trying to fade a text but it just pops to the end states without fading in-between (partially with delay, too).

I'm using CSS for the fading (opacity: 0/1 and transform: opacity) and, after a lot of debugging I discovered that this was happening due to a totally unrelated position: absolute element underneath. Here's a fiddle:

var $root = $('.root');
$('#butt_fadetext').click(function(){
  $root.toggleClass('dermineyda');
});
$('#butt_hidefancy').click(function(){
  $root.toggleClass('nofancy');
});
.root {
  background-color: #b87988;
}

.container {
  transition: opacity 0.5s;
  opacity: 1;
  height: 100px;
}

.dermineyda .container {
  opacity: 0;
}

.inn {
  position: absolute;
  z-index: 1;
}

.unrelated {
  background-color: blanchedalmond;
  width: 100px;
  height: 30px;
  position: absolute;
  top: 0;
  left: 0;
}

.nofancy .unrelated {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="root">
  <div class="container">
    <div class="inn">text</div>
  </div>
  <div class="unrelated">fancy fx</div>
</div>
<input type="button" value="fade text" id="butt_fadetext" />
<input type="button" value="hide fancy fx" id="butt_hidefancy" />


Solution

  • I learned just now that changing an element's opacity can alter its order in the stacking context:

    Using this property with a value different than 1 places the element in a new stacking context.

    Solution

    I fixed it by forcing its order upwards in the stacking context.

    var $root = $('.root');
    $('#butt_fadetext').click(function(){
      $root.toggleClass('dermineyda');
    });
    $('#butt_hidefancy').click(function(){
      $root.toggleClass('nofancy');
    });
    .root {
      background-color: #b87988;
    }
    
    .container {
      transition: opacity 0.5s;
      opacity: 1;
      height: 100px;
      position: relative;
      z-index: 500;
    }
    
    .dermineyda .container {
      opacity: 0;
    }
    
    .inn {
      position: absolute;
      z-index: 1;
    }
    
    .unrelated {
      background-color: blanchedalmond;
      width: 100px;
      height: 30px;
      position: absolute;
      top: 0;
      left: 0;
    }
    
    .nofancy .unrelated {
      display: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <div class="root">
      <div class="container">
        <div class="inn">text</div>
      </div>
      <div class="unrelated">fancy fx</div>
    </div>
    <input type="button" value="fade text" id="butt_fadetext" />
    <input type="button" value="hide fancy fx" id="butt_hidefancy" />