Giter Club home page Giter Club logo

wswmsword / postcss-mobile-forever Goto Github PK

View Code? Open in Web Editor NEW
233.0 2.0 18.0 6.17 MB

一款 PostCSS 插件,将固定尺寸的视图转为可跟随宽度变化而等比例伸缩的视图。To adapt different displays by one mobile viewport.

Home Page: https://wswmsword.github.io/examples/mobile-forever/vanilla/

License: MIT License

JavaScript 49.94% HTML 10.07% CSS 14.00% Vue 13.99% Svelte 1.76% SCSS 0.32% TypeScript 9.72% Dockerfile 0.05% Less 0.16%
postcss css-scale media-queries mobile-design pixel-units viewport-units responsive-web-design css postcss-px-to-viewport mobile-first

postcss-mobile-forever's Introduction

postcss-mobile-forever

PostCSS

996.icu

⚠️ Warning

使用本插件转换视口单位(如 vw),或是其它使用动态根元素 font-size 结合 rem,这两种方法生成的伸缩视图,不能触发浏览器的缩放功能(可以通过快捷键同时按下 CMD/Ctrl+/- 触发),不能满足针对缩放的可访问性标准,因此存在可访问性问题。查看一个关于 vw 伸缩视图的可访问性实验

一款 PostCSS 插件,用于将基于特定宽度的固定尺寸的视图,转为可跟随宽度变化而等比例伸缩的视图,并提供超出某一宽度后停止放大视图的方法,这种视图常见于移动端页面的适配。postcss-mobile-forever 可以配合 scale-view 使用,前者用于编译阶段,后者用于运行阶段。postcss-mobile-forever 具备以下特性:

  • 转换用于伸缩视图的视口单位(px->vw);
  • 提供两种方法限制伸缩视图的最大宽度,
    • 生成适应桌面端和横屏的媒体查询(@media),
    • 或是利用 CSS 函数限制视口单位最大值(min(vw, px));
  • 矫正 fixed 定位的元素,支持逻辑属性的转换。
使用媒体查询限制最大宽度的方法,能够为桌面端与横屏各自设置最大宽度。

您可以查看一个在线范例,通过旋转屏幕、改变窗口大小、在不同屏幕查看展示效果。范例顶部的文字会提示您,当前的视图是移动端竖屏(Portrait)、移动端横屏(Landscape)还是桌面端(Desktop)。

  • 移动端竖屏,正常使用可伸缩(vw)的移动端竖屏视图;
  • 移动端横屏,使用居中的较小固定宽度的移动端竖屏视图;
  • 平板、笔记本、桌面端,使用居中的较大固定宽度的移动端竖屏视图;
  • 穿戴设备,使用可伸缩(vw)的移动端竖屏视图。

下面的三张图是使用本插件生成媒体查询,移动端、移动端横屏和桌面端的展示效果:

移动端的展示效果 移动端横屏的展示效果
桌面端的展示效果

在“范例”一节查看,源码中提供了范例,用于在本地运行后验证演示效果,或者您也可以查看文档开头的在线范例。

您也可以通过配合 px2vw,把转换视口单位(适配移动端竖屏)的任务交给 px2vw 完成,然后打开本插件的 disableMobile,关闭本插件的视口单位转换功能。这样做只适用于上面的第二种方法,生成媒体查询的方法。

如果您在使用 postcss-px-to-viewport 实现伸缩界面的时候,不希望界面在大屏设备上撑满整个屏幕而难以浏览,希望界面在达到某一个合适的宽度后停止伸缩(限制最大宽度),您可以使用本插件。

移动端模版和范例

