自定义表单伪元素样式
开发 Web 应用时,表单控件的默认样式由浏览器客户端控制,不同浏览器渲染效果差异明显,往往无法满足业务的视觉需求。可以借助浏览器提供的引擎私有伪元素钩子修改表单控件外观。
这类伪元素属于浏览器私有扩展,必须带上对应浏览器引擎前缀,且不同引擎的 API 完全不互通。
注意:这类私有伪元素不属于标准 CSS,浏览器随时可能移除或变更,生产环境使用务必谨慎,仅部分 CSS 属性可以生效。
浏览器内核与 CSS 前缀
浏览器内核分为渲染引擎(负责 HTML、CSS 布局绘制)与 JS 引擎(负责 JS 解析执行),表单控件的 Shadow DOM、私有伪元素行为完全由渲染引擎决定。
| 渲染引擎 | 代表浏览器 | CSS 前缀 |
|---|---|---|
| Trident | IE10+ | -ms- |
| Gecko | Firefox | -moz- |
| WebKit | Blink(Chrome)、Safari、iOS 全部浏览器 | -webkit- |
| Presto | 旧版 Opera(已废弃) | -o- |
备注:Blink 是 WebKit 的分支,Chrome、新版 Opera 依旧沿用 -webkit- 前缀。
Shadow DOM 查看方式
HTML5 表单控件的原生 UI,底层由浏览器内置 User-Agent Shadow DOM 实现,不在普通 DOM 树中。
Chrome 开启查看:开发者工具 → 设置 → Preferences → Elements → Show user agent shadow DOM。
appearance 属性
appearance 用来清除控件原生系统样式,是自定义表单样式的常用前置属性。
input {
-webkit-appearance: none;
appearance: none;
}
表单元素的伪元素
1. input[type=color]
WebKit、Blink:
::-webkit-color-swatch-wrapper:外层容器::-webkit-color-swatch:颜色预览色块

<style>
.color input { width: 120px; }
.color_item::-webkit-color-swatch-wrapper {
border: 1px solid #777;
background-image: linear-gradient(to right, red, orange 15%, yellow 30%, green 50%, darkcyan 65%, blue 80%, purple);
}
.color_item::-webkit-color-swatch {
height: 21px;
position: relative;
left: 135px;
top: -5px;
}
</style>
<section class="color">
<input type="color">
<br><br>
<input class="color_item" type="color">
</section>
2. input[type=date]
WebKit、Blink,8 个私有伪元素:
::-webkit-datetime-edit:整体编辑区域::-webkit-datetime-edit-fields-wrapper:年月日外层容器::-webkit-datetime-edit-text:年月日之间分隔符::-webkit-datetime-edit-month-field:月份::-webkit-datetime-edit-day-field:日期::-webkit-datetime-edit-year-field:年份::-webkit-inner-spin-button:增减上下箭头::-webkit-calendar-picker-indicator:日历下拉图标

