【css】设计稿尺寸不一致怎么办?一行代码轻松搞定!

相信不少前端小伙伴在开发的过程中会遇到这样的问题:我明明是按照设计稿的尺寸去设置元素的宽高,但为什么结果要么大了要么小了,怎么办呀?

一开始遇到这个问题,可能有的同学很快就能反应过来,根本原因在于,设计稿的大小和屏幕大小存在差异!比如,设计稿的尺寸是 2000px*1200px,而屏幕的大小是 1000px*800px,就会出现:设计稿上 2000px 宽度的元素,刚好占满设计稿的宽度,对应我们的屏幕,就应该是刚好占满屏幕的,可是如果我们在代码中也设置为 2000px,结果元素远远超出屏幕一大截!如果是宽度为 800px 的元素,在设计稿中只有不到一半的占比,但在屏幕上却几乎铺满。

下面我将深入浅出地介绍了使用百分比、vw/vh、em/rem、以及 TailwindCSS 等方法来实现设计稿与屏幕尺寸的匹配,同时也提出了推荐的解决方案。

方案一:百分比

可能有的朋友会想,这不是很简单吗?100%,40%,搞定!确实,使用百分比可以解决现在这个问题,这样,屏幕上的元素占比和设计稿上的占比是一致的,从结果上看,很好地还原了设计图。

但是,百分比是通过父元素的宽度计算的,这意味如果存在多层嵌套,计算会变得非常容易出错和麻烦。比如我们把 800px 宽度元素放在一个宽 1200px 元素里,那么我们需要先设置 1200px 元素的宽度为 60%,再设置 800px 元素的宽度是 66.6%,一旦要将 800px 元素移动到其它元素下,又需要重新计算百分比,非常不好维护!而且,如果元素是绝对布局,那么它的宽度跟随最近的被设置为相对布局的祖先元素,计算时也非常容易出错!

方案二:vw/vh

vw 和 vh 是两个相对于屏幕宽度和屏幕高度计算的尺寸,取值为 0 到 100,表示相对于整个屏幕宽度和高度的占比,它们最终被计算为 px 单位。vw/vh 和百分比的思想类似,就是通过计算元素与设计稿的比例进而还原我们的设计稿。但是 vw/vh 的优势在于,它们总是相对于屏幕,于是,800px 宽度元素不管嵌套在多少层元素中,我们都可以通过设置 40vw,来实现对设计稿的还原。

这种方法的不足就是需要将所有 px 换成 vw 或 vh,计算量还是有的。然而,css 预处理工具 postcss 有支持将 px 转换为 vw/vh 的插件,这意味着,我们只需要按照设计图给定的 px 直接写在我们的 css 中,再通过配置 postcss,就可以将我们的所有代码中的 px 自动计算为 vw/vh,接近百分百还原我们的设计稿!

这里我分享在 vite+vue/react 等任意框架中,配置 px 转 vw/vh 插件的方法:

  1. 安装开发依赖:pnpm install postcss-px-to-viewport -D
  2. 配置插件:
js 复制代码
import px2Vw from 'postcss-px-to-viewport'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: ...,
  css: {
    postcss: {
      plugins: [
        new px2Vw({
          viewportWidth: 1512, // 这里写设计稿的宽度
          unitPrecision: 4, // 计算精度
          viewportUnit: 'vw',
          minPixelValue: 1,
          mediaQuery: false
        })
      ]
    }
  }
})

简单讲解一下:这里我们在 vite 中配置了一个 postcss-px-to-viewport 插件,需要传入我们屏幕的宽度,这样,插件就会将拿到的元素宽度除以设计稿宽度得到 vw/vh 单位对应的值。更多配置可以到 npmjs. com 上搜索这个插件查看文档。

在没有 vite 的项目中,我们也可以通过安装和配置 postcss 来实现同样的功能,也是非常简单方便的。

方案三 em 与 rem

em 与 rem 的关系就像百分比和 vw/vh 的关系一样,前者 em 是基于父元素的字体大小计算的,后者 rem 是基于根元素的字体大小计算的。默认情况下,html 元素的 font-size 属性值为 16px,那么,我们在任何地方使用 rem,1rem 都等于 16px。

那么,我们就可以通过修改 html 元素的字体大小,来改变 1rem 的值,进而改变屏幕中各个元素的大小。现在,我们假设设计图宽 1600px,屏幕宽 1200px。默认情况下,设置 100rem,可以得到 1600px,那么如果设置 1rem=12px,100rem 就可以变换为适合屏幕的宽度。

具体要怎么操作呢?首先,在我们得到设计稿元素的尺寸后,我们将其除以 16,得到对应的 rem 值,我们用这个值设定元素大小。在完成设置之后,显然,在默认 1rem=16px 的条件下,我们的尺寸完全和设计稿一致,当然这时元素会显得很大,我们只要设置 1rem=12px,元素就都变小了,刚好符合我们屏幕的大小。这里有两点要点:第一,我们需要由设计稿尺寸计算 rem,并用 rem 替换 px,第二,在完成设计后,我们需要把 rem 代表的 px 大小改到适合我们屏幕的值。第一点,我们只能手动计算了(后面有更好的办法),第二点我们可以通过媒体查询或者 JavaScript 的方法得到屏幕的尺寸,根据屏幕和设计稿的比例,来设置根元素的字体。