下面是一个宽屏展示良好的移动端模版列表,每一条都包含了演示链接和代码,打开演示,查看模版在使用 postcss-mobile-forever 之后在不同宽度屏幕下的展示效果,打开代码,查看配置方法。

  • vue3-vant-mobile——一个基于 Vue 3 生态系统的移动 web 应用模板,帮助你快速完成业务开发。(代码 & 演示自动矫正定位代码 & 演示
  • vue3-vant4-mobile——👋👋👋 基于Vue3.4、Vite5、Vant4、Pinia、Typescript、UnoCSS等主流技术开发,集成 Dark Mode(暗黑)模式和系统主题色,且持久化保存,集成 Mock 数据,包括登录/注册/找回/keep-alive/Axios/useEcharts/IconSvg 等其他扩展。你可以在此之上直接开发你的业务代码!(代码 & 演示
  • v-shop——🛒 v-shop 是一个移动端 H5 商城。(代码 & 演示
  • vue-h5-template——一个快速开发的 Vue H5 移动端脚手架。(代码 & 演示
文件夹 “example/” 内提供了在诸如 React、Svelte、Vue、Next.js、Nuxt 和原生 JavaScript 中使用 postcss-mobile-forever 的范例,范例中也包含部分上面的移动端模板,克隆本仓库后,通过命令行进入对应的范例文件夹中,即可运行。
cd example/react/
npm install
npm run start

安装

npm 安装最新版本(基于 postcss@^8.0.0)(yarn 则是 yarn add -D postcss postcss-mobile-forever):

npm install --save-dev postcss postcss-mobile-forever

npm 安装最新的兼容版本(基于 postcss@^6.0.0)(yarn 则是 yarn add -D postcss-mobile-forever@legacy):

npm install postcss-mobile-forever@legacy --save-dev

查看兼容版本的 mobile-forever 文档,目前兼容版本不支持逻辑属性的处理。

安装之后在 postcss.config.js 配置文件中引入,或者其它框架配置文件中引入。

postcss.config.js 有好几种配置格式,下面是其中一种配置方法:

import mobile from 'postcss-mobile-forever' // <---- 这里
import autoprefixer from 'autoprefixer'
// 省略……
{
	postcss: {
		plugins: [
			autoprefixer(),
			mobile({ // <---- 这里
				appSelector: '#app',
				viewportWidth: 375,
				maxDisplayWidth: 580,
			}),
		]
	}
}
// 省略……

webpack-contrib/postcss-loader#172

配置参数

查看使用 postcss-mobile-forever 适配移动端视图的流程图(白色图片),以理解配置的过程和一些关键的配置选项。 一张展示使用 postcss-mobile-forever 适配移动端的流程图

一大波配置参数正在靠近,不必焦虑,尽在掌握,在这之前可以先尝试最基础的配置参数。下方是一个基础配置,表示了应用正在基于 750px 的宽度开发,经过 mobile-forever 转换后,浏览器中,应用视图将被限制在 600px 宽度以内进行等比例伸缩,当宽度大于 600px,视图将不改变,并且根元素 #app 的应用视图是居中于浏览器窗口的:

{
  "viewportWidth": 750,
  "appSelector": "#app",
  "maxDisplayWidth": 600
}

下面的每一项都是可选的。

Name Type Default Desc
viewportWidth number|(file: string, selector: string) => number 750 应用基于该宽度进行开发,转换后的伸缩视图将会以该宽度的视图作为标准进行比例伸缩;可以传递函数动态生成宽度,例如 file => file.includes("vant") ? 375 : 750 表示在名称包含“vant”的文件内使用 375px 的宽度,而其他文件使用 750px 的宽度
mobileUnit string "vw" 移动端竖屏视口视图,转换成什么视口单位?
maxDisplayWidth number / 限制视口单位的最大宽度
enableMediaQuery boolean false 打开媒体查询模式,打开后将自动关闭 maxDisplayWidth
desktopWidth number 600 适配到桌面端时,展示的视图宽度
landscapeWidth number 425 适配到移动端横屏时,展示的视图宽度
appSelector string / 页面最外层选择器,例如“#app”,用于设置在桌面端和移动端横屏时的居中样式
appContainingBlock "calc"|"manual"|"auto" "calc" 该属性和矫正 fixed 定位元素有关,manual 将不矫正;calc 将通过插件主动计算的方式矫正元素尺寸;auto 将通过 transform: translateZ(0) 强制设置根包含块appSelector,从而自动矫正元素,并且此时需要设置属性 necessarySelectorWhenAuto
necessarySelectorWhenAuto string / appContainingBlock 设为 auto 时,需要指定该属性,该属性指定了 appSelector 往内一层的元素选择器,查看一个关于指定元素作为包含块的实验以了解如何使用该属性,您也可以查看使用这个属性的示例项目以了解如何使用这个属性
border boolean|string false 在页面外层展示边框吗,用于分辨居中的小版心布局和背景,可以设置颜色字符串
disableDesktop boolean false 打开则不做桌面端适配,使用该参数前需要打开 enableMediaQuery
disableLandscape boolean false 打开则不做移动端横屏适配,使用该参数前需要打开 enableMediaQuery
disableMobile boolean false 打开则不做移动端竖屏适配,把 px 转换为视口单位,如 vw
exclude RegExp|RegExp[] / 排除文件或文件夹
include RegExp|RegExp[] / 包括文件或文件夹
unitPrecision number 3 单位精确到小数点后几位?
propList string[] ['*'] 哪些属性要替换,哪些属性忽略?用法参考 postcss-px-to-viewport 文档
selectorBlackList (string|RegExp)[] [] 选择器黑名单,名单上的不转换
propertyBlackList propertyBlackList [] 属性黑名单,名单上的不转换,如果要指定选择器内的属性,用对象的键表示选择器名称,具体用法见 vant 的范例代码
valueBlackList (string|RegExp)[] [] 属性值黑名单,名单上的值不转换
rootContainingBlockSelectorList (string|RegExp)[] [] 包含块是根元素的选择器列表,效果和标注注释 /* root-containing-block */ 相同
verticalWritingSelectorList (string|RegExp)[] [] 纵向书写模式的选择器列表,效果和在选择器顶部标注注释 /* vertical-writing-mode */ 相同
minDesktopDisplayWidth number / 宽度断点,如果不提供这个值,默认使用 desktopWidth 的值,视图大于这个宽度,则页面宽度是桌面端宽度 desktopWidth,“原理和输入输出范例”一节具体介绍了该值的触发情况
maxLandscapeDisplayHeight number 640 高度断点,视图小于这个高度,并满足一定条件,则页面使用移动端横屏宽度,“原理和输入输出范例”一节具体介绍了该值的触发情况
side any / 侧边配置,在桌面端媒体查询中生效,用于利用宽屏的空间,后文将介绍它的若干子属性
comment any / 自定义注释,改变注释的名称,后文将介绍它的若干子属性
customLengthProperty any / 用于指定需要添加到桌面端或横屏的自定义变量(css 变量,var(...)),如果不指定,默认所有和长度有关的属性,如果使用了自定义变量,都会被添加入桌面端和横屏,后文将介绍它的若干子属性
experimental.extract boolean false 提取桌面端与横屏样式代码,用于生产环境,用于代码分割优化产包,具体查看“注意事项”一节
experimental.minDisplayWidth number / 限制最小宽度,和 maxDisplayWidth 搭配使用

下面是属性 customLengthProperty 的子属性,用于自定义变量,并且每一个属性都是可选的。customLengthProperty 有两个作用,一个是指定转换方式,例如基于根包含块的 leftright,则需要 customLengthProperty.rootContainingBlockList_LR 进行指定,来得到正确的转换结果,另一个作用是,在媒体查询模式下,避免所有和长度有关的使用 CSS 变量的属性,都被添加到媒体查询中,用于指定真正需要添加到桌面端或横屏的自定义变量:

Name Type Default Desc
rootContainingBlockList_LR string[] [] 用于根包含块的,left、right 的自定义属性,例如设置 ["--len-a", "--len-b"] 后,--len-a--len-b 的值会转换为用于 leftright 属性,并且包含块是根包含块的值,并添加到桌面端和横屏中
rootContainingBlockList_NOT_LR string[] [] 用于根包含块的,非 left、right 的自定义属性
ancestorContainingBlockList string[] [] 用于非根包含块的自定义属性,这些属性值不会被转换,但是会添加到桌面端和横屏,用于避免优先级问题
disableAutoApply boolean false 关闭自定义属性自动添加到桌面端和横屏,设置上面的三个选项后,这个选项自动为 true
还有一些属性可以把页面上某个部分在宽屏设备上转移到侧边,例如可以把在移动端底部的二维码转移到桌面端的侧边栏区域以利用空白区域,这些属性不常用,您可以展开查看具体属性情况。

下面是属性 side 的子属性,每一个属性都是可选的,side 用于配制侧边内容,只有当打开媒体查询模式、disableDesktop 为 false 的时候,side 将生效:

Name Type Default Desc
width number / 侧边宽度,如果指定的选择器下有 width 属性,则无需设置
gap number 18 侧边布局的上下左右间隔
selector1 string / 左上侧边元素选择器
selector2 string / 右上侧边元素选择器
selector3 string / 右下侧边元素选择器
selector4 string / 左下侧边元素选择器
width1 number / 左上侧边宽度,优先级大于 width
width2 number / 右上侧边宽度
width3 number / 右下侧边宽度
width4 number / 左下侧边宽度

也可以通过在样式文件中添加注释,来标记局部的尺寸该如何转换,下面是一些标记注释:

  • /* apply-without-convert */,标记在一行属性之后,表示属性不经过转换,将直接添加到桌面端和横屏(可用于属性覆盖的情况);
  • /* root-containing-block */,标记在选择器上面,用于表示当前选择器的包含块是根元素,是浏览器窗口(如果选择器中已有“position: fixed;”,则无需标注该注释);
  • /* not-root-containing-block */,标记在选择器上面,用于表示当前选择器所属元素的包含块不是根元素;
  • /* mobile-ignore-next */,标记在一行属性的上面,表示下一行属性不需要进行转换;
  • /* mobile-ignore */,标记在一行属性后面,表示当前行属性不需要进行转换;
  • /* vertical-writing-mode */,标记在选择器上面,表示当前选择器是纵向书写模式,内部的逻辑属性需要被转换。
标记注释的名称可以通过属性自定义,这些属性不常用,您可以展开查看属性的具体说明。

下面是属性 comment 的子属性,每一个属性都是可选的,comment 用于自定义注释:

Name Type Default Desc
applyWithoutConvert string "apply-without-convert" 直接添加进屏幕媒体查询,不转换
rootContainingBlock string "root-containing-block" 包含块注释
notRootContainingBlock string "not-root-containing-block" 非包含块注释
ignoreNext string "mobile-ignore-next" 忽略选择器内的转换
ignoreLine string "mobile-ignore" 忽略本行转换
verticalWritingMode string "vertical-writing-mode" 纵向书写模式
虽然配置选项的数量看起来很多,但是只需要指定选项 viewportWidth 后,就可以输出伸缩视图的结果,通常我们还需要让伸缩视图具有最大宽度,只要再添加 appSelector 和 maxDisplayWidth,即可完成。开发中,如果在浏览器看到了宽屏的视图有和在移动端视图不一样的地方,再考虑配置其它选项也不迟。

下面的配置会激活第一种方法,使用 CSS 函数限制视口单位的最大值,当屏幕宽度超过 600px 后,视图不会再变化:

{
  "viewportWidth": 750,
  "appSelector": "#app",
  "maxDisplayWidth": 600
}

下面的配置会激活第二种方法,生成媒体查询,适配桌面端和横屏,桌面端视图的宽度是 600px,横屏的宽度是 425px:

{
  "viewportWidth": 750,
  "appSelector": "#app",
  "enableMediaQuery": true
}

如果暂时不希望优化视图在大屏的可访问性,不做最大宽度的限制,可以像下面这样配置:

{
  "viewportWidth": 750
}
展开查看默认的配置参数。
{
  "viewportWidth": 750,
  "maxDisplayWidth": null,
  "enableMediaQuery": false,
  "desktopWidth": 600,
  "landscapeWidth": 425,
  "minDesktopDisplayWidth": null,
  "maxLandscapeDisplayHeight": 640,
  "appSelector": "#app",
  "appContainingBlock": "calc",
  "necessarySelectorWhenAuto": null,
  "border": false,
  "disableDesktop": false,
  "disableLandscape": false,
  "disableMobile": false,
  "exclude": null,
  "include": null,
  "unitPrecision": 3,
  "selectorBlackList": [],
  "valueBlackList": [],
  "rootContainingBlockSelectorList": [],
  "verticalWritingSelectorList": [],
  "propList": ["*"],
  "mobileUnit": "vw",
  "side": {
    "width": null,
    "gap": 18,
    "selector1": null,
    "selector2": null,
    "selector3": null,
    "selector4": null,
    "width1": null,
    "width2": null,
    "width3": null,
    "width4": null
  },
  "comment": {
    "applyWithoutConvert": "apply-without-convert",
    "rootContainingBlock": "root-containing-block",
    "notRootContainingBlock": "not-root-containing-block",
    "ignoreNext": "mobile-ignore-next",
    "ignoreLine": "mobile-ignore",
    "verticalWritingMode": "vertical-writing-mode"
  },
  "customLengthProperty": {
    "rootContainingBlockList_LR": [],
    "rootContainingBlockList_NOT_LR": [],
    "ancestorContainingBlockList": [],
    "disableAutoApply": false
  },
  "experimental": {
    "extract": false,
    "minDisplayWidth": null
  }
}

单元测试与参与开发

npm install
npm run test

修改源码后,编写单元测试,验证是否输出了预期的结果。另外,在文件夹 example/ 内提供了一些范例,可以用来模拟生产环境使用插件的场景,这些范例项目中依赖的 postcss-mobile-forever 来自源码,因此当修改源码后,可以通过在范例里 npm i 安装依赖,然后本地运行,通过浏览器验证自己的修改是否符合预期。

如果您是移动端模版的开发者,成功引入 postcss-mobile-forever 之后,您可以按照“移动端模版和范例”一节的格式,提交 PR,将您的模版仓库以及在线演示地址添加到后续的列表中,这样可以为您的模版提供更多的曝光,也能够表示您的移动端模版具有良好的桌面端体验。

一起开发,让程序的变量命名更合适、性能和功能更好。

输入输出范例和原理

插件配置:

{
  "viewportWidth": 750,
  "maxDisplayWidth": 560,
  "appSelector": "#app"
}

输入范例:

#app {
  width: 100%;
}

.nav {
  position: fixed;
  width   : 100%;
  height  : 72px;
  left    : 0;
  top     : 0;
}

输出范例:

#app {
  width       : 100%;
  max-width   : 560px !important;
  margin-left : auto !important;
  margin-right: auto !important;
}

.nav {
  position: fixed;
  width   : min(100%, 560px);
  height  : min(9.6vw, 53.76px);
  left    : calc(50% - min(50%, 280px));
  top     : 0;
}
查看打开选项 enableMediaQuery,媒体查询模式下的输出范例。

插件配置:

{
  "appSelector": "#app",
  "enableMediaQuery": true
}

输出范例:

#app {
  width: 100%;
}

.nav {
  position: fixed;
  width   : 100%;
  height  : 9.6vw;
  left    : 0;
  top     : 0;
}

/* 桌面端媒体查询 */
@media (min-width: 600px) and (min-height: 640px) { /* 这里的 600 是默认值,可以自定义 */
  #app {
    max-width: 600px !important;
  }

  .nav {
    height: 57.6px;
    top   : 0;
    left  : calc(50% - 300px); /* calc(50% - (600 / 2 - 0 * 600 / 750)px) */
    width : 600px; /* 100% -> 600px */
  }
}

