整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript 伸缩的两级菜单

<html>
<head>
<title>伸缩的菜单</title>
<style>
<!--
body{
background-color:#ffdee0;
}
#navigation {
width:200px;
font-family:Arial;
}
#navigation > ul {
list-style-type:none; /* 不显示项目符号 */
margin:0px;
padding:0px;
}
#navigation > ul > li {
border-bottom:1px solid #ED9F9F; /* 添加下划线 */
}
#navigation > ul > li > a{
display:block; /* 区块显示 */
padding:5px 5px 5px 0.5em;
text-decoration:none;
border-left:12px solid #711515; /* 左边的粗红边 */
border-right:1px solid #711515; /* 右侧阴影 */
}
#navigation > ul > li > a:link, #navigation > ul > li > a:visited{
background-color:#c11136;
color:#FFFFFF;
}
#navigation > ul > li > a:hover{ /* 鼠标经过时 */
background-color:#990020; /* 改变背景色 */
color:#ffff00; /* 改变文字颜色 */
}
/* 子菜单的CSS样式 */
#navigation ul li ul{
list-style-type:none;
margin:0px;
padding:0px 0px 0px 0px;
}
#navigation ul li ul li{
border-top:1px solid #ED9F9F;
}
#navigation ul li ul li a{
display:block;
padding:3px 3px 3px 0.5em;
text-decoration:none;
border-left:28px solid #a71f1f;
border-right:1px solid #711515;
}
#navigation ul li ul li a:link, #navigation ul li ul li a:visited{
background-color:#e85070;
color:#FFFFFF;
}
#navigation ul li ul li a:hover{
background-color:#c2425d;
color:#ffff00;
}
#navigation ul li ul.myHide{ /* 隐藏子菜单 */
display:none;
}
#navigation ul li ul.myShow{ /* 显示子菜单 */
display:block;
}
-->
</style>
<script language="javascript">
function change(){
//通过父元素li,找到兄弟元素ul
var oSecondDiv = this.parentNode.getElementsByTagName("ul")[0];
//CSS交替更换来实现显、隐
if(oSecondDiv.className == "myHide")
oSecondDiv.className = "myShow";
else
oSecondDiv.className = "myHide";
}
window.onload = function(){
var oUl = document.getElementById("listUL"); //一级菜单的ul标签
var aLi = oUl.childNodes; //子元素
var oA;
for(var i=0;i<aLi.length;i++){
//如果子元素为li,且这个li有子菜单ul
if(aLi[i].tagName == "LI" && aLi[i].getElementsByTagName("ul").length){
oA = aLi[i].firstChild; //找到超链接
oA.onclick = change; //动态添加点击函数
}
}
}
</script>
</head>
<body>
<div id="navigation">
<ul id="listUL">
<li><a href="#">Home</a></li>
<li><a href="#">News</a>
<ul class="myHide">
<li><a href="#">Lastest News</a></li>
<li><a href="#">All News</a></li>
</ul>
</li>
<li><a href="#">Sports</a>
<ul class="myHide">
<li><a href="#">Basketball</a></li>
<li><a href="#">Football</a></li>
<li><a href="#">Volleyball</a></li>
</ul>
</li>
<li><a href="#">Weather</a>
<ul class="myHide">
<li><a href="#">Today's Weather</a></li>
<li><a href="#">Forecast</a></li>
</ul>
</li>
<li><a href="#">Contact Me</a></li>
</ul>
</div>
</body>
</html>

上菜单为二级菜单,伸缩菜单是在一级菜单<li>下点击实现的


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>伸缩菜单</title>
<meta name="keywords" content="关键字列表" />
<meta name="description" content="网页描述" />
<link rel="stylesheet" type="text/css" href="" />
<style type="text/css">
body,p,ul,li{padding:0px;margin:0px;}
ul li{list-style:none;}
body{font-size:13px;}
.menu{
width:210px;
margin:50px auto;
border:1px solid #ccc;
}
.menu p{
height:25px;
line-height:25px;
font-weight:bold;
background:#eee;
border-bottom:1px solid #ccc;
padding-left:5px;
cursor:pointer;
}

.menu ul li{
height:24px;
line-height:24px;
padding-left:5px;
}
</style>
<script type="text/javascript">
//分析思路
//当页面加载完成后
//获取到所有的p元素 获取到所有的ul元素
//给每一个p元素绑定一个onclick事件
//判断每一个p元素对应的ul是否是隐藏或者是显示
window.onload = function(){
//获取id=menu对象
var div_obj = document.getElementById("menu");
//获取所有的p元素
var ps_obj = div_obj.getElementsByTagName("p");
var ps_length = ps_obj.length;
//获取到所有的ul元素
var uls_obj = div_obj.getElementsByTagName("ul");
//给每一个p元素绑定一个onclick事件
for(var i=0;i<ps_length;i++){
ps_obj[i].id = i; //给每一个p元素加上一个标识
ps_obj[i].onclick = function(){
//判断对应的ul是否是显示或者隐藏

if(uls_obj[this.id].style.display == "none"){
uls_obj[this.id].style.display = "block";
}else{
uls_obj[this.id].style.display = "none";
}

}
}
}

