关于css:你不知道的-CSS-进度条

1次阅读

共计 5460 个字符,预计需要花费 14 分钟才能阅读完成。

  • 作者:陈大鱼头
  • github:KRISACHAN

进度条是一个十分常见的性能,实现起来也不难,个别咱们都会用 div 来实现。

作为一个这么常见的需要,whatwg 必定是不会没有原生组件提供(尽管有咱们也不肯定会用),那么就让咱们来康康有哪些有意思的进度条实现形式。

惯例版 — div 一波流

这是比拟惯例的实现形式,先看成果:

源码如下:

<style>
  .progress1 {
    height: 20px;
    width: 300px;
    background-color: #f5f5f5;
    border-bottom-right-radius: 10px;
    border-top-right-radius: 10px;
  }
  .progress1::before {counter-reset: progress var(--percent, 0);
    content: counter(progress) '%\2002';
    display: block;
    height: 20px;
    line-height: 20px;
    width: calc(300px * var(--percent, 0) / 100);
    font-size: 12px;
    color: #fff;
    background-color: #2486ff;
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    border-bottom-right-radius: 10px;
    border-top-right-radius: 10px;
  }
  .btn {margin-top: 30px;}
</style>
<div id="progress1" class="progress1"></div>
<button id="btn" class="btn"> 点我一下嘛~</button>
<script>
  'use strict';
  let startTimestamp = (new Date()).getTime();
  let currentPercentage = 0;
  let maxPercentage = 100;
  let countDelay = 100;
  let timer = null;
  let start = false;
  const percentageChange = () => {const currentTimestamp = (new Date()).getTime();
    if (currentTimestamp - startTimestamp >= countDelay) {
      currentPercentage++;
      startTimestamp = (new Date()).getTime();
      progress1.style = `--percent: ${currentPercentage}`;
    };
    if (currentPercentage < maxPercentage) {timer = window.requestAnimationFrame(percentageChange);
    } else {window.cancelAnimationFrame(timer);
    };
  };
  const clickHander = () => {if (!start) {
      start = true;
      percentageChange();};
  };
  btn.addEventListener('click', clickHander);
</script>

这种办法的外围就是以以后盒子为容器,以 ::before 为内容填充。用 <div> 的益处就是实现简略,兼容性强,拓展性高,然而美中不足的是标签语义化不强。

进阶版 — input type=”range”

<input /> 是一个十分实用的替换元素,不同的 type 能够做不同的事件。第二种就是用 <input type="range" /> 来实现的。首先咱们来看看成果:

源码如下:

