纯CSS实现极简下拉菜单:从入门到精通Stylus

718 阅读7分钟

引言

作为一个前端新手,我在最近的学习过程中,逐渐接触到了CSS、Stylus重要的技术点。在编写前端页面时,使用Stylus可以让我们的CSS代码更加简洁和可维护。通过这次学习和实践,我不仅掌握了基础知识,还尝试将它们应用于实际项目中,希望我的分享能对同样处于学习阶段的掘友们有所帮助。

Stylus入门与进阶

什么是Stylus?

Stylus是一种CSS预处理器,它允许我们使用更简洁的语法来编写CSS代码,支持变量、嵌套、函数等高级功能,在stylus编写的内容会同步更新在css中,从而提高开发效率和代码可维护性。

安装与配置Stylus

要使用Stylus,我们首先需要进行安装和配置。以下是具体步骤:

  1. 安装Node.js和npm(Node.js的包管理工具)。

  2. 通过npm安装Stylus:

npm install stylus -g
  1. 创建一个可编译Stylus文件(例如styles.styl),并使用命令行工具编译它,同时会生成一个同名的css文件:
stylus -w styles.styl -o styles.css

Stylus基础语法与特点

Stylus的语法比CSS更简洁,支持无分号和花括号的写法。以下是一些基础语法和特点:

变量

primary-color = #3498db
body
  background-color primary-color

嵌套

nav
  ul
    margin 0
    padding 0
  li
    display inline-block

通过缩进实现子菜单

Stylus通过缩进实现CSS的嵌套,从而简化了代码结构,特别适用于子菜单的样式编写。

nav
  ul
    li
      &:hover
        ul
          display block

自动补全父选择器

tylus可以自动补全父选择器,使代码更加简洁。

ul
  li
    &.active
      color red

这里的 &.active 会自动补全为 ul li.active

'+' 兄弟选择器

.accordion
    width 300px
    article
        cursor pointer
        & + article // 除了第一个article外,其它的article添加上margin-top
            margin-top 5px

+ 兄弟选择器用于选择紧接在指定元素之后的兄弟元素,除了第一个article外,其它的article添加上margin-top 5px的样式

~ 相邻同层选择器

label
  display inline-block
  margin-right 10px

label ~ input
  margin-left 10px

~ 相邻同层选择器用于选择所有匹配的后续兄弟元素。在这个示例中,所有位于 label 之后的 input 元素会有左侧的间距。

那么接下来我们通过实现一个简单的下拉菜单来熟悉一下stylus的代码编写

下拉菜单

我们通过实现一个下拉菜单来实战编写一下stylus

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="./demo.css">
</head>

<body>
    <div class="accordion">
        <input type="checkbox" id="collpase1" hidden>
        <input type="checkbox" id="collpase2" hidden>
        <input type="checkbox" id="collpase3" hidden>
        <!-- (article>lable+p*4)*3  div替代品,html5 语义化标签 SEO 比较重要-->
        <article>
            <label for="collpase1">列表1</label>
            <p>内容1</p>
            <p>内容2</p>
            <p>内容3</p>
            <p>内容4</p>
        </article>
        <article>
            <label for="collpase2">列表2</label>
            <p>内容1</p>
            <p>内容2</p>
            <p>内容3</p>
            <p>内容4</p>
        </article>
        <article>
            <label for="collpase3">列表3</label>
            <p>内容1</p>
            <p>内容2</p>
            <p>内容3</p>
            <p>内容4</p>
        </article>
    </div>
</body>
</html>

1. 控制菜单的展开与折叠

  • type="checkbox"hidden:这里我们先设置了三个复选框,并将它们隐藏,但它们的状态(选中或未选中)可以通过其他元素来控制,例如<label>

  • 当复选框被选中时,对应的菜单项会展开;当复选框未被选中时,对应的菜单项会折叠。

