Search code examples
javascripthtmlcsspositiontransition

How to remove div re-positioning when zoom up? (shrink the browser)


I've made a simple slider that responses the mouseenter event.

The algorithm is when if the user moves its mouse pointer one of Appear menu contents, a div called .slate goes down.

My problem is in Chrome or Opera, when the user zoomed up by using CTRL + Mouse Wheel Up, the .slate is going to spills a bit and goes back up smoothly while Firefox doesn't:

enter image description here enter image description here

I'm looking for a solution to remove this unwanted re-positioning except not using transition.

I've tried to give the transition more dynamically to resolve the problem. Add the transition when mouse entered to the Appear, remove it when mouse entered to Disappear.

But this one didn't work with an another new issue. The transition is going to ignore when I wag the mouse like this:

enter image description here

Are there any ways to resolve this problem?

CodePen: Original Code / Attempt 2

Snippet (Original):

'use strict';
class Slate {
  constructor(header) {
    this.header = document.querySelector(header);
    this.slate = document.querySelector('.slate');
    this.menu = this.header.querySelector('.menu');
    this.contents = this.menu.querySelectorAll('.contents');
    this.addEvent();
  }
  addEvent() {
    this.contents.forEach((cur, idx) => {
      cur.addEventListener('mouseenter', (e) => this.expand(e, idx));
    })
  }
  expand(e, index) {
    let lesser = (index < 2),
        ternary = {
          toggle: (lesser) ? this.slate.classList.add('toggle') : this.slate.classList.remove('toggle')
        };
  }
}
const proSlate = new Slate('header');
      * {
        margin: 0;
        padding: 0;
        font-family: Helvetica;
      }
      div, section, header {
        position: relative;
      }
      ul, li {
        list-style-type: none;
      }
      header, .slate {
        width: 800px;
      }
      header {
        height: 100px;
        line-height: 100px;
        background-color: rgba(69, 255, 0, .4);
      }
      .slate {
        height: 400px;
        line-height: 400px;
        text-align: center;
        color: white;
        background-color: steelblue;
        top: -25rem;
        transition: top 500ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
        z-index: -1;
        font-size: 4rem;
      }
      .menu {
        width: 100%;
        display: flex;
      }
      .contents {
        margin: 0 20px;
      }
      .toggle {
        top: 0;
      }
    <header>
      <ul class="menu">
        <li class="contents">Appear</li>
        <li class="contents">Appear</li>
        <li class="contents">Disapper</li>
        <li class="contents">Disapper</li>
      </ul>
    </header>
    <div class="slate">
      CONTEXT OF SLATE
    </div>


Solution

  • Instead of using top, go for transform

    'use strict';
    class Slate {
      constructor(header) {
        this.header = document.querySelector(header);
        this.slate = document.querySelector('.slate');
        this.menu = this.header.querySelector('.menu');
        this.contents = this.menu.querySelectorAll('.contents');
        this.addEvent();
      }
      addEvent() {
        this.contents.forEach((cur, idx) => {
          cur.addEventListener('mouseenter', (e) => this.expand(e, idx));
        })
      }
      expand(e, index) {
        let lesser = (index < 2),
          ternary = {
            toggle: (lesser) ? this.slate.classList.add('toggle') : this.slate.classList.remove('toggle')
          };
      }
    }
    const proSlate = new Slate('header');
    * {
      margin: 0;
      padding: 0;
      font-family: Helvetica;
    }
    
    div,
    section,
    header {
      position: relative;
    }
    
    ul,
    li {
      list-style-type: none;
    }
    
    header,
    .slate {
      width: 800px;
    }
    
    header {
      height: 100px;
      line-height: 100px;
      background-color: rgba(69, 255, 0, .4);
    }
    
    .slate {
      height: 400px;
      line-height: 400px;
      text-align: center;
      color: white;
      background-color: steelblue;
      transform: translateY(-100%);
      transition: transform 500ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
      z-index: -1;
      font-size: 4rem;
    }
    
    .menu {
      width: 100%;
      display: flex;
    }
    
    .contents {
      margin: 0 20px;
    }
    
    .toggle {
      transform: translateY(0);
    }
    <header>
      <ul class="menu">
        <li class="contents">Appear</li>
        <li class="contents">Appear</li>
        <li class="contents">Disapper</li>
        <li class="contents">Disapper</li>
      </ul>
    </header>
    <div class="slate">
      CONTEXT OF SLATE
    </div>