CSS & JS Effect – Hamburger Menu
效果

参考:
Youtube – Responsive Navigation Menu Bar + Hamburger Menu Toggle - Only with CSS
Youtube – Making an animated hamburger button and a challenge to you!
Youtube – JavaScript - How to Create a Responsive Hamburger Menu with HTML, CSS, & JavaScript
做法
一条一条的 bar 是 div / span 做的.
点击的时候, 中间的 bar 消失, 上下的 bar rotate 就形成了 X
HTML
<div class="nav">
<input class="hamburger-toggle" type="checkbox" />
<span class="hamburger"></span>
</div>
checkbox 用来做 toggle, 其实用 JS 做会比较容易. checkbox 的 size 不容易控制, 又要搞定位什么的, 很不直观.
hamburger bar 虽然有三条, 但上下 2 条是用 ::before ::after 搞出来的. 其实要用 3 个 span 也是 ok 的, 甚至更直观.
CSS Style
3 bar style
.hamburger,
.hamburger::before,
.hamburger::after {
background-color: black;
width: 2rem;
height: 0.25rem;
display: inline-block;
transition-property: transform top opacity;
transition-duration: 0.4s;
}
3 条 bar 一起画.
transition 是等下 toggle 时 rotate 和 opacity 的过渡效果.
top, bottom bar style
.hamburger {
  position: relative;
  &::before,
  &::after {
    content: "";
    position: absolute;
  }
  &::before {
    top: -0.5rem;
  }
  &::after {
    top: 0.5rem;
  }
}
这里要注意, 3 条 bar 并不是 sibling. 它是 parent child

但是眼睛看上去应该要是 before, hamburger, after sibling才对.
所以就需要用到绝对定位. 感觉很不直观...
通过绝对定位, 它们就重叠了, 然后 before top -0.5rem 往上, after top 0.5rem 往下, 最终就形成 3 条 bar 了.
checkbox style
.nav {
  position: relative;
  .hamburger-toggle {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 2rem;
    height: 100%;
    z-index: 1;
    opacity: 0;
    cursor: pointer;
  }
}
它也是绝对定位, 因为要和 3 条 bar 重叠, 这样才点击的到, 用 opacity 让它消失 (看不见但是点击的到)
toggle checked style
.hamburger-toggle {
  &:checked ~ .hamburger {
    background-color: transparent;
    &::before {
      transform: rotate(45deg);
      top: 0;
    }
    &::after {
      transform: rotate(-45deg);
      top: 0;
    }
  }
}
checked 时让中间的 bar, 也就是 .hamburger background-color transparent 消失. 这里不可以用 opacity 哦.
因为 opacity 会同时让它的 child (before, after) 一起消失, 这不是想要的.
before 和 after 就 rotate 45°, 一个往上, 一个往下, 默认的 rotate origin (轴心) 是 center 所以必须加上 top 0 调回正中间.
如果没有 top: 0 效果是下面这样.

红色是原来的位置, 黑色是 rotate 以后的位置. 当把 2 个 set 成 top:0, 上面的 bar 往下移, 下面的往上移, 2 个 bar 在中间交会就形成了 X.
注: rotate 以后 width 就比原本的短了, 所以左边会有一点点偏移, 但是看不太出来, 所以不用理会.

完整代码
HTML

<div class="nav">
<input class="hamburger-toggle" type="checkbox" />
<span class="hamburger"></span>
</div>
Sass

.nav {
  position: relative;
  .hamburger-toggle {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 2rem;
    height: 100%;
    z-index: 1;
    opacity: 0;
    cursor: pointer;
    &:checked ~ .hamburger {
      background-color: transparent;
      &::before {
        transform: rotate(45deg);
        top: 0;
      }
      &::after {
        transform: rotate(-45deg);
        top: 0;
      }
    }
  }
  .hamburger,
  .hamburger::before,
  .hamburger::after {
    background-color: black;
    width: 2rem;
    height: 0.25rem;
    display: inline-block;
    transition-property: transform top opacity;
    transition-duration: 0.4s;
  }
  .hamburger {
    position: relative;
    &::before,
    &::after {
      content: "";
      position: absolute;
    }
    &::before {
      top: -0.5rem;
    }
    &::after {
      top: 0.5rem;
    }
  }
}
直观版本
如果不喜欢搞一堆的定位, before after, 也可以用最简单的 way.
HTML
<button class="menu-btn">
<span class="top-bar"></span>
<span class="center-bar"></span>
<span class="bottom-bar"></span>
</button>
CSS Style
.menu-btn {
  --bar-gap: 0.75rem;
  width: 100px;
  height: 100px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--bar-gap);
  .top-bar,
  .center-bar,
  .bottom-bar {
    background-color: currentColor;
    height: 1rem;
    width: 100%;
    border-radius: 999px;
    transition-property: transform opacity;
    transition-duration: 0.4s;
  }
  &.opened {
    .center-bar {
      opacity: 0;
    }
    .top-bar {
      transform: translateY(calc(var(--bar-gap) + 100%)) rotate(45deg);
    }
    .bottom-bar {
      transform: translateY(calc(-1 * (var(--bar-gap) + 100%))) rotate(-45deg);
    }
  }
}
需要留意它的 transform 还加上了 translateY 桥位置.
JS
document.querySelector('.menu-btn').addEventListener('click', event => {
  event.currentTarget.classList.toggle('opened');
});
CSS & JS Effect – Hamburger Menu的更多相关文章
- CSS+JS实现兼容性很好的无限级下拉菜单
		
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DT ...
 - CSS+JS下拉菜单和纯CSS下拉菜单
		
下拉菜单 (思路:先把二级定位到屏幕外,鼠标悬停重新定位回来:另一个就是ul浮动,li也浮动) 下拉菜单的一般思路就是把子导航嵌套在无序列表中,把列表定位到屏幕之外,当鼠标悬停在其父列表项上时,重新定 ...
 - 下拉的DIV+CSS+JS二级树型菜单
		
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
 - 190310HTML&CSS&JS
		
一.HTML 1.web server import socket def handle_request(client): buf = client.recv(1024) client.send(by ...
 - 前端小白页面开发注意事项及小工具(html\css\js)
		
技术一直在向前发展.但是有一些是相通的,要找准重点,将80%的时间放在提升基础问题上,余下的20%再去学习框架,库和工具. HTML 1. HTML 属性应当按照以下给出的顺序依次排列,确保代码的易读 ...
 - html鼠标自定义右键菜单:css+js实现自定义html右键菜单
		
我们在网页中很多都有右键菜单的功能,一般点击右键显示的是浏览器默认的菜单选项,那么我们直接如何通过css+js实现html的右键菜单呢?这篇文章将讲解html鼠标自定义右键菜单的实现原理和实现代码. ...
 - CSS & JS 制作滚动幻灯片
		
==================纯CSS方式==================== <!DOCTYPE html> <html> <head> <met ...
 - 【转】Maven Jetty 插件的问题(css/js等目录死锁)的解决
		
Maven Jetty 插件的问题(css/js等目录死锁,不能自动刷新)的解决: 1. 打开下面的目录:C:\Users\用户名\.m2\repository\org\eclipse\jetty ...
 - Css Js Loader For Zencart
		
Css Js Loader 描述:这个插件很早就出来了,可能知道人非常少 这个插件的功能是整合所有的网站的CSS和JS内容到一个文件里边. 因为CSS和JS文件到了一个文件,加快了程序的运行 在配合其 ...
 - 购物车数字加减按钮HTML+CSS+JS(有需要嫌麻烦的小伙伴拿走不谢)
		
之前在写详情页的时候,如下图 因为自己嫌麻烦,就去看其他网站是怎么写的,想直接拿来用,后来看来看去觉得写得很麻烦,于是最后还是决定自己写,附上HTML+CSS+JS代码,一条龙一站式贴心服务2333 ...
 
随机推荐
- 使用JavaScript编写vue指令v-model,v-model原理实现
			
首先先要知道的是v-model的作用是实现数据的双向绑定,即: 数据在视图层的双向响应. 实现思路主要分为两步: 第一步:数据层到视图层的响应 将数据响应到视图层的方式,在vue2使用的是Object ...
 - 逆向动态加载Dex(内存加载class)
			
逆向一个app, 其核心算法是通过反射调用的, 反编译软件中无法找到该类, 并且也无法hook. Java.perform(function(){ Java.enumerateClassLoaders ...
 - php 选择驱动写法
			
在 ThinkPHP 5.1 中,若要根据配置文件 sms.conf 中的设置在不同的短信渠道之间进行切换,可以采用以下步骤: 第一步:定义接口 首先,创建一个接口,这个接口将由所有短信渠道类实现.这 ...
 - 【Mybatis】01 概述 & 快速入门Part1
			
什么是 MyBatis? MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作. MyB ...
 - 【Java】逻辑错误BUG
			
开局一张图来解释就够了 查询 COUNT() 结果数,有且仅有一条记录 好死不死判断查询的结果数量等等于0, 这不永远都是取TRUE返回 花了一个下午的时间就为了解决这个BUG
 - python之理解super及MRO列表   ( 示例版  )
			
例子 1: class A0: def pri(self): super().pri() print("A0") class A1(A0): def pri(self): su ...
 - NVIDIA显卡原生管理查询功能nvidia-smi的部分使用功能
			
本文是使用NVIDIA原生管理工具查询NVIDIA显卡使用情况的一些记录(使用远程管理工具的效率没有使用原生管理接口nvml的效率高,有效率需求者建议使用python版本捆绑的nvml库,具体:htt ...
 - 伪代码中ties broken arbitrarily是什么含义?
			
最近在看一个物联网的论文,论文的伪代码中有这么一个地方标有:ties broken arbitrarily,对这个写法有些搞不清楚含义,于是网上找到了下面的资料: https://www.zhihu. ...
 - 不符合自身利益的科学讨论是否应该得到尊重——  读《自家员工质疑Jeff Dean领衔的Nature论文被解雇,谷歌:我们彻查了,质疑不符合标准》有感
			
读了一篇博文<自家员工质疑Jeff Dean领衔的Nature论文被解雇,谷歌:我们彻查了,质疑不符合标准>,其问大致是说Google提了一篇使用reinforcement learnin ...
 - Apache DolphinScheduler 1.3.4升级至3.1.2版本过程中的踩坑记录
			
因为在工作中需要推动Apache DolphinScheduler的升级,经过预研,从1.3.4到3.1.2有的体验了很大的提升,在性能和功能性有了很多的改善,推荐升级. 查看官方的升级文档,可知有提 ...