从WeUI学习到的知识点

 

WeUI是微信Web服务开发的UI套件, 目前包含12个模块 (Button, Cell, Toast, Dialog, Progress, Msg, Article, ActionSheet, Icons, Panel, Tab, SearchBar).

Demo页面: https://weui.io

Github页面: https://github.com/weui/weui

下面讲一讲我从WeUI中学到的CSS技巧.

Button

从这里我开始注意到, WeUI的实现中, 很多边框都是用:before:after绘制的.

  1. .weui_btn:after {
  2. content: " ";
  3. width: 200%;
  4. height: 200%;
  5. position: absolute;
  6. top: 0;
  7. left: 0;
  8. border: 1px solid rgba(0, 0, 0, 0.2);
  9. -webkit-transform: scale(0.5);
  10. transform: scale(0.5);
  11. -webkit-transform-origin: 0 0;
  12. transform-origin: 0 0;
  13. box-sizing: border-box;
  14. border-radius: 10px;
  15. }

这么做是为了在Retina屏(视网膜屏)上确保1px真的是1pixel. 详见Retina屏的移动设备如何实现真正1px的线?

Cell

weui_cell

  1. .weui_cell {
  2. padding: 10px 15px;
  3. position: relative;
  4. display: -webkit-box;
  5. display: -webkit-flex;
  6. display: -ms-flexbox;
  7. display: flex;
  8. -webkit-box-align: center;
  9. -webkit-align-items: center;
  10. -ms-flex-align: center;
  11. align-items: center;
  12. }

看到这里发现WeUI大量使用了flex布局方式. 对这个布局方式我整理了另一篇文章, 见这里.

Cell (列表项)

之前一直比较困惑如何实现列表项之间的, 左边有些空缺的边框. border属性又不支持只显示一条边上的一部分, 难道要插入<hr>?

WeUI的实现方式是: 利用.weui_cells:before.

  1. .weui_cell:before {
  2. content: " ";
  3. position: absolute;
  4. left: 15px;
  5. top: 0;
  6. width: 100%;
  7. height: 1px;
  8. border-top: 1px solid #D9D9D9;
  9. color: #D9D9D9;
  10. -webkit-transform-origin: 0 0;
  11. transform-origin: 0 0;
  12. -webkit-transform: scaleY(0.5);
  13. transform: scaleY(0.5);
  14. }

left: 15px(左边的空缺)配合上.weui_cells_titleoverflow: hidden(隐藏右边超出的部分)就可以显示有空缺的边框了.

列表项末尾的右箭头的实现方式竟然是weui_cell_ft::after的旋转了45度的border. 我本以为会用iconfont.

  1. .weui_cells_access .weui_cell_ft:after {
  2. content: " ";
  3. display: inline-block;
  4. -webkit-transform: rotate(45deg);
  5. transform: rotate(45deg);
  6. height: 6px;
  7. width: 6px;
  8. border-width: 2px 2px 0 0;
  9. border-color: #C8C8CD;
  10. border-style: solid;
  11. position: relative;
  12. top: -2px;
  13. top: -1px;
  14. margin-left: .3em;
  15. }

Radio (单选列表项)

在每个行内部嵌入了一个隐藏的

  1. <input type="radio" class="weui_check" name="radio1">

隐藏的方式是:

  1. .weui_check {
  2. position: absolute;
  3. left: -9999em;
  4. }

在每个input.weui_check的后面放置了一个用于显示对勾的spaninput.weui_check.weui_icon_checked是兄弟关系.

  1. <span class="weui_icon_checked"></span>
  1. .weui_cells_radio .weui_check:checked + .weui_icon_checked:before {
  2. display: block;
  3. content: '\EA08';
  4. color: #09BB07;
  5. font-size: 16px;
  6. }

Checkbox (复选列表项)

复选框如上面的单选框一样被隐藏了.

  1. <input type="checkbox" class="weui_check" name="checkbox1">

