从设计图到CSS:rem+viewport+媒体查询+Sass
根据UI图对移动端的h5页面做样式重构,是前端工程师的本职工作,看似简单,不过想做好却并不容易。下面总结一下其中要点。
rem
rem是一种相对长度单位,参考的基准是<html>
标签定义的font-size
。比如:
html {
font-size: 16px;
}
.intro {
font-size: 1.2rem;
margin-top: 0.2rem;
}
那么实际效果就是:
.intro {
font-size: 16px * 1.2rem = 19.2px;
margin-top: 16px * 0.2rem = 3.2px;
}
viewport
做移动端的h5,通常会在HTML文件中指定一个<meta>
标签:
<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,即满足:
写入CSS的尺寸/屏幕宽度 = UI图标注的尺寸/UI图宽度
因此:
写入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
于是自然想到媒体查询:
@media (min-width: 320px) {
p.intro {
font-size: 14.22px;
}
}
@media (min-width: 360px) {
p.intro {
font-size: 16px;
}
}
@media (min-width: 375px) {
p.intro {
font-size: 16.67px;
}
}
@media (min-width: 1440px) {
p.intro {
font-size: 64px;
}
}
天啊,如果这样写,如果UI图上标注了另一个段落的字体大小为60px
,岂不又要写一遍媒体查询!
解决方法是,在<html>
标签上只做一次媒体查询,而在p.intro
上使用rem单位。
// 对html做媒体查询,定义基准的font-size
@media (min-width: 320px) {
html {
font-size: 14.22px;
}
}
@media (min-width: 360px) {
html {
font-size: 16px;
}
}
@media (min-width: 375px) {
html {
font-size: 16.67px;
}
}
@media (min-width: 1440px) {
html {
font-size: 64px;
}
}
// CSS单位使用rem
p.intro {
font-size: 1rem;
}
这样一来,其他元素也可以共享<html>
的基准font-size
,无需媒体查询,只需引入rem单位,如:
// 另一个段落
p.another-intro {
font-size: 0.9375rem; // UI图上标注60px
height: 1.5625rem; // UI图上标注100px
margin: 0.5rem; // UI图上标注32px
}
有点匪夷所思?先来看看如上换算是否满足等比例性。再回顾一下公式:
写入CSS的尺寸/屏幕宽度 = UI图标注的尺寸/UI图宽度
以p.another-intro
的margin
属性为例:
- 屏幕宽度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
。
于是,又多了一条媒体查询规则:
@media (min-width: 414px) {
html {
font-size: 18.4px; // 414/1440*64
}
}
查阅常见移动设备的屏幕尺寸规格,可以得到一个较为完整的媒体查询规则:
html {
font-size: 12px;
}
@media (min-width:320px){
html{
font-size: 14.2222px;
}
}
@media (min-width:360px){
html{
font-size: 16px;
}
}
@media (min-width:375px){
html{
font-size: 16.6667px;
}
}
@media (min-width:412px){
html{
font-size: 18.2857px;
}
}
@media (min-width:480px){
html{
font-size: 21.3333px;
}
}
@media (min-width:640px){
html{
font-size: 28.4444px;
}
}
@media (min-width:720px){
html{
font-size: 32px;
}
}
@media (min-width:768px){
html{
font-size: 34.1333px;
}
}
@media (min-width:1440px){
html{
font-size: 64px;
}
}
CSS预编译
之前所讲的内容,已经可以使你做出移动端适配的h5页面了,但并不优雅。因为CSS是不支持计算的,“标注尺寸/64”只能手工计算,也就意味着UI图上的每个标注都要手动换算,你会疯掉。
不过,借助CSS预编译工具,如Less/Sass,可以避免这种重复劳动。以下以Scss为例,比如:
p.intro {
font-size: 64px/64px * 1rem;
}
p.another-intro {
font-size: 60px/64px * 1rem; // UI图上标注60px
height: 100px/64px * 1rem; // UI图上标注100px
margin: 32px/64px * 1rem; // UI图上标注32px
}
当然也可以使用变量:
// 计算rem的基准字体
$rem-base-font-size: 64px;
p.intro {
font-size: 64px/$rem-base-font-size * 1rem;
}
p.another-intro {
font-size: 60px/$rem-base-font-size * 1rem; // UI图上标注60px
height: 100px/$rem-base-font-size * 1rem; // UI图上标注100px
margin: 32px/$rem-base-font-size * 1rem; // UI图上标注32px
}
这样做的好处是,如果某一天不使用64px作为参考值,只需修改$rem-base-font-size
变量。
以上代码看着很冗余,不如写一个函数,隐藏计算过程:
// 将设计图标注的px尺寸,转换为相应的CSS
@function convertPxFormUI($px) {
$rem-base-font-size: 64px;
@return $px / $rem-base-font-size * 1rem;
}
p.intro {
font-size: convertPxFormUI(64px);
}
p.another-intro {
font-size: convertPxFormUI(60px); // UI图上标注60px
height: convertPxFormUI(100px); // UI图上标注100px
margin: convertPxFormUI(32px); // UI图上标注32px
}
这样做的好处是,如果某一天摒弃了rem,使用了其他换算规则,只需修改convertPxFormUI()
函数体即可。
更进一步
既然Sass帮助我们计算,那么媒体查询中的一堆font-size
,Sass是否可以代劳呢?
之前介绍了计算规则:屏幕宽度/UI图宽度*64
。OK,看来可以这样写:
// 计算rem的基准字体
$rem-base-font-size: 64px;
// UI设计图的分辨率宽度
$UI-resolution-width: 1440px;
@mixin html-font-size() {
@media (min-width:320px){
html{
font-size: 320px / $UI-resolution-width * $rem-base-font-size;
}
}
@media (min-width:360px){
html{
font-size: 360px / $UI-resolution-width * $rem-base-font-size;
}
}
@media (min-width:375px){
html{
font-size: 375px / $UI-resolution-width * $rem-base-font-size;
}
}
@media (min-width:412px){
html{
font-size: 412px / $UI-resolution-width * $rem-base-font-size;
}
}
@media (min-width:480px){
html{
font-size: 480px / $UI-resolution-width * $rem-base-font-size;
}
}
@media (min-width:640px){
html{
font-size: 640px / $UI-resolution-width * $rem-base-font-size;
}
}
@media (min-width:720px){
html{
font-size: 720px / $UI-resolution-width * $rem-base-font-size;
}
}
@media (min-width:768px){
html{
font-size: 768px / $UI-resolution-width * $rem-base-font-size;
}
}
@media (min-width:1440px){
html{
font-size: 1440px / $UI-resolution-width * $rem-base-font-size;
}
}
}
很冗余,用循环来实现:
// 计算rem的基准字体
$rem-base-font-size: 64px;
// UI设计图的分辨率宽度
$UI-resolution-width: 1440px;
// 需要适配的屏幕宽度
$device-widths: 320px, 360px, 375px, 412px, 480px, 640px, 720px, 768px, 1440px;
@mixin html-font-size() {
@each $current-width in $device-widths {
@media (min-width: $current-width) {
html {
$x: $UI-resolution-width / $current-width; // 计算出是几倍屏
font-size: $rem-base-font-size / $x;
}
}
}
}
这样做的好处是,如果某一天老板说,屏幕宽度450px时效果不理想。你只需在$device-widths
中新增一个宽度即可。
Sass最终方案
_variables.scss
:定义变量
// 计算rem的基准字体
$rem-base-font-size: 64px;
// UI设计图的分辨率宽度
$UI-resolution-width: 1440px;
// 需要适配的屏幕宽度
$device-widths: 240px, 320px, 360px, 375px, 412px, 480px, 540px, 640px, 720px, 768px, 1024px, 1440px;
_utils.scss
:定义函数与mixin
// 根据不同设备的屏幕宽度,定义<html>的基准font-size
@mixin html-font-size() {
@each $current-width in $device-widths {
@media (min-width: $current-width) {
html {
$x: $UI-resolution-width / $current-width; // 计算出是几倍屏
font-size: $rem-base-font-size / $x;
}
}
}
}
// 将设计图标注的px尺寸,转换为相应的CSS
@function convertPxFormUI($px) {
@return $px / $rem-base-font-size * 1rem;
}
index.scss
:Scss入口文件
@import 'utils', 'variables';
@include html-font-size();
p.intro {
font-size: convertPxFormUI(64px);
}
p.another-intro {
font-size: convertPxFormUI(60px);
height: convertPxFormUI(100px);
margin: convertPxFormUI(32px);
}
总结
rem + viewport + 媒体查询 + Sass
从设计图到CSS:rem+viewport+媒体查询+Sass的更多相关文章
- CSS基础教程 -- 媒体查询屏幕适配
响应式布局 Media Query 的使用方法 在上例中, 我们使用Media Queries来根据3种不同尺寸的窗口使用3种不同的样式.通过不同的媒体类型和条件定义样式表规则,媒体查询让CSS可以更 ...
- rem适配布局(rem+less+媒体查询 和 rem+flexible.js)
1. rem 基础 rem 是一个相对单位,类似于 em ,em 是父元素字体大小. em 是相对于父元素 的字体大小来说的 rem 是相对于 html 元素 字体大小来说的 rem 优点 就是可以 ...
- css样式,媒体查询,垂直居中,js对象
下面是一些截图,有关查询效率,css样式,媒体查询,垂直居中,js基本类型.
- Web移动前端开发-——rem+less+媒体查询,rem+flexble.js+媒体查询
实际开发搞搞起来!!!! rem适配方案 媒体查询+rem+less 基础知识铺垫 第一步,我们需要拿到设计稿,安装设计稿的要求来设置一个合适的html字体大小. 第二步,计算元素大小的取值 页面re ...
- 总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法。(转)
<meta http-equiv="X-UA-Compatible" content="IE=edge"><!--兼容ie-->< ...
- CSS media queries 媒体查询
最近在做一些页面打印时的特殊处理接触到了media queries,想系统学习一下,在MOZILLA DEVELOPER NETWORK看到一篇文章讲的很不错,结合自己的使用总结一下. CSS2/me ...
- (原)css 响应式媒体查询 模板
@media only screen and (max-width:340px) { html,input{ font-size:80%; } } @media only screen and (ma ...
- CSS媒体查询及其使用
1.什么是媒体查询 媒体查询可以让我们根据设备显示器的特性(如视口宽度.屏幕比例.设备方向:横向或纵向)为其设定CSS样式,媒体查询由媒体类型和一个或多个检测媒体特性的条件表达式组成.媒体查询中可用于 ...
- CSS媒体查询,CSS根据不同的分辨率显示不同的样式
在写自适应网页的时候,我们需要网页有几种显示方式,我们可以用CSS实现这个功能 使用CSS提供的媒体查询,我们可以根据屏幕分辨率来使用相应的CSS样式 @media screen and (max-w ...
随机推荐
- BZOJ1856:[SCOI2010]字符串——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1856 lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还 ...
- HHVM,高性能的PHP执行引擎
HHVM (HipHop Virtual Machine) 是 Facebook 开源的 PHP 执行引擎. HHVM 采用一种JIT(just-in-time)的编译机制实现了高性能,同时又保持对 ...
- bzoj1211: [HNOI2004]树的计数(purfer编码)
BZOJ1005的弱化版,不想写高精度就可以写这题嘿嘿嘿 purfer编码如何生成?每次将字典序最小的叶子节点删去并将其相连的点加入序列中,直到树上剩下两个节点,所以一棵有n个节点的树purfer编码 ...
- bzoj2165: 大楼(倍增floyd)
题目大意:一个有向图,n(<=100)个点求一条长度>=m(<=10^18)的路径最少经过几条边. 一开始以为是矩乘,蓝鹅当时还没开始写,所以好像给CYC安利错了嘿嘿嘿QWQ 第一眼 ...
- [NOI2017]蔬菜——时光倒流+贪心
题目链接 题解: 貌似一眼看过去是一个贪心. 其他的算法要记录的东西就太多了. 部分分其实很高.但是没有什么提示. 想一些套路:二分?不行还要贪心判断. 分治?前后取法是有影响的. 时光倒流? 也许可 ...
- 关于javascript数组的定义与其一些常用方法总结
由于JavaScript是一门宽松的语言,这种宽松可能会带来更加麻烦的事情.比如JavaScript的数组,定义与使用的方式太灵活有时候让人迷惑.下面将JavaScript中关于数组常用的方法.定义之 ...
- selenium测试-open chrome
通过selenium来打开浏览器测试之前,需要确认本地已安装相应的webdriver,本例以chrome为例. 1. 查看本地chrome版本,以此确认需要安装的webdriver版本 查看chrom ...
- 自己做的jquery的autocomplete的一个例子
转载自:http://dada-fangfang.iteye.com/blog/695464 首先下载jquery.js和jquery.autocomplete.js 注意:jquery.js 要放在 ...
- android极光推送初步了解
推送可以及时,主动的与用户发起交互 (1)继承jar包,照示例AndroidManifest.xml添加. (2)自定义MyApp继承自Application,在onCreate方法中调用JPushI ...
- 【Codeforces542E】Playing on Graph [Bfs][Dfs]
Playing on Graph Time Limit: 20 Sec Memory Limit: 512 MB Description Input Output Sample Input 5 4 ...