根据UI图对移动端的h5页面做样式重构,是前端工程师的本职工作,看似简单,不过想做好却并不容易。下面总结一下其中要点。

rem

rem是一种相对长度单位,参考的基准是<html>标签定义的font-size。比如:

  1. html {
  2. font-size: 16px;
  3. }
  4. .intro {
  5. font-size: 1.2rem;
  6. margin-top: 0.2rem;
  7. }

那么实际效果就是:

  1. .intro {
  2. font-size: 16px * 1.2rem = 19.2px;
  3. margin-top: 16px * 0.2rem = 3.2px;
  4. }

viewport

做移动端的h5,通常会在HTML文件中指定一个<meta>标签:

  1. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximun-scale=1.0, user-scalable=no">

关于Viewport,可以参考更专业的教程:

http://www.cnblogs.com/chengkun101/p/5461500.html

http://www.cnblogs.com/2050/p/3877280.html


媒体查询

手机屏幕的分辨率越来越高,比如iPhone 5为640*1136 px、iPhone 6/6S为750*1334 px。我拿到的UI图,其参考分辨率为1440*2560 px

而在写CSS时,通常是以屏幕宽度为参考的。打开Chrome的响应式设计工具,就可以看到各种设备的屏幕宽度,比如iPhone 5的屏幕宽度是320*568 px,iPhone 6/6S的屏幕宽度为375*667 px。分辨率和屏幕宽度之间,是有一个倍屏系数换算的。

设计师给了一张宽为1440px的UI图,而做不同设备的适配,就是前端工程师的职责了。

比如UI图上标注了某个段落的字体大小为64px。为了保证在各种屏幕上的不失真,就要根据实际屏幕宽度做等比例换算,才能写进CSS,即满足:

  1. 写入CSS的尺寸/屏幕宽度 = UI图标注的尺寸/UI图宽度
  2. 因此:
  3. 写入CSS的尺寸 = UI图标注的尺寸/UI图宽度*屏幕宽度

比如上例,当标注尺寸为64px、UI图宽度为1440px时,针对不同屏幕宽度,写入CSS的属性分别为:

  • 屏幕宽度320px:font-size: 64/1440*320 = 14.22px
  • 屏幕宽度360px:font-size: 64/1440*360 = 16px
  • 屏幕宽度375px:font-size: 64/1440*375 = 16.67px
  • ...
  • 屏幕宽度1440px:font-size: 64/1440*1440 = 64px

于是自然想到媒体查询:

  1. @media (min-width: 320px) {
  2. p.intro {
  3. font-size: 14.22px;
  4. }
  5. }
  6. @media (min-width: 360px) {
  7. p.intro {
  8. font-size: 16px;
  9. }
  10. }
  11. @media (min-width: 375px) {
  12. p.intro {
  13. font-size: 16.67px;
  14. }
  15. }
  16. @media (min-width: 1440px) {
  17. p.intro {
  18. font-size: 64px;
  19. }
  20. }

天啊,如果这样写,如果UI图上标注了另一个段落的字体大小为60px,岂不又要写一遍媒体查询!

解决方法是,在<html>标签上只做一次媒体查询,而在p.intro上使用rem单位。

  1. // 对html做媒体查询,定义基准的font-size
  2. @media (min-width: 320px) {
  3. html {
  4. font-size: 14.22px;
  5. }
  6. }
  7. @media (min-width: 360px) {
  8. html {
  9. font-size: 16px;
  10. }
  11. }
  12. @media (min-width: 375px) {
  13. html {
  14. font-size: 16.67px;
  15. }
  16. }
  17. @media (min-width: 1440px) {
  18. html {
  19. font-size: 64px;
  20. }
  21. }
  22. // CSS单位使用rem
  23. p.intro {
  24. font-size: 1rem;
  25. }

这样一来,其他元素也可以共享<html>的基准font-size,无需媒体查询,只需引入rem单位,如:

  1. // 另一个段落
  2. p.another-intro {
  3. font-size: 0.9375rem; // UI图上标注60px
  4. height: 1.5625rem; // UI图上标注100px
  5. margin: 0.5rem; // UI图上标注32px
  6. }

有点匪夷所思?先来看看如上换算是否满足等比例性。再回顾一下公式:

  1. 写入CSS的尺寸/屏幕宽度 = UI图标注的尺寸/UI图宽度