比较出乎我意料的是选中和未被选中的效果都是用iconfont实现的. 本以为未被选中的效果是用border实现, 选中效果用一个check的iconfont配合水平竖直居中定位.

  1. /* 选中效果 */
  2. .weui_cells_checkbox .weui_check:checked + .weui_icon_checked:before {
  3. content: '\EA06';
  4. color: #09BB07;
  5. }
  6. /* 未选中效果 */
  7. .weui_cells_checkbox .weui_icon_checked:before {
  8. content: '\EA01';
  9. color: #C9C9C9;
  10. font-size: 23px;
  11. display: block;
  12. }

Switch (开关)

  1. <input class="weui_switch" type="checkbox">

之前觉得这个效果很难做啊, 看了weui的实现竟然只用css就行了!

  1. .weui_switch {
  2. -webkit-appearance: none;
  3. -moz-appearance: none;
  4. appearance: none;
  5. position: relative;
  6. width: 52px;
  7. height: 32px;
  8. border: 1px solid #DFDFDF;
  9. outline: 0;
  10. border-radius: 16px;
  11. box-sizing: border-box;
  12. background: #DFDFDF;
  13. }
  14. .weui_switch:checked {
  15. border-color: #04BE02;
  16. background-color: #04BE02;
  17. }
  18. .weui_switch:before {
  19. content: " ";
  20. position: absolute;
  21. top: 0;
  22. left: 0;
  23. width: 50px;
  24. height: 30px;
  25. border-radius: 15px;
  26. border-top-left-radius: 15px;
  27. border-top-right-radius: 15px;
  28. border-bottom-right-radius: 15px;
  29. border-bottom-left-radius: 15px;
  30. background-color: #FDFDFD;
  31. -webkit-transition: -webkit-transform .3s;
  32. transition: -webkit-transform .3s;
  33. transition: transform .3s;
  34. transition: transform .3s, -webkit-transform .3s;
  35. }
  36. .weui_switch:checked:before {
  37. -webkit-transform: scale(0);
  38. transform: scale(0);
  39. }
  40. .weui_switch:after {
  41. content: " ";
  42. position: absolute;
  43. top: 0;
  44. left: 0;
  45. width: 30px;
  46. height: 30px;
  47. border-radius: 15px;
  48. background-color: #FFFFFF;
  49. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  50. -webkit-transition: -webkit-transform .3s;
  51. transition: -webkit-transform .3s;
  52. transition: transform .3s;
  53. transition: transform .3s, -webkit-transform .3s;
  54. }
  55. .weui_switch:checked:after {
  56. -webkit-transform: translateX(20px);
  57. transform: translateX(20px);
  58. }

其中, .weui_switch提供了边框, 未选中时背景色#DFDFDF(深灰), 选中时#04BE02(绿色).

.weui_switch:before提供了边框内部的浅灰色#FDFDFD. 被选中时scale(0)缩小消失.

.weui_switch:after提供了圆形按键. 被选中时向右边移动20px.

效果如下:

Form (表单)

  1. <input class="weui_input" type="number" pattern="[0-9]*" placeholder="请输入qq号">

inputpattern="[0-9]*限制了输入只能是0-9的数字(pattern的值是正则表达式).

input[type="number"]在Chrome上默认会在最右边显示上下箭头. WeUI通过下面的代码禁用了箭头, 这段代码在Chrome的Dev Tool里面是看不到的, 只能从CSS里面看, 害我找了半天.

  1. .weui_input::-webkit-outer-spin-button,
  2. .weui_input::-webkit-inner-spin-button {
  3. -webkit-appearance: none;
  4. margin: 0;
  5. }

相关: 如何隐藏数字输入框的上下箭头?

点选input[type="number"]在iOS上会自动打开数字键盘.

Upload (上传)