/* 移动端媒体查询 */
@media (min-width: 600px) and (max-height: 640px),
(max-width: 600px) and (min-width: 425px) and (orientation: landscape) { /* 这里的 640 和 425 是默认值,可自定义 */
  #app {
    max-width: 425px !important;
  }

  .nav {
    height: 40.8px;
    top   : 0;
    left  : calc(50% - 212.5px); /* calc(50% - (425 / 2 - 0 * 425 / 750)px) */
    width : 425px; /* 100% -> 425px */
  }
}

/* 桌面端和移动端公共的媒体查询 */
@media (min-width: 600px),
(orientation: landscape) and (max-width: 600px) and (min-width: 425px) {
  #app {
    margin-left : auto !important;
    margin-right: auto !important;
  }
}

相比使用 CSS 函数,使用媒体查询限制宽度,生成的代码量更大。

查看原理

注意事项

插件提供了两个方法限制伸缩视图的最大宽度。使用媒体查询的方法会生成较多代码量,但是可以分别设置桌面端与横屏的不同最大宽度(在线范例配置);使用 CSS 函数的方法生成代码量较少,只能设置单个最大宽度(在线范例配置)。

appSelector 所在元素的居中属性会被占用,包括 margin-leftmargin-rightmax-width,如果开启了 border,box-shadow 会被占用。

