Почему анимация влияет на положение других элементов?

Рейтинг: 2Ответов: 1Опубликовано: 30.03.2023

На сайте, сразу под меню, есть блок с анимированными элементами. Именно: несколько изображений циклично сменяют друг друга и поверх них текст, который выезжает слева и справа.

Все было ничего, но потребовалось поменять шрифт меню. Шрифта этого (Jaapokki) в Google Fonts нет, поэтому пришлось скачать его и устанавливать через @font-face. Сразу после этого начались проблемы с меню - оно теперь тоже при загрузке страницы выезжает с право стороны.

Баг этот проявляется только при включенной эмуляции мобильного устройства в браузере. Если просто сузить окно браузера, баг не проявляется.

Подскажите, пожалуйста, в чем проблема и как ее решить?

Посмотреть на поведение меню можно здесь:

// ACTIVE MENU LINK DECORATION
let activeLinks = document.querySelectorAll(".menuLink");
console.log(activeLinks);
 
for (let i = 0; i < activeLinks.length; i++) {
  activeLinks[i].addEventListener("click", function() {
    let current = document.getElementsByClassName("active");
 
    if (current.length > 0) {
      current[0].className = current[0].className.replace(" active", "");
    }
 
    this.className += " active";
  });
} 
 
// BURGER MENU
const iconMenu = document.querySelector('.menuIcon');
const menuBody = document.querySelector('.menuBody');
if (iconMenu) {
    iconMenu.addEventListener("click", function (e) {
        document.body.classList.toggle('_lock');
        iconMenu.classList.toggle('_active');
        menuBody.classList.toggle('_active');
    });
}
 
 
// SMOOTH SCROLLING WHEN CLICKING THE MENU LINK
const menuLinks = document.querySelectorAll('.menuLink[data-goto]');
if (menuLinks.length > 0) {
    menuLinks.forEach(menuLink => {
        menuLink.addEventListener("click", onMenuLinkClick);
    });
 
    function onMenuLinkClick(e) {
        const menuLink = e.target;
        if (menuLink.dataset.goto && document.querySelector(menuLink.dataset.goto)) {
            const gotoBlock = document.querySelector(menuLink.dataset.goto);
            const gotoBlockValue = gotoBlock.getBoundingClientRect().top + pageYOffset - document.querySelector('header').offsetHeight;
 
            if (iconMenu.classList.contains('_active')) {
                document.body.classList.remove('_lock');
                iconMenu.classList.remove('_active');
                menuBody.classList.remove('_active');
            }
 
            window.scrollTo({
                top: gotoBlockValue,
                behavior: "smooth"
            });
            e.preventDefault();
        }
    }
}
 
// FIRST SCREEN GALLERY
initImg('#firstScreen img', [
    'img/intro_01.webp', 
    'img/intro_02.webp', 
    'img/intro_03.webp', 
    'img/intro_04.webp', 
    'img/intro_05.webp'
  ]); 
  
  function initImg(selector, srcArr) {
    const img = document.querySelector(selector); 
    Object.assign(img, {
      buf: Object.assign(new Image(), { img }), 
      srcArr: [...srcArr], 
      changeInterval: 5e3,
      bufIdx: 0,
      change: function () {
        this.style.animationName = 'img-in'; 
        this.src = this.buf.src || this.nextImage(); 
        this.buf.src = this.nextImage(); 
      }, 
      nextImage: function () {
        this.bufIdx = ++this.bufIdx < this.srcArr.length ? this.bufIdx : 0;
        return this.srcArr[this.bufIdx];
      }
    }); 
    img.buf.addEventListener('load', loadHandler); 
    img.addEventListener('animationend', animEndHandler); 
    img.change(); 
    return img; 
  
    function loadHandler() {
      setTimeout(
        () => this.img.style.animationName = 'img-out', 
        this.img.changeInterval 
      ); 
    }
    function animEndHandler({ animationName }) {
      if (animationName === 'img-out') 
        this.change(); 
    }
  }
/*Normalizing Styles*/
*{
    padding: 0;
    margin: 0;
    border: 0;
}
*,*:before,*:after{
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}
:focus,:active{outline: none;}
a:focus,a:active{outline: none;}
 
nav,footer,header,aside{display: block;}
 
html,body{
    height: 100%;
    line-height: 1;
    -ms-text-size-adjust: 100%;
    -moz-text-size-adjust: 100%;
    -webkit-text-size-adjust: 100%;
}
 
input,button,textarea{font-family:inherit;}
 
input::-ms-clear{display: none;}
button{cursor: pointer;}
button::-moz-focus-inner {padding:0;border:0;}
a, a:visited{text-decoration: none;}
a:hover{text-decoration: none;}
ul li{list-style: none;}
img{vertical-align: top;}
 
/*End of Normalizing Styles*/
 
@font-face{
    font-family: 'MyWebFont';
    src: url('../fonts/jaapokki-regular.eot');
    src: url('../fonts/jaapokki-regular.eot') format('eot'),
    url('../fonts/jaapokki-regular.woff') format('woff'),
    url('../fonts/jaapokki-regular.ttf') format('truetype'),
    url('../fonts/jaapokki-regular.svg') format('svg');
    font-weight: normal;
    font-style: normal;
}
 
body {
    font-family: 'Roboto', sans-serif;
}
 
/* MENU */
 
.menuWraper {
    position: fixed;
    width: 100%;
    top: 0;
    left: 0;
    z-index: 3;
}
 
.upperPannel {
    margin: 0 auto;
    background-color: #fff;
}
 
.menuContainer {
    max-width: 100%;
    margin: 0px auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 70px;
}
 
.menuIcon {
    display: none;
}
 
.menuList > li {
    position: relative;
    margin: 0px 30px 0px 10px;
    width: fit-content;
}
.menuLink {
    font-family: jaapoki;
    color: #000;
    font-size: calc(10px + 8 * (100vw / 1800));
}
 
@media (min-width: 1401px) {
    .menuLink {
        font-size: 22px;
    }
}
.menuLink:hover {
    color: red;
}
 
.menuLink.active {
    color: red;
    font-weight: 700;
}
 
@media (min-width: 950px) {
    .menuList {
        display: flex;
        align-items: center;
    }
    .menuList > li {
        padding: 10px 0;
    }
    .menuSubList {
        transform: translate(0px, 10%);
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transition: all 0.3s ease 0s;
    }
}
@media (max-width: 950px) {
    #logo {
        z-index: 1;
        margin-left: -30px;
    }
    .menuIcon {
        z-index: 5;
        display: block;
        position: relative;
        width: 30px;
        height: 18px;
        cursor: pointer;
        margin-right: 10px;
    }
    .menuIcon span,
    .menuIcon::before,
    .menuIcon::after {
        left: 0;
        position: absolute;
        height: 10%;
        width: 100%;
        transition: all 0.3s ease 0s;
        background-color: #000;
    }
    .menuIcon::before,
    .menuIcon::after {
        content: "";
        }
    .menuIcon::before {
        top: 0;
        }
    .menuIcon::after {
        bottom: 0;
    }
    .menuIcon span {
        top: 50%;
        transform: scale(1) translate(0px, -50%);
    }
 
    .menuIcon._active span {
        transform: scale(0) translate(0px, -50%);
    }
    .menuIcon._active::before {
        top: 50%;
        transform: rotate(-45deg) translate(0px, -50%);
    }
    .menuIcon._active::after {
        bottom: 50%;
        transform: rotate(45deg) translate(0px, 50%);
    }
 
    .menuBody {
        position: fixed;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background-color: #fff;
        padding: 100px 30px 30px 30px;
        transition: left 0.3s ease 0s;
        overflow: auto;
    }
    .menuBody._active {
        left: 0;
    }
 
    .menuBody::before {
        content: "";
        position: fixed;
        width: 100%;
        top: 0;
        left: 0;
        height: 80px;
        background-color: #fff;
        z-index: 20;
    }
 
    .menuList > li {
        flex-wrap: wrap;
        margin: 0px 0px 30px 0px;
    }
    .menuList > li:last-child {
        margin-bottom: 0;
    }
    .menuList > li._active .menuSubList {
        display: block;
    }
    .menuLink {
        font-size: 24px;
    }
    .menuSubList {
        position: relative;
        background-color: #fff;
        flex: 1 1 100%;
        margin: 20px 0px 0px 0px;
        display: none;
    }
    .menuSubLink {
        font-size: 20px;
        color: #000;
    }
}
 
/* FIRST SCREEN */
 
#firstScreen { 
    max-width: 100vw;
    height: 100vh;
    /*height: calc(100vh - 80px);*/
    margin: 0 0 0 0;
    padding: 0 0 0 0;
    overflow: hidden;
    position: relative;
}
#firstScreen img {
    width: 100%;
    height: 100vh;
    /*height: calc(100vh - 80px);*/
    object-fit: cover;
    position: absolute;
    top: 0;
    left: 0;
    animation: none 2s linear forwards; 
}
 
@keyframes img-in {
    0% { filter: scale(100%); opacity: 0;}
   50% { filter: scale(100%); opacity: 1; }
  100% { filter: scale(0); }}
@keyframes img-out {
    0% { filter: scale(0); opacity: 1; }
   30% { filter: scale(100%); }
  100% { filter: scale(100%); opacity: 0; }}
  
 
#greeting {
    margin: 0 auto;
    padding: 0 20px 0 20px;
    color: white;
    font-size: calc(24px + 46 * (100vw / 1800));
    line-height: 1.2;
    z-index: 1;
    width: 100%;
    height: calc(100vh - 80px);
    position: absolute;
    left: 0%;
    top: 40%;
    text-align: center;
    opacity: 1;
    transition: 1s;
    animation: show 3s 1; 
    animation-fill-mode: forwards;
    animation-delay: 3s;
}
 
@media (min-width: 1400px) {
    #greeting {
        font-size: 80px;
    }
}
 
#line1 {
    position: relative;
    animation: showLeft 3s;
    z-index: 1;
}
 
@keyframes showLeft {
    from {left:-100%;}
    to {left:0;}
}
 
