无法使 CSS 动画居中

Unable to make CSS animation centered

我正在制作来自 Animista 的 CSS 动画,它没有居中。进入动画开始和结束不居中,退出动画从中间开始向下滑动。这不是动画应该如何工作的。

该动画用于在 1-2 秒后触发的弹出窗口,当用户单击关闭按钮时弹出窗口应该消失。

这里是狙击手:

const allEl = document.querySelectorAll('body > *:not(#popup):not(script)');
const closeBtn = document.querySelector('#popup-close-btn');
const popup = document.querySelector('#popup');

allEl.forEach(el => {
  el.setAttribute('id', 'blur');
});

const blur = document.querySelector('#blur');

setTimeout(() => {
  blur.classList.add('active');
  popup.style.display = "block";
  popup.classList.add('slide-in-fwd-center');
  popup.classList.remove('slide-out-fwd-center');
}, 2000);

closeBtn.addEventListener('click', () => {
  blur.classList.toggle('active');
  popup.classList.add('slide-out-fwd-center');
  popup.classList.remove('slide-in-fwd-center');
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  position: relative;
}

#blur.active {
  filter: blur(10px);
  pointer-events: none;
  user-select: none;
}

a {
  position: relative;
  padding: 5px 20px;
  display: inline-block;
  margin-top: 20px;
  text-decoration: none;
  color: #fff;
  background: #111;
}

#popup {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate( -50%, -50%);
  padding: 50px;
  box-shadow: 0 5px 30px rgba(0, 0, 0, .30);
  width: 600px;
  background: #fff;
  display: none;
}

.slide-in-fwd-center {
  animation: slide-in-fwd-center 0.4s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
}

@keyframes slide-in-fwd-center {
  0% {
    transform: translateZ(-1400px);
    opacity: 0;
  }
  100% {
    transform: translateZ(0);
    opacity: 1;
  }
}

.slide-out-fwd-center {
  animation: slide-out-fwd-center 0.7s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;
}

@keyframes slide-out-fwd-center {
  0% {
    -webkit-transform: translateZ(1);
    transform: translateZ(1);
    opacity: 1;
  }
  100% {
    -webkit-transform: translateZ(600px);
    transform: translateZ(600px);
    opacity: 0;
  }
}
<div class="container">
  <div class="content">
    <h2>
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum, harum aspernatur. Hic corrupti inventore voluptatum suscipit soluta sapiente odit delectus, beatae dolor, ea minus nesciunt distinctio dolore nihil itaque odio.
    </h2>
  </div>
</div>

<div id="popup">
  <h2>Lorem safasfasflijlkasfj oafljka aufhskafkl asoifj </h2>
  <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit dolore, recusandae enim quisquam nisi, architecto hic sed fugit modi quibusdam odit quia illum ipsa doloremque at reiciendis vitae nam inventore.</p>
  <a href="#" id="popup-close-btn">Close</a>
</div>

我做错了什么?

第一个问题是您的 body 加载不足。 min-height: 100vh; 解决了这个问题。

第二个问题是您添加的动画 类 正在覆盖您的默认变换 属性。只需将 X 和 Y 添加到动画 类.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            position: relative;
            min-height: 100vh;
        }

        #blur.active {
            filter: blur(10px);
            pointer-events: none;
            user-select: none;
        }

        a {
            position: relative;
            padding: 5px 20px;
            display: inline-block;
            margin-top: 20px;
            text-decoration: none;
            color: #fff;
            background: #111;
        }

        #popup {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translateX(-50%) translateY(-50%);
            padding: 50px;
            box-shadow: 0 5px 30px rgba(0, 0, 0, .30);
            width: 600px;
            background: #fff;
            display: none;
        }

        .slide-in-fwd-center {
            animation: slide-in-fwd-center 0.4s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
        }

        @keyframes slide-in-fwd-center {
            0% {
                transform: translateZ(-1400) translateX(-50%) translateY(-50%);
                opacity: 0;
            }
            100% {
                transform: translateZ(0) translateX(-50%) translateY(-50%);
                opacity: 1;
            }
        }

        .slide-out-fwd-center {
            animation: slide-out-fwd-center 0.7s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;
        }

        @keyframes slide-out-fwd-center {
            0% {
                -webkit-transform: translateZ(1) translateX(-50%) translateY(-50%);
                transform: translateZ(1) translateX(-50%) translateY(-50%);
                opacity: 1;
            }
            100% {
                -webkit-transform: translateZ(600) translateX(-50%) translateY(-50%);
                transform: translateZ(600) translateX(-50%) translateY(-50%);
                opacity: 0;
            }
        }
    </style>