WeUI用下面这个简单的方法实现了图片前面的灰层. absolute定位加上top:0; right:0; bottom:0; left:0;就会让元素被抻开到父元素的边界.

  1. .weui_uploader_status:before {
  2. content: " ";
  3. position: absolute;
  4. top: 0;
  5. right: 0;
  6. bottom: 0;
  7. left: 0;
  8. background-color: rgba(0, 0, 0, 0.5);
  9. }

图片上传状态用了一个经典的(水平+垂直)居中方式, 利用top: 50%(让元素的上边界定位到父元素的50%位置)和transform: translateY(-50%)(让元素往上移动元素自身高度的50%).

  1. .weui_uploader_status .weui_uploader_status_content {
  2. position: absolute;
  3. top: 50%;
  4. left: 50%;
  5. -webkit-transform: translate(-50%, -50%);
  6. transform: translate(-50%, -50%);
  7. color: #FFFFFF;
  8. }

我平时常用的垂直居中方式如下. 水平居中类似.

  1. .vertical-center {
  2. position: relative;
  3. top: 50%;
  4. transform: translateY(-50%);
  5. }

最后的上传按钮:

  1. <div class="weui_uploader_input_wrp">
  2. <input class="weui_uploader_input" type="file" accept="image/jpg,image/jpeg,image/png,image/gif" multiple="">
  3. </div>

input[type="file"]在iOS上会自动触发选择"拍照"还是"照片"的菜单.

方框是用.weui_uploader_input_wrp画出来的, 而加号是用.weui_uploader_input_wrp:before:after.

真正的input利用opacity:0隐藏起来了.

  1. .weui_uploader_input_wrp:before {
  2. width: 2px;
  3. height: 39.5px;
  4. }
  5. .weui_uploader_input_wrp:after {
  6. width: 39.5px;
  7. height: 2px;
  8. }
  9. .weui_uploader_input_wrp:before,
  10. .weui_uploader_input_wrp:after {
  11. content: " ";
  12. position: absolute;
  13. top: 50%;
  14. left: 50%;
  15. -webkit-transform: translate(-50%, -50%);
  16. transform: translate(-50%, -50%);
  17. background-color: #D9D9D9;
  18. }
  19. .weui_uploader_input {
  20. position: absolute;
  21. z-index: 1;
  22. top: 0;
  23. left: 0;
  24. width: 100%;
  25. height: 100%;
  26. opacity: 0;
  27. -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  28. }

Form Error (表单报错)

  1. <input class="weui_input" type="date" value="">
  2. <input class="weui_input" type="datetime-local" value="" placeholder="">

在iOS上, 点选input[type="date"]会出现"年-月-日"的选择框, 点选input[type="datetime-local"]会出现"月-日-上午/下午-时-分"的选择框.

Select (选择)

电话号码+86位置的右箭头和分割线是用:before:after绘制的.

Toast

  1. <div id="toast" style="display:none">
  2. <div class="weui_mask_transparent"></div>
  3. <div class="weui_toast">
  4. <i class="weui_icon_toast"></i>
  5. <p class="weui_toast_content">已完成</p>
  6. </div>
  7. </div>

.weui_mask_transparent就是一个position:fixed占满全屏的透明幕布, 让用户无法操作界面.

.weui_toast才是页面中间的黑块.

竟然是纯用HTML+CSS(animation+transition)实现的.

  1. <div id="loadingToast" class="weui_loading_toast" style="/* display: none; */">
  2. <div class="weui_mask_transparent"></div>
  3. <div class="weui_toast">
  4. <div class="weui_loading">
  5. <div class="weui_loading_leaf weui_loading_leaf_0"></div>
  6. <div class="weui_loading_leaf weui_loading_leaf_1"></div>
  7. <div class="weui_loading_leaf weui_loading_leaf_2"></div>
  8. <div class="weui_loading_leaf weui_loading_leaf_3"></div>
  9. <div class="weui_loading_leaf weui_loading_leaf_4"></div>
  10. <div class="weui_loading_leaf weui_loading_leaf_5"></div>
  11. <div class="weui_loading_leaf weui_loading_leaf_6"></div>
  12. <div class="weui_loading_leaf weui_loading_leaf_7"></div>
  13. <div class="weui_loading_leaf weui_loading_leaf_8"></div>
  14. <div class="weui_loading_leaf weui_loading_leaf_9"></div>
  15. <div class="weui_loading_leaf weui_loading_leaf_10"></div>
  16. <div class="weui_loading_leaf weui_loading_leaf_11"></div>
  17. </div>
  18. <p class="weui_toast_content">数据加载中</p>
  19. </div>
  20. </div>
  1. .weui_loading_leaf {
  2. position: absolute;
  3. top: -1px;
  4. opacity: 0.25;
  5. }
  6. .weui_loading_leaf:before {
  7. content: " ";
  8. position: absolute;
  9. width: 8.14px;
  10. height: 3.08px;
  11. background: #d1d1d5;
  12. box-shadow: rgba(0, 0, 0, 0.0980392) 0px 0px 1px;
  13. border-radius: 1px;
  14. -webkit-transform-origin: left 50% 0px;
  15. transform-origin: left 50% 0px;
  16. }
  17. .weui_loading_leaf_0 {
  18. -webkit-animation: opacity-60-25-0-12 1.25s linear infinite;
  19. animation: opacity-60-25-0-12 1.25s linear infinite;
  20. }
  21. .weui_loading_leaf_0:before {
  22. -webkit-transform: rotate(0deg) translate(7.92px, 0px);
  23. transform: rotate(0deg) translate(7.92px, 0px);
  24. }
  25. /* ... */
  26. .weui_loading_leaf_11 {
  27. -webkit-animation: opacity-60-25-11-12 1.25s linear infinite;
  28. animation: opacity-60-25-11-12 1.25s linear infinite;
  29. }
  30. .weui_loading_leaf_11:before {
  31. -webkit-transform: rotate(330deg) translate(7.92px, 0px);
  32. transform: rotate(330deg) translate(7.92px, 0px);
  33. }
  34. @-webkit-keyframes opacity-60-25-0-12 {
  35. 0% {
  36. opacity: 0.25;
  37. }
  38. 0.01% {
  39. opacity: 0.25;
  40. }
  41. 0.02% {
  42. opacity: 1;
  43. }
  44. 60.01% {
  45. opacity: 0.25;
  46. }
  47. 100% {
  48. opacity: 0.25;
  49. }
  50. }
  51. /* ... */
  52. @-webkit-keyframes opacity-60-25-11-12 {
  53. 0% {
  54. opacity: 0.895958333333333;
  55. }
  56. 91.6767% {
  57. opacity: 0.25;
  58. }
  59. 91.6867% {
  60. opacity: 1;
  61. }
  62. 51.6767% {
  63. opacity: 0.25;
  64. }
  65. 100% {
  66. opacity: 0.895958333333333;
  67. }
  68. }

4. Dialog

  1. <div class="weui_dialog_confirm" id="dialog1">
  2. <div class="weui_mask"></div>
  3. <div class="weui_dialog">
  4. <div class="weui_dialog_hd"><strong class="weui_dialog_title">弹窗标题</strong></div>
  5. <div class="weui_dialog_bd">自定义弹窗内容,居左对齐显示,告知需要确认的信息等</div>
  6. <div class="weui_dialog_ft">
  7. <a href="javascript:;" class="weui_btn_dialog default">取消</a>
  8. <a href="javascript:;" class="weui_btn_dialog primary">确定</a>
  9. </div>
  10. </div>
  11. </div>

你能看到的边框都是用:after实现的.

5. Progress

略. ( *・ω・)✄╰ひ╯

6. Msg

略. ( *・ω・)✄╰ひ╯

7. Article

略. ( *・ω・)✄╰ひ╯

8. ActionSheet

  1. <div id="actionSheet_wrap">
  2. <div class="weui_mask_transition" id="mask" style="display: none;"></div>
  3. <div class="weui_actionsheet" id="weui_actionsheet">
  4. <div class="weui_actionsheet_menu">
  5. <div class="weui_actionsheet_cell">示例菜单</div>
  6. <div class="weui_actionsheet_cell">示例菜单</div>
  7. <div class="weui_actionsheet_cell">示例菜单</div>
  8. <div class="weui_actionsheet_cell">示例菜单</div>
  9. </div>
  10. <div class="weui_actionsheet_action">
  11. <div class="weui_actionsheet_cell" id="actionsheet_cancel">取消</div>
  12. </div>
  13. </div>
  14. </div>

值得一提的是, 页面下方的ActionSheet始终是显示的, 只不过平时通过transform: translateY(100%)隐藏了起来, 显示时用translateY(0). 这方法无需JS就可以自适应任意高度的ActionSheet.

  1. .weui_actionsheet {
  2. position: fixed;
  3. left: 0;
  4. bottom: 0;
  5. -webkit-transform: translate(0, 100%);
  6. transform: translate(0, 100%);
  7. -webkit-backface-visibility: hidden;
  8. backface-visibility: hidden;
  9. z-index: 2;
  10. width: 100%;
  11. background-color: #EFEFF4;
  12. -webkit-transition: -webkit-transform .3s;
  13. transition: -webkit-transform .3s;
  14. transition: transform .3s;
  15. transition: transform .3s, -webkit-transform .3s;
  16. }
  17. .weui_actionsheet_toggle {
  18. -webkit-transform: translate(0, 0);
  19. transform: translate(0, 0);
  20. }

9. Icons

一堆iconfont. ( *・ω・)✄╰ひ╯

10. Panel

略. ( *・ω・)✄╰ひ╯

11. Tab

Navbar:

TabBar:

略. ( *・ω・)✄╰ひ╯

12. SearchBar

无焦点状态:

有焦点状态:

  1. <div class="weui_search_bar weui_search_focusing" id="search_bar">
  2. <form class="weui_search_outer">
  3. <!-- 搜索框有焦点时的搜索图标, 搜索框和清空按钮 -->
  4. <div class="weui_search_inner">
  5. <i class="weui_icon_search"></i>
  6. <input type="search" class="weui_search_input" id="search_input" placeholder="搜索" required="">
  7. <a href="javascript:" class="weui_icon_clear" id="search_clear"></a>
  8. </div>
  9. <!-- 搜索框没有焦点时的显示 -->
  10. <label for="search_input" class="weui_search_text" id="search_text">
  11. <i class="weui_icon_search"></i>
  12. <span>搜索</span>
  13. </label>
  14. </form>
  15. <!-- 搜索框有焦点时的取消键 -->
  16. <a href="javascript:" class="weui_search_cancel" id="search_cancel">取消</a>
  17. </div>

这里我最好奇的是, 当用户点击搜索框时, 弹出的键盘上右下角的按键是"搜索"而不是"换行".

我测试的效果是, 在微信中点击搜索框时键盘显示"搜索"按键, 在Safari中打开时则显示"换行".

这就很诡异了, 说明微信做了什么手脚. 难道与JS有关?

但是我在网上搜索了下, 发现只要确保input[type="search"]form包围, 且formaction属性即可. 示例:

  1. <form action="">
  2. <input type="search" name="search" placeholder="search">
  3. </form>

但是WeUI的实现中, form并没有action属性, 所以暂时不知道WeUI是如何做的.

相关: 如何让搜索框的键盘显示搜索按键?

参考

H5项目常见问题汇总及解决方案
html5手机常见问题与工具分享
A very simple router for the demo of WeUI