p.another-intromargin属性为例:

  • 屏幕宽度320px:margin: 14.22*0.5 = 7.11px,而7.11/320 = 32/1440
  • 屏幕宽度360px:margin: 16*0.5 = 8px,而8/360 = 32/1440
  • 屏幕宽度375px:margin: 16.67*0.5 = 8.335px,而8.335/375 = 32/1440
  • ...
  • 屏幕宽度1440px:margin: 64*0.5 = 32px,而32/1440 = 32/1440

完美。

可以发现一个规律:在媒体查询中,min-width: 1440px时定义了html { font-size: 64px; },那么UI图上标注的尺寸,直接除以64,就可以带个rem尾巴,写入到CSS中。记住64这个参考值,非常有用,下文会经常用到。

当然,你也可以不使用64作为参考值,只要符合等比例规则就可以。下文均是以64为例的。


适配所有规格

以上只以320px、360px、375px为例,得到了<html>的基准font-size。对于iPhone 6s Plus,其屏幕宽度为414px,如何计算font-size

很简单:屏幕宽度/UI图宽度*64

于是,又多了一条媒体查询规则:

  1. @media (min-width: 414px) {
  2. html {
  3. font-size: 18.4px; // 414/1440*64
  4. }
  5. }

查阅常见移动设备的屏幕尺寸规格,可以得到一个较为完整的媒体查询规则:

  1. html {
  2. font-size: 12px;
  3. }
  4. @media (min-width:320px){
  5. html{
  6. font-size: 14.2222px;
  7. }
  8. }
  9. @media (min-width:360px){
  10. html{
  11. font-size: 16px;
  12. }
  13. }
  14. @media (min-width:375px){
  15. html{
  16. font-size: 16.6667px;
  17. }
  18. }
  19. @media (min-width:412px){
  20. html{
  21. font-size: 18.2857px;
  22. }
  23. }
  24. @media (min-width:480px){
  25. html{
  26. font-size: 21.3333px;
  27. }
  28. }
  29. @media (min-width:640px){
  30. html{
  31. font-size: 28.4444px;
  32. }
  33. }
  34. @media (min-width:720px){
  35. html{
  36. font-size: 32px;
  37. }
  38. }
  39. @media (min-width:768px){
  40. html{
  41. font-size: 34.1333px;
  42. }
  43. }
  44. @media (min-width:1440px){
  45. html{
  46. font-size: 64px;
  47. }
  48. }

CSS预编译

之前所讲的内容,已经可以使你做出移动端适配的h5页面了,但并不优雅。因为CSS是不支持计算的,“标注尺寸/64”只能手工计算,也就意味着UI图上的每个标注都要手动换算,你会疯掉。

不过,借助CSS预编译工具,如Less/Sass,可以避免这种重复劳动。以下以Scss为例,比如:

  1. p.intro {
  2. font-size: 64px/64px * 1rem;
  3. }
  4. p.another-intro {
  5. font-size: 60px/64px * 1rem; // UI图上标注60px
  6. height: 100px/64px * 1rem; // UI图上标注100px
  7. margin: 32px/64px * 1rem; // UI图上标注32px
  8. }

当然也可以使用变量:

  1. // 计算rem的基准字体
  2. $rem-base-font-size: 64px;
  3. p.intro {
  4. font-size: 64px/$rem-base-font-size * 1rem;
  5. }
  6. p.another-intro {
  7. font-size: 60px/$rem-base-font-size * 1rem; // UI图上标注60px
  8. height: 100px/$rem-base-font-size * 1rem; // UI图上标注100px
  9. margin: 32px/$rem-base-font-size * 1rem; // UI图上标注32px
  10. }

这样做的好处是,如果某一天不使用64px作为参考值,只需修改$rem-base-font-size变量。

以上代码看着很冗余,不如写一个函数,隐藏计算过程:

  1. // 将设计图标注的px尺寸,转换为相应的CSS
  2. @function convertPxFormUI($px) {
  3. $rem-base-font-size: 64px;
  4. @return $px / $rem-base-font-size * 1rem;
  5. }
  6. p.intro {
  7. font-size: convertPxFormUI(64px);
  8. }
  9. p.another-intro {
  10. font-size: convertPxFormUI(60px); // UI图上标注60px
  11. height: convertPxFormUI(100px); // UI图上标注100px
  12. margin: convertPxFormUI(32px); // UI图上标注32px
  13. }

这样做的好处是,如果某一天摒弃了rem,使用了其他换算规则,只需修改convertPxFormUI()函数体即可。


更进一步

