关于Html5使用js+sass+compass实现高清适配

jopen 8年前

手机适配问题,已经是移动前端老话常谈的主题了,繁星UED上也写过了关于rem的使用文章(wangfajing大神),然而在繁星移动前端的页面中却没有把这一套适配方案使用起来,Amfe阿里无线前端团队双11技术连载分享中也提到了手淘的H5页面是如何实现多终端适配,于是本人借鉴阿里的方案,在繁星移动前端进行实践踩坑。

一、多屏适配问题

适配各种手机屏幕大小,目前最好方案莫过于使用相对单位rem。

rem的原理是根据html根元素的font-size值对元素进行大小设置,比如在根元素设定font-size = 16px,那么一个div宽度为1rem,实际即1*16px。

根据这个原理,我们针对不同手机的屏幕宽度,动态改变根节点html的font-size,就可以等比例的放大缩小页面各个元素,从而达成适配。

1.了解viewport

viewport不局限于浏览器的可视区域大小,它可能比浏览器的可视区域要大,也可能比浏览器的可视区域要小。一般来讲,移动设备上的viewport都是要大于浏览器可视区域的,这是因为考虑到移动设备的分辨率相对于桌面电脑来说都比较小,所以为了能在移动设备上正常显示那些传统的为桌面浏览器设计的网站,移动设备上的浏览器都会把自己默认的viewport设为980px或1024px。这也是手机上看电脑网页为什么缩小的原因。因此加下面一段代码可以让viewport等于手机屏幕宽度。这时候看电脑的网页,会出现左右滑动,因为页面的元素css宽度超过了viewport。

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">

2.提取基准:

document.documentElement.style.fontSize = clientWidth / 10 + 'px';

除以10,是为了取整,方便计算,理论上可以是任何值。clientWidth为移动设备上的viewport宽度。

2.计算rem(sass+compass)

由于rem是写在css里面的,但每个元素大小的值都要计算得出,需要在css里面写函数计算,这时sass登场了。参考 sass十分钟入门

先安装ruby,再安装sass以及compass,compass是把sass文件.scss编译成css文件,这里需要手动敲命令编译,暂时没自动化。

gem install sass  gem install compass

新建index.scss

$uiWidth:360px;//UI效果图的宽度一半  @function pxToRem($px){        @return 10*$px/$uiWidth/2*1rem;  }  div{      width:pxToRem(100px);  }

执行编译操作就得到想要的index.css

sass --watch index.scss:index.css

3.举个例子验证

一个720px的UI图(一般UI会放大两倍画图),其中一个div100px,在320px宽的手机上该div应该显示多少?典型等比例计算:

手机css宽度=320*100/720=(320*100*10)/(720*10)=(320*100*10)/(360*2*10)=((100*10)/(360*2)) * (320/10)    手机css宽度=rem * font-size    ((100*10)/(360*2))作为rem数值,100即$px,360即uiWidth,于是把10*$px/$uiWidth/2*1rem作为pxToRem函数的返回值,只要在UI图上测量多少,代入$px,自动算出对应的rem值多少;    (320/10)作为基准赋予font-size,320即clientWidth

二、retina下border:1px问题

在retina屏幕中1px的border会显得粗一点,解决办法是根据设备像素比dpr,对页面中的所有的border: 1px都缩小1/dpr倍,从而达到高清效果。注意:放大两倍viewport,对于px为单位的元素其实就缩小了两倍。

<meta name="viewport" content="width=device-width, initial-scale=1/dpr, minimum-scale=1/dpr, maximum-scale=1/dpr, user-scalable=no">

三、图片高清和文字大小问题

1.retina屏幕需要高清图片,然而普通屏幕加载高清图片却浪费资源耗带宽,因此根据不同手机dpr加载不同的图片可以解决这问题。

@mixin img-dpr(){      background-image: url(image.jpg);//默认        [data-dpr="2"] & {          background-image: url(image@2x.jpg);//两倍高清        }        [data-dpr="3"] & {          background-image: url(image@3x.jpg);//三倍高清        }  }  .content{      @include img-dpr();   }

2.使用了rem之后,页面元素会随着屏幕的增大而等比例放大,但是某些内容我们不愿意被放大,例如正文段落,而是为显示更多的文字,这时文字则不使用rem作为单位,而是用px。但由于在解决border:1px问题的时候对页面进行了缩放scale,因此设置字体需要乘上dpr,否则字体会变得很小。

@mixin font-dpr($font-size){        font-size: $font-size;        [data-dpr="2"] & {          font-size: $font-size * 2;        }        [data-dpr="3"] & {          font-size: $font-size * 3;        }  }  .content{      @include font-dpr(12px);      }

注意:别忘了在html设置data-dpr属性,css hack用。document.documentElement.setAttribute('data-dpr', dpr);由于android酷狗内嵌页对于缩放scale不支持,因此dpr始终为1,即忽略border:1px问题,而且这个影响不大,反正个人觉得厚一点的border也没那么难看。

四、总结

如有理解错误,欢迎纠正。以上陈述都倾向直接运用,如果需要了解详细的概念,参考以下地址:

http://www.html-js.com/article/3041

http://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html //淘宝方案

来自: http://ued.fanxing.com/guan-yu-html5shi-yong-jssasscompassshi-xian-gao-qing-gua-pei/