WeUI的更多相关文章

  1. 微信官方开源UI库-WeUI

    概述 WeUI是一套同微信原生视觉体验一致的基础样式库,为微信Web开发量身设计,可以令用户的使用感知更加统一.包含button.cell.dialog.toast.article.icon等各式元素 ...

  2. weui 图片弹框

    添加图片与弹出效果对比: HTML: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...

  3. weui 搜索框

    点击搜索,会显示关键字取消按钮,输入文字,会在搜索框下,有相应的列表显示. HTML: <!DOCTYPE html> <html> <head> <meta ...

  4. weui dialog

    切记:weui dialog 的样式是在weui.css,而不是在weui.min.css HTML: <!DOCTYPE html> <html> <head> ...

  5. weui tabbar 切换

    Html: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <met ...

  6. weui 多网页切换效果分析

    weui的文档写的不怎么详尽,简单的来讲WeUI 为微信 Web 服务量身设计的h5框架. WeUI是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信 Web 开发量身设计,可以令用户 ...

  7. TODO:小程序集成WeUI

    TODO:小程序集成WeUI WeUI 为微信 Web 服务量身设计.WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信 Web 开发量身设计,可以令用户的使用感知更加统一. ...

  8. 微信小程序之使用weui.wxss(八)

    [未经作者本人同意,请勿以任何形式转载] 什么是WeUI? WeUI是在遵守微信视觉设计规范下,由官方设计团队为小程序量身定制的基础样式库. 这里把WeUI放到基础篇里,是因为WeUI是官方出品,并且 ...

  9. 移动端前端UI库—Frozen UI、WeUI、SUI Mobile

    [MUI]http://www.dcloud.io/ [Clouda]http://clouda.baidu.com/blend2是百度历时两年共同研发的开源App技术框架,基于Node.js,简单易 ...

  10. WeUI 为微信 Web 服务量身设计-h5前端框架

    WeUI是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信 Web 开发量身设计,可以令用户的使用感知更加统一.包含button.cell.dialog. progress. toas ...

随机推荐

  1. POJ3026 最小生成树

    问题: POJ3026 分析: 采用BFS算出两两之间的距离,再用PRIM算法计算最小生成树. AC代码: //Memory: 220K Time: 32MS #include <iostrea ...

  2. EF调用存储过程实例

    创建实体: public class User { public string UserID { get; set; } public string UserName { get; set; } pu ...

  3. BZOJ 1458 士兵占领

    http://www.lydsy.com/JudgeOnline/problem.php?id=1458 题意:n x m的棋盘,k个位置不能放,每行和每列都有要求至少的士兵,求能否有最少的满足条件的 ...

  4. 基于stm32f103zet6的FAT16文件系统学习0(读SD卡扇区)

    SD卡已经看了两天了,主要是因为测试出来的卡容量不对,所以一直找原因,最终还是发现了,总比不过是单位上面出现了问题,或许是之前没有接触到SD的缘故吧,所以对其中的一些寄存器很不了解,一切都是重新开始, ...

  5. Planner – 项目管理软件

    http://www.appinn.com/planner/   Planner 是一款开源.易用.跨平台的项目管理软件.@appinn 二猪用了 OpenProject 几年,现在已经受够了它的各种 ...

  6. Linux安装开发环境,必须配置的环节(Fedora15版本)

    前提:U盘安装fedora:<[原]U盘安装Fedora15 DVD镜像>.<Grub引导安装Fedora15>   1.设置代理上网:<fedora 配置网络代理> ...

  7. 【转】在Eclipse中安装和使用TFS插件

    文章地址:http://www.cnblogs.com/judastree/archive/2012/09/05/2672640.html 问题: 在Eclipse中安装和使用TFS插件. 解决过程: ...

  8. WebGL 初探

    官方网站:http://webglfundamentals.org/ WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenG ...

  9. Topological Sorting

    Topological sorting/ ordering is a linear ordering of its vertices such that for every directed edge ...

  10. LeeCode(Database)-Customers Who Never Order

    Suppose that a website contains two tables, the Customers table and the Orders table. Write a SQL qu ...