既然Sass帮助我们计算,那么媒体查询中的一堆font-size,Sass是否可以代劳呢?

之前介绍了计算规则:屏幕宽度/UI图宽度*64。OK,看来可以这样写:

  1. // 计算rem的基准字体
  2. $rem-base-font-size: 64px;
  3. // UI设计图的分辨率宽度
  4. $UI-resolution-width: 1440px;
  5. @mixin html-font-size() {
  6. @media (min-width:320px){
  7. html{
  8. font-size: 320px / $UI-resolution-width * $rem-base-font-size;
  9. }
  10. }
  11. @media (min-width:360px){
  12. html{
  13. font-size: 360px / $UI-resolution-width * $rem-base-font-size;
  14. }
  15. }
  16. @media (min-width:375px){
  17. html{
  18. font-size: 375px / $UI-resolution-width * $rem-base-font-size;
  19. }
  20. }
  21. @media (min-width:412px){
  22. html{
  23. font-size: 412px / $UI-resolution-width * $rem-base-font-size;
  24. }
  25. }
  26. @media (min-width:480px){
  27. html{
  28. font-size: 480px / $UI-resolution-width * $rem-base-font-size;
  29. }
  30. }
  31. @media (min-width:640px){
  32. html{
  33. font-size: 640px / $UI-resolution-width * $rem-base-font-size;
  34. }
  35. }
  36. @media (min-width:720px){
  37. html{
  38. font-size: 720px / $UI-resolution-width * $rem-base-font-size;
  39. }
  40. }
  41. @media (min-width:768px){
  42. html{
  43. font-size: 768px / $UI-resolution-width * $rem-base-font-size;
  44. }
  45. }
  46. @media (min-width:1440px){
  47. html{
  48. font-size: 1440px / $UI-resolution-width * $rem-base-font-size;
  49. }
  50. }
  51. }

很冗余,用循环来实现:

  1. // 计算rem的基准字体
  2. $rem-base-font-size: 64px;
  3. // UI设计图的分辨率宽度
  4. $UI-resolution-width: 1440px;
  5. // 需要适配的屏幕宽度
  6. $device-widths: 320px, 360px, 375px, 412px, 480px, 640px, 720px, 768px, 1440px;
  7. @mixin html-font-size() {
  8. @each $current-width in $device-widths {
  9. @media (min-width: $current-width) {
  10. html {
  11. $x: $UI-resolution-width / $current-width; // 计算出是几倍屏
  12. font-size: $rem-base-font-size / $x;
  13. }
  14. }
  15. }
  16. }

这样做的好处是,如果某一天老板说,屏幕宽度450px时效果不理想。你只需在$device-widths中新增一个宽度即可。


Sass最终方案

  • _variables.scss:定义变量
  1. // 计算rem的基准字体
  2. $rem-base-font-size: 64px;
  3. // UI设计图的分辨率宽度
  4. $UI-resolution-width: 1440px;
  5. // 需要适配的屏幕宽度
  6. $device-widths: 240px, 320px, 360px, 375px, 412px, 480px, 540px, 640px, 720px, 768px, 1024px, 1440px;
  • _utils.scss:定义函数与mixin
  1. // 根据不同设备的屏幕宽度,定义<html>的基准font-size
  2. @mixin html-font-size() {
  3. @each $current-width in $device-widths {
  4. @media (min-width: $current-width) {
  5. html {
  6. $x: $UI-resolution-width / $current-width; // 计算出是几倍屏
  7. font-size: $rem-base-font-size / $x;
  8. }
  9. }
  10. }
  11. }
  12. // 将设计图标注的px尺寸,转换为相应的CSS
  13. @function convertPxFormUI($px) {
  14. @return $px / $rem-base-font-size * 1rem;
  15. }
  • index.scss:Scss入口文件
  1. @import 'utils', 'variables';
  2. @include html-font-size();
  3. p.intro {
  4. font-size: convertPxFormUI(64px);
  5. }
  6. p.another-intro {
  7. font-size: convertPxFormUI(60px);
  8. height: convertPxFormUI(100px);
  9. margin: convertPxFormUI(32px);
  10. }

总结

rem + viewport + 媒体查询 + Sass

