<li>新玩法:list-style-image属性超简单实现星级评分

1,456 阅读2分钟

CSS自CSS3以来,被拆分为多个模块进行更新。今天在查阅文档CSS Lists Module Level 3的时候看到li标签的冷门属性list-style-image,它可以设置列表开头的标记为图片

li { list-style-image: url("http://www.example.com/ellipse.png") }

笔者联想或许可以实现星级评分,下面是实践过程:

达到的效果:

  1. 鼠标点击或移动到星星上,该星星及其之前的星星会变成选中状态(金色),而该星星及其之后的星星则是未选中的状态(空星)。
  2. 任意改变星级(可以不按顺序地改变星级,也就是任意改变着色星星的数量)

1. html

<ul id="ul">
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>

2. css

 ul {
     display: flex;
     margin-left: 500px;
}

ul li {
    height: 36px;
    width: 36px;
    cursor: pointer;
    list-style-position: inside;
    list-style-image: url("./star.png")
}
  1. li父元素ul实现flex布局使得子元素由纵向排列变成横向排列

  2. 由于两张图片(空星和金星)大小不同,需要统一

  3. 核心样式:

    list-style-position: inside;
    list-style-image: url("./star.png")
    

    list-style-position: 使得listy-style-image占据文本位置

    inside 标记盒是主要块盒中的第一个行内盒,处于元素的内容流之后

    如不设置则会:

    li的标记盒始终位于li之前

    list-style-image: 设置li的标记盒(标记元素)为图片

    笔者在实现鼠标移动事件的过程中,最初的考虑是不使用js,而用:hover伪类实现,但是实现了鼠标事件后发现:hover失效了, 所以改用onmouseover事件来实现

    ul li:hover {
        height: 36px;
        width: 36px;
        list-style-image: url("./goldStar.png")
    } 
    
    ul li:hover~li {
        height: 36px;
        width: 36px;
        list-style-image: url("./goldStar.png")
    }
    

3. js

let ul = document.getElementById('ul').children // 获取所有li
let length = ul.length // li总数
// 图片转换常量
let lsi = "list-style-image"
let goldStarUrl = `url("./goldStar.png")`
let starUrl = `url("./star.png")`

for (let i in ul) {
    ul[i].onclick = function () {
        rate(ul, i, starUrl, goldStarUrl)
    }

    ul[i].onmouseover = function () {
        rate(ul, i, starUrl, goldStarUrl)
    }
}
// list-style-image地址转换操作
function selectStar(ele, star) { ele.style[lsi] = star }
// 完成星级评分操作
function rate(ul, i, star, gstar) {
    for (let index = Number.parseInt(i); index >= 0; index--) {
        selectStar(ul[index], gstar)
    }
    for (let j = Number.parseInt(i) + 1; j < length; j++) {
        selectStar(ul[j], star)
    }
}
  1. 获取所有li
  2. 遍历所有li并给他们添加点击事件和鼠标移动事件
  3. 发生操作时(点击、鼠标移动):改变元素(星星)及元素之前(选中)和元素之后(不选中)的样式

4. 发现

笔者检查元素时发现每个li会自带一个 ::marker 伪类

注释后发现其实它恰恰就是li的标记盒,也就是我们熟悉的小圆点

它扩展了li标记盒的展示空间,可以给li标记盒添加更多的样式

ul li::marker {
  color: red;
  font-size: 1.5em;
}

或许可以实现更多好玩的样式,详情请参照MDN文档::marker

如果觉得不错的话可以点个赞哟~😄如有错误欢迎指正,欢迎交流。✌️