一个select元素自定义设计的新思路:appearance: none之后利用<>符号制造小箭头
最近工作时解决了一个前端小问题(如下图所示):在Safari中,select的控件之上有不和谐的灰色部分。 刚开始时我以为是backgrand或是border设置不当之类产生的问题,在搜索了很久之后终于找到了问题所在:这个灰色部分来自于Safari默认的select设计,所以我需要用 appearance: none 来去除默认设计,但是这样一来,右侧的小箭头就会消失。本文将会详细描述我是如何添加小箭头的,该方法灵感来自于上司,目前没有在网上找到类似答案(当然网上也有不少别的好方法:比如使用background添加一个url的小箭头图片)。
我先直接附上我的方法,采用了一个自己编的例子便于讲解。
1 <html> 2 <head> 3 <style type="text/css"> 4 #selectDiv select { 5 -webkit-appearance: none; 6 -moz-appearance: none; 7 -ms-appearance: none; 8 width: 100px; 9 background-color: transparent; 10 font-size: 16px; 11 padding: 3px 15px; 12 margin: 0;} 13 #selectDiv { 14 width: 100px; 15 } 16 #selectDiv:after { 17 content: '<>'; 18 font: 13px Consolas,monospace; 19 color: #000; 20 font-weight: 700; 21 -webkit-transform: rotate(90deg); 22 -moz-transform: rotate(90deg); 23 -ms-transform: rotate(90deg); 24 transform: rotate(90deg); 25 position: absolute; 26 left: 85px; 27 top: 14px; 28 pointer-events: none; 29 } 30 </style> 31 </head> 32 <body> 33 <div id="selectDiv"> 34 <select> 35 <option value="apple">Apple</option> 36 <option value="banana">Banana</option> 37 <option value="orange">Orange</option> 38 <option value="pear">Pear</option> 39 </select> 40 </div> 41 </body> 42 </html>
Safari (11.1)和Chrome (66.0.3359.139) 中最终的效果如下图:
Firefox (59.0.2) 中最终的效果如下图:
以上存在差别是由于依然还有默认的border设置,所以只需要再加上自定义的border设置就好了。
(如果你看懂了上面的代码,那你就不需要继续看下面的解释;如果你对其中的css有疑惑,那么你可能可以从下文中找到答案。如果你看完本文后有任何意见,欢迎留言。)
基本思路
简而言之,就是将<>符号旋转九十度就能得到一个类似于向上向下的小箭头,很简洁,而且可以根据自己的喜好调整大小粗细和风格。
部分CSS详解及注意事项
1. ::after (:after)
这是伪元素,两个冒号是CSS3中的写法,是为了将其与伪类(:hover/:active等)区分。一个冒号是CSS2中的写法,但是为了兼容,很多浏览器依然支持一个冒号的写法。这个能产生一个在原有元素之后的元素,默认是与原有元素在同一行的。我认为用这个伪元素比另建一个div更方便。
2. -webkit-appearance: none; -moz-appearance: none; -ms-appearance: none;
这个作用就是去除浏览器中默认的格式,-webkit- 作用于Chrome,-moz-作用于Firfox,-ms-作用于IE,相同的道理也适用于之后的transform。
3. <>字体需要挑选
这两个符号在某些字体时可能会连接在一起或是形状不合适,所以需要挑选合适的字体以得到满意的图案。效果图中展示的是Consolas字体,另外我还写了另一个字体monospace备选。后者的形状会尖一些。建议大家再尝试看看别的字体,也许有更合适的。另外,符号是否加粗和字体大小就全凭个人感觉了。
4. pointer-events: none;
加上这句的效果直接体现在点击符合与点击框中别的地方的效果相同,如果少了这段文字,则会使点击符号时选项不会展开。某官方解释是“元素永远不会成为鼠标事件的target。但是,当其后代元素的pointer-events
属性指定其他值时,鼠标事件可以指向后代元素,在这种情况下,鼠标事件将在捕获或冒泡阶段触发父元素的事件侦听器。”大家自行理解一下。
5. 在select之外包裹div
我在select之外加了父元素,因为我发现我无法直接添加select:after。(如果有人知道原因,欢迎留言!)