作为俺网页设计课的某个实验作业,觉得老师提供的案例代码过于简陋,于是自己琢磨了个优雅又精美的下拉菜单功能。
效果

菜单点击触发,点击事件实现收起展开菜单,点击菜单项收起其他菜单项的一打开菜单,每项自带的after伪元素实现的三角提示标,并随收起展开状态动态变换效果。。。做完直接对👴🏿的聪明才智佩服的五体投地。
代码实现也简洁,层次属实清晰,可谓惊天地泣鬼神集代码带成者😅
代码实现
下拉菜单功能的中心思想是通过一个类表示按下菜单后的样式,本例取active类。
设置active类的元素即样式表示为菜单选中状态。无active类下,子级菜单为隐藏状态,即透明度为0,且关闭鼠标事件,三角图形向下指示展开。设置active类下,子菜单显示,透明度为1,启用鼠标事件,三角图形向上指示收起。
为了实现鼠标事件,单击元素为其设置active类,动态切换分配active类,则需用javascript配置交互。
HTML
作为数量众多的菜单项与相应的子级菜单元素,需要将菜单划分为主级与子级两层,且需要将属于同菜单块的菜单项存放在无序列表中,故基础HTML架构应有如下排布:
<ul id="mainMenu">
<li>
<a href="#" role="button" id="mainBtn">Xbox Game Pass</a>
<ul id="subMenu">
<li><a href="#">概观</a></li>
<li><a href="#">浏览游戏</a></li>
<li><a href="#">Xbox Game Pass for PC</a></li>
<li><a href="#">Xbox Live Gold</a></li>
</ul>
</li>
<li>
<a href="#" role="button" id="mainBtn">游戏</a>
<ul id="subMenu">
<li><a href="#">选购所有主机游戏</a></li>
<li><a href="#">使用Xbox的电脑游戏</a></li>
<li><a href="#">所有游戏展示</a></li>
</ul>
</li>
<li>
<a href="#" role="button" id="mainBtn">设备</a>
<ul id="subMenu">
<li>
<p>所有Xbox主机</p>
</li>
<li><a href="#">全新 Xbox Series X</a></li>
<li><a href="#">全新 Xbox Series S</a></li>
<hr>
<li>
<p>所有Xbox配件</p>
</li>
<li><a href="#">控制器</a></li>
<li><a href="#">头戴式设备</a></li>
<li><a href="#">硬盘与存储空间</a></li>
</ul>
</li>
<li>
<a href="#" role="button" id="mainBtn">社群</a>
<ul id="subMenu">
<li><a href="#">Xbox Community</a></li>
<li><a href="#">多人游戏</a></li>
</ul>
</li>
<li>
<a href="#" role="button" id="mainBtn">支持</a>
<ul id="subMenu">
<li><a href="#">支持首页</a></li>
<li><a href="#">Xbox Live 状态</a></li>
<li><a href="#">无障碍游戏</a></li>
<li><a href="#">支持服务的新功能</a></li>
</ul>
</li>
</ul>其中,mainMenu用于标识主菜单类,subMenu用于标识二级菜单列表,mainBtn标识主菜单项,即文字背后需要添加三角形指示图形的元素。
接下来开始对元素具体装饰
CSS
首先对主菜单类容器指定项目的行内弹性盒子排布,使其菜单项横向排列:
#mainMenu{
display:inline-flex;
}子菜单与主菜单同样是以无序列表存放,对于子菜单,需要将子菜单块准确置于对应主菜单项的底下,故需先将子菜单项设置绝对定位,再给子菜单的父li类设置相对定位,以标识参考系。配置了必要及其他装饰属性代码应如下:
#mainMenu li{
position: relative;
}#subMenu{
opacity: 0;
position: absolute;
top: 100%;
left: 0;
min-width: 100%;
background-color: white;
border: 1px solid lightgray;
pointer-events: none;
border-radius: .366em;
-webkit-border-radius: .366em;
-moz-border-radius: .366em;
-ms-border-radius: .366em;
-o-border-radius: .366em;
transition: all 0.2s;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
}其他对a标签的按钮样式及hover伪元素样式设置就不作过多赘述,接下来实现主菜单项的指示三角形,这里使用after伪元素样式。
- ::after对具有行内属性的标签的作用相当于加在文字尾部的样式,必须指定content属性,否则无法显示。
- 实现三角形形状,需要灵活使用border属性,对尖头方向的border设置为none
配置了基本样式及微调下的::after应如下:
#mainBtn::after{
display: inline-block;
margin-left: .255rem;
vertical-align: .255rem;
content: '';
border-top: .3em solid;
border-left:.3em solid transparent;
border-right: .3em solid transparent;
border-bottom: none;
transition: all 0.2s;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
}接下来应对active类进行样式设置;
对于active类下的子菜单块,设置显示等属性:
.active #subMenu{
opacity: 1;
top: 120%;
pointer-events: all;
}对三角图形伪元素类,设置为向上指示,可重新配置border实现尖头向上,本例则为了方便且具有动态效果,利用了transform旋转:
.active #mainBtn::after{
transform-origin: center;
transform: rotateZ(180deg);
-webkit-transform: rotateZ(180deg);
-moz-transform: rotateZ(180deg);
-ms-transform: rotateZ(180deg);
-o-transform: rotateZ(180deg);
}核心CSS设置完成,为实现active类的动态分配,需编写javascript。
Javascript
为实现active类的统一控制,将该类分配给主菜单块的li标签;
编写自定义函数实现类切换功能:
const mainBtn = document.querySelectorAll('#mainMenu #mainBtn');
//active类切换器
function activeToggler(index) {
for (let j = 0; j < mainBtn.length; j++) {
const activeList = mainBtn[j].parentElement;
if (j != index) {
activeList.classList.remove('active'); //移除索引外的active
}
}
mainBtn[index].parentElement.classList.toggle('active');activeToggler函数带有1个index参数,表示mainBtn类数组的序号,以该序号作为索引,for循环遍历所有mainBtn类,按照传入的index,移除除index索引元素外的active类。由于active需加在li上,故需选择mainBtn的父元素,即父li。
toggle方法能实现灵活执行add与remove方法,具有指定类则remove,没有指定类则add这个类。
为每个mainBtn绑定点击事件,实现点击按钮即为其父li配置active类:
//绑定点击事件
for (let i = 0; i < mainBtn.length; i++) {
const btn = mainBtn[i];
btn.onclick = function () {
activeToggler(i);
}
}为养成好的习惯,同学们需要将这些交互功能代码放置在页面加载对象window.onload中,故完整js代码应如图:
window.onload = function () {
const mainBtn = document.querySelectorAll('#mainMenu #mainBtn');
//绑定点击事件
for (let i = 0; i < mainBtn.length; i++) {
const btn = mainBtn[i];
btn.onclick = function () {
activeToggler(i);
}
}
//active类切换器
function activeToggler(index) {
for (let j = 0; j < mainBtn.length; j++) {
const activeList = mainBtn[j].parentElement;
if (j != index) {
activeList.classList.remove('active'); //移除索引外的active
}
}
mainBtn[index].parentElement.classList.toggle('active');
}
}结语
下拉菜单实现其实用不了多少js代码,如果单纯使子菜单在hover时而不是鼠标单击时显示的话,甚至可以直接用纯CSS实现,无需半句javascript。
单击显示也无非是利用了css设置active类样式,js动态控制active这一基本思想,虽说在带佬们眼中,这种小技巧实属常识中的常识,但对初学者来说还是受益匪浅滴。
怎么样铁汁们,学废了🐴,另外现在评论区可以发emoji了嗷,蛆宝宝们走起来😅


华纳东方明珠客服电话是多少?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠开户专线联系方式?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
如何联系华纳东方明珠客服?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠官方客服联系方式?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠客服热线?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠开户客服电话?(▲182(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠24小时客服电话?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠客服邮箱?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠官方客服在线咨询?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠客服微信?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
By 鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099 at November 1st, 2025 at 04:21 pm.
华纳东方明珠客服电话是多少?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠开户专线联系方式?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
如何联系华纳东方明珠客服?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠官方客服联系方式?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠客服热线?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠开户客服电话?(▲182(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠24小时客服电话?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠客服邮箱?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠官方客服在线咨询?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠客服微信?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
By 鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099 at November 1st, 2025 at 04:21 pm.
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
By pfweomozhf at October 7th, 2025 at 10:53 am.
新盘新项目,不再等待,现在就是最佳上车机会!
By hpebwzrehd at October 5th, 2025 at 04:30 am.
内容的丰富性和深度让人仿佛置身于知识的海洋,受益匪浅。
By olxmjycmib at March 4th, 2025 at 07:57 pm.
建议多用口语化表达,拉近与读者距离。
By fzxnhkojub at March 3rd, 2025 at 07:10 am.
建议引入反面案例,增强辩证性。
By lgicdvcrmc at March 3rd, 2025 at 04:36 am.
哈哈哈,写的太好了https://www.lawjida.com/
By kusfrkqekj at January 6th, 2025 at 02:42 pm.
兄弟写的非常好 https://www.cscnn.com/
By sfcocyznuh at October 19th, 2024 at 05:33 pm.
看的我热血沸腾啊www.jiwenlaw.com
By lujacjmeex at October 6th, 2024 at 07:56 pm.
看的我热血沸腾啊https://www.ea55.com/
By egedwwglwl at October 4th, 2024 at 10:13 pm.
想想你的文章写的特别好https://www.237fa.com/
By vlbolygycj at October 1st, 2024 at 09:32 pm.
怎么收藏这篇文章?
By ctbtuuttup at September 27th, 2024 at 01:43 pm.
叼茂SEO.bfbikes.com
By emvwwyoqrr at September 23rd, 2024 at 08:02 am.
添加了一堆表情,不知道要不要加点qq和微信的表情
By cvlocke at January 16th, 2021 at 05:07 pm.