You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

纯CSS侧边栏子菜单数量少于4时显示异常问题求助

纯CSS侧边栏子菜单数量过少时显示异常问题分析与解决

问题描述

找到一款纯CSS侧边栏,当删减子菜单至数量少于4个(尤其是仅1个时),会出现显示异常:鼠标移至子菜单下方区域时,子菜单会意外收回(异常显示截图:异常显示截图)。

完整代码示例

HTML部分

<section class="app">
  <aside class="sidebar">
    <header>
      Menu
    </header>
    <nav class="sidebar-nav">
      <ul>
        <li>
          <a href="#"><i class="ion-bag"></i> <span>Menu 1</span></a>
          <ul class="nav-flyout">
            <li>
              <a href="#"><i class="ion-ios-color-filter-outline"></i>Menu Item 1</a>
            </li>
            <li>
              <a href="#"><i class="ion-ios-clock-outline"></i>Menu Item 2</a>
            </li>
            <li>
              <a href="#"><i class="ion-android-star-outline"></i>Menu Item 3</a>
            </li>
            <li>
              <a href="#"><i class="ion-heart-broken"></i>Menu Item 4</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#"><i class="ion-ios-settings"></i> <span>Menu 2</span></a>
          <ul class="nav-flyout">
            <li>
              <a href="#"><i class="ion-ios-alarm-outline"></i>Menu Item 1</a>
            </li>
            <li>
              <a href="#"><i class="ion-ios-camera-outline"></i>Menu Item 2</a>
            </li>
            <li>
              <a href="#"><i class="ion-ios-chatboxes-outline"></i>Menu Item 3</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#"><i class="ion-ios-briefcase-outline"></i> <span>Menu 3</span></a>
          <ul class="nav-flyout">
            <li>
              <a href="#"><i class="ion-ios-flame-outline"></i>Menu Item 1</a>
            </li>
            <li>
              <a href="#"><i class="ion-ios-lightbulb-outline"></i>Menu Item 2</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#"><i class="ion-ios-analytics-outline"></i> <span>Menu 4</span></a>
          <ul class="nav-flyout">
            <li>
              <a href="#"><i class="ion-ios-timer-outline"></i>Menu Item 1</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#"><i class="ion-ios-paper-outline"></i> <span>Menu 5</span></a>
          <ul class="nav-flyout">
            <li>
              <a href="#"><i class="ion-ios-filing-outline"></i>Menu Item 1</a>
            </li>
            <li>
              <a href="#"><i class="ion-ios-information-outline"></i>Menu Item 2</a>
            </li>
            <li>
              <a href="#"><i class="ion-ios-paperplane-outline"></i>Menu Item 3</a>
            </li>
            <li>
              <a href="#"><i class="ion-android-star-outline"></i>Menu Item 4</a>
            </li>
             <li>
              <a href="#"><i class="ion-android-star-outline"></i>Menu Item 5</a>
            </li>
            <li>
              <a href="#"><i class="ion-android-star-outline"></i>Menu Item 6</a>
            </li>
            <li>
              <a href="#"><i class="ion-android-star-outline"></i>Menu Item 7</a>
            </li>
            <li>
              <a href="#"><i class="ion-android-star-outline"></i>Menu Item 8</a>
            </li>
          </ul>
        </li>
      </ul>
    </nav>
  </aside>
</section>

CSS部分

@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,300,600);

body {
  font-family: "Lato";
  font-size: 100%;
  overflow-y: scroll;
  font-family: sans-serif;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  background-color: #fefefe;
}

a {
  text-decoration: none;
  -webkit-transition: all 0.6s ease;
  -moz-transition: all 0.6s ease;
  transition: all 0.6s ease;
}
a:hover {
  -webkit-transition: all 0.6s ease;
  -moz-transition: all 0.6s ease;
  transition: all 0.6s ease;
}

.app {
  height: 100vh;
}

/* -------------
Sidebar
----------------*/
.sidebar {
  position: absolute;
  width: 17em;
  height: 100%;
  top: 0;
  overflow: hidden;
  background-color: #19222a;
  -webkit-transform: translateZ(0);
  visibility: visible;
  -webkit-backface-visibility: hidden;
}
.sidebar header {
  background-color: #09f;
  width: 100%;
  display: block;
  padding: 0.75em 1em;
}

