HTML+CSS实现进度条

最近业务上有了产品预约进度条的需求,故学习已有的一些成熟方案,便捷掌握使用方法

  • 均分滚动条

首先是网易云音乐的用户等级进度条


网易云音乐进度条

经过一番搬运整理,我们也可以实现间隔均分段的滚动条,代码中的图像文件来自网易云音乐用户等级页面,感兴趣的读者可到官网上拿取。
以下为CSS样式

<style>
    .sub {
        width: 100%;
        position: relative;
        z-index: 1;
        padding-top: 31px;
        height: 34px;
        overflow: hidden;
    }
    .sub .subbg {
        width: 835px;
        height: 10px;
        position: absolute;
        left: 0;
        bottom: 0;
        z-index: 2;
        border-radius: 10px;
        background: #dcdfe6;
    }
    .sub .subbg span {
        /*一条渐变线*/
        background: url(mylevelbar.png) 0 0 repeat-y;
        width: 100%;
        height: 10px;
        display: block;
        border-radius: 10px;
        -webkit-animation: subbar 2s;
        animation: subbar 2s;
    }
    .sub .subnum {
        width: 100%;
        height: 40px;
        left: 0;
        bottom: 0;
        position: absolute;
        z-index: 2;
    }
    .divison {
        position: absolute;
        left: 13px;
        bottom: 0;
        width: 100%;
        height: 10px;
    }
    .divison span {
        float: left;
        display: inline;
        width: 1px;
        background: #fff;
        height: 10px;
        margin-left: 80px;
    }
    .divnum {
        position: absolute;
        left: -40px;
        top: -20px;
        font-family: 'Microsoft YaHei';
        font-size: 18px;
        color: #c4c6cc;
        width: 980px;
    }
    .divnum li.z-ov {
        color: #ed5757;
        -webkit-animation: show 3s;
        animation: show 3s;
    }
    .divnum li {
        float: left;
        width: 25px;
        height: 28px;
        line-height: 24px;
        display: inline;
        margin-right: 56px;
        text-align: center;
    }
    li {list-style: none;}
    .divnum li.z-on {
        color: #fff;
        -webkit-animation: show1 2s;
        animation: show1 2s;
        background-position: 0 -50px;
    }
    .h3 em,
    .divnum li.z-on,
    .n-pow .telist li,
    .n-level i,
    .n-level-big i {
        /*此处的 0 -50px 和官网上的 0 9999px 有差异*/
        background: url(mylevel.png) no-repeat 0 -50px;
    }
    /*动画效果*/
    @keyframes subbar {
        0% {
            width: 0;
        }
        100% {
            width: 100%;
        }
    }
    @keyframes show {
        0% {
            color: #c4c6cc;
        }
        100% {
            color: #ed5757;
        }
    }
    @keyframes show1 {
        0% {
            color: #c4c6cc;
            background-position: 9999px 9999px;
        }
        50% {
            color: #c4c6cc;
            background-position: 0 -50px;
        }
        100% {
            color: #fff;
        }
    }
    </style>

以下为HTML结构

<!-- 网易云音乐web版进度条 -->
<div class="sub">
    <div class="subbg">
        <!-- 通过js控制div的宽度实现进度条的进度,用动画控制前进效果 -->
        <div style="width:820.8666666666667px;"><span></span></div>
        <!-- /宽度为25+81x等级x70% -->
    </div>
    <div class="subnum">
        <div class="divison"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
        <div class="divnum">
            <ul>
                <li class="z-ov">0</li>
                <li class="z-ov">1</li>
                <li class="z-ov">2</li>
                <li class="z-ov">3</li>
                <li class="z-ov">4</li>
                <li class="z-ov">5</li>
                <li class="z-ov">6</li>
                <li class="z-ov">7</li>
                <li class="z-ov">8</li>
                <li class="z-on">9</li>
                <li class="">10</li>
            </ul>
        </div>
        <!-- / .ov已过等级样式 .on达到等级样式 -->
    </div>
</div>

最终效果

效果图

