- 之前給公司做的一個小型知識庫管理網站時遇到一個問題,在這裡記錄下解決的過程。 公司的美工要求首頁導航菜單 要跟他們公司的網站風格保持一致,如圖所示 (子菜單是平鋪的) 我一看,心想很簡單嘛 先貼一下通用菜單html結構 <li> <a href="" class="abc">熱設計</a> <u ...
-
之前給公司做的一個小型知識庫管理網站時遇到一個問題,在這裡記錄下解決的過程。
公司的美工要求首頁導航菜單 要跟他們公司的網站風格保持一致,如圖所示
(子菜單是平鋪的)
我一看,心想很簡單嘛
先貼一下通用菜單html結構
<li>
<a href="" class="abc">熱設計</a>
<ul>
<li><a href="">設計規範</a></li>
<li><a href="">案例分享</a></li>
<li><a href="">經驗文章</a></li>
</ul>
</li>
只要設置子菜單的<li>css為float:left,並給<ul>設置背景就可以了嘛
但是 實現的時候發現並不簡單,因為<ul>的位置是基於一級菜單<li>的位置的,所以<ul>的背景欄只會從一級菜單的<li>的位置開始顯示,不會顯示通欄(背景欄會鋪滿頁面)
於是我想給子菜單的<ul>外麵包一層<div>,並設置<div> position:absolute; left:0; top:0;並取消一級菜單<li>的position:relative屬性
最終得到這樣的結果
雖然背景欄鋪滿了,但是子菜單卻不跟一級菜單對齊了。
通常是設置以及菜單的<li>為position:relative;而子菜單的<ul>(或本例中外層的div)為position:absolute,(偏移多少可以自行設置left跟top)這樣就可以使子菜單隨父菜單對齊了,
但是為了設置通欄的背景,去掉了一級菜單<li>的position:relative屬性,導致子菜單無法跟蹤父菜單;
於是設想 仍設置一級菜單<li>為position:relative,而設置div為position:fixed(position為fixed時只會根據整個屏幕進行佈局,並始終懸浮,父容器的position是否為relative並不影響)
同時設置子菜單的<ul>為position:absolute,意圖是想讓子菜單<ul>跨過其父容器<div>,而去跟蹤祖容器(即一級菜單的<li>)位置(因為瞭解到容器的position設置為absolute時,會去查找它父容器是否設置了position為relative,若設置了則根據其位置進行定位,若未設置就繼續往上層祖容器查找,若都未設置,則根據頁面進行定位)
結果如圖:
子菜單全部移動到最左側了(因為設置了left:0),說明子菜單沒有追蹤一級菜單的<li>,而是跟隨了其父容器<div>的位置,就是說父容器只要設置了position屬性,不管是否為relative,子容器都會根據其位置進行定位。
這樣從邏輯上確定了只靠css是無法實現需要的效果的
{
1 要想設置背景為通欄,只能設置div為positon:absolute;left:0;且不能設置一級菜單<li>的position屬性;
2 要想讓子菜單追蹤父菜單的位置,必須設置父菜單的position:relative,同時設置子菜單position:absolute;
1與2互相矛盾
}
所以 我們只能另尋他法,即jquery
jquery有一個名為 offset() 的方法,可以獲取某個元素的位置(若該元素是基於父元素的位置定位的,在該方法獲得相對於父元素的位置,不然則是相對於整個屏幕的位置)
如元素p, var pos=p.offset(), pos具有兩個屬性:p.top , p.left,根據字面意思就可以瞭解其含義;同時offset(top:x;top:y)可以動態設置元素的位置
我們在菜單的hover事件中對子菜單進行定位,代碼如下所示
var _this1 = null; $('.nav>li').hover(function () { _this1 = $(this); _this1.find('.second-nav').show(); var p = _this1.offset(); _this1.find('.second-nav').find('ul').offset({top:p.top+50,left:p.left-50}) _this1.find('.abc').css('color', ' #ff6a00') var _this2 = null; _this1.find('.second-nav').find('li').hover(function () { _this2 = $(this); _this2.find('.third-nav').show(); _this2.find('.third-nav').hover(function () { $(this).show(); }, function () { $(this).hide(); }); }, function () { _this2.find('.third-nav').hide(); }); }, function () { _this1.find('.second-nav').hide(); _this1.find('.abc').css('color', ' #fff') });
其中加粗斜體為新加的兩行代碼(其他的代碼都是導航菜單原有的),其中_this變數為滑鼠滑過的一級菜單標題的<li>,
_this.offset()取得當前激活標題相對於屏幕的位置,並存入變數p,然後
_this1.find('.second-nav').find('ul').offset({top:p.top+50,left:p.left-50})
然後根據_this找到子代元素<ul>應用offset(top:x,left:y)方法進行定位,最後得到需要的結果
現在來看,這實在不算什麼問題,解決方案也很簡單,如果對jquery瞭解夠多的話
當然,這都是後話了,當時還是糾結了好久,心路歷程很曲折哈哈。
還是要把基礎學扎實。