/* -------------
Sidebar Nav
----------------*/
.sidebar-nav {
  position: fixed;
  background-color: #19222a;
  height: 100%;
  font-weight: 400;
  font-size: 1.2em;
  overflow: auto;
  padding-bottom: 6em;
  z-index: 9;
  overflow: hidden;
  -webkit-overflow-scrolling: touch;
}
.sidebar-nav ul {
  list-style: none;
  display: block;
  padding: 0;
  margin: 0;
}
.sidebar-nav ul li {
  margin-left: 0;
  padding-left: 0;
  display: inline-block;
  width: 100%;
}
.sidebar-nav ul li a {
  color: rgba(255, 255, 255, 0.9);
  font-size: 0.75em;
  padding: 1.05em 1em;
  position: relative;
  display: block;
}
.sidebar-nav ul li a:hover {
  background-color: rgba(0, 0, 0, 0.9);
  -webkit-transition: all 0.6s ease;
  -moz-transition: all 0.6s ease;
  transition: all 0.6s ease;
}
.sidebar-nav ul li i {
  font-size: 1.8em;
  padding-right: 0.5em;
  width: 9em;
  display: inline;
  vertical-align: middle;
}
.sidebar-nav > ul > li > a:after {
  content: "";
  font-family: ionicons;
  font-size: 0.5em;
  width: 10px;
  color: #fff;
  position: absolute;
  right: 0.75em;
  top: 45%;
}
.sidebar-nav .nav-flyout {
  position: absolute;
  background-color: #080D11;
  z-index: 9;
  left: 2.5em;
  top: 0;
  height: 100vh;
  -webkit-transform: translateX(100%);
  -moz-transform: translateX(100%);
  -ms-transform: translateX(100%);
  -o-transform: translateX(100%);
  transform: translateX(100%);
  -webkit-transition: all 0.5s ease;
  -moz-transition: all 0.5s ease;
  transition: all 0.5s ease;
}
.sidebar-nav .nav-flyout a:hover {
  background-color: rgba(255, 255, 255, 0.05);
}
.sidebar-nav ul > li:hover .nav-flyout {
  -webkit-transform: translateX(0);
  -moz-transform: translateX(0);
  -ms-transform: translateX(0);
  -o-transform: translateX(0);
  transform: translateX(0);
  -webkit-transition: all 0.5s ease;
  -moz-transition: all 0.5s ease;
  transition: all 0.5s ease;
}

问题原因分析

核心问题在于hover触发范围与子菜单定位的冲突:

  • 子菜单.nav-flyout设置了height:100vh,高度覆盖整个视口,但它的显示仅由父级<li>的hover状态控制。
  • 父级<li>的高度由自身内容(主菜单文字)决定,当子菜单数量少时,<li>的高度远小于子菜单的100vh高度。
  • 当鼠标从父<li>移到子菜单超出父<li>高度的区域时,会脱离父<li>的hover范围,导致子菜单触发transform: translateX(100%)收回,从而出现显示异常。

解决方案

修改CSS中控制子菜单显示的hover规则,让子菜单自身被hover时也保持显示状态,扩展hover触发范围:

/* 替换原有的hover规则 */
.sidebar-nav ul > li:hover .nav-flyout,
.sidebar-nav ul > li .nav-flyout:hover {
  -webkit-transform: translateX(0);
  -moz-transform: translateX(0);
  -ms-transform: translateX(0);
  -o-transform: translateX(0);
  transform: translateX(0);
  -webkit-transition: all 0.5s ease;
  -moz-transition: all 0.5s ease;
  transition: all 0.5s ease;
}

额外优化:给.nav-flyout添加固定宽度,避免内容排版混乱:

.sidebar-nav .nav-flyout {
  /* 保留原有属性 */
  width: 17em; /* 与侧边栏宽度保持一致 */
}

这样无论子菜单数量多少,鼠标移到子菜单的任意区域都能保持显示,彻底解决异常问题。

内容的提问来源于stack exchange,提问作者Dennis van Vugt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 23:54:50