如何根据 media-query 个断点被命中来实现 CSS 动画?
How to implement CSS animations based on media-query breakpoints being hit?
作为使我们的网络系统响应移动设备的一部分,我使用 CSS 媒体查询在 header 栏和汉堡菜单之间交替。
现在我认为如果它在桌面用户调整浏览器大小时 window 超出媒体查询定义的范围时在两种布局之间进行动画处理,那将是一个不错的噱头。作为一个 proof-of-concept 测试,我一直在试验我们的大徽标和小徽标之间的 t运行 位置。
我的 animations.scss 文件包含这两个动画:
@mixin ToSmallLogo() {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapToSmallLogo;
@keyframes SwapToSmallLogo {
0% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
}
@mixin SwapToBigLogo() {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapToBigLogo;
@keyframes SwapToBigLogo {
0% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
}
}
然后我有一个专门用于媒体查询的 SCSS 文件,包含:
@import '../../Variables/Sizes.scss';
@import '../Animations/animations.scss';
@media screen and (max-width: $bigToSmallFISLogo) {
#franklin {
@include ToSmallLogo();
}
}
@media screen and (min-width: $bigToSmallFISLogo){
#franklin{
@include SwapToBigLogo();
}
}
而应用媒体查询之前的CSS是这样的:
#franklin {
display: block;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
}
我的问题是,虽然将屏幕缩小到超过定义的尺寸效果很好,但返回时只会捕捉到没有动画的较大图像。我认为罪魁祸首是我在应用媒体查询之前在 CSS 中定义了图像,所以我删除了那部分;但这只是导致没有图像。
然后在输入这个问题时我想到了使用媒体查询来确定动画的方向,如下所示:
@mixin SwapLogo() {
/* background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;*/
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapLogo;
@media screen and (max-width: $bigToSmallFISLogo) {
animation-direction: normal;
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
@media screen and (min-width: $bigToSmallFISLogo) {
animation-direction: reverse;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
@keyframes SwapLogo {
0% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
}
这导致动画在页面加载时 运行,但在调整大小时没有。
有什么方法可以满足我的要求吗?
选项 1 包含一些错误 css
您已在 SwapToBigLogo
上将起点设置为 width: 100%;
@keyframes SwapToBigLogo {
0% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
width: 100%; <---- culprit
background-image: url('../../../PageAssets/Fis.png');
}
本质上,您是从 width: 100%
到 width:100%
的动画。如果您删除该行,它可能会起作用。
选项 2 棘手的反转
反转动画时,不会重置动画的迭代次数和进度。
IE 如果你 'reverse' 一个动画在 100% 完成。它只会应用 'reverse' 状态的 100% 完成。 不是从 0% 反转开始并动画到 100% 反转
如果您想规避
,请参阅我对此的回答
替代方案,改用过渡
如果您不需要复杂的动画,只想从一种状态平滑过渡到另一种状态。
我更愿意使用 css 转换。
#franklin {
display: block;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
transition: width 2s ease-in; // <--- this will animate when the media query kicks in.
}
@media screen and (max-width: $bigToSmallFISLogo) {
#franklin {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
@media screen and (min-width: $bigToSmallFISLogo){
#franklin{
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
}
奖金
您可以将过渡应用于 * 选择器。 (对于生产级网站,我不建议这样做,但玩起来很有趣。)当您的媒体查询发生变化时,它将使一切顺利过渡 widths/layouts.
* {
transition: all 2s;
}
body {
background-color: red;
color: black;
font-size: 30px;
}
.logo {
width: 200px;
border: 5px solid black;
border-radius: 30px;
padding:20px;
}
/* On screens that are 992px wide or less, the background color is blue */
@media screen and (max-width: 630px) {
body {
background-color: blue;
color: white;
font-size: 20px;
}
.logo {
width: 100px;
border: 3px solid orange;
border-radius: 10px;
padding:10px;
}
}
/* On screens that are 600px wide or less, the background color is olive */
@media screen and (max-width: 400px) {
body {
background-color: lime;
color: white;
font-size: 12px;
}
.logo {
width: 50px;
border: 1px solid indigo;
border-radius: 5px;
padding:2px;
}
}
<h1>Resize window</h1>
<p>
<img class="logo" src="http://placekitten.com/200/300" alt="logo">
</p>
经过大量实验,我终于猜到了。本质上,正如拉斯指出的那样,我忘记删除了一些位;但是我最终得到的解决方案(看起来更平滑一些,因为它将一个图像淡入另一个图像)是将基础 CSS 设置为:
#franklin {
display: block;
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
}
然后 mixin 应用动画如下:
@mixin SwapLogo($img, $width, $startIMG, $startWidth, $animationName) {
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: $animationName;
background-image: $img;
width: $width;
@keyframes #{$animationName} {
0% {
width: $startWidth;
background-image: $startIMG;
}
100% {
background-image: $img;
width: $width;
}
}
}
媒体查询为:
@media screen and (max-width: calc($bigToSmallFISLogo + 10px)) { //This overlap of 10px basically allows for the animation to take effect as the other animation is removed.
#franklin {
@include SwapLogo(url('../../../../PageAssets/fissmall.png'), 7%, url('../../../../PageAssets/Fis.png'), 100%, LogoGoSmall);
margin-top: 13px;
}
}
@media screen and (min-width: $bigToSmallFISLogo) {
#franklin {
@include SwapLogo(url('../../../../PageAssets/Fis.png'), 100%, url('../../../../PageAssets/fissmall.png'), 7%, LogoGoBig);
}
}
@media screen and (max-width: $minSizeForDesktopMenu) and (min-width: $bigToSmallFISLogo) {
#franklin {
margin-top: 26px;
}
}
@media screen and (min-width: $minSizeForDesktopMenu) {
#franklin {
margin-top: 13px;
}
}
作为使我们的网络系统响应移动设备的一部分,我使用 CSS 媒体查询在 header 栏和汉堡菜单之间交替。
现在我认为如果它在桌面用户调整浏览器大小时 window 超出媒体查询定义的范围时在两种布局之间进行动画处理,那将是一个不错的噱头。作为一个 proof-of-concept 测试,我一直在试验我们的大徽标和小徽标之间的 t运行 位置。
我的 animations.scss 文件包含这两个动画:
@mixin ToSmallLogo() {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapToSmallLogo;
@keyframes SwapToSmallLogo {
0% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
}
@mixin SwapToBigLogo() {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapToBigLogo;
@keyframes SwapToBigLogo {
0% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
}
}
然后我有一个专门用于媒体查询的 SCSS 文件,包含:
@import '../../Variables/Sizes.scss';
@import '../Animations/animations.scss';
@media screen and (max-width: $bigToSmallFISLogo) {
#franklin {
@include ToSmallLogo();
}
}
@media screen and (min-width: $bigToSmallFISLogo){
#franklin{
@include SwapToBigLogo();
}
}
而应用媒体查询之前的CSS是这样的:
#franklin {
display: block;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
}
我的问题是,虽然将屏幕缩小到超过定义的尺寸效果很好,但返回时只会捕捉到没有动画的较大图像。我认为罪魁祸首是我在应用媒体查询之前在 CSS 中定义了图像,所以我删除了那部分;但这只是导致没有图像。
然后在输入这个问题时我想到了使用媒体查询来确定动画的方向,如下所示:
@mixin SwapLogo() {
/* background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;*/
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: SwapLogo;
@media screen and (max-width: $bigToSmallFISLogo) {
animation-direction: normal;
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
@media screen and (min-width: $bigToSmallFISLogo) {
animation-direction: reverse;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
@keyframes SwapLogo {
0% {
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
100% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
}
这导致动画在页面加载时 运行,但在调整大小时没有。
有什么方法可以满足我的要求吗?
选项 1 包含一些错误 css
您已在 SwapToBigLogo
width: 100%;
@keyframes SwapToBigLogo {
0% {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
width: 100%; <---- culprit
background-image: url('../../../PageAssets/Fis.png');
}
本质上,您是从 width: 100%
到 width:100%
的动画。如果您删除该行,它可能会起作用。
选项 2 棘手的反转
反转动画时,不会重置动画的迭代次数和进度。
IE 如果你 'reverse' 一个动画在 100% 完成。它只会应用 'reverse' 状态的 100% 完成。 不是从 0% 反转开始并动画到 100% 反转
如果您想规避
,请参阅我对此的回答替代方案,改用过渡
如果您不需要复杂的动画,只想从一种状态平滑过渡到另一种状态。
我更愿意使用 css 转换。
#franklin {
display: block;
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
transition: width 2s ease-in; // <--- this will animate when the media query kicks in.
}
@media screen and (max-width: $bigToSmallFISLogo) {
#franklin {
background-image: url('../../../../PageAssets/fissmall.png');
width: 7%;
}
}
@media screen and (min-width: $bigToSmallFISLogo){
#franklin{
width: 100%;
background-image: url('../../../PageAssets/Fis.png');
}
}
奖金
您可以将过渡应用于 * 选择器。 (对于生产级网站,我不建议这样做,但玩起来很有趣。)当您的媒体查询发生变化时,它将使一切顺利过渡 widths/layouts.
* {
transition: all 2s;
}
body {
background-color: red;
color: black;
font-size: 30px;
}
.logo {
width: 200px;
border: 5px solid black;
border-radius: 30px;
padding:20px;
}
/* On screens that are 992px wide or less, the background color is blue */
@media screen and (max-width: 630px) {
body {
background-color: blue;
color: white;
font-size: 20px;
}
.logo {
width: 100px;
border: 3px solid orange;
border-radius: 10px;
padding:10px;
}
}
/* On screens that are 600px wide or less, the background color is olive */
@media screen and (max-width: 400px) {
body {
background-color: lime;
color: white;
font-size: 12px;
}
.logo {
width: 50px;
border: 1px solid indigo;
border-radius: 5px;
padding:2px;
}
}
<h1>Resize window</h1>
<p>
<img class="logo" src="http://placekitten.com/200/300" alt="logo">
</p>
经过大量实验,我终于猜到了。本质上,正如拉斯指出的那样,我忘记删除了一些位;但是我最终得到的解决方案(看起来更平滑一些,因为它将一个图像淡入另一个图像)是将基础 CSS 设置为:
#franklin {
display: block;
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
}
然后 mixin 应用动画如下:
@mixin SwapLogo($img, $width, $startIMG, $startWidth, $animationName) {
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-name: $animationName;
background-image: $img;
width: $width;
@keyframes #{$animationName} {
0% {
width: $startWidth;
background-image: $startIMG;
}
100% {
background-image: $img;
width: $width;
}
}
}
媒体查询为:
@media screen and (max-width: calc($bigToSmallFISLogo + 10px)) { //This overlap of 10px basically allows for the animation to take effect as the other animation is removed.
#franklin {
@include SwapLogo(url('../../../../PageAssets/fissmall.png'), 7%, url('../../../../PageAssets/Fis.png'), 100%, LogoGoSmall);
margin-top: 13px;
}
}
@media screen and (min-width: $bigToSmallFISLogo) {
#franklin {
@include SwapLogo(url('../../../../PageAssets/Fis.png'), 100%, url('../../../../PageAssets/fissmall.png'), 7%, LogoGoBig);
}
}
@media screen and (max-width: $minSizeForDesktopMenu) and (min-width: $bigToSmallFISLogo) {
#franklin {
margin-top: 26px;
}
}
@media screen and (min-width: $minSizeForDesktopMenu) {
#franklin {
margin-top: 13px;
}
}