从设计图到CSS:rem+viewport+媒体查询+Sass的更多相关文章

  1. CSS基础教程 -- 媒体查询屏幕适配

    响应式布局 Media Query 的使用方法 在上例中, 我们使用Media Queries来根据3种不同尺寸的窗口使用3种不同的样式.通过不同的媒体类型和条件定义样式表规则,媒体查询让CSS可以更 ...

  2. rem适配布局(rem+less+媒体查询 和 rem+flexible.js)

    1. rem 基础 rem 是一个相对单位,类似于 em ,em 是父元素字体大小. em 是相对于父元素  的字体大小来说的 rem 是相对于 html 元素 字体大小来说的 rem 优点 就是可以 ...

  3. css样式,媒体查询,垂直居中,js对象

    下面是一些截图,有关查询效率,css样式,媒体查询,垂直居中,js基本类型.  

  4. Web移动前端开发-——rem+less+媒体查询,rem+flexble.js+媒体查询

    实际开发搞搞起来!!!! rem适配方案 媒体查询+rem+less 基础知识铺垫 第一步,我们需要拿到设计稿,安装设计稿的要求来设置一个合适的html字体大小. 第二步,计算元素大小的取值 页面re ...

  5. 总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法。(转)

    <meta http-equiv="X-UA-Compatible" content="IE=edge"><!--兼容ie-->< ...

  6. CSS media queries 媒体查询

    最近在做一些页面打印时的特殊处理接触到了media queries,想系统学习一下,在MOZILLA DEVELOPER NETWORK看到一篇文章讲的很不错,结合自己的使用总结一下. CSS2/me ...

  7. (原)css 响应式媒体查询 模板

    @media only screen and (max-width:340px) { html,input{ font-size:80%; } } @media only screen and (ma ...

  8. CSS媒体查询及其使用

    1.什么是媒体查询 媒体查询可以让我们根据设备显示器的特性(如视口宽度.屏幕比例.设备方向:横向或纵向)为其设定CSS样式,媒体查询由媒体类型和一个或多个检测媒体特性的条件表达式组成.媒体查询中可用于 ...

  9. CSS媒体查询,CSS根据不同的分辨率显示不同的样式

    在写自适应网页的时候,我们需要网页有几种显示方式,我们可以用CSS实现这个功能 使用CSS提供的媒体查询,我们可以根据屏幕分辨率来使用相应的CSS样式 @media screen and (max-w ...

随机推荐

  1. BZOJ4539 [Hnoi2016]树 【倍增 + 主席树】

    题目链接 BZOJ4539 题解 我们把每次复制出来的树看做一个点,那么大树实际上也就是一棵\(O(M)\)个点的树 所以我们只需求两遍树上距离: 大树上求距离,进入同一个点后在模板树上再求一次距离 ...

  2. Codechef MARCH14 GERALD07加强版

    强制在线不代表不能预处理! 考虑暴力怎么干? 开始n个联通块.now=n 不断加入边,如果连接两个联通块,--now 否则不动. 后者的前提是和[l,id-1]的边构成环 所以,我们考虑每个[l,r] ...

  3. PowerDesigner12.5下载汉化及破解

    一.下载: 在网上直接输入PowerDesigner12.5下载,很多地方都可以下载成功. 二.汉化: 直接将解压的汉化文件复制[覆盖]到安装目录即可. 三.破解[稍微费事一点]: 1.安装完成后,修 ...

  4. XOR and Favorite Number (莫对算法)

    E. XOR and Favorite Number time limit per test 4 seconds memory limit per test 256 megabytes input s ...

  5. 最新eclipse安装SVN插件

    转载自:http://welcome66.iteye.com/blog/1845176 eclipse里安装SVN插件,一般来说,有两种方式: 直接下载SVN插件,将其解压到eclipse的对应目录里 ...

  6. 【Foreign】画方框 [主席树]

    画方框 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output 输出一行一个整数,表示 CD 最多可能画了几个方框. Sam ...

  7. mysql 索引最左原则原理

    索引本质是一棵B+Tree,联合索引(col1, col2,col3)也是. 其非叶子节点存储的是第一个关键字的索引,而叶节点存储的则是三个关键字col1.col2.col3三个关键字的数据,且按照c ...

  8. JS之document例题讲解2

    例题三.图片轮播 <body> <div style="width:1000px; height:250px; margin-top:30px"> < ...

  9. [bzoj3993][SDOI2015]星际战争-二分+最大流

    Brief Description 3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战.在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai. ...

  10. vue双向绑定原理源码解析

    当我们学习angular或者vue的时候,其双向绑定为我们开发带来了诸多便捷,今天我们就来分析一下vue双向绑定的原理. 简易vue源码地址:https://github.com/maxlove123 ...