Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

行内样式自动转换vw vh 不生效 #147

Open
MaDeLu opened this issue Dec 9, 2022 · 16 comments
Open

行内样式自动转换vw vh 不生效 #147

MaDeLu opened this issue Dec 9, 2022 · 16 comments

Comments

@MaDeLu
Copy link

MaDeLu commented Dec 9, 2022

发现一个问题。用 这个插件,无法自动转换,写在标签上的行内样式

@LuoRiWuSheng
Copy link

是的, 得自己写方法转换

/** px 转 vw, 375 是设置的屏幕宽度 */
export const px2vw = (px: number): string => `${(window.screen.width / 375) * px}vw`

@MaDeLu
Copy link
Author

MaDeLu commented Feb 8, 2023

你写的这个,我感觉好怪啊 window.screen.width 不就是375 嘛?

@wswmsword
Copy link

每个设备的 window.screen.width 的值不一样,iPhone SE 是 375,iPhone XR 是 414

@yozojo
Copy link

yozojo commented Mar 7, 2023

@vaynevayne
Copy link

vaynevayne commented Apr 22, 2023

是的, 得自己写方法转换

/** px 转 vw, 375 是设置的屏幕宽度 */
export const px2vw = (px: number): string => `${(window.screen.width / 375) * px}vw`

@LuoRiWuSheng luo 大佬, 请教下, 设计图是1920x1080(宽x高), 量的设计图上一个元素左侧100px,宽200px,高100px,字体大小20px,

公式是这样吗?

export const px2vw = (px: number): string => `${(window.screen.width / 1920) * px}vw`

.box{
margin-left: px2vw(100); // 19.53125vw
width:px2vw(200); // 39.0625vw
height:100px; //高度不用转对吧? px2vierport 好像也没转
font-size:px2vw(20); // 3.90625vw
}

// 假设用户使用iphone se(375x667),浏览器显示的是

{
margin-left: 73.2421875px; // 375/ 100 * 19.53125
width:146.484375px; // 375/ 100 * 39.0625
height:100px;
font-size:14.6484375px // 375/ 100 * 3.90625
}

是这样理解吗?

@vaynevayne
Copy link

不对啊, window.screen.width 是一个运行时变量, 怎么可能在插件编译时使用呢

@wswmsword
Copy link

@vaynevayne 你说的函数 px2vw 就是在运行时使用,不是在编译时使用的,vw 这个单位就相当于百分比,只不过百分比的基准是基于屏幕的宽度,也就是 window.screen.width

@vaynevayne
Copy link

vaynevayne commented Apr 22, 2023

哦哦。那么这个插件的原理是什么啊,大哥@wswmsword

@wswmsword
Copy link

哦哦。那么这个插件的原理是什么啊,大哥

就是编译的时候做 px 转换的,插件依赖 postcss,postcss 又会在打包工具 webpack 或者 vite 上用,用的时候都是根据文件类型来决定是不是做编译转换,所以基本上都是在独立的 css 文件用这个插件。如果你能用某个工具找到所有行内样式,那也能用这个插件,不然不好做。

@vaynevayne
Copy link

vaynevayne commented Apr 23, 2023

我问的是他用不了运行时变量,那他的转换公式又是什么?
我看了下首页的demo 貌似公式得到的vw是 100 / designAllwidth * designElementWidth ,问题来了,假设1920,font-size是20px 那么经过这个公式,得到 100/1920×20=1.041666667vw,
用户在414宽度的手机上使用时,414/100×1.041666667=4.312500001px ,可以看到20px的字体变成了4px,这是正确的吗?然后浏览器最小字体大小是12px,最终显示的是12px,这是因为字体有浏览器兜底,但是其他元素 没有浏览器兜底的,会不会出现错误啊?

@wswmsword
Copy link

wswmsword commented Apr 23, 2023

@vaynevayne 不好意思,我重新看了 @LuoRiWuSheng 的公式,是有问题的,计算 vw 不需要运行时的 window.screen.width。如果你的设计图宽度是 375,px 转 vw 的公式应该是 100/375*value,这个 value 是行内样式的 px 值。

