通过一个原生标签学习去掉 WebKit 的默认样式

看到了这篇文章 《这样写 step 步骤条就轻松了》 | 志语自乐

<progress> 标签为 HTML5 新增标签,可以用于制作进度条样式。在此之前都是用 div 结合 JavaScript 画的,并封装成组件,通过这个标签可以节省一部分代码,但在样式的实现上略显捉襟见肘,因为 Chrome 有自己的默认样式。

Chrome 的大部分元素默认样式可以通过 Css ResetNormalize.css 去掉,将页面所有元素还原为基础样式,但有一部分元素是新增标签或有浏览器内部实现的样式还在,我们需要知道这些样式要怎么去除默认并自定义。

这里展开用 div 画的 progress 组件(Vue2.x实现)

Snipaste_2021-06-17_10-55-36.png

<template>
    <div class="progress-bar-list">
    <div class="one" v-for="i in list">
        <span>{{i.name}}</span>
        <span>
        <span class="bar" :style="{width: i.value/maxValue * 288 + 'px'}"></span>
        </span>
        <span>{{i.value}}</span>
    </div>
    </div>
</template>

<style lang="less">
.progress-bar-list {
  height: 150px;
  margin: 7px 0 0 15px;
  background-color: rgba(255, 255, 255, 0.1);

  .one {
    margin: 6px 9px;
    white-space: nowrap;

    span {
      display: inline-block;
      vertical-align: top;
      font-size: 21px;
      width: 126px;

      &:nth-child(1) {}

      &:nth-child(2) {
        width: 288px;

        .bar {
          height: 5px;
          vertical-align: middle;
          background-color: #7ebfe4;
        }
      }

      &:nth-child(3) {
        color: rgb(126, 191, 228);
      }
    }
  }
}
</style>

<script>
    export default {
    props: {
        /**
        * 数据格式样例
        *  [{ name: '住宅', value: 4749 },
            { name: '办公楼宇', value: 3628 }]
        */
        list: {
            type: Array,
            default: [],
        },
    },
    computed: {
        maxValue() {
        if (!this.list && this.list.length <= 0) {
            return 1 // 作除数 不设置0默认值 防止 data infinite error
        }
        return this.list.reduce((acc,cur)=> acc>cur?.value?acc:cur?.value,0)
        },
    }
    }
</script>

开启 Devtools 中 Show user agent shadow DOM

<progress> 标签可以点这个链接可以看到使用方式和效果 => W3School TIY Editor

简单的来说就是

<progress value="33" min="1" max="100">33</progress>

如果通过这个标签去自定义样式,则需要获取到它内部的元素。但在默认情况下打开 Chrome 选中这个元素会发现,它只是一个元素,并没有子元素。

所以需要打开 DevTools 设置中的 Show user agent shadow DOM 打开,然后再选中这个 progress 元素,就会有新的内容出现了。

Snipaste_2021-06-17_11-04-16.png

打开上述设置后的 progress 元素

progress 元素

自定义样式如下

/* 很粗暴的用一张雪碧图来处理了一下,图片就是前面的那张步骤条图片,只不过最终的效果就是根据不同的 value 值,展示高亮部分的步骤。如果要好好完整的搞,那么还需要做细节地处理。 */
progress {
  display: block;
  width: 300px;
  height: 35px;
  margin-bottom: 10px;
  -webkit-appearance: auto;
}
progress::-webkit-progress-bar {
  background: url(bg_step.png) no-repeat 0 0;
}
progress::-webkit-progress-value {
  background: url(bg_step.png) no-repeat 0 -50px;
}
progress[value="2"]::-webkit-progress-value {
  background-position: 0 -100px;
}
progress[value="3"]::-webkit-progress-value {
  background-position: 0 -150px;
}

【关键】去除 Chrome 默认样式

以上代码运行后会发现,我们写的样式并没有生效。这是因为对于 <progress> 元素,Chrome 有自己的默认样式,我们需要将默认样式移除,需要在 progress 中加入这个。

progress {
  -webkit-appearance: none;
}

appearance

该属性的主要作用是改变元素的外观,而 progress 内置了一个外观样式,默认值是 auto,也就代表着这个元素将很有可能会跟着系统的主题而变化。在 MDN 有这么一句介绍:

The appearance CSS property is used to display an element using platform-native styling, based on the operating system’s theme.

同时必不可少的会附带上了很多属性值的效果,在这里就不再一一展开说明了。但需要注意,如果我们要对一些特殊的组件,尤其是表单类型的,在不在是否有默认的外观属性,就随手加一下。当然啦,最稳妥的方式就是通过 DevTools 看一下 computed 后的样式就知道了。