<style>
  .progress2[type='range'] {
    display: block;    
    font: inherit;
    height: 20px;
    width: 300px;
    pointer-events: none;
    background-color: linear-gradient(to right, #2376b7 100%, #FFF 0%);
  }
  .progress2[type='range'],
  .progress2[type='range']::-webkit-slider-thumb {-webkit-appearance: none;};
  .progress2[type='range']::-webkit-slider-runnable-track {
    border: none;
    border-bottom-right-radius: 10px;
    border-top-right-radius: 10px;
    height: 20px;
    width: 300px;
  }
  .btn {margin-top: 30px;}
</style>
<input id="progress2" class="progress2" type='range' step="1" min="0" max="100" value="0"/>
<button id="btn" class="btn"> 点我一下嘛~</button>
<script>
  'use strict';
  let startTimestamp = (new Date()).getTime();
  let currentPercentage = 0;
  let maxPercentage = 100;
  let countDelay = 100;
  let timer = null;
  let start = false;
  let percentageGap = 10;
  const percentageChange = () => {const currentTimestamp = (new Date()).getTime();
    if (currentTimestamp - startTimestamp >= countDelay) {
      currentPercentage++;
      startTimestamp = (new Date()).getTime();
      progress2.value = currentPercentage;
      progress2.style.background = `linear-gradient(to right, #2376b7 ${currentPercentage}%, #FFF 0%`;
    };
    if (currentPercentage < maxPercentage) {timer = window.requestAnimationFrame(percentageChange);
    } else {window.cancelAnimationFrame(timer);
    };
  };
  const clickHander = () => {if (!start) {
      start = true;
      percentageChange();};
  };
  btn.addEventListener('click', clickHander);
</script>

写完这个 demo 才发现,<input type="range" /> 并不适宜做这个性能。。一个是实现艰难,这个 type 组件的每个元件都能够独自批改款式,然而成果并不是很好。

另一个是因为 range 有专属语意 —— 范畴,所以它更适宜做上面这种事:

以上 demo 来自:https://developer.mozilla.org…

高级版 — progress 鸭

当然,上述两种形式都是模仿进度条,实际上咱们并不需要模仿,因为 whatwg 有为咱们提供原生的进度条标签 —— <progress>

咱们先看成果:

实现如下:

<style>
  .progress3 {
    height: 20px;
    width: 300px;
    -webkit-appearance: none;
    display: block;
  }
  .progress3::-webkit-progress-value {
    background: linear-gradient(
      -45deg, 
      transparent 33%, 
      rgba(0, 0, 0, .1) 33%, 
      rgba(0,0, 0, .1) 66%, 
      transparent 66%
    ),
      linear-gradient(
        to top, 
        rgba(255, 255, 255, .25), 
        rgba(0, 0, 0, .25)
      ),
      linear-gradient(
        to left,
        #09c,
        #f44);
    border-radius: 2px; 
    background-size: 35px 20px, 100% 100%, 100% 100%;
  }
  .btn {margin-top: 30px;}
</style>
<progress id="progress3" class="progress3" max="100" value="0"></progress>
<button id="btn" class="btn"> 点我一下嘛~</button>
<script>
  'use strict';
  let startTimestamp = (new Date()).getTime();
  let currentPercentage = 0;
  let maxPercentage = 100;
  let countDelay = 100;
  let timer = null;
  let start = false;
  const percentageChange = () => {const currentTimestamp = (new Date()).getTime();
    if (currentTimestamp - startTimestamp >= countDelay) {
      currentPercentage++;
      startTimestamp = (new Date()).getTime();
      progress3.setAttribute('value', currentPercentage);
    };
    if (currentPercentage < maxPercentage) {timer = window.requestAnimationFrame(percentageChange);
    } else {window.cancelAnimationFrame(timer);
    };
  };
  const clickHander = () => {if (!start) {
      start = true;
      percentageChange();};
  };
  btn.addEventListener('click', clickHander);
</script>

尽管有原生的进度条标签,然而标准里并没有规定它的具体表现,所以各个浏览器厂商齐全能够依照本人的爱好去定制,款式齐全不可控,所以标签虽好。。可用性却不强,有点惋惜。

终极版 — meter 赛高

当然,可能实现进度条性能的标签,除了下面所说的,还有 <meter> 标签。先看成果:

代码如下:

<style>
  .progress4 {
    display: block;    
    font: inherit;
    height: 50px;
    width: 300px;
    pointer-events: none;
  }
  .btn {margin-top: 30px;}
</style>
<meter id="progress4" class="progress4" low="60" high="80" min="0" max="100" value="0"></meter>
<button id="btn" class="btn"> 点我一下嘛~</button>
<script>
  'use strict';
  let startTimestamp = (new Date()).getTime();
  let currentPercentage = 0;
  let maxPercentage = 100;
  let countDelay = 100;
  let timer = null;
  let start = false;
  const percentageChange = () => {const currentTimestamp = (new Date()).getTime();
    if (currentTimestamp - startTimestamp >= countDelay) {
      currentPercentage++;
      startTimestamp = (new Date()).getTime();
      progress4.value = currentPercentage;
    };
    if (currentPercentage < maxPercentage) {timer = window.requestAnimationFrame(percentageChange);
    } else {window.cancelAnimationFrame(timer);
    };
  };
  const clickHander = () => {if (!start) {
      start = true;
      percentageChange();};
  };
  btn.addEventListener('click', clickHander);
</script>

这个标签可能比拟生疏,实际上它跟 <input type="range"> 的语义是一样的,用来显示已知范畴的标量值或者分数值。不一样的就是。。。它款式改起来更麻烦。

总结

本文测评了 4 种实现进度条的形式,得出的论断就是 —— <div> 赛高。。。尽管有的时候想优雅一点谋求标签语义化,然而资源不反对,也很难堪。

嗯,万能的 <div>

以上 demo 都能够我的 codepen 上查看:https://codepen.io/krischan77…

正文完
 0