前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >响应式或自适应布局的流派

响应式或自适应布局的流派

原创
作者头像
一起重学前端
修改2024-09-30 07:41:49
1060
修改2024-09-30 07:41:49

响应式或自适应布局的流派

(此图有可能名称反了,但不重要,我个人更偏向于 bootstrap 被叫作响应式的)

本文旨在罗列实现响应式或自适应布局的几种方案。

前言

四种设备:移动端、PC 端、超大屏、高清屏

两种环境:没 device-width、有 device-width

其他注意事项:毛细线、多端兼容、设计稿还原精度

在 @media  出现之前,大家是怎么过的呢?

PC 页面大多是给容器定宽的,手机上屏宽等于定宽,想看清内容就得靠缩放拖拽。

弊端在哪呢,每进一页就要放大一次,PC 端与移动端设计必然多套。

栅栏布局 方案

随后 @media  和  viewport device-width 的组合拳之下,偷懒的方案栅栏布局横空出世。

如果将元素或内容看作是一个个的区块,那么搬运一下位置岂不是挺方便的嘛,

将宽度分为 12 栏,左边占 3 栏,中间占 7 栏,右边占 2 栏;

当宽度变小时,左边占 12 栏跑到上面去,中间占 9 栏,右边占 3 栏,相应变化。

且  device-width 自动会让文字跟随屏幕放大,

原本 PC 端 3 栏的内容,到移动端看到 12 栏的内容,一眼所能看到的信息量是相近的。

很明显,栅栏布局能非常方便且粗浅的处理 PC 端与移动端的样式调整,

字体大小会变大,适合小屏设备阅读,多端简单地适配操作非常简单。

但依旧有着问题,比如专注于小屏设备的话误差很大,专注于超大屏的话还缺些火候。

em 方案

本方案算是优化的一类,可以稍稍弥补上述所说的大小屏问题。

虽然有着  device-width 文字得到了放大,

但 320px 小屏中的 12px 与 414px 小屏中的 12px 视觉上还是有较大差异的。

那么,用 em 去跟随这些细小的适配粒度,再放大一次呢。

代码语言:html
复制
html { font-size: 10px; }
@media screen and (min-width: 321px) and (max-width: 375px) {
  html { font-size: 11px; }
}
@media screen and (min-width: 376px) and (max-width: 414px) {
  html { font-size: 12px; }
}
@media screen and (min-width: 415px) and (max-width: 639px) {
  html { font-size: 15px; }
}
@media screen and (min-width: 640px) and (max-width: 719px) {
  html { font-size: 20px; }
}
@media screen and (min-width: 720px) and (max-width: 749px) {
  html { font-size: 22.5px; }
}
@media screen and (min-width: 750px) and (max-width: 799px) {
  html { font-size: 23.5px; }
}

说实话,设定字体大小、边距间隙、定宽定高、动画位移,需要用到 px 的场景并不太多,

前两者甚至可以统一公共类来完成,所以随着 em 缩放一些,能够比较粗浅轻易的适配更小的粒度。

还带来了一个蛮有意思的效果,在只有 px 的时候,宽度变化想要高度也变化是困难的,

而宽度随 em 变化时,如果高度也写成 em 那就很妙了。

但这也有点小问题,就是 em 中的 em 其实是翻倍,这计算量可就哦豁了。

rem 方案

如果 em 会面临嵌套后多倍计算的话,直接用 rem 不就好了吗。

再进一步,em 方案中根节点的字体大小能否直接不用 @media  而用 js 来实现,

这也便造就了 lib-flexible 等插件的出现。

而 px2rem 或 postcss-pxtorem 等工具也让开发不用侧重于写 rem 而是写 px 了。

主要代码

代码语言:js
复制
function flexable(remRatio = 75) {
  function setRem() {
    var winW = docEl.getBoundingClientRect().width;
    $style.innerText = 'html{font-size:' + (docEl.style.fontSize = winW / remRatio + 'px') + ' !important;}';
  }
  var win = window,
    doc = document,
    docEl = doc.documentElement,
    $style = doc.createElement('style');
  doc.head.appendChild($style);
  setRem();
  win.addEventListener('resize', setRem, !1);
}

flexable(7.5); // 7.5rem = 100vw

postcss-px-to-viewport

代码语言:js
复制
module.exports = {
  plugins: {
    autoprefixer: {},
    'postcss-px-to-viewport': {
      unitToConvert: 'px',
      viewportWidth: 10000,
      unitPrecision: 5,
      propList: ['*'],
      viewportUnit: 'rem',
      fontViewportUnit: 'rem',
      selectorBlackList: ['.ignore'],
      minPixelValue: 1,
      mediaQuery: false,
      replace: true,
      exclude: [],
      landscape: false,
      landscapeUnit: 'rem',
      landscapeWidth: 568,
    },
  },
};

改动 viewport

https://foreverz133.github.io/demos/works/lib-flexible/js/lib-flexible.js

众所周知,小数和单数的尺寸数值其实并不精准,甚至 1px 就能造成 float 布局的错位,

而 rem 方案中转化为实际 px 其实相当多情况都是小数,所以会更注重毛细线效果的结果。

而  initial-scale 一定程度上可以稍稍减小误差的概率。

也能让高清屏得到  initial-scale 放大,显得更清晰细致(不包括图片)。

代码语言:js
复制
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;
metaEl.setAttribute(
  'content',
  'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'
);

body 的 font-size

在很多插件中,body 的 font-size 会被设置为 12 * dpr 的大小。

而如果将其设为 12rem 的话将出现一种很优秀的效果。

就是 Ctrl + 加号 去缩放屏幕时,并不会改变视图。

vw 方案

然而当开始使用 rem 后你会发现一个问题, @media  不再那么有效了,

那么我想用  @media(min-height: 414px)  或 @media(min-height: 414rem)  去调整些什么都是不可行的。

vw 方案则比较好地能部分解决这个问题,毕竟它并没有改变什么比例基准。

而 initial-scale 也可以靠  @media(min-device-pixel-ratio)  来搞搞。

可以说 vw 方案其实要比 rem 方案更应该被推崇,至少大漠也这么认为。

但是吧,rem 方案 和 vw 方案,在非全屏宽布局中其实都不太 OK。

代码语言:html
复制
.container {
  width: 1280px;
  margin-left: auto;
  margin-right: auto;
}

pt 方案

以上方案,都用到了 viewport 的  device-width 来进行屏幕宽度的响应,而 pt 方案则不然。

代码语言:html
复制
<meta name="viewport" content="user-scalable=no" />
代码语言:css
复制
@function px($px, $designWidth: 750) {
  @return (735 / $designWidth) * $px * 1pt;
}

它有着 rem 方案类似的效果,但不需要修改根节点字体大小。

比如:此处的 px(375, 750) 相当于 50vw。

不过,此方案在屏宽大于 980px 后就没用了,因此只适用于手机端。

以前有试用过三个月,没有出现过纰漏,感觉也是个非常有效的方案。

具体原理不详,原文来自于 移动端 HTML 响应式布局之神奇的 pt

其实这和流行 viewport 前的原始形态很相似,也是字体大小会随屏幕缩放,

但有个比例尺后,就和设计稿尺寸对应上了,妙哉妙哉。

固定视图 方案

代码语言:html
复制
<meta name="viewport" content="width=750,user-scalable=no" />

此方案就很骚了,直接改 viewport 其他都按 px 来。

不搞什么自动间隙,什么左右靠齐,就是固定宽,开发起来贼舒服。

以前试用了半年多,用于移动端也完全没问题,PC 端有极少设备不能用。

百分比定位

其实这是最常见的响应式方案了,只是并不处理文字而已。

所以仅有图片等元素的很多活动 H5 就直接用百分比绝对定位来实现自适应了。

scale 缩放居中

以上方案都是根据屏宽来产生响应的,那么有没有办法以容器宽度来响应的呢。

很遗憾,要么 iframe 要么 transform 的 scale 来实现了。

比如一个游戏界面,只要固定的宽高不超出屏幕,居中就完事了。

代码语言:js
复制
function initWindowSize(designWidth = 750, designHeight = 1334) {
  var winW = window.innerWidth;
  var winH = window.innerHeight;
  var $body = $('.container');
  var ww, hh;
  if (winW / winH < designWidth / designHeight) {
    ww = winW;
    hh = (designWidth / designHeight) * ww;
  } else {
    hh = winH;
    ww = (designWidth / designHeight) * hh;
  }

  var scale = ww / designWidth;
  $body.css('transform', 'scale(' + scale + ')');
}

而且此方案特别适合横屏应用,是改造量最少的方案。

腾讯技术创作特训营s9其他文章

学习NestJS的第一个接口(一)

学习NestJS开发小程序后台(一)

学习NestJS开发小程序后台(二)检测图片敏感内容

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 响应式或自适应布局的流派
    • 前言
      • 栅栏布局 方案
        • em 方案
          • rem 方案
            • 主要代码
            • postcss-px-to-viewport
            • 改动 viewport
            • body 的 font-size
          • vw 方案
            • pt 方案
              • 固定视图 方案
                • 百分比定位
                  • scale 缩放居中
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档