看完了均匀进度的进度条,分享一下不均匀进度的进度条,一个移动端demo

  • 不均分进度条

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>我的等级</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0,maximum-scale=1.0, user-scalable=0" />
  <link rel="stylesheet" href="style.css">
  <style id="dynamic"></style>
  <script>
     var Config = {
        // 等级大图片url地址
        courierRankBigUrl:  'images/grade3-icon.png',

        // 配送员等级名称
        courierRankName: '3级鲜锋官',

        // 同时可接单数
        courierCanPackgeCountDoing:  '10',

        // 积分数组1,2,3,4,5;50,100,150,200,250
        integrationRankString:  '1,2,3,4,5;0,100,150,200,250',

        // 经验豆数组1,2,3,4,5;50,100,150,200,250
        experienceBeanRankString: '',

        // 本月累计积分
        monthCompletedWaybills:  '200'
     };
  </script>
  <script>
      function setStyle(obj,css){
         for(var i in css){
            obj.style[i] = css[i];
         }
     }
     // 将积分数组切成两块,并用split方法转换成数组
      var scores = Config.integrationRankString.split(";")[1].split(',');
      console.log((Config.integrationRankString.split(";")[1]));
      console.log( Config.integrationRankString.split(";")[1].split(',') instanceof Array);

      // 后台返回的积分
      var score = Config.monthCompletedWaybills;
        /*
         * 进度条的宽度百分比的计算方式设计如下:
         * 假如第一段50分 第二段100分 第三段300分  第四段500分 那么假如服务器返回的是375分,那么在浏览器下占比如下
         * 由于页面分了5段,每段显示20%的宽度; 遍历数组[50,100,300,500],定义一个遍历count = 0;
         * 如果数组任何一段小于服务器返回375的话,那么count自加1,因此count=3
         * 比例如下:(375 - 300) / (500 - 300) + 3 = 3/8 + 3 = 3.375; 最后 3.375 / 5 * 100%= 67.5%;
         * 记住 因为数组arrs去掉了第一项了 所以curNum要减去1 即:curNum - 1
         */
         /*
          * @todo 计算进度条的百分比
          * @param {score,arrs} 服务器返回的总分 服务器返回的数组
          */
         var count = 0;
         function percent(score,arrs) {
            var tempCount = 0;
            var percent;
            //  如果积分大于数组最后一个总积分的话, 那么进度条就是最大的
            if(score*1 > arrs[arrs.length -1] * 1) {
                score = arrs[arrs.length -1];
            }
            for(var i = 0; i < arrs.length; i+=1) {
                if(score*1 > arrs[i]*1) {
                    tempCount++;
                }
            }
            count = tempCount;
            if(tempCount*1 < 1) {
                percent = (score / arrs[0]) / 5 * 100;
            }else {
                percent = ((score - arrs[tempCount - 1]) / (arrs[tempCount] - arrs[tempCount - 1]) + tempCount) / 5 * 100;
            }

            return percent + "%";
         }
         if(scores[0] == 0) {
            scores.shift();
         }
         // 返回第五段的值 计算方法 val fiveVal = arrs[arrs.length - 1] * 2
         var fiveVal = scores[scores.length - 1] * 2 + "";
         scores.push(fiveVal);

         var width = percent(score,scores);

         var dynamic = document.getElementById("dynamic");
         dynamic.innerHTML = '@-webkit-keyframes load {0% {width: 0%;}100% {width: '+width+';}}';

         window.onload = function(){
            var bar = document.getElementById("progress-bar");
            setStyle(bar,{width:width});
         }
  </script>
 </head>
 <body>
    <div class="myGrade-container">
        <div class="myGrade-header">
            <p class="grade-img" id="grade-img"></p>
            <p class="grade-desc" id="courierRankName">二级鲜锋官</p>
            <p class="grade-amount">可同时接单数<i id="grade-amount">2</i>单</p>
        </div>
        <div class="myGrade-progress-bar">
            <h4>本月升级进度</h4>
            <div class="myGrade-integral">
                <div class="maGrade-wrap">
                    <h3 id="minMonthScore">本月累计积分<i id="monthScore">(97分)</i></h3>
                    <div class="progress-bar-inner">
                        <div class="progree-nums" id="progree-nums">
                            <!--
                            <span>1级</span>
                            <span>2级</span>
                            <span>3级</span>
                            <span>4级</span>
                            <span>5级</span>
                            -->
                        </div>
                        <div id="progress-box" class="progress-box">
                            <div class="division-bar" id="division-bar">
                                <span class="pbar w20"></span>
                                <span class="pbar w40"></span>
                                <span class="pbar w60"></span>
                                <span class="pbar w80"></span>
                            </div>
                            <div id="progress-bar" class="progress-bar">
                            </div>
                            <div></div>
                        </div>
                        <div class="progress-score" id="progress-score">
                            <!--
                            <i>0</i>
                            <span>50分</span>
                            <span>100分</span>
                            <span>300分</span>
                            <span>500分</span>
                            -->
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <p class="myGrade-state">本月累计获得的积分决定下月的等级</p>
        <ul class="myGrade-list">
            <li id="show-grade">查看等级特权<i></i></li>
            <li id="how-grade">如何提升等级<i></i></li>
        </ul>
    </div>

    <script>
        function $Id(id){
            return document.getElementById(id);
        };
        function hasClass(obj, cls) {
            return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
        }

        function addClass(obj, cls) {
            if (!hasClass(obj, cls)) obj.className += " " + cls;
        }
        var bar = $Id("progress-bar"),                 // 进度条id
            gradeImg = $Id("grade-img"),               // 等级图片icon
            courierRankName = $Id("courierRankName"),  // 配送员等级名称
            gradeAmount = $Id("grade-amount"),         // 可同时接单数
            monthScore = $Id("monthScore"),            // 本月累计积分
            scoreGrade = $Id("progree-nums"),          // 等级id
            progressScore = $Id("progress-score"),     // 积分id
            divisionBar = $Id("division-bar");         // 进度条分隔条

        // 服务器返回的等级图片
        gradeImg.style.backgroundImage="url("+Config.courierRankBigUrl+")";

        // 服务器返回的等级名称
        courierRankName.innerHTML = Config.courierRankName;

        // 可同时接单数
        gradeAmount.innerHTML = Config.courierCanPackgeCountDoing;

        // 本月累计积分
        monthScore.innerHTML = "(" + Config.monthCompletedWaybills + "分" + ")";
        if(Config.monthCompletedWaybills *1 < 0) {
            var minMonthScore = $Id("minMonthScore");
            if(!hasClass(minMonthScore,'current')) {
                addClass(minMonthScore,'current');
            }
        }
        // 服务器返回的等级和积分数组
        var grades = Config.integrationRankString.split(";")[0].split(','),
            scores = Config.integrationRankString.split(";")[1].split(','),
            gradesHTML = '';
            scoresHTML = '';
        for(var i = 0; i < grades.length; i++) {
            gradesHTML += '<span>'+grades[i]+'级</span>';
        }
        scoreGrade.innerHTML = gradesHTML;
        for(var j = 0; j < scores.length; j++) {
            if(j == 0) {
                scoresHTML += '<i>'+scores[j]+'</i>';
            }else {
                scoresHTML += '<span>'+scores[j]+'分</span>';
            }
        }
        progressScore.innerHTML = scoresHTML;
        var divisionBarSpans = divisionBar.getElementsByTagName("span");
        // 后台返回的积分
        var score2 = Config.monthCompletedWaybills;

        var curIndex = scores.indexOf(score2);
        if(count*1 > 0) {
             for(var i = 0; i < count; i++) {
                if(!hasClass(divisionBarSpans[i],'current')) {
                    // 比如返回积分是200 正好数组也有200这个积分 正好相等的话 ,那么就不添加current类名
                    if(i !== curIndex) {
                        (function(i){
                            setTimeout(function(){
                                addClass(divisionBarSpans[i],'current');
                            },2500);
                        })(i)
                    }
                }
             }
        }
    </script>
 </body>
</html>

css 样式

// css reset
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{margin:0;padding:0;font-family:"Microsoft yahei";color:#000;}
     ul,ol,li{list-style:none;}
     i,em{font-style:normal}
     img{max-width:100%;}
     html{font-size:62.5%;}
     html,body{background:#f5f5f5;}

     .myGrade-container {width:100%;background:#f5f5f5;}
     .myGrade-header {width:100%;margin-top:20px;border-top:1px solid #d7d7d7;border-bottom:1px solid #d7d7d7;text-align:center;background:#fff;padding:18px 0 20px 0;}
     .grade-img {background-repeat:no-repeat;background-size:66px 66px;width:66px;height:66px;margin:0 auto;}
     .grade-desc {padding:12px 0;color:#fc6605;}
     .grade-amount {font-size:1em;font-family:"Microsoft yahei";}
     .grade-amount i{padding-left:4px;}
     .myGrade-progress-bar {width:100%;}
     .myGrade-progress-bar h4{color:#707070;font-size:1.125em;font-weight:500;padding-left:10px;padding-top:30px;}
     .myGrade-integral {border-top:1px solid #d8d7d8;border-bottom:1px solid #d8d7d8;background:#fff;margin-top:8px;}
     .maGrade-wrap {width:90%;margin:0 auto;padding-bottom:20px;}
     .myGrade-integral h3{font-size:1.125em;font-weight:500;padding:16px 0;}
     .myGrade-integral h3 i{color:#81bb3b;}
     .progress-bar-inner {position:relative;}
     .progree-nums {width:100%;font-size:0;overflow:hidden;}
     .progree-nums span,.progress-score span{float:left;display:inline-block;width:20%;text-align:center;color:#757575;}
     .progress-box{position:relative;height:16px;border:1px solid #a0db58;border-radius:30px;margin-top:5px;}
     .progress-bar{position:absolute;left:0;top:0;height:16px;background:#a0db58;border-radius:30px;z-index:9;}

     .division-bar {position:absolute;left:0;top:0;width:100%;z-index:11;}
     .division-bar .pbar {position:absolute;height:16px;background-color:#a0db58;left:20%;width:1px;}
     .division-bar .w20 {left:20%;}
     .division-bar .w40 {left:40%;}
     .division-bar .w60 {left:60%;}
     .division-bar .w80 {left:80%;}

     .progress-score {position:relative;margin-top:5px;font-size:0;overflow:hidden;}
     .progress-score span{text-align:right;}
     .progress-score i{position:absolute;left:0;top:0;color:#757575;}
     .myGrade-state {width:95%;height:50px;padding-left:5%;margin-top:15px;background:#f5f5f5;color:#707070;border-bottom:1px solid #d8d7d8;}
     .myGrade-list li{width:95%;padding-left:5%;background:#fff;border-bottom:1px solid #d8d7d8;height:60px;line-height:60px;}
     .myGrade-list li i{float:right;padding-right:4%;background:url("images/arrow.png") no-repeat;width:10px;height:17px;background-size:10px 17px;margin-top:22px;}


     /* 当前加粗 */
     .progree-nums span.current{font-weight:700;color:#212121;}
     .division-bar span.current{background-color:#fff;}
     .myGrade-integral h3.current,.myGrade-integral h3.current i{color:#f44336;}
     /* 媒体查询 */
     .grade-desc{font-size:1.8rem;}
     .grade-amount{font-size:1.6rem;}
     .myGrade-progress-bar h4{font-size:1.5rem;}
     .myGrade-integral h3{font-size:1.6rem;}
     .progree-nums span,.progress-score span{font-size:1.5rem;}
     .myGrade-state {font-size:1.5rem;}
     .myGrade-list li {font-size:1.8rem;}
     .progress-score i{font-size:1.5rem;}
     @media (min-width:360px) and (max-width: 399px) {

     }
     @media (min-width: 320px) and (max-width:359px){
        .progress-score i,.progress-score span{font-size:1.3rem;}
     }

     .progress-bar {background:-webkit-gradient(linear, 0 0, 0 100%,from(#a0db58),to(#a0db58));-webkit-animation: load 3s ease-out 1;}

完成效果

完成效果

移动端的demo来自网络,这个demo涉及到了进度条的动态实现,代码比较长比较复杂,实现不均匀进度。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 各种纯css图标 CSS3可以实现很多漂亮的图形,我收集了32种图形,在下面列出。直接用CSS3画出这些图形,要比...
    剑残阅读 9,472评论 0 8
  • 1、垂直对齐 如果你用CSS,则你会有困惑:我该怎么垂直对齐容器中的元素?现在,利用CSS3的Transform,...
    kiddings阅读 3,147评论 0 11
  • 1. tab列表折叠效果 html: 能源系统事业部 岗位名称: 工作地点 岗位名...
    lilyping阅读 1,829评论 0 1
  • 不会用代码框,所以看着有些乱套,,,,html部分 <!DOCTYPE html> 迅雷看看 ...
    这就是个帅气的名字阅读 1,525评论 0 0
  • 清晨起来,有雾有雾, 我在路上看见—— 四处的假面。 枯木伸手向天空张望, 它疼痛的呼喊, 一切似无非无, 一切似...
    释迦干屎橛阅读 307评论 0 0