本文作者: 文蔺
本文地点: http://www.wemlion.com/2015/a…
本文由 @文蔺 创作,转载请保存此声明。 一切权保存,请勿用于贸易目标。
【资本一】基础知识恕不回忆
基础知识参考以下两篇博客:
http://isux.tencent.com/web-a…
http://www.w3cplus.com/css3/d…
【资本二】淘宝m站首页的动态完成
进修http://m.taobao.com 首页的完成。
近来读到@大漠的新文章《运用Flexible完成手淘H5页面的终端适配》,和本部份有点关联。临时加上来以供参考。(updated 2015-11-24)
源码举行美化、解读以后,基础规划部份的代码已被我复原出来了:(2016-01-13补充:厥后才发明,早就开源在github上了)
!function(win, lib) {
var timer,
doc = win.document,
docElem = doc.documentElement,
vpMeta = doc.querySelector('meta[name="viewport"]'),
flexMeta = doc.querySelector('meta[name="flexible"]'),
dpr = 0,
scale = 0,
flexible = lib.flexible || (lib.flexible = {});
// 设置了 viewport meta
if (vpMeta) {
console.warn("将依据已有的meta标签来设置缩放比例");
var initial = vpMeta.getAttribute("content").match(/initial\-scale=([\d\.]+)/);
if (initial) {
scale = parseFloat(initial[1]); // 已设置的 initialScale
dpr = parseInt(1 / scale); // 装备像素比 devicePixelRatio
}
}
// 设置了 flexible Meta
else if (flexMeta) {
var flexMetaContent = flexMeta.getAttribute("content");
if (flexMetaContent) {
var initial = flexMetaContent.match(/initial\-dpr=([\d\.]+)/),
maximum = flexMetaContent.match(/maximum\-dpr=([\d\.]+)/);
if (initial) {
dpr = parseFloat(initial[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximum) {
dpr = parseFloat(maximum[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
// viewport 或 flexible
// meta 均未设置
if (!dpr && !scale) {
// QST
// 这里的 第一句有什么用 ?
// 和 Android 有毛关联 ?
var u = (win.navigator.appVersion.match(/android/gi), win.navigator.appVersion.match(/iphone/gi)),
_dpr = win.devicePixelRatio;
// 所以这里似乎是将一切 Android 装备都设置为 1 了
dpr = u ? ( (_dpr >= 3 && (!dpr || dpr >= 3))
? 3
: (_dpr >= 2 && (!dpr || dpr >= 2))
? 2
: 1
)
: 1;
scale = 1 / dpr;
}
docElem.setAttribute("data-dpr", dpr);
// 插进去 viewport meta
if (!vpMeta) {
vpMeta = doc.createElement("meta");
vpMeta.setAttribute("name", "viewport");
vpMeta.setAttribute("content",
"initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no");
if (docElem.firstElementChild) {
docElem.firstElementChild.appendChild(vpMeta)
} else {
var div = doc.createElement("div");
div.appendChild(vpMeta);
doc.write(div.innerHTML);
}
}
function setFontSize() {
var winWidth = docElem.getBoundingClientRect().width;
if (winWidth / dpr > 540) {
(winWidth = 540 * dpr);
}
// 根节点 fontSize 依据宽度决议
var baseSize = winWidth / 10;
docElem.style.fontSize = baseSize + "px";
flexible.rem = win.rem = baseSize;
}
// 调解窗口时重置
win.addEventListener("resize", function() {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}, false);
// 这一段是我本身加的
// orientationchange 时也须要重算下吧
win.addEventListener("orientationchange", function() {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}, false);
// pageshow
// keyword: 倒退 缓存相干
win.addEventListener("pageshow", function(e) {
if (e.persisted) {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}
}, false);
// 设置基准字体
if ("complete" === doc.readyState) {
doc.body.style.fontSize = 12 * dpr + "px";
} else {
doc.addEventListener("DOMContentLoaded", function() {
doc.body.style.fontSize = 12 * dpr + "px";
}, false);
}
setFontSize();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = setFontSize;
flexible.rem2px = function(d) {
var c = parseFloat(d) * this.rem;
if ("string" == typeof d && d.match(/rem$/)) {
c += "px";
}
return c;
};
flexible.px2rem = function(d) {
var c = parseFloat(d) / this.rem;
if ("string" == typeof d && d.match(/px$/)) {
c += "rem";
}
return c;
}
}(window, window.lib || (window.lib = {}));
注重:
淘宝首页在iPhone4上设置的initial-scale是0.5(其他尺寸相似)。
因而,这句在iPhone4上得出的效果是640:
var winWidth = docElem.getBoundingClientRect().width;
恰是因为淘宝这类奇特的设置,使得 ios 上 1px边框的题目圆满处置惩罚(1px变2px, 又被 initial-scale=0.5
缩小了一半)。
【资本三】通例状况下js依据屏幕宽度动态盘算
运用js动态盘算:
!(function(doc, win) {
var docEle = doc.documentElement,
evt = "onorientationchange" in window ? "orientationchange" : "resize",
fn = function() {
var width = docEle.clientWidth;
width && (docEle.style.fontSize = 20 * (width / 320) + "px");
};
win.addEventListener(evt, fn, false);
doc.addEventListener("DOMContentLoaded", fn, false);
}(document, window));
【资本四】媒体查询较麋集的断点
运用css3 media query 完成
@media screen and (min-width: 320px) {
html {font-size: 14px;}
}
@media screen and (min-width: 360px) {
html {font-size: 16px;}
}
@media screen and (min-width: 400px) {
html {font-size: 18px;}
}
@media screen and (min-width: 440px) {
html {font-size: 20px;}
}
@media screen and (min-width: 480px) {
html {font-size: 22px;}
}
@media screen and (min-width: 640px) {
html {font-size: 28px;}
}
【资本五】壮大的单元——vw
运用单元 vw 完成动态盘算。
html {
font-size: 31.25vw; /* 表达式:100*100vw/320 */
}
不过斟酌到国内兼容性的题目,照样连系媒体查询来运用比较好。(媒体查询的断点临时是借用上面的例子)
@media screen and (min-width: 320px) {
html {
font-size: 100px;
}
}
@media screen and (min-width: 360px) {
html {
font-size: 112.5px;
}
}
@media screen and (min-width: 400px) {
html {
font-size: 125px;
}
}
@media screen and (min-width: 440px) {
html {
font-size: 137.5px;
}
}
@media screen and (min-width: 480px) {
html {
font-size: 150px;
}
}
@media screen and (min-width: 640px) {
html {
font-size: 200px;
}
}
html {
font-size: 31.25vw;
}
【总结】
对以上各种要领的综合:
1、meta:viewport, 照样initial-scale为 1;
2、320px屏幕下,把页面根元素html的字体大小设置为50px;
3、鉴于我们拿到的设想图如今是640px宽的基准,如许我们就不必每次本身除以2了,直接在PS中量就好;
4、宽度什么的最好照样用百分比处置惩罚;涉及到高度、字体大小之类的则用rem。
eg:
设想稿上,div高度为40px;那末css就是 div {height: 0.4rem;}
效果就只剩下一步转换:设想稿上量的长度转化为小数。 50% => 0.5
这类盘算,不要太简朴。。。
【要领一】地道css,支撑calc函数的动态盘算;不支撑的用css媒体查询断点,文雅降级。
@media screen and (min-width: 320px) {
html {
font-size: 50px;
}
}
@media screen and (min-width: 360px) {
html {
font-size: 56px;
}
}
@media screen and (min-width: 400px) {
html {
font-size: 63px;
}
}
@media screen and (min-width: 440px) {
html {
font-size: 69px;
}
}
@media screen and (min-width: 480px) {
html {
font-size: 75px;
}
}
/**
* 2016-01-13 修订
* 做恰当限定
* 大于640的屏幕 固定为100px
* 同时须要对body或许最外层wrapper做max-width: 640px的限定
*/
/*
@media screen and (min-width: 640px) {
html {
font-size: 100px;
}
}
html {
font-size: 15.625vw;
}
*/
html {
font-size: 15.625vw;
}
@media screen and (min-width: 640px) {
html {
font-size: 100px;
}
}
【要领二】剧本动态盘算
大前提:
1、initial-scale 为 1;
2、在项目css中(注重不要被大众的base、common之类的影响了,资本加载递次也是蛮主要的),先把html的fontSize设置为 50px(或许加上媒体查询代码), 防止加载未完成时刻款式紊乱;
/* css */
html {font-size: 50px;}
/* javascript */
!(function(win, doc){
function setFontSize() {
// 猎取window 宽度
// zepto完成 $(window).width()就是这么干的
var winWidth = window.innerWidth;
// doc.documentElement.style.fontSize = (winWidth / 640) * 100 + 'px' ;
// 2016-01-13 修订
// 640宽度以上举行限定 须要css举行合营
var size = (winWidth / 640) * 100;
doc.documentElement.style.fontSize = (size < 100 ? size : 100) + 'px' ;
}
var evt = 'onorientationchange' in win ? 'orientationchange' : 'resize';
var timer = null;
win.addEventListener(evt, function () {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}, false);
win.addEventListener("pageshow", function(e) {
if (e.persisted) {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}
}, false);
// 初始化
setFontSize();
}(window, document));
嗯。。。
就这么愉快地完毕了。。。
不知道解读了某宝首页的一点点代码,然后发在这里,会不会有什么效果。。。
==================================================
2016年1月13日补充
写过这篇博客以后,又连续读过几篇关于规划的文章。
详细已忘了,大约是大漠的文章,另有一篇应当是搜车前端的博文,别的应当另有关于手淘首页的剖析的文章。
别的,本身也用rem规划实践过几个项目。
不得不说,个人以为rem规划如今已能够摒弃了。flex
规划已很好用了,早已有之的百分比规划等稍用点心机也并不难。
这篇博客一向想改。但懒散老是占有着我的身材。
末了再说下,字体大小自适应是毛病的,字体大小自适应是毛病的,字体大小自适应是毛病的。
rem 规划,能够告别了。
驱逐 flex 规划吧。
=========================================
写在末了
这篇博客写于半年前,那时刻照样个刚毕业的菜鸟。
偶然有点主意,看了一些大牛的文章,有了这篇博客。
这也是半年来唯一一篇产出。
5k的浏览量,95珍藏,13引荐,已让我很惊奇了。
感谢各路大神们的关注。
半年来感受到的前端大环境变化照样很大。虽然在公司没有太多变化,但眼睛总得看着天下吧。
接下来,还得继承进修。
因为手上没什么项目,一向想探究出一套本身的自动化流程,但到如今也只是积累了很多版的草稿。
nodejs
方面也得有所探究,nodejs
再加上 shelljs
和 yargs
用起来是真的很爽。(道谢阮大神的文章)
算是年终总结了。在前端的路上继承走吧。
=========================================
一点主意:批评区的复兴
媒体查询和js动态盘算是两种体式格局。
起首,支撑 CSS3 calc
要领 和 rem
、vw
单元的浏览器下,只须要html {font-size: 15.625vw;}
如许一句就好,别的加个媒体查询限定下。
之前的一大堆麋集的断点只是为了hack不支撑calc
或许calc
的状况。其次,js动态设置html的font-size
,只需浏览器支撑rem单元即可。
为何会斟酌到麋集的mq断点呢,因为当时还在斟酌文字大小的自适应题目。
实践证明,字体大小自适应是一种毛病的主意。
挪动开发在必要状况的下,能够恰当运用mq来调解字体大小,但做成完整自适应则是一种存在题目的做法。
因而,这里提到的 calc
和vh
rem
合营的做法,最好只用来做规划的事情。js动态盘算也是相似,更适合做规划。
更新
Articles on responsive font: