响应式设计专刊
适配方案
一般而言,常用的有以下几种适配方案。当然前提是都要先设置好viewport,一般是initial-scale为1。之前也有了解实践过在dpr为2或3时设置initial-scale为.5或是.33,可是我还是觉得没什么必要哎…或许是没有领会到这样设置的用途。
全军px系列
即padding,font-size。margin都以px为单位,优点是方便,在大屏下也显得蛮优雅的,缺点是不少地方不能写死,比如宽度尽可能的按百分比来,等分定位的话可以用flex等。
现在的 vw/vh 系列
px2viewport 就 ok 方便控制其他的引入组件。
module: {
rules: [
{
test: /\.(less|css)$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env',
{
'postcss-px-to-viewport': {
unitToConvert: 'px',
viewportWidth: 750,
unitPrecision: 6,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: ['wrap'],
minPixelValue: 1,
replace: true,
// 注:下面有问题,只处理组件包就 ok 了
// exclude: [/node_modules/],
// include: [/\/node_modules\/antd-mobile\//],
landscape: false,
},
},
],
},
},
},
{
loader: 'less-loader',
options: {
lessOptions: { javascriptEnabled: true },
},
},
],
},
],
},
注意 viewport 这里是 750。一般组件库会以 375 为 base,像 antd-mobile 亦提供了 750 为 base 的引入版本。
rem系列
用rem的话,根字体大小一般以屏幕css宽度/10来计算,当然也有不同的实践。优点是任何定位都可以根据rem写死…毕竟可以理解成不同的屏幕大小整个就是一等比缩放。字体可以按rem,也可以按px。缺点是pad下会显得过于大了。
脍炙人口的flexible.js设置方案如下:
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 \* dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// 关键拉 set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
// offsetHeight是包括border的,所以由此判断
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
ps: 实现极细border
0.5px的border又称为hairlines。那么当然要先判断当前浏览器资不资词0.5px的border-width,这个在上面的flexible.js里就包括拉!如不支持,可通过其他方式实现极细border的方案,主要有两种:一是按border来写,另一是不按border来写…
依然按border来写的话,可以①通过border-background设置一半透明一半有线的背景。②将viewport缩小一倍,即initial-scale=.5。
不按border来写的话,即各种伪造border。比如在::after里面放一个1px高的div线再scale(0.5)阿,通过border-image来乔装阿…这种。
历史调研
美团
375宽度 html的font-size: 31.25px
320宽度font-size: 26.67px
值得借鉴之处:
整个主要部分被一个wrapper包了起来:(max-width: 12rem 约414px)/…如果我scale .5的话就大概是820px。这样可以保证pc网页打开宽度也不会太宽。那么html的font-size当然就是以这个wrapper的宽度来计算。
----我自己试了了一下 其余的挺好 有两个需要注意的点
①fixed-position定位的元素
width 100%的话会变成全屏那么长
②scale必须是1!因为viewport只在手机页面上才生效,而这个wrapper的max-width表示的应该是pc页面和手机页面的临界值。而pc页面的显示效果就是1:1。如果按我scale .5的话 换算成手机页面width 都有六七百宽 岂不是都比414px大了,如果还要再加上一条区分是否pc/mobile页面的条件来动态改变wrapper的max-width的话 又略显麻烦了
知乎
采用 px 的方式,如果是 iPad 的话采取 pc 端样式
我的疑惑:岂不是大屏显示的字一行多 小屏显示的一行字少?那么做“xxxx....”这样截取某些字数时,字数要如何选择呢?唔…果然不同屏幕多少行不固定的!
手淘
375宽度:112.5px 就是10: 1*3的关系!手淘有设置根font-size,但是计算方案比较不同,iPhone6对应的html的font-size是100px,另外布局中的样式几乎都是实时计算出来的行内样式,单位px。
至于为什么要设计成33.3% 意为放大三倍 那么是为了考虑到dpr为3的比如iphone6这种手机 字体和css控制的东西不会有问题 但是图片可能就会放大而显得模糊了。
这样子设计的话 一个小logo图很可能就是200px多 所以可以实现在iphone上的1:1展示。
不过其实嘛 图片做大一点就好咯!
天猫
375宽度:37.5px 就是10:1的关系!
手机京东
https://m.jd.com/ 终于找到用rem方案的了!并且是全rem形式。不过京东的根字体大小是根据media query设置的:
@media only screen and (min-width:320PX) and (max-width:360PX){html{font-size:13.65px}}
@media only screen and (min-width:360PX) and (max-width:375PX){html{font-size:15.36px}}
@media only screen and (min-width:375PX) and (max-width:390PX){html{font-size:16px}}
@media only screen and (min-width:390PX) and (max-width:414PX){html{font-size:16.64px}}
@media only screen and (min-width:414PX) and (max-width:640PX){html{font-size:17.664px}}
@media screen and (min-width:640PX){html{font-size:27.31px}}