默认情况,插件会把所有 fixed 定位的元素的包含块当成根元素,如果希望跳过处理非根元素的包含块,请在选择器上方添加注释,/* not-root-containing-block */,这样设置后,插件会知道这个选择器内的计算方式统一使用非根包含块的计算方式:

/* not-root-containing-block */
.class {
  position: fixed;
  left: 50%;
}

对于 fixed 定位元素的包含块是祖先元素,而不是根元素(浏览器窗口,visual viewport)的条件,请查看“其它”一节。

对于包含块,如果“position: fixed;”和“left: 0;”不在同一选择器,可以在需要重新计算的选择器上标记注释“/* root-containing-block */”(另一个方法是设置“rootContainingBlockSelectorList”参数)。
.position {
	position: fixed;
}
/* root-containing-block */
.top-box {
	right: 0;
	bottom: 0;
	width: 66px;
	height: 66px;
	border-radius: 9px;
}

插件转换的是选择器中的属性的值,不转换 At 规则中的属性,例如 @font-face 中的属性。

展开查看关于“experimental.extract”选项的一些说明。
  • 打开选项后,样式文件会被分割为 mobile.xxx.csslandscape.xxx.cssdesktop.xxx.css,这有利于使用代码分割进行产包优化;
  • 该选项需要设置 css-loadermodules.getLocalIdent 选项,需要从本插件导入 remakeExtractedGetLocalIdent 函数进行传递,这是为了防止选择器名称中的哈希值出现错误(哈希值会通过文件路径计算,而被分割的文件路径是不同的);
  • 暂时不支持热重载,可以仅在生产模式下打开该选项;
  • 被分割的文件暂时不支持运行本插件(postcss-mobile-forever)后面的其它 postcss 插件;
  • 如果使用 HtmlWebpackPlugin 自动插入样式产包,需要注意顺序,顺序可以通过 optimization.splitChunks.cacheGroups.[group].priority 来决定,优先级越高,插入到 html 的顺序越靠前。
展开查看使用“experimental.extract”的一份范例配置。
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { defaultGetLocalIdent } = require("css-loader");
const { remakeExtractedGetLocalIdent } = require("postcss-mobile-forever");

const isProdMode = process.env.NODE_ENV === "production";

module.exports = {
  mode: isProdMode ? "production" : "development",
  entry: "./src/index.js",
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "build"),
    clean: true,
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [isProdMode ? MiniCssExtractPlugin.loader : "style-loader", {
          loader: "css-loader",
          options: {
            modules: {
              localIdentName: isProdMode ? "[hash:base64]" : "[path][name]__[local]",
              getLocalIdent: isProdMode ? remakeExtractedGetLocalIdent({ defaultGetLocalIdent }) : undefined, // 开发环境不分割,因此设置为 undefined
            },
          }
        }, {
          loader: "postcss-loader",
          options: {
            postcssOptions: [
              ["postcss-mobile-forever", {
                appSelector: ".root-class",
                experimental: {
                  extract: isProdMode, // 生产环境打开文件的提取
                },
              }]
            ]
          }
        }],
      }
    ],
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        desktop: {
          chunks: "all",
          enforce: true,
          test: /desktop[^\\/]*?\.css$/, // 分割桌面端样式
          name: "desktop",
          priority: 101, // 第三位被加载
        },
        landscape: {
          chunks: "all",
          enforce: true,
          test: /landscape[^\\/]*?\.css$/, // 分割横屏样式
          name: "landscape",
          priority: 102, // 第二位被加载
        },
        mobile: {
          chunks: "all",
          enforce: true,
          test: /mobile[^\\/]*?\.css$/, // 分割移动端样式
          name: "mobile",
          priority: 103, // 第一位被加载
        },
      }
    }
  },
};

前往范例查看可运行的配置。

关于 CSS 自定义属性,默认情况下,所有和长度相关的属性,如果使用了自定义属性,都会被添加入桌面端和横屏,这可能会带来一些冗余的添加,也可能会有一些转换的错误,转换的错误和包含块相关。

下面的例子,默认的情况,--len-a 的值在桌面端会被转为 60px,横屏会被转为 42.5px,但是可以看到实际的应用场景中,定位是 fixed,因此包含块是根包含块,所以默认的转换是错误的,正确的转换应该是,桌面端会被转为 calc(50% - 240px),横屏会被转为 calc(50% - 170px)

:root {
  --len-a: 75px;
}
.rule {
  left: var(--len-a);
  position: fixed;
}

上面的例子中,如果要正确的转换,需要在配置中明确指定,--len-a 用于根包含块,并且被用于 left 属性:

{
  // ...其它配置
  customLengthProperty: {
    rootContainingBlockList_LR: ["--len-a"]
  }
}

本插件媒体查询模式的目标是在不同尺寸的屏幕上展示合适的视图,在宽一点的屏幕上展示大一点的视图,在扁一点的屏幕上展示小一点的视图,在窄一些的屏幕展示移动端竖屏视图,而非准确地识别具体的设备或平台来应用对应视图。

使用插件转换后的浏览器兼容性情况:媒体查询模式下会利用 CSS 函数 calc(),因此兼容性略有降低,Opera Mini 完全不可用,max-display-width 模式利用了 CSS 函数 max()min() 以及 calc(),会有兼容性问题,IE、Opera Mini、QQ 浏览器 13.1 完全不可用,具体可以查看 caniuse min(), max()caniuse calc()

期望效果

在不同设备上,duozhuayu.com(多抓鱼)公用一套 UI,访问无障碍,没有巨大字体和全宽的问题。

查看“多抓鱼“在移动端、移动端横屏和桌面端的展示效果。
移动端的展示效果 移动端横屏的展示效果
桌面端的展示效果

多抓鱼官网用百分比单位做适配,最大宽度是 600px,小于这个宽度则向内挤压,大于这个宽度则居中移动端竖屏视图,这种小版心布局在不同尺寸屏幕的设备上,展示效果很好。这样的适配方法舍弃了对设计稿的“完美”还原,相应的,代码没有了预处理,更轻量了,没有了“完美”的限制,开发的过程也变得灵活,对于一种布局,有很多方式实现适配,而且,这样适配也能很好地触发浏览器的缩放功能,满足了针对缩放的可访问性标准

CHANGELOG

查看更新日志

版本规则

查看语义化版本 2.0.0

协议

查看 MIT License

支持与赞助

请随意 Issue、PR 和 Star,您也可以支付该项目,支付金额由您从该项目中获得的收益自行决定。

展开查看用于微信支付和支付宝支付的二维码。
微信支付 支付宝支付
Pay through WeChat Pay through AliPay

其它

如果仅使用 postcss-px-to-viewport,并且项目无路由,可以通过 iframe 嵌套 vw 伸缩界面(来源链接),来达到限制最大宽度的目的。
<style>
  body {
    margin: 0;
  }
  #iframe {
    max-width: 520px;
    width: 100%;
    height: 100%;
    margin: 0 auto;
    display: block;
  }
</style>
<body>
  <!-- vw-index.html 为 postcss-px-to-viewport 转换后的伸缩界面 -->
  <iframe id="iframe" src="./vw-index.html" frameborder="0"></iframe>
<body>

与本项目有关或者可以配合使用的项目:

对于包含块,插件默认的处理方式不能处理下面的情况,如果某个情况设置在祖先元素上,那么当前定位为 fixed 元素的包含块就是那个祖先元素,而插件默认所有的 fixed 元素的包含块是浏览器窗口(visual viewport):

  • transform 或 perspective 的值不是 none;
  • will-change 的值是 transform 或 perspective;
  • filter 的值不是 none 或 will-change 的值是 filter(只在 Firefox 下生效);
  • contain 的值是 paint(例如:contain: paint;);
  • backdrop-filter 的值不是 none(例如:backdrop-filter: blur(10px);)。

相关链接:

postcss-mobile-forever's People

Contributors

wswmsword avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

postcss-mobile-forever's Issues

设置了之后移动端和pc端是不是都会限制最大宽度

设置如下:
{
"viewportWidth": file => file.includes("vant") ? 375 : 375,
"appSelector": "#app",
"maxDisplayWidth": 600
}

需求:想使用移动端的设计稿,兼容移动端和pc端的显示,我想到的问题就是在pc端会变得非常大,因为pc端是横屏,所以我找到了这个库,按照我的理解就是可以限制一个最大宽度,无论在pc端和移动端只要超过限制就不会发生转换。
问题:当我切换到pc的时候,显示变得异常大,我不知道是我对这个库的使用场景理解有误还是设置有问题?麻烦帮忙看看,需要提供什么额外信息请告知。

vue-cli + vue2 + vant2 + postcss-px-to-viewport 不生效

我前段时间使用vite + vue3 + vant4 + postcss-px-to-viewport 根据example-with-postcss-px-to-viewport-vue中的配置,是生效的。这个有一个老的vue2项目,我根据example都试了一编,都没生效,不知道怎么回事

color属性无效

如: color: #781A05, 会经过转换变为: color: #781A5;
最终浏览器不识别颜色代码, 造成无效

uni-app使用

企业微信截图_17142849681058
你好 我在uni-app中使用 报错了 这个怎么改

[Feature] The 1px scenario needs to be considered

I hope to have a configuration option similar to minPixelValue in postcss-px-to-viewport to adapt to more scenarios.

希望留一个配置项类似 postcss-px-to-viewportminPixelValue 以适应更多的场景。

设置桌面端最大宽度

image
你好,请问一下desktopWidth为600时如何设置桌面端最大宽度为375px。通过自定义媒体查询无法覆盖。

include是否有使用demo

使用vite vue 多页应用,如何只是mobile下面的文件才生效,配置了include: /mobile/,不起效果

feat: 支持运行时转换

暴露一个运行时函数,可以进行运行时的代码转换:

transform("750px") ==>  输出100vw

这样行内样式我们可以自己处理(一般行内样式都是用于动态的逻辑处理):

import { transform } from "xxxx";

function A () {
  //宽高比
  const rate = 2;
  return <img src="xxx" width={transform(750)}  height={transform(750/rate)} />
}

bug: css 变量默认值不转换

输入:

.test {
    font-size: var(--row-font-size, 14px);
}

实际输出:

.test {
    font-size: var(--row-font-size, 14px);
}

希望输出:

.test {
    font-size: var(--row-font-size, min(19.2vw, 99.84px));
}

`border` 属性的实现,用 `box-shadow` 去模拟是否会更合适

目前设置开启 border 后,在暗黑模式下左右两侧会显示白边

image

虽然可以设置改变颜色,但 border 会占用实际的空间,导致容器实际宽度会减 2px ,这应该是不符合预期的