你说的设计图尺寸是 1920,字体 20px,那转换之后就是 100/1920*20=1.04167,也就是 1.04167vw,在任何宽度都是这个值。1.04167vw 在宽度是 414 的设备上经过浏览器计算最终是 4px,我测了火狐和 Safari 可以正常显示,Chrome 和 edge 会卡最小字体大小 12px,不过这个问题和视口单位转换无关,任何字体单位都会被卡最小值。

px 转换成 vw 的公式(设计图宽度 375):

export const px2vw = (px: number): string => `${(100 / 375) * px}vw`;

@vaynevayne
Copy link

vaynevayne commented Apr 23, 2023

嗯,谢谢, 我也搞懂了, css里的%单位是相对于父元素或其他规则 ,其实vw就是运行时会帮你把分母换成设备宽度的%单位, 这样的话理解vw就简单了:

在设计阶段, 我们要得到一个百分比值, 在渲染阶段使用这个百分比结合屏幕宽度,计算出最终的px单位

设计阶段:

  • 100vw就是设计稿宽度: 1920
  • 200宽的元素 就是 200/1920 得到一个 100/1920 * 200=10.416666666666668 vw

在浏览器渲染时,比如在414px(window.screen.width)的屏幕上, 1vw就是 414/100 = 4.14 px,
10.416666666666668 * 4.14 = 43.125px

绕这半天,其实就是

200 / 1920 === 43.125 / 414  // true

不过有个需要注意的点:

  • 设计稿1920 ,隐含了是1倍屏, 在ps里,量的多少,就在代码里写多少px,
  • 但是如果设计稿是750,隐含了是2倍屏, 那么ps里量的20像素,你的代码得写10px (ps里元素尺寸 / 倍率 = 20/2)

@ys3322
Copy link

ys3322 commented Sep 6, 2023

  • 这个插件会把垂直方向的值自动转成vw,而并不是vh,那么怎么能实现等比例缩放呢?
  • 垂直方向的长度值有:height\line-heiht\top\bottom\margin-bottom等,我的操作是调用scss函数的计算,转换垂直方向的长度值变成vh。
  • 这样才够实现等比例缩放。我感觉未免麻烦些了,不知道各位大佬有什么好方案,可以实现垂直方向自动vh?

@africa1207
Copy link

如果是vite脚手架的react框架可以使用https://github.com/yozojo/inline-px-to-viewport,处理内联style的px,如果对你有帮助,可以给star吗

如果能增加排除目录就好了,有些UI库样式写在style上,也被转换了

@yozojo
Copy link

yozojo commented Apr 2, 2024 via email

@africa1207
Copy link

africa1207 commented Apr 3, 2024

把px大写就不会被转换了在 2024年4月2日,12:00,africa1207 @.> 写道: 如果是vite脚手架的react框架可以使用https://github.com/yozojo/inline-px-to-viewport,处理内联style的px,如果对你有帮助,可以给star吗 如果能增加排除目录就好了,有些UI库样式写在style上,也被转换了 —Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.>

我知道大写PX或者不写可以不转换,但是UI库不听我指挥。。我使用import { createFilter } from '@rollup/pluginutils';将node_modules过滤掉直接返回code没效果,仍然被转换了

import { createFilter } from '@rollup/pluginutils';

function InlinePx2Vw(customOptions = defaultsProp) {

    const { exclude,include } = customOptions;

    const filter = createFilter(include , exclude);

    return {
        name: 'inline-px-to-viewport',
        transform(code, id) {
            if (!filter(id))  return { code };

            if (fileGlobalReg.test(id)) {
                if (pxGlobalReg.test(code)) {
                    const $_source = code.replace(
                        pxGlobalReg,
                        createPxReplace(
                            customOptions.viewportWidth,
                            customOptions.minPixelValue,
                            customOptions.unitPrecision,
                            customOptions.viewportUnit,
                        ),
                    );
                    code = code.replace(code, $_source);
                }
            }
            return { code };
        },
    };
}
const viteConfig = {
    plugins: [
        ConfigInlinePxToVwPlugin({
            exclude: ['node_modules'],
        }),
    ],
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants