1

移动端布局方案浅谈

 2 years ago
source link: https://snayan.github.io/post/mobile-layout/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一直想抽时间总结一下现在业界可用的移动端布局方案。需求多,995 模式,身心被掏空,一拖再拖,终于在周六的晚上,做着梦弄完成的,不足之道 😪,请指教改正 🤠。

media+百分比

直接采用媒体查询加百分比去布局。

核心思想:

  • 页面主体布局基本采用百分比去设置。
  • 然后,其他块内布局,例如 font-size 等可通过设置媒体查询的断点来分设置,已达到兼容其他手机尺寸。
  • 灵活,简单
  • 兼容性好,媒体查询,97.65%的浏览器都支持了。
  • 媒体查询的断点设置麻烦,只能在选取的几个主流设备尺寸下呈现完美适配。
  • 1px 的问题,需要额外做处理,比如 transform:scaleX(0.5)。

例子:京东

hotcss

hotcss

这个方案比较简单和实用,理解起来也不难。项目地址查看这里

  • 自动通过 hotcss.js 计算页面的htmlfont-size的大小,其后在布局中使用 rem 作为像素单位,使得页面在不同的移动设备上可以视觉一致。
  • 通过获取 dpr,在html上设置属性data-dpr,在设置font-size时,可以配合data-dpr来使用 px 作为像素单位。
  • 计算 scale,为页面设置viewport,使得页面根据 dpr 进行缩放,最终达到,1 个物理像素=1px。这样,也有效解决了 1px 的问题。
  • 默认在 320px 屏幕中(非 Retina 屏),1rem=20px;

核心源码:

计算 dpr 并设置data-dprscale

// 计算dpr
var dpr = window.devicePixelRatio || 1
// 在其他的一些方案中,会区分ios和android,对android统一设置为1.
dpr = dpr >= 3 ? 3 : dpr >= 2 ? 2 : 1
// 设置data-dpr
document.documentElement.setAttribute("data-dpr", dpr)
// 计算scale
var scale = 1 / dpr,
  content =
    "width=device-width,initial-scale=" +
    scale +
    ",minimum-scale=" +
    scale +
    ",maximum-scale=" +
    scale +
    ",user-scalable=no"
// 插入meta,设置页面缩放
var viewport = document.createElement("meta")
viewport.setAttribute("name", "viewport")
viewport.setAttribute("content", content)
document.head.appendChild(viewport)

计算font-size并设置htmlfont-size

// 获取设备的宽度
var innerWidth =
  document.documentElement.getBoundingClientRect().width || window.innerWidth
// 计算font-seize,默认320px中,1rem=20px.
document.documentElement.style.fontSize = (innerWidth * 20) / 320 + "px"
  • 后续布局处理简单,配合 px2rem 插件等,使用十分方便。
  • 基本能很好适配市面即大多数尺寸手机。
  • 兼容性也比较好,97.62%浏览器基本支持 rem 单位了。
  • 通过设置缩放比例,有效解决了 1px 的问题。
  • 页面需要额外引入 js 脚本去计算,增加一次额外的 http 请求,或内嵌到页面中增加页面体积大小。

例子:卷皮

hotcss

flexible

这个是手机淘宝推出来一个方案,解决手机淘宝 H5 在移动端的布局。项目地址查看这里

  • 自动通过 flexible.js 计算页面htmlfont-size的大小,然后在页面布局中使用 rem 作为单位,而非 px。
  • 如果页面指定了meta[name="viewport"],则直接根据已有的 meta 标签来设置缩放比例;否则,通过dpr来自动计算页面缩放比例。
  • 设置 1rem=10vw,例如,在 320px 屏幕(非 Retina 屏),1rem=32px;

核心源码:

计算缩放比例

// 参试获取页面已定义的缩放比例
var metaEl = doc.querySelector('meta[name="viewport"]')
if (metaEl) {
  console.warn("将根据已有的meta标签来设置缩放比例")
  var match = metaEl.getAttribute("content").match(/initial\-scale=([\d\.]+)/)
  if (match) {
    scale = parseFloat(match[1])
    dpr = parseInt(1 / scale)
  }
}
// 如果没有,则自动计算
if (!dpr && !scale) {
  var isAndroid = win.navigator.appVersion.match(/android/gi)
  var isIPhone = win.navigator.appVersion.match(/iphone/gi)
  var devicePixelRatio = win.devicePixelRatio
  if (isIPhone) {
    // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
    if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
      dpr = 3
    } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
      dpr = 2
    } else {
      dpr = 1
    }
  } else {
    // 其他设备下,仍旧使用1倍的方案
    dpr = 1
  }
  scale = 1 / dpr
}

设置 meta

if (!metaEl) {
  metaEl = doc.createElement("meta")
  metaEl.setAttribute("name", "viewport")
  metaEl.setAttribute(
    "content",
    "initial-scale=" +
      scale +
      ", maximum-scale=" +
      scale +
      ", minimum-scale=" +
      scale +
      ", user-scalable=no"
  )
  if (docEl.firstElementChild) {
    docEl.firstElementChild.appendChild(metaEl)
  } else {
    var wrap = doc.createElement("div")
    wrap.appendChild(metaEl)
    doc.write(wrap.innerHTML)
  }
}

计算页面的 html 的 font-size

var width = docEl.getBoundingClientRect().width
// 最大屏幕宽度为540*dpr
if (width / dpr > 540) {
  width = 540 * dpr
}
// 设置1rem=10vw
var rem = width / 10
docEl.style.fontSize = rem + "px"
flexible.rem = win.rem = rem

优缺点同 hotcss。

例子:淘宝

hotcss

rem+vw

这种方案就是在计算 html 的 font-size 时,是根据 vw 去自动计算,而不是用 js 脚本去动态计算。vw 是一种新的单位,类似的还有 vh,vmin,vmax。定义如下:

  • vw:1vw 等于视口宽度的 1%;例如,320px 宽度视口中,1vw=3.2px,10vw=32px,100vw=320px;
  • vh:1vh 等于视口高度的 1%;例如,568px 高度视口中,1vh=5.58px,10vh=56.8px,100vh=568px;
  • vmin:选取 vw 和 vh 中最小的那个;
  • vmax:选取 vw 和 vh 中最大的那个;

核心思想:

不用 js 去动态计算页面的 font-size ,而是设置根元素 html 的 font-size=a vw;这里的a,可以选取一种屏幕尺寸去参考计算。例如,我们想 iPhone6 下,html 的 font-size 为 100px。那个 html 的 font-size=100/375=0.26666666666666666vw。那么,其他屏幕的适配计算方式就是:

iphone5:屏幕是320*568
html的font-size=0.26666666666666666*320=85.33333333333333

iphone6s:屏幕是414*736
html的font-size=0.26666666666666666*414=110.39999999999999

页面布局采用 rem 布局,而非 px。根据 html 的 font-size 和 rem 单位自动计算出了布局 px。

  • 不需要额外引入 js 脚本去计算,自动根据 vw 去计算 font-size
  • 后续布局也超级简单,采用 rem 即可。
  • vw 单位的支持相对比 rem 的浏览器少一些,目前有 93.65%的浏览器都支持了。

例子:拼多多

hotcss

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK