原生实现拖拽改变菜单宽度,点击收起展开,悬浮展开

文章介绍了如何利用Flex布局使右侧内容自适应,通过CSS变量控制菜单的展开和收起状态,以及处理悬停展开的CSS伪类问题。在收起状态下,鼠标移入导航菜单会自动展开,同时实现了通过拖拽调整左右内容宽度的功能。完整代码已上传至Gitee。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

  • 实现左侧菜单收起展开,悬停展开
  • 实现拖拽控制左右内容动态宽度
    在这里插入图片描述

1.flex布局实现右侧内容自适应

  • 左侧为 aside,右侧为 main
  • 将 main 设置为 flex:1

index.html

  <div class="container">
    <aside class="transition">
      <nav>
        <ul>
          <li>所有事务</li>
          <li>未处理事务</li>
          <li>最近已查看</li>
          <li>最近已解决</li>
          <li>最近已更新</li>
        </ul>
      </nav>
    </aside>
    <div class="side-bar">
      <div class="switch-bar"><span class="iconfont icon-arrowleft">
        <div class="switch-display"></div>
      </span>
      </div>
      <div class="resize-bar"></div>
    </div>
    <main>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Voluptas unde recusandae esse, vitae nesciunt corporis ipsum quod harum natus sunt suscipit quaerat veritatis sequi sapiente provident sint temporibus cupiditate laboriosam.</main>
  </div>

index.css

div.container {
  display: flex;
  width: 100%;
  height: calc(100vh - var(--header-height));
  margin-top: var(--header-height);
  overflow: hidden;
}

2.控制菜单状态(展开/收起)

  • 通过 css 变量 --left-side-width 即菜单的宽度,判断菜单收起展开状态

index.js

/**
 * 修改菜单栏状态,展开或收起,同时修改按钮图标
 */
function changeSideState() {
  let asideWidth = var_get('--left-side-width', 'px')
  // 收起状态
  if (asideWidth !== 20) {
    collapseSide()
  } else {
    openSide()
  }
}
  • 折叠菜单,设置宽度,添加折叠类名 collapse,控制按钮图标,收起时不允许拖拽

index.js

// 折叠菜单,设置宽度,添加折叠类名,控制按钮图标,收起时不允许拖拽
function collapseSide() {
  var_set('--left-side-width', '20px')
  aside.classList.add('collapse')
    switchBar.children[0].classList.remove('icon-arrowleft')
    switchBar.children[0].classList.add('icon-arrow-right')
    // 菜单收起状态,取消拖拽事件
  sideBar.removeEventListener('mousedown', dragLine)
}
  • 展开菜单,设置宽度,移除折叠类名 collapse,控制按钮图标,展开时允许拖拽

index.js

// 展开菜单,设置宽度,移除折叠类名,控制按钮图标,展开时允许拖拽
function openSide() {
  var_set('--left-side-width', var_get('--left-side-base-width'))
    aside.classList.remove('collapse')
    switchBar.children[0].classList.add('icon-arrowleft')
    switchBar.children[0].classList.remove('icon-arrow-right')
    aside.classList.remove('fix')
    // 菜单打开状态,添加拖拽事件
    sideBar.addEventListener('mousedown', dragLine)
}

2.1 获取/设置 css 变量

var r = document.querySelector(':root');
// 设置
r.style.setProperty('变量名', '变量值');
// 获取
var rs = getComputedStyle(r);
var result = rs.getPropertyValue('变量名')
  • 为了方便使用,我写成了两个函数

index.js

/** 获取css变量
 * @param var_name 变量名称
 * @param var_unit 变量单位,可选
**/
function var_get(var_name,var_unit) {
  // Get the styles (properties and values) for the root
  var rs = getComputedStyle(r);
  var result = rs.getPropertyValue(var_name)
  if (var_unit) {
    return Number(result.replace(var_unit,''))
  } 
  return result
}

/** 设置css变量
 * @param var_name 变量名称
 * @param var_value 变量值 
**/
function var_set(var_name,var_value) {
  // Set the value of variable --blue to another value (in this case "lightblue")
  r.style.setProperty(var_name, var_value);
}

3.收起状态,鼠标移入后展开nav

  • 通过类名 collapse,为 aside 添加 hover伪类,展开nav层,并控制sideBar位置

index.css

aside.collapse:hover nav{
  width: var(--left-side-base-width);
  background-color: var(--side-bg-color);
  transition: all .3s;
  z-index: 2;
  visibility: visible;
}
aside.collapse:hover + .side-bar {
  left: var(--left-side-base-width);
  transition: all .3s;
}

3.1 “悬停”CSS伪状态冒泡DOM树。bug

  • 实现 hover 展开菜单后,当鼠标放到 switchBar 上点击收起时,菜单确实改变宽度呈现收起状态,但是同时触发了 aside 的 hover 效果,nav层展开。
  • 查阅后发现,如果悬停元素,则会自动悬停其所有祖先。
  • 解决办法:将 sideBar 和 aside 设置成同级。
  • 但是这样修改后又有了新的问题,hover展开菜单的情况下,不能点击 switchBar 了,只能在菜单收起的情况下点击 switchBar 。。。。TAT。
  • 所以菜单收起时我把 switchBar 隐藏了
aside.collapse:hover + .side-bar .switch-bar {
  opacity: 0;
}

4 完整代码已上传gitee

地址:https://gitee.com/slimmerYu/layout-demo

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值