100DaysCss第二天教程

 

 第二天是一个菜单按钮的动画效果

结构分析

点击切换状态

在html中,可以实现点击切换的就是input中的checkbox

而label标签可以将checkbox的点击事件绑定到label标签上

而这个事件就是原生checkbox的选中和不选中,即我们不需要写js代码就可以控制

 

那么我们的html结构如下

 <div class="day2">
    <label class="menu">
      <input type="checkbox" style="display: none;"/>
      <div class="line"></div>
      <div class="line"></div>
      <div class="line"></div>
    </label>
  </div>

一个不显示的checkbox,和一个控制checkbox选中事件的label标签

在label标签中包裹一个checkbox,就可以不需要label的for属性来绑定checkbox

 

label标签-mdn 

样式分析

静止时的三条杠 

首先是这个一条横线

.line{
    width: 100%;
    height: $lh;
    border-radius: 5px;
    background-color: #fff;
    box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.3);
  }

在sass中,使用$加变量名即可声明或者使用变量,我们后面的动画还需要用到这个height的值,我们不把它硬编码,防止后面反复修改

$lh: 8px;

对于包裹这三个杠的菜单div,它的样式是一个竖着的排列的flex布局

.menu{
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  gap: $gap;
  width: 80px;
}

gap是flex中的的属性,意为间隔,我们可以将间隔设为一个值,然后让flex布局中的元素的间隔都为同一个值

$gap: 16px;

我们后续还要用到gap的值,先不要硬编码

到此,我们的静止时的三条杠已经写好

选中后的交叉的两条杠

到此时,我们可以点击这三个杠所组成的菜单来控制checkbox的选中了

但是我们还没有将checkbox的选中与css样式关联起来,要与之关联,我们有2种办法

  1. 使用~选择checkbox的所有兄弟元素
  2. 使用:has()来选择checkbox的父类元素

 

这两种方法都可以实现,我写的是使用:has()的实现 

.menu:has(input:checked){
    
  }

选择了 -> 存在子类已经被选中的checkbox的.menu类

主语是.menu,所以这个选择器选择的是checkbox的父类 .menu

当然我们也可以选择不存在子类已经被选中的checkbox的.menu类

.menu:has(input:not(:checked)){

}

 此时我们就可以通过这个.menu类来控制它的子类line了

.menu:has(input:checked){
    .line:nth-child(2){
      
    }
    .line:nth-child(3){
     
    }
    .line:nth-child(4){
     
    }
  }

在父类中是第几个子元素的.line元素

在html中,我们可以看到这三个.line元素是第2,3,4个子元素。那么我们使用:nth-child()就是选择2,3,4

我们要计算第一个杠和第三个杠他们的位置要移到哪里去,是不是就是y坐标移到第二条杠上面

那么第一条杠就是Y坐标减下$lh和$gap了,也就是

transform: translateY(calc($gap + $lh));

第二条杠就是Y坐标加上$lh和$gap

然后他们就会与第三条杠重叠

最后再给它加上rotate即可

//第一条杠
transform: translateY(calc($gap + $lh)) rotate(-45deg);
//第三条杠
transform: translateY(calc(-1 * ($gap + $lh))) rotate(135deg);

对于第二条杠点击之后会从大到小消失,就是 

那么完整的交叉后的两条杠的代码如下

.menu:has(input:checked){
    .line:nth-child(2){
      transform: translateY(calc($gap + $lh)) rotate(-45deg);
    }
    .line:nth-child(3){
      scale: 0;
      opacity: 0;
      transition: all $time;
    }
    .line:nth-child(4){
      transform: translateY(calc(-1 * ($gap + $lh))) rotate(135deg);
    }
  }
  .menu:has(input:not(:checked)){
    .line:nth-child(2){
      transform: none;
    }
    .line:nth-child(3){
      scale: 1;
      opacity: 1;
      transition: all $time;
    }
    .line:nth-child(4){
      transform: none;
    }
  }

动画分析 

杠变叉的时候,是第一个杠和第三个杠向中间靠拢,然后再去rotate

那么up动画就是第三个杠,down动画就是第一个杠

@keyframes up {
  0%{
    transform: none;
  }
  65%{
    transform: translateY(calc(-1 * ($gap + $lh)));
  }
  100%{
    transform: translateY(calc(-1 * ($gap + $lh))) rotate(45deg);
  }
}
@keyframes down {
  0%{
    transform: none;
  }
  65% {
    transform: translateY(calc($gap + $lh));
  }
  
  100% {
    transform: translateY(calc($gap + $lh)) rotate(135deg);
  }
}

叉变杠的动画,是先将rotate设为0再去向上移和向下移

 

 

@keyframes upBack {
  0% {
    transform: translateY(calc(-1 * ($gap + $lh))) rotate(45deg);
  }

  65% {
    transform: translateY(calc(-1 * ($gap + $lh)));
  }

  100% {
    transform: none;
  }
}
​​@keyframes downBack {
  0% {
    transform: translateY(calc($gap + $lh)) rotate(135deg);
  }

  65% {
    transform: translateY(calc($gap + $lh));
  }

  100% {
    transform: none;
  }
}

总代码

<script setup>
</script>
<template>
  <div class="day2">
    <label class="menu">
      <input type="checkbox" style="display: none;"/>
      <div class="line"></div>
      <div class="line"></div>
      <div class="line"></div>
    </label>
  </div>
</template>


<style lang="scss" scoped>
.day2{
  background-color: #3FAF82;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
$gap: 16px;
$lh: 8px;
$time: 0.7s;
.menu{
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  
  gap: $gap;
  width: 80px;
  .line{
    
    width: 100%;
    height: $lh;
    border-radius: 5px;
    background-color: #fff;
    box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.3);
  }
  &:has(input:checked){
    .line:nth-child(2){
      transform: translateY(calc($gap + $lh)) rotate(-45deg);
      animation: down $time forwards;
    }
    .line:nth-child(3){
      scale: 0;
      opacity: 0;
      transition: all $time;
    }
    .line:nth-child(4){
      transform: translateY(calc(-1 * ($gap + $lh))) rotate(135deg);
      animation: up $time forwards;
    }
  }
  &:has(input:not(:checked)){
    .line:nth-child(2){
      transform: none;
      animation: downBack $time forwards;
    }
    .line:nth-child(3){
      scale: 1;
      opacity: 1;
      transition: all $time;
    }
    .line:nth-child(4){
      transform: none;
      animation: upBack $time forwards;
    }
  }
}
@keyframes up {
  0%{
    transform: none;
  }
  65%{
    transform: translateY(calc(-1 * ($gap + $lh)));
  }
  100%{
    transform: translateY(calc(-1 * ($gap + $lh))) rotate(45deg);
  }
}
@keyframes upBack {
  0% {
    transform: translateY(calc(-1 * ($gap + $lh))) rotate(45deg);
  }

  65% {
    transform: translateY(calc(-1 * ($gap + $lh)));
  }

  100% {
    transform: none;
  }
}
@keyframes down {
  0%{
    transform: none;
  }
  65% {
    transform: translateY(calc($gap + $lh));
  }
  
  100% {
    transform: translateY(calc($gap + $lh)) rotate(135deg);
  }
}
@keyframes downBack {
  0% {
    transform: translateY(calc($gap + $lh)) rotate(135deg);
  }

  65% {
    transform: translateY(calc($gap + $lh));
  }

  100% {
    transform: none;
  }
}
</style>

 

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值