纯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
相关产品推荐
相关产品推荐