</script>
</head>
<body>
<div id="menu" class="menu">
<div>
<p>web前端</p>
<ul style="display:none;">
<li>HTML</li>
<li>DIV+CSS</li>
<li>JAVASCRIPT</li>
<li>jQuery</li>
<li>Bootstrap</li>
</ul>
</div>
<div>
<p>PHP+MYSQL核心编程</p>
<ul style="display:none;">
<li>PHP</li>
<li>MYSQL</li>
<li>HTTP协议</li>
<li>PHP绘图技术</li>
</ul>
</div>
<div>
<p>PHP高级</p>
<ul style="display:none;">
<li>XML编程</li>
<li>AJAX</li>
<li>MVC</li>
</ul>
</div>
</div>
</body>
</html>

类似QQ伸缩菜单:

面试官:同学考你一个简单css内容,写一个可展开列表。

我:笑出了声。心想真的会出这么简单的内容哈哈哈!

面试官:同学不能用js哦,如果可以用stylus编写就更好啦!

我:小脑刹那间萎缩了......

Stylus 是一种 CSS 预处理器。预处理器是一种脚本语言,它扩展了 CSS 的功能,使得编写 CSS 更加高效、灵活和强大。Stylus 特别之处在于其简洁而灵活的语法,它允许开发者使用变量、嵌套规则、混合(Mixins)、继承、操作符、函数以及条件语句等高级功能来编写样式代码。

接下来,让我们通过一个腾讯的面试题,来更加深层次认识这个stylus语言带给css的便捷。虽然考察的是纯html+css内容,要想纯html+css达到完美可却不简单。

效果

有三个列表,并且可以展开和收缩,这题目看起来简单,但是且听我细细道来,你会发现里面有很多的秘密!

html部分

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>纯css菜单</title>
    <link rel="stylesheet" href="1.css">
</head>

<body>
    <div class="accordion">
        <input type="checkbox" id="collapse1" hidden>
        <input type="checkbox" id="collapse2" hidden>
        <input type="checkbox" id="collapse3" hidden>
        <!-- div替代品 html5语义化标签 SEO比较重要 -->
        <article>
            <label for="collapse1">列表1</label>
            <p>内容1</p>
            <p>内容2</p>
            <p>内容3</p>
            <p>内容4</p>
        </article>
        <article>
            <label for="collapse2">列表2</label>
            <p>内容1</p>
            <p>内容2</p>
            <p>内容3</p>
            <p>内容4</p>
        </article>
        <article>
            <label for="collapse3">列表3</label>
            <p>内容1</p>
            <p>内容2</p>
            <p>内容3</p>
            <p>内容4</p>
        </article>
    </div>
</body>

</html>


首先我们要进行stylus语言环境的配置,并引入其生成的css文件,配置好之后,我们先看看html部分。

  1. 我们设置了三个复选框,并且复选框的id与label标签的for相对应,可以方便用户的操作。服务于用户。
  2. 我们用article语义化标签,这有助于搜索引擎优化(SEO)和屏幕阅读器更好地理解页面结构。每个标签里面放入四段列表。

到此我们html部分就结束啦,我们重点讲解一下css部分。

css部分

* {
  margin: 0;
  padding: 0;
}
.accordion {
  width: 300px;
}
.accordion article {
  cursor: pointer;
}
.accordion article + article {
  margin-top: 5px;
}
.accordion label {
  display: block;
  height: 40px;
  padding: 0 20px;
  background-color: #f00;
  cursor: pointer;
  line-height: 40px;
  font-size: 16px;
  color: #fff;
}
.accordion p {
  overflow: hidden;
  padding: 0 20px;
  border: 1px solid #f66;
  border-top: none;
  border-bottom-width: 0;
  max-height: 0;
  line-height: 30px;
  transition: all 500ms;
}
.accordion input:nth-child(1):checked ~ article:nth-of-type(1) p,
.accordion input:nth-child(2):checked ~ article:nth-of-type(2) p,
.accordion input:nth-child(3):checked ~ article:nth-of-type(3) p {
  max-height: 600px;
}
    <生成css>
---------------------------
    <书写的stylus>
    
    *
    margin 0
    padding 0
.accordion 
    width 300px
    article
        cursor pointer
        & + article
            margin-top 5px
    label
        display block
        height 40px
        padding 0 20px
        background-color red
        cursor pointer
        line-height 40px
        font-size 16px
        color #fff
    p
        overflow: hidden
        padding: 0 20px
        border: 1px solid #f66
        border-top: none
        border-bottom-width 0
        max-height: 0
        line-height 30px
        transition: all 500ms
    input  
        &:nth-child(1):checked ~ article:nth-of-type(1)  p , 
        &:nth-child(2):checked ~ article:nth-of-type(2)  p ,
        &:nth-child(3):checked ~ article:nth-of-type(3)  p 
            max-height:  600px


  1. 我们首先清除默认的内外边距。
  2. 对整体的accordion设置宽度。
  3. 对article标签设置鼠标经过变成小手。
  4. 通过相邻兄弟选择器我们设置第二个和第三个article的margin top 值。
  5. 对label标签我们设置一些基本的样式。
  6. 接下来就是我们最重要的部分,我们这里运用了全体兄弟选择器,我们以input下第一段为例子说明,后面都是一样的,我们选中第一个被勾选的复选框,然后通过全体兄弟选择器找到所有的article,并根据复选框的序号找到对应article的位置,然后将里面的p显现出来,这一段是我们的核心部分!所以也可以理解为nth-child搭配input,nth-of-type搭配article。


作者:落雪遥夏
链接:https://juejin.cn/post/7379873506543616010