Search code examples
csscss-transitionsmarkup

Strange hover behavior based on order of sibling markup


I found a strange issue while hovering over a div that took me some time to troubleshoot. I'm curious to why this happened to help myself and others in the future.

<div>
  <img src="http://placehold.it/300x300" alt="" />
  <h3>Smoooth</h3>
</div>
<div>
  <h3>Janky</h3>
  <img src="http://placehold.it/300x300" alt="" />
</div>

Essentially, hover over the first one i get the expected result. But when the h3 is before the image, it acts all janky.

codepen attached.

See the Pen zqZOPN by Mark Szymanski


Solution

  • Actually the bug is that the h3 is visible in the second version. It should be hidden behind the img since it comes before it in the DOM. For some weird reason, if you change the opacity of the img to a value less that 1, the h3 disappears, as it should.

    img {
      display: block;
      opacity: .99;
      margin: 0;
      -webkit-backface-visibility: hidden;
      /* Chrome, Safari, Opera */
      backface-visibility: hidden;
      transition: opacity 200ms ease-in-out;
    }
    

    * {
      box-sizing: border-box;
    }
    section {
      width: 600px;
      margin: 3em auto;
    }
    div {
      float: left;
      position: relative;
      width: 48%;
      margin: 1%;
      background-color: dodgerblue;
      overflow: hidden;
      cursor: pointer;
    }
    img {
      display: block;
      opacity: .99;
      margin: 0;
      -webkit-backface-visibility: hidden;
      /* Chrome, Safari, Opera */
      backface-visibility: hidden;
      transition: opacity 200ms ease-in-out;
    }
    h3 {
      position: absolute;
      z-index: 0;
      top: 50%;
      left: 15%;
      text-align: center;
      width: 70%;
      background-color: dodgerblue;
      color: #fff;
      font-weight: 300;
      padding: 1em;
      transform: translateY(-75%);
      -webkit-backface-visibility: hidden;
      /* Chrome, Safari, Opera */
      backface-visibility: hidden;
      transition: background-color 200ms ease-in-out;
    }
    div:hover h3 {
      background-color: transparent;
    }
    div:hover img {
      opacity: 0.25;
    }
    <section>
      <h4>Why does the h3 jump on hover when it's placed before the image in the mark-up?</h4>
      <div>
        <img src="http://placehold.it/300x300" alt="" />
        <h3>Smoooth</h3>
      </div>
      <div>
        <h3>Janky</h3>
        <img src="http://placehold.it/300x300" alt="" />
      </div>
    </section>

    And that is the reason of the flickering, because as soon as the img opacity changes to a value lower than 1, the h3 hides behind the img.

    To solve your problem, you have to add z-index:1 to your h3 to force it to come in frond of the img