三種方法解決純css下拉選單滑鼠移入選單內容時選單隱藏消失的問題

hzh2019發表於2020-04-24

情景描述

假設我們希望導航欄上有一個元素(以下簡稱“選單標題”),把滑鼠移到標題上面時其下方會彈出一列選單,滑鼠離開時選單又隱藏起來。

然而,當試圖把滑鼠從選單標題移到選單內容中時,選單竟然也隱藏了。

我的選單內容(平時隱藏的那一部分)是由一個 <ul> 充當的。

html

<html>
	<head>
		<title>test1</title>
		<link rel="stylesheet" type="text/css" href="test1.css">
	</head>
	
	<body>
	
		<div class="dropdown">
			<span>選單</span>
			<ul class="dropdown-content">
				<li>a</li>
				<li>b</li>
				<li>c</li>
			</ul>
		</div>
		<div>後續內容</div>
		
	</body>
</html>

css

.dropdown{
	display:inline-block;
	position:relative;
}

.dropdown-content{
	display:none;
	position:absolute;
}

.dropdown:hover .dropdown-content{
	display:block;
}

.dropdown , .dropdown-content{
	border-width:2px;
	border-style:dotted;
}

原因和解決方案

首先分析這個選單的結構:由 <div class="dropdown"> 充當父元素,它有兩個子元素:一個 <span> 做觸發下拉選單的起點,一個 <ul> 做平時被隱藏的選單內容。由於 css 原始碼中的 :hover 是作用在父元素上的,因此按理來說即使滑鼠移到了選單內容 <ul> 上,滑鼠其實也還是在父元素內的(但其實不是!)。

我通過讓相關元素顯示邊框(如上),找到了原因:<ul> 與父元素 <div class="dropdown"> 之間有空隙,滑鼠經過這個空隙的瞬間就完全離開了父元素了。因此得出兩種解決思路:一是為 <ul> 設定 margin-top:0; 使這個空隙消失;二是把實現這個選單內容的 <ul> 替換成(另一個)<div>(猜想也許不同種類的元素的預設 margin-top 不一樣?進一步猜想,這個不同也許就是塊元素與內聯元素的區別之一?)。

進一步細究,還會發現一個問題:父元素的邊框竟然沒有包住子元素!我想,這是因為我們把選單內容設定成了 position: absolute 。為什麼要這樣做?因為如果子元素被包在父元素內(position 保持預設值),那麼當下拉選單向下彈出時,頁面中從此開始的後續內容也就跟著往下移了,我們通常不希望有這種效果。當然,這也勉強算是解決本文問題的又一種方案吧。

解決方案一:margin-top:0

在 css 中,為充當選單內容的元素(class為 .dropdown-content )新增 margin-top:0

解決方案二:選單內容改成其它種類元素

在 html 中,將充當選單內容的元素改成另一種,比如 <div>

解決方案三(通常不推薦):去除 position: absolute

在 css 中,為充當選單內容的元素(class為 .dropdown-content )刪去 position:absolute。這會導致當下拉選單向下彈出時,頁面中從此開始的後續內容也就跟著往下移。

相關文章