image

而用 box-shadow 则不会占用实际的像素,就像这样:

box-shadow: -1px 0 0 0 #ccc, 1px 0 0 0 #ccc;

About Nuxt DevTools Width Display

  • Description

When using the maxDisplayWidth property in our plugin, it seems to disrupt the width display in Nuxt DevTools.

  • Steps to Reproduce
  1. Add the plugin to a Nuxt project.
  2. Set maxDisplayWidth.
  3. Observe width display in Nuxt DevTools.
  • Expected Behavior

The maxDisplayWidth property should not affect the display width of Nuxt DevTools.

  • Demo

https://github.com/CharleeWa/nxm

配置include和exclude不生效

{
appSelector: '#app',
viewportWidth: 350,
maxDisplayWidth: 600,
include: [//pages/index//],
}
包含和排除都不生效,使用postcss-px-to-viewport配置可以

移动端竖屏不能转换vh单位,请作者大大 麻烦看看 是不是我没配置好

module.exports = {
plugins: {
autoprefixer: {}, //给不同的浏览器添加前缀
"postcss-mobile-to-multi-displays": {
"viewportWidth": 375,
"desktopWidth": 375,
"landscapeWidth": 425,
"yAxisBreakPoint": null,
"xAxisBreakPoint": 375,
"rootClass": "root-class",
"border": false,
"disableDesktop": false,
"disableLandscape": false,
"enableMobile": true,
"pass1px": true,
"exclude": null,
"include": null,
"unitPrecision": 3,
"mobileConfig": {
"propList": ['*'],
"viewportUnit": "vw",
"fontViewportUnit": "vw",
"selectorBlackList": ['van'],
"replace": true
}
},
"postcss-px-to-viewport": {
unitToConvert: 'px', //需要转换的单位
viewportWidth: '375', //视窗的宽度,对应设计稿的宽度 理想视口宽度为375
viewportHeight: '667',//视窗的高度,对应设计搞的高度
viewportUnit: 'vw',//转换的视窗单位
selectorBlackList: ['TabBarItem', '.pc-container','van'], // 指定不需要转换的类
minPixelValue: 1,//小于或者等于1px 不转换
mediaQuery: false,//是否允许媒体查询中转换px
unitPrecision: 5,//转换后的精度,即小数点
// mediaQuery:true
}
}
}

关于开启border后,min-height: 100vh 属性在ios下的问题

开启 border 后,插件默认会给 #app 节点增加以下样式

box-shadow: 0 0 0 1px #8888881f;
min-height: 100vh;
height: auto !important;

这会导致网页在 ios safari 下浏览时出现滚动条,在 https://www.sabhya.dev/handling-ios-safari-toolbar-for-full-height-web-content 这个链接里有对这一问题进行了详细的描述,并且也提供了解决方案,就是采用 dvh 单位。

我认为生成的代码应该这样会更合理

box-shadow: 0 0 0 1px #8888881f;
min-height: 100vh;
min-height: 100dvh;
height: auto !important;

当然如果能处理成这样会更友好

@supports (min-height: 100dvh) {
	#app {
		min-height: 100dvh;
	}
}

配置了这个插件,出现iphone15白边问题和定位不了的问题

module.exports = () => {
return {
plugins: {
'postcss-mobile-forever': {
// 应用基于该宽度进行开发,转换后的伸缩视图将会以该宽度的视图作为标准进行比例伸缩
viewportWidth: 750,
// 页面最外层选择器,例如“#app”,用于设置在桌面端和移动端横屏时的居中样式
appSelector: '#app',
// 限制视口单位的最大宽度
maxDisplayWidth: 750,
// 打开媒体查询模式,打开后将自动关闭 maxDisplayWidth
enableMediaQuery: true,
// 适配到桌面端时,展示的视图宽度
desktopWidth: 430,
// 适配到移动端横屏时,展示的视图宽度
landscapeWidth: 425,
// 高度断点,视图小于这个高度,并满足一定条件,则页面使用移动端横屏宽度,“原理和输入输出范例”一节具体介绍了该值的触发情况
// maxLandscapeDisplayHeight: 640,
// 移动端竖屏视口视图,转换成什么视口单位
// 原来的配置
viewportUnit: 'vw',
fontViewportUnit: 'vw',
// 现在的配置
// mobileUnit: 'vw',
// 单位精确到小数点后几位
unitPrecision: 3,
// 选择器黑名单,名单上的不转换
selectorBlackList: ['md-'],
// 排除文件或文件夹
exclude: [/node_modules/]
}
}
}
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.