</head>
<body>
<div class="container">
    <div class="content">
        <h2>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum, harum aspernatur. Hic corrupti inventore voluptatum suscipit soluta sapiente odit delectus, beatae dolor, ea minus nesciunt distinctio dolore nihil itaque odio.
        </h2>
    </div>
</div>

<div id="popup">
    <h2>Lorem safasfasflijlkasfj oafljka aufhskafkl asoifj </h2>
    <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit dolore, recusandae enim quisquam nisi, architecto hic sed fugit modi quibusdam odit quia illum ipsa doloremque at reiciendis vitae nam inventore.</p>
    <a href="#" id="popup-close-btn">Close</a>
</div>
<script
        src="https://code.jquery.com/jquery-1.12.4.min.js"
        integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
        crossorigin="anonymous"></script>
<script type="application/javascript">
    const allEl = document.querySelectorAll('body > *:not(#popup):not(script)');
    const closeBtn = document.querySelector('#popup-close-btn');
    const popup = document.querySelector('#popup');

    allEl.forEach(el => {
        el.setAttribute('id', 'blur');
    });

    const blur = document.querySelector('#blur');

    setTimeout(() => {
        blur.classList.add('active');
        popup.style.display = "block";
        popup.classList.add('slide-in-fwd-center');
        popup.classList.remove('slide-out-fwd-center');
    }, 2000);

    closeBtn.addEventListener('click', () => {
        blur.classList.toggle('active');
        popup.classList.add('slide-out-fwd-center');
        popup.classList.remove('slide-in-fwd-center');
    });

</script>

</body>
</html>

这是添加到所提供答案的另一种方法:

#popup 元素是 position:absolute,因此要使其 居中,您可以利用 CSS 中的 calc() ,因为此函数允许混合单位(如 calc(50% - 300px)),即弹出窗口宽度 (600px) 的 300px 一半:

left: calc(50% - 300px);

但是,后来我注意到由于某种原因 translateZ() 无法按预期工作。

初步想法:
在你的情况下我们应该使用 translateZ() 吗?
因为CSS函数translateZ()3Dspace中沿z-axis重新定位一个元素,因此更适合[=85] =]3D objects.
MDN translateZ()

但是,这里我们有一个普通的 2D 弹出窗口。因此,我们可以使用 2D CSS 变换函数 代替。

下面是 2D 变换 的 2 个备选方案:

  1. slide-in / slide-out
    translate(x, y)
  2. zoom-in / zoom-out
    scale(x)

2D slide-in / slide-out

开始时没有缩放效果,将 translateZ() 替换为 translate(x, y):

const allEl = document.querySelectorAll('body > *:not(#popup):not(script)');
const closeBtn = document.querySelector('#popup-close-btn');
const popup = document.querySelector('#popup');

allEl.forEach(el => {
  el.setAttribute('id', 'blur');
});

const blur = document.querySelector('#blur');

setTimeout(() => {
  blur.classList.add('active');
  popup.style.display = "block";
  popup.classList.add('slide-in-fwd-center');
  popup.classList.remove('slide-out-fwd-center');
}, 2000);

closeBtn.addEventListener('click', () => {
  blur.classList.toggle('active');
  popup.classList.add('slide-out-fwd-center');
  popup.classList.remove('slide-in-fwd-center');
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  position: relative;
}

#blur.active {
  filter: blur(10px);
  pointer-events: none;
  user-select: none;
}

a {
  position: relative;
  padding: 5px 20px;
  display: inline-block;
  margin-top: 20px;
  text-decoration: none;
  color: #fff;
  background: #111;
}

#popup {
  position: absolute;
  top: 50%;
  left: calc(50% - 300px);
  padding: 50px;
  box-shadow: 0 5px 30px rgba(0, 0, 0, .30);
  width: 600px;
  background: #fff;
  display: none;
}

.slide-in-fwd-center {
  animation: slide-in-fwd-center 0.4s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
}

@keyframes slide-in-fwd-center {
  0% {
    transform: translate(-1400px, -1400px);
    opacity: 0;
  }
  100% {
    transform: translate(0, 0);
    opacity: 1;
  }
}

.slide-out-fwd-center {
  animation: slide-out-fwd-center 0.7s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;
}

@keyframes slide-out-fwd-center {
  0% {
    -webkit-transform: translate(0, 0);
    transform: translate(0, 0);
    opacity: 1;
  }
  100% {
    -webkit-transform: translate(1400px, 1400px);
    transform: translate(1400px, 1400px);
    opacity: 0;
  }
}
<div class="container">
  <div class="content">
    <h2>
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum, harum aspernatur. Hic corrupti inventore voluptatum suscipit soluta sapiente odit delectus, beatae dolor, ea minus nesciunt distinctio dolore nihil itaque odio.
    </h2>
  </div>
</div>

<div id="popup">
  <h2>Lorem safasfasflijlkasfj oafljka aufhskafkl asoifj </h2>
  <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit dolore, recusandae enim quisquam nisi, architecto hic sed fugit modi quibusdam odit quia illum ipsa doloremque at reiciendis vitae nam inventore.</p>
  <a href="#" id="popup-close-btn">Close</a>
</div>

2D zoom-in / zoom-out

使用scale(x):
注:

  • 0% 到 99%:我们 动画缩放 (scale()),然后 ...
  • 99% 到 100%:将弹出窗口移出屏幕 (translate())
    (否则下面的内容将被我们不可见的 opacity:0 弹出窗口覆盖)

const allEl = document.querySelectorAll('body > *:not(#popup):not(script)');
const closeBtn = document.querySelector('#popup-close-btn');
const popup = document.querySelector('#popup');

allEl.forEach(el => {
  el.setAttribute('id', 'blur');
});

const blur = document.querySelector('#blur');

setTimeout(() => {
  blur.classList.add('active');
  popup.style.display = "block";
  popup.classList.add('slide-in-fwd-center');
  popup.classList.remove('slide-out-fwd-center');
}, 2000);

closeBtn.addEventListener('click', () => {
  blur.classList.toggle('active');
  popup.classList.add('slide-out-fwd-center');
  popup.classList.remove('slide-in-fwd-center');
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  position: relative;
}

#blur.active {
  filter: blur(10px);
  pointer-events: none;
  user-select: none;
}

a {
  position: relative;
  padding: 5px 20px;
  display: inline-block;
  margin-top: 20px;
  text-decoration: none;
  color: #fff;
  background: #111;
}

#popup {
  position: absolute;
  top: 50%;
  left: calc(50% - 300px);
  padding: 50px;
  box-shadow: 0 5px 30px rgba(0, 0, 0, .30);
  width: 600px;
  background: #fff;
  display: none;
}

.slide-in-fwd-center {
  animation: slide-in-fwd-center 0.4s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
}

@keyframes slide-in-fwd-center {
  0% {
    -webkit-transform: scale(5);
    transform: scale(5);
    opacity: 0;
  }
  100% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 1;
  }
}

.slide-out-fwd-center {
  animation: slide-out-fwd-center 0.7s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;
}

@keyframes slide-out-fwd-center {
  0% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 1;
  }
  99% {
    -webkit-transform: scale(5);
    transform: scale(5);
    opacity: 0;
  }
  100% {
    -webkit-transform: scale(5);
    transform: scale(5);
    -webkit-transform: translate(1400px, 1400px);
    transform: translate(1400px, 1400px);
    opacity: 0;
  }
}
<div class="container">
  <div class="content">
    <h2>
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum, harum aspernatur. Hic corrupti inventore voluptatum suscipit soluta sapiente odit delectus, beatae dolor, ea minus nesciunt distinctio dolore nihil itaque odio.
    </h2>
  </div>
</div>

<div id="popup">
  <h2>Lorem safasfasflijlkasfj oafljka aufhskafkl asoifj </h2>
  <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit dolore, recusandae enim quisquam nisi, architecto hic sed fugit modi quibusdam odit quia illum ipsa doloremque at reiciendis vitae nam inventore.</p>
  <a href="#" id="popup-close-btn">Close</a>
</div>

最终评论:
您正在分配 id 属性 (#blur) 以访问 blur-effect 的 <body> 的所有直接 children 元素。在您提供的代码片段中没问题,因为您的 body 只有 1 个直接 child (parent-child 选择器 > ,因此 <div class="container" id="blur">)。

但是如果我们有几个直接的 children 元素,比如 header、内容和页脚呢?
然后,我们的 id #blur 在我们的 DOM 中将不再是唯一的,因为它会重复多次。

您可以考虑修改您的代码,将 ID #blur 替换为 class .blur,因此:

CSS:

.blur.active {
  filter: blur(10px);
  pointer-events: none;
  user-select: none;
}

JS:

allEl.forEach(el => {
  el.classList.add('blur');
});