一行 Javascript 代码就可以完成根元素字体的设置:我们通过 window.innerWidth 获取屏幕宽度,并计算其在设计稿宽度 presetWidth 的占比。

js 复制代码
document.documentElement.style.fontSize = window.innerWidth / presetWidth +'rem';

注意这里我使用了 rem 为单位,这样它会与原来的大小 16px 相乘,得到修改后的大小,比如 0.75rem(屏幕 1200 除以设计稿 1600),16px 乘以 0.75 就等于 12px。等同于 window.innerWidth/presetWidth*16+'px'

使用 rem 的整个过程看起来是这样的:假设元素宽度 160px(在 1600设计图中占 10%),我们设置 10rem,修改根元素字体大小为 12px,那么 10rem 就是 120px,也占整个屏幕(1200px)的 10%。

下面是修改根部字体大小方法参考: 媒体查询:

css 复制代码
/* 媒体查询:屏幕宽度小于 768px 时 */
@media (max-width: 767px) {
  html {
    font-size: 14px; /* 修改根元素的字体大小为 14px */
  }
}

/* 媒体查询:屏幕宽度大于等于 768px 且小于 1024px 时 */
@media (min-width: 768px) and (max-width: 1023px) {
  html {
    font-size: 15px; /* 修改根元素的字体大小为 15px */
  }
}

/* 媒体查询:屏幕宽度大于等于 1024px 时 */
@media (min-width: 1024px) {
  html {
    font-size: 16px; /* 修改根元素的字体大小为 16px */
  }
}

JavaScript 方法:

JavaScript 复制代码
const presetWidth = 1600;

function setRootFontSize() {
  document.documentElement.style.fontSize = window.innerWidth / presetWidth +'rem';
}

// 页面加载时设置根元素的字体大小
window.onload = setRootFontSize;

// 窗口大小变化时重新设置根元素的字体大小
window.onresize = setRootFontSize;

与方案二对比,方案三并没有优秀多少。方案二通过配置插件来实现比例缩放,方案三通过原生的 css 或 js 方法来实现比例缩放,看起来方案三更轻,不依赖 vite 或 postcss,在原生环境中可以直接使用。但是使用方案三的前提是需要将设计稿的 px 手动计算为 rem,每个尺寸去除以 16,这可不算小的计算量了。但是只要解决了这个计算问题,方案三也是非常强大的!

方案四 TailwindCSS 的选择

作为目前最流行最现代化的 css 框架,TailwindCSS 将原子化的思想发扬光大。在 Tailwind 中,大部分尺寸使用的都是 rem。之所以选择 rem,是因为 rem 是原生支持的,不需要依赖其它插件,只需要修改根字体,就可以调整所有元素。

前面说到方案三的问题是计算问题,这个问题可以通过 Tailwind 的插件解决。只要安装了 Tailwind 的插件,那么就会有语法提示,将 rem 以 16px 为基础计算为对应的 px 大小。

比如,原子类 text-xs 对应的 font-size:0.75rem,那么插件会告诉我们等同 12px。有了插件的提示,我们只需要关心等同的 px 是多少就行,但是却在不知不觉中输入了 rem!

所以,在使用 Tailwind 的前提下,我们完全没有方案三的计算问题,然后我们只需要根据需要修改我们的根组件字体大小,就可以实现设计稿的还原。

html 复制代码
<html style="font-size: calc( 屏幕宽度 / 设计稿宽度 * 1rem);">
	...
</html>

总结

本文对于处理在前端开发中常见的设计稿尺寸与屏幕尺寸不匹配的问题提供了多种解决方案,并对这些方案进行了详细的比较和分析。

其中,个人比较推荐的是方案四。在选择 Nextjs 作为开发框架时,我往往会搭配 tailwind 一起使用。在这个过程中,我们只需要根据设计稿给出的 px,结合插件的语法提示,就可以无负担地将 rem 写入到我们的代码中,最后修改根字体大小就可以了,几乎是零配置的。对于简单的个人项目或者页面,可以选择使用方案二的方法来处理尺寸问题。这种方法简单直接,适合快速实现设计稿与屏幕尺寸的匹配。

但是不管是哪种方案,它们都有两个共用点:第一,它们都是通过相同比例的思想来还原设计稿,解决设计稿和屏幕尺寸不一致问题。第二,它们都不使用 px 作为单位,但是在渲染的时候,都会被渲染引擎计算为最终的 px 显示(可以在开发者工具 > element > computed 中查看)。

相关推荐
asleep70139 分钟前
第8章利用CSS制作导航菜单
前端·css
风尚云网6 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
酷酷的威朗普9 小时前
医院绩效考核系统
javascript·css·vue.js·typescript·node.js·echarts·html5
渊兮兮9 小时前
Vue3 + TypeScript +动画,实现动态登陆页面
前端·javascript·css·typescript·动画
土豆湿10 小时前
拥抱极简主义前端开发:NoCss.js 引领无 CSS 编程潮流
开发语言·javascript·css
鸽鸽程序猿12 小时前
【前端】CSS
前端·css
爱上语文1 天前
HTML和CSS 表单、表格练习
前端·css·html
小肚肚肚肚肚哦1 天前
盘点浏览器盒模型中各种 width、height 、边距和位置属性
css·html
NightCyberpunk1 天前
HTML、CSS
前端·css·html
南城FE1 天前
12个更现代化的CSS单行优化技巧
前端·css