笔记:使用 CSS 伪类为 select 元素添加 placeholder


遇到的问题:

表单中各种 <input/><textarea/> 元素从上至下排列,其中夹杂 <select/> 是一个挺常见的场景。前者通过 placeholder 属性可以直接为元素添加占位符,同时利用 ::placeholder 来给占位符文字添加一定的样式,比如文字颜色、大小,如下:

例子中直接使用了 ::placeholder ,实际情况是 Chrome,Safari,Firebox,IE,EDGE 都需要兼容,加上对应的 vender perfix,可以参考 caniuse#placeholder,和 CSS-Trick 对应的文章

问题在于select 元素没有 placeholder 属性,除了通过其它元素制作一个伪 select 之外,有没有通过纯 CSS 的方法,来解决?在这里我们对 placeholder 的需求是:

  1. 可以看到,但是不可以选择;
  2. 可以自定义颜色。

解决问题:

通过 JavaScript 配合 onchange 事件

配合 <select/>onchange 事件,直接去找当前 selected<option/> 上预先定义好的 class,如下:

demo:

See the Pen style color with option:first-child 3 by Lien (@movii) on CodePen.

通过伪类

通过 option:first-child 的方式来对第一个 option 元素进行关于颜色的实现,事实证明自己太天真,同时也得把需求描述改的更加精确一些:这里需要的 placeholder 自定义颜色的效果是针对页面上 select 的,不是 option 元素的,参考如下 Pen 中的效果

See the Pen style color with option:first-child 1 by Lien (@movii) on CodePen.

于是,实现颜色的需求就变成:如何给 select 添加不同的状态的,在 x 状态的时候实现一个占位符的样式(placeholder style,比如说一个淡灰色),在 y 状态的是一个普通的状态(default style,比如说黑色)。

琢磨到这类的时候反映出来了是不是有什么伪类::pseudo-class 可以借来使用,类似做 <input type="checkbox"/><input type="radio"> 时候会使用 :checked 的属性来做样式一样,最后在 stackoverflow 如愿以偿找到了答案,具体问题在这:链接

但是还没完,问题答案里的最高票的一千多 vote 的回答是这样的:

可以在答案里 stackoverflow 提供的 run code snippet 里试一下,会发现,我们想要的是 <select/> 默认显示是灰色,点击打开之后的下拉里是正常的黑色,而这段代码正好反过来了。他默认是黑色,点击打开后的第一个 <option/> 元素确实是灰色。,利用了 <option disabled/> 来实现这个效果,不过怎么都不是我们想要的效果,不知道那个最高票数怎么来的。

一个答案被枪毙了,还有很多答案值得参考,最接近我们需要的效果的答案在这里:链接

原理

根据上面的例子做下基本的解释:

  • HTML5 中,针对客户端验证(client-side validation)提供了 required 属性,同时在 CSS 里可以使用 :required (MDN:链接) 配合基本的选择器(selector)来对样式进行声明: select:required

  • HTML5 中表单的 required 属性施加在表单[、控件]上,表示这个表单[、控件]的值是必须有的

  • 反之,没有的时候就是非法,此时 CSS 提供了 :invalid 表示非法的伪类,一个 <select/> 是必选(:required)的但是没有选择的时候、或者值为空(value="")属于非法,可以这么来选择:select:required:invalid;

  • 上文给出的例子里,第一个 <option/>value="", 默认它是 selected (选中)的,配合有 required 属性的 parent <select/> 的时,value="" 的当前 <select/>,是一个 :invalid (非法)的,配合 CSS 声明,就可以对 <select/> 制作一个 faked 的 placeholder 样式;

  • 第一个 <option/> 中还有一个 disabled 属性,在这里的作用是点开 <select/> 的下拉菜单之后也不能选择当这个 <option/>

D is for Demonstration

See the Pen style color with option:first-child 2 by Lien (@movii) on CodePen.

限制

1. disable<option/> 不能再次选择

disabled 了的 placeholder 存在的 <option/> 元素上是必须的,会造成,第一步选择了其它选项后,不能再次选择 placeholder 的问题;这一点如果本身是一个必选的表单,没问题,如果当前的 <select/> 是一个可选可不选的,那会产生问题;

2. <form required> 非 ajax 提交时,其中不能有可选的表单控件

与第一点类似,在 <form/> 上对整个表单进行 required 属性添加:<form required>[...]</form>,如果提交方式是默认的浏览器提交、而不是 ajax,那么 form 中的任何一个控件都不可以是 optional,modern browser 对这个属性已经有了比较好的支持,会提示是一个 required field。


参考

感谢阅读

你们好, 2018 年初把小站从 Jekyll 迁移到 Hugo 的过程中,删除了评论区放的 Disqus 插件,考虑有二:首先无论评论、还是对笔记内容的进一步讨论,读者们更喜欢通过邮件、或者 Twitter 私信的方式来沟通;其次一年多以来 Disqus 后台能看到几乎都是垃圾留言(spam),所以这里直接贴一下邮件、以及 Twitter 账户 地址。

技术发展迭代很快,所以这些笔记内容也有类似新闻的时效性,不免有过时、或者错误的地方,欢迎指正 ^_^。

BEST
Lien(A.K.A 胡椒)
本站总访问量 本站总访客量 本文总阅读量