<style>
.date::-webkit-datetime-edit { padding: 1em; background: #f2f2f2; }
.date::-webkit-datetime-edit-fields-wrapper { background: silver; }
.date::-webkit-datetime-edit-text { color: red; padding: 0 0.3em; }
.date::-webkit-datetime-edit-month-field { color: blue; }
.date::-webkit-datetime-edit-day-field { color: green; }
.date::-webkit-datetime-edit-year-field { color: purple; }
.date::-webkit-inner-spin-button { display: none; }
.date::-webkit-calendar-picker-indicator { background: #f2f2f2; color: orange }
</style>
<section>
<input type="date">
<br /><br />
<input class="date" type="date">
</section>
3. input[type=file]
- Trident(IE10+):
::-ms-browse,文件选择按钮 - WebKit、Blink:
::-webkit-file-upload-button,文件选择按钮

<style>
.file::-ms-browse {
background: #0aa;
color: white;
padding: 1em;
border: 1px solid blue;
line-height: 20px;
}
.file::-webkit-file-upload-button {
background: #0aa;
color: white;
padding: 1em;
border: 1px solid blue;
line-height: 20px;
}
</style>
<section>
<input type="file">
<input class="file" type="file">
</section>
4. input[type=number]
WebKit、Blink:
::-webkit-textfield-decoration-container:箭头外层容器::-webkit-inner-spin-button:数字上下箭头,一般仅做隐藏,很多样式不生效::-webkit-outer-spin-button:极少生效

<style>
.number::-webkit-textfield-decoration-container {
border: 2px solid #0aa;
}
.number::-webkit-inner-spin-button {
/*color: red; // 无效
background: blue; // 无效*/
-webkit-appearance: none;
}
.number::-webkit-outer-spin-button {}
</style>
<section>
<input type="number">
<br /><br />
<input class="number" type="number">
</section>
5. input[type=password]
Trident(IE10+):::-ms-reveal,控制密码框显示明文的眼睛图标,可修改样式或隐藏。
<style>
.password::-ms-reveal {
color: white; background: #0aa;
}
</style>
<section>
<input type="password">
<br /> <br />
<input class="password" type="password">
</section>
6. placeholder 属性占位文本
注意:现行标准伪元素是 ::placeholder,生产优先使用。IE 使用伪类 :-ms-input-placeholder(单冒号),旧版 WebKit、Firefox 为带前缀的伪元素。

<style>
.placeholder::-moz-placeholder { color: red; }
.placeholder:-ms-input-placeholder { color: red; }
.placeholder::-webkit-input-placeholder { color: red; }
</style>
<section>
<input type="text" placeholder="placeholder">
<input class="placeholder" type="text" placeholder="placeholder">
</section>
7. input[type=range] 滑块
Gecko(Firefox):
::-moz-range-track:轨道::-moz-range-thumb:滑块手柄
Trident(IE10+):
::-ms-fill-lower:已滑动部分::-ms-fill-upper:未滑动部分::-ms-thumb:手柄::-ms-track:轨道::-ms-ticks-before、::-ms-ticks-after:刻度::-ms-tooltip:提示,仅支持display:none
WebKit、Blink:
::-webkit-slider-runnable-track:轨道::-webkit-slider-thumb:滑块手柄

<style>
.range::-moz-range-track {
border: 2px solid red;
height: 20px;
background: orange;
}
.range::-moz-range-thumb { background: blue; height: 30px; }
.range::-ms-fill-lower { background: orange; }
.range::-ms-fill-upper { background: green; }
.range::-ms-ticks-after { display: block; color: blue; }
.range::-ms-ticks-before { display: block; color: red; }
.range::-ms-thumb { background: red; }
.range::-ms-track { padding: 20px 0; }
.range::-ms-tooltip { display: none; /* display and visibility only */ }
.range::-webkit-slider-runnable-track {
border: 2px solid #0aa;
background: #f2f2f2;
padding: 5px 0;
}
.range::-webkit-slider-thumb { outline: 2px solid #0aa; }
</style>
<section>
<input type="range">
<br /> <br />
<input class="range" type="range">
</section>
8. input[type=search]
WebKit、Blink:
::-webkit-search-cancel-button:搜索框清除叉号::-webkit-search-results-button:搜索放大镜图标
备注:大多场景只能做隐藏,自定义图片样式兼容性较差。
<style>
.search { -webkit-appearance: none; }
.search::-webkit-search-cancel-button { -webkit-appearance: none; }
.search::-webkit-search-results-button { -webkit-appearance: none; }
</style>
<section>
<input type="search">
<br /> <br />
<input class="search" type="search">
</section>
9. meter 计量条
WebKit、Blink:
::-webkit-meter-bar:外层底条::-webkit-meter-optimum-value:最优状态::-webkit-meter-suboptimum-value:一般状态::-webkit-meter-even-less-good-value:较差状态
注意:::-webkit-meter-* 已标记废弃,新版 Chrome 上效果不稳定,不要作为生产依赖。

<style>
.meter ::-webkit-meter-bar {
height: 30px;
background: #f2f2f2;
border: 1px solid #0aa;
}
.meter ::-webkit-meter-optimum-value { background: green; }
.meter ::-webkit-meter-suboptimum-value { background: orange; }
.meter ::-webkit-meter-even-less-good-value { background: blue; }
</style>
<section>
<div>
<meter low="69" high="80" max="100" optimum="100" value="92">A</meter>
<meter low="69" high="80" max="100" optimum="100" value="72">C</meter>
<meter low="69" high="80" max="100" optimum="100" value="52">E</meter>
</div>
<div class="meter">
<meter low="69" high="80" max="100" optimum="100" value="92">A</meter>
<meter low="69" high="80" max="100" optimum="100" value="72">C</meter>
<meter low="69" high="80" max="100" optimum="100" value="52">E</meter>
</div>
</section>
10. progress 进度条
WebKit、Blink:
::-webkit-progress-inner-element::-webkit-progress-bar:背景条::-webkit-progress-value:已完成进度
Gecko(Firefox):::-moz-progress-bar
Trident(IE10+):::-ms-fill

<style>
.progress progress { -webkit-appearance: none; }
.progress ::-webkit-progress-inner-element { background: black; }
.progress ::-webkit-progress-bar { border: 2px solid #0aa; }
.progress ::-webkit-progress-value { background: orange; }
.progress ::-moz-progress-bar { background: red; }
.progress ::-ms-fill { background: red; }
</style>
<section>
<div>
<progress max="100" value="50"></progress>
<progress max="100" value="75"></progress>
<progress max="100" value="90"></progress>
</div>
<div class="progress">
<progress max="100" value="50"></progress>
<progress max="100" value="75"></progress>
<progress max="100" value="90"></progress>
</div>
</section>
11. textarea
WebKit、Blink:::-webkit-resizer,右下角拖拽手柄。
备注:仅能隐藏手柄;想要彻底关闭拖拽能力,请使用标准 CSS resize: none。

<style>
.textarea { resize: none; }
.textarea::-webkit-resizer {
display: none;
-webkit-appearance: none;
}
</style>
<section>
<textarea></textarea>
<textarea class="textarea"></textarea>
</section>
总结
- 全部伪元素属于浏览器私有扩展,不是 W3C 标准,版本迭代中随时会失效;
- 不同引擎伪元素名称完全不同,没有通用方案,必须写多套分支;
- 很多伪元素仅支持
display、visibility,颜色、宽高等样式会被浏览器忽略; - 复杂表单控件(
select、date),生产优先使用 JS 模拟组件,不要强依赖私有伪元素。