2. 与label配合使用

  • 通过设置<label for="checkbox_id">,点击label会触发对应的复选框切换其为选中状态。

  • 例如,点击<label for="collpase1">会切换<input type="checkbox" id="collpase1">的状态,label中的for属性值和input中的id属性值需一致,互相绑定ID。

Stylus

1. 全局样式重置

* 
    padding 0
    margin 0

重置所有元素的默认内边距和外边距,确保样式一致性。

2. .accordion:定义手风琴菜单的样式

.accordion
    width 300px

设置手风琴菜单的宽度为300px。

3. article:定义每个菜单项的样式

article
    cursor pointer
    & + article
        margin-top 5px
  • 设置鼠标悬停时的指针样式。

  • 使用兄弟选择器& + article为每个article添加5px的上边距,除了第一个article

4. 利用input:checked伪类,可以控制对应菜单项的样式变化

.accordion
    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
  • 使用:nth-child(n):checked选择特定的复选框并应用样式。

  • 当特定复选框被选中时,使用~选择对应的article中的p元素,将其max-height设置为600px,以实现展开效果。

  • 通过这种方式,可以控制不同article内容的展开与折叠,无需JavaScript,仅通过CSS和HTML的交互即可实现。

5. label:定义标签的样式

label
    display block
    height 40px
    padding 0 20px
    background-color #f66
    cursor pointer
    line-height 40px
    font-size 16px
    color #fff
  • 设置为块级元素。

  • 设置高度、内边距、背景颜色、鼠标指针样式、行高、字体大小和颜色。

6. p:定义菜单内容项的样式。

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 // 过渡
  • 设置溢出隐藏。

  • 设置内边距和边框样式。

  • 设置最大高度为0,以实现折叠效果。

  • 设置行高和过渡效果,使展开和折叠更加平滑,而不是立即切换。

完整 stylus 代码如下:

*
    padding 0
    margin 0

.accordion
    width 300px
    article
        cursor pointer
        & + article // 除了第一个article外,其它的article添加上margin-top
            margin-top 5px
    input
        &:nth-child(1):checked ~ article:nth-of-type(1) p,// 获取第一个input,当被选中时,article:nth-of-type(1)的p的max-height变为600px
        &:nth-child(2):checked ~ article:nth-of-type(2) p, 
        &:nth-child(3):checked ~ article:nth-of-type(3) p
            max-height 600px

    label
        display block
        height 40px
        padding 0 20px
        background-color #f66
        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 // 默认为0
        line-height 30px
        transition all 500ms // 0.5s内过渡

同步生成的css代码如下:

* {
  padding: 0;
  margin: 0;
}
.accordion {
  width: 300px;
}
.accordion article {
  cursor: pointer;
}
.accordion article + article {
  margin-top: 5px;
}
.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;
}
.accordion label {
  display: block;
  height: 40px;
  padding: 0 20px;
  background-color: #f66;
  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;
}

效果展示

总结

  1. CSS高级选择器:利用兄弟选择器& + article、相邻同层选择器~、以及:nth-child(n):nth-of-type(n)选择特定元素并应用样式。
  2. 复选框与标签交互:隐藏的复选框与标签绑定,通过点击标签切换复选框的选中状态,进而控制对应内容的展开与折叠。
  3. 过渡效果:通过transition all 500ms,使内容的高度变化平滑过渡,提供更好的用户体验。
  4. 语义化HTML:使用<article><label>等语义化标签,有助于SEO和代码可读性。

我们通过这种方式,实现了一个简单但以易于维护的纯CSS下拉菜单。使用Stylus编写CSS代码,不仅简化了语法,还提供了模块化和代码复用的能力,使得样式定义更加简洁和高效。通过适当的CSS选择器和过渡效果,可以使我们的项目交互效果更好,我分享的只是一个极其简单的下拉菜单,希望能够在我今后的项目中运用到,我们拭目以待。

别忘了点赞收藏+关注哦~