#line3 {
    position: relative;
    animation: showLeft 3s;
    z-index: 1;
}
 
@keyframes showLeft {
    from {left:-100%;}
    to {left:0;}
}
 
#line2 {
    position: relative;
    animation: showRight 3s;
    z-index: 1;
}
    
@keyframes showRight {
    from {left:100%;}
    to {left:0;}
}
 
/* SCREEN DIMMING */
#screen {
    background-color: black;
    opacity: 0.7;
    width: 100%;
    height: 100%;
    z-index: 3;
    margin-bottom: 50px;
}
 
hr {
    margin: 0 auto;
    width: 90%;
    height: 3px;
    background-color: black;
    opacity: 0.2;
    margin-bottom: 50px;
}
<!DOCTYPE html>
<html lang="fr-FR">
 
<head>
  <title></title>
  <meta http-equiv="Content-type" content="text/html" charset="utf-8">
  <meta name="Robots" content="all">
  <meta name="description" content="">
  <meta name="keywords" content="">
  <meta name="viewport" content="width=device-width" initial-scale=1.0 maximum-scale=1.0 user-scalable=0>
     
  <link href="css/style.css" rel="stylesheet" />
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
 
  <script src="https://kit.fontawesome.com/f5ead13868.js" crossorigin="anonymous"></script>
 
</head>
 
<body>
    
<!-- <div class="wraper"> -->
 
<!-- NAVIGATION PANNEL -->
      
<div class="menuWraper">
  <div class="upperPannel">
    <div class="menuContainer">
      <img src="img/logo.png" id="logo" alt="logo">
      <div class="upperMenu menu">
        <div class="menuIcon">
          <span></span>
        </div>
          <nav class="menuBody">
            <ul class="menuList">
              <li><a data-goto=".page__section_1" href="#" class="menuLink">ACCUEIL</a></li>
              <li><a data-goto=".page__section_2" href="#" class="menuLink">DEEJAY</a></li>
              <li><a data-goto=".page__section_3" href="#" class="menuLink">PHOTO/VIDEO</a></li>
              <li><a data-goto=".page__section_3" href="#" class="menuLink">DECORATION</a></li>
              <li><a data-goto=".page__section_3" href="#" class="menuLink">WEDDING</a></li>
              <li><a data-goto=".page__section_3" href="#" class="menuLink">TRANSPORT</a></li>
              <li><a data-goto=".page__section_3" href="#" class="menuLink">CONNEXION</a></li>
            </ul>
          </nav>
      </div>
    </div>
  </div>
</div>
<div id="greeting">
  <span id="line1">SITENAME</span><br />
  <span id="line2">un lieu où les rêves et les possibilités</span><br />
  <span id="line3">se rencontrent</span><br />
</div>
<div id="screen">
  <div id="firstScreen">
    <img>            
        
  </div>
</div>
 
<hr>

</body>

</html>

Ответы

▲ 2Принят

Решение Вашей задачи заключается в том чтобы ограничить ширину верстки. Я предлагаю сделать это:

#greeting {
    overflow-x: hidden; 
}

Дело в том что когда вы делаете left: 100% при анимации, это действие растягивает страницу (Вы можете заметить появление горизонтального скрола), а меню у Вас выровнено условно по центру, но центр смещается вправо при увеличении ширины, далее при анимации страница сужается, в итоге возникает ощущение что вверху происходит анимация, но это не так.

Эту задачу можно решить и другими способами, если переосмыслить все что происходит сейчас, например каким-то другим способом задавать позиционирование меню. Я бы остановился на моем способе, так как появление скрола на странице явно лишнее. Ну и с JS это никак не связано, так как она воспроизводится даже при отсутствии скрипта.

Обновление

Для решения вопроса нужно прописать в стилях .menuWraper ширину 100, но не в % а в размере view т.е. единицах vw. Разница между 100% и 100vw заключается в том что 100% это всегда относится к размеру родительского элемента, а 100vw более постоянно так как относится к размеру видимой области экрана (в случае с мобильной верисией) или окна (в случае десктопной версии) ну в общем размера видимой на экране области сайта (исключая dev tools и т.п.). Т.е. когда .menuWraper имел ширину 100% он при любом удобном случае растягивался за ширину экрана таким образом меню уползало за экран и потом возвращалось.

.menuWraper {
    position: fixed;
    width: 100vw;
    top: 0;
    left: 0;
    z-index: 3;
}

Это не единственное решение, вторым решением будет укрощение контейнера который увеличивает область больше ширины экрана, навешиванием стиля overflow-x в данном случае это класс .rectangle

.rectangle {
    position: absolute;
    top: 56%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: calc(200px + (300 - 100) * ((100vw - 320px) / (1800 - 320)));
    height: calc(300px + (800 - 600) * ((100vw - 320px) / (1800 - 320)));
    background-color: rgba(255, 255, 255, 0.5);
    border: 5px solid white;
    text-align: center;
    font-family: 'Jaapolli-regular', serif;
    opacity: 0;
    transition: opacity 1.5s ease-out;
    overflow-x: hidden;
} 

И вероятно второе изменение лучше, хотя можно сделать оба.