个人文档
  • AI编程Cursor
  • GPT使用笔记
  • npm常用库合集
  • 同步用
  • 小Demo们
  • 工具网站教程集合
  • HTML、CSS 工具方法集合
    • HTML 全局属性
    • css常用功能
    • font-face 字体|子集相关
    • iframe父子页面传值
    • input输入优化
    • loading状态
    • nodejs使用谷歌邮箱发邮件
    • 为 Dom 自定义事件监听
    • 初始html的head标签配置
    • 拼音输入中文汉字的事件监听
    • 文字颜色效果
    • 文档片段范围 Range
    • 移动端开发-rem
    • 等宽字体推荐
    • 网站SEO优化注意点
    • 邮件html模板
  • JS 工具方法集合
    • Axios 简单使用
    • Axios 简单封装
    • Gitbook的安装和使用
    • Github 登录开发
    • HTML转为纯文本
    • JS 中强大的操作符
    • cookie 操作
    • js 动态加载js资源
    • js 常用功能语句
    • js取代trycatch的方法封装
    • js接口下载二进制
    • script 标签的异步属性
    • 判断当前是移动端还是pc端
    • 刷新token队列管理
    • 前端多线程 Web Worker
    • 加密-AES对称加密
    • 加密-node进行rsa加密解密
    • 地区省市区三级联动的地址数据 + 功能
    • 复制插件
    • 开发时环境变量
    • 得到随机图片
    • 数字格式整理集合
    • 数学计算插件
    • 时间格式整理
    • 获取ip地址
    • 获取url传参
    • 进制转换和位运算符
    • 页面隐藏|激活|关闭的监听
  • JS 知识点研究
    • Babel 历史和原理
    • Babel 配置和使用
    • Function 的 apply、call、bind
    • HTTP浏览器缓存粗解
    • Source map 文件还原为源码
    • TS常用技巧
    • js 的加载和模块化
    • js 的新数据类型 Symbol
    • js的代理对象 proxy 和 defineProperty
    • js的原型链 prototype
    • vite 打包体积优化
    • webpack 可视化打包文件大小插件
    • webpack 基础使用配置
    • webpack 版本5的报错
    • yeoman 开发脚手架的工具
    • 同步异步和微任务宏任务
    • 移动端调试---谷歌工具+eruda+vconsole
    • 转换-Blob URL
    • 转换-FileReader
    • 转换-Js文件类型和转换
    • 转换-前端开发的URL的编码和解码
    • 转换-字符串和Base 64的转换
  • Node 和 Npm 相关
    • Node 开发环境配置
    • express + jwt 校验
    • node 常用方法
    • node后台服务器-PM2
    • node基本使用
    • npm 中依赖的版本问题
    • npm 功能使用
    • npm指令说明和其他对比
    • nvm版本管理+自动切换node版本
  • React 学习
    • React Hook
    • React 项目基础开发
    • React.memo 和 React.PureComponent
    • React懒加载进阶
    • useContext Hook
    • useEffect Hook
    • useMemo 和 useCallback - Hook
    • useRef Hook
    • useState Hook
    • 同步修改变量功能封装 useVal for react
    • 轻便的传值组件
  • Rust 语言相关
    • Rust 基本
    • Rust 基础学习
    • Rust 调用 Object-C 的API
    • Tauri 基本使用
    • Tauri 是什么
  • VUE 学习
    • Vue3 使用
    • Vue3使用hook
    • Vue开发小技术点
    • vue路由切换时的动画效果
    • 花式引入组件和资源-打包时拆包减少js体积
  • Web3相关
    • Web3.0开发上-准备和概念理解
    • Web3.0开发下-功能代码示例
    • 以太坊区块链和Web3.0
    • 开发智能合约
  • python
    • pyenv版本管理工具
    • python初始化
    • python基本概念
    • venv虚拟环境
  • 个人其他
    • Steam Deck的基本设置和插件
  • 其他编程相关
    • Git教程和常用命令
    • Java开发-JDK和Maven的安装和卸载
    • Jenkins安装和基本使用
    • Linux系统指令
    • Mac 使用2K屏幕开启缩放
    • Mac 使用VS code打开项目
    • Mac 安装 Homebrew
    • Mac 的终端 shell 与 zsh
    • Mac 软件和插件
    • MacBook使用建议
    • Mac升降级到指定版本的系统
    • Mac安装Zsh
    • Mac安装软件各种提示
    • Mac系统脚本语言 AppleScript 的使用
    • Mac终端代理工具
    • Markdown(md)文档开发-Typora
    • Mysql 的安装和使用
    • Nginx 安装和基础使用
    • Nginx 稍微高深的配置
    • Slate - Api 的文档开发工具
    • Sublime配置
    • Ubuntu的 apt-get 使用
    • VScode配置
    • Windows 软件和插件
    • curl 工具使用
    • github 网站访问优化
    • host 文件
    • inquirer 终端中和用户交互
    • uTools的插件开发教程
    • vim 文本编辑功能
    • 使用 Github Pages 免费部署网站
    • 压缩指令 zip 和 unzip
    • 油猴的安装和开发(Tampermonkey)
    • 阿里云简略使用
  • 微信开发
    • 微信小程序开发
    • 微信开发必读
    • 微信开发提前购买域名
    • 微信手机打开的页面中授权登录
    • 微信扫码登录
    • 微信服务号登录+推送服务提醒
    • 自定义分享卡片-node.js实现
  • 数据结构与算法
    • KMP算法
    • Wildcard字符串分析算法
    • 二叉树
    • 字典树
    • 时间复杂度浅析
    • 算法神器——动态规划
Powered by GitBook
On this page
  • 移动端开发-rem
  • 设置自适应的根字体大小
  • rem的用法
  • 使用scss封装方法(暂不推荐使用了)
  • 使用tailwindcss的问题
  • 总结
  • css中的px自动转为rem的功能

Was this helpful?

  1. HTML、CSS 工具方法集合

移动端开发-rem

title: 移动端开发-rem id: 0c93e609de269c6210338739adcbe3b0 tags: [] date: 2000/01/01 00:00:00 updated: 2025/02/05 14:50:26 isPublic: true --#|[分隔]|#--

移动端开发-rem

在开发移动端时,需要使用rem,就需要设置根字体大小(font-size),同时监听屏幕尺寸变化,实时调整根字体大小。

设置自适应的根字体大小

众所周知,根字体大小需要和屏幕宽度挂钩,这里就有两种方式。

一种是很简单,直接一行css就行。

第二种比较麻烦,就是使用js获取屏幕宽度,计算后再赋值,并且监听屏幕宽度变化,实时计算并修改覆盖。

我之前一直使用的都是第二种,后来再微信公众号中,看到了第一种纯css的写法,才豁然开朗。

这里推荐优先是第一种纯css的方式。

直接使用css配置(推荐)

直接使用css配置,方便快捷。

html {
  font-size: calc(因数 * (100vw / UI图总宽度));
}

/* or */

/* 页面可视区域宽度小于等于 1000px 时,里面css生效 */
@media (max-width: 1000px) {
  html {
    font-size: calc(因数 * (100vw / UI图总宽度));
  }
}

其中,UI图总宽度不用多说,就是移动端页面的设计图的总宽度。

因数只是一个值,建议填写100,这样后面开发每个标签的样式时,直接把从UI图上测得的值,除以100,单位再改为rem即可,比如测得一个按钮的宽度是50px,那写这个按钮的宽度时,值就写成0.5rem。

其中100这个因数必须要有,可以不是100。 因为,比如这里把因数改为1,且手机屏幕宽度恰好和UI图总宽度一样宽,这样计算完,font-size的值为1px,这里就应该设置根字体大小为1px。 但由于浏览器可能为了用户体验,可能会设置一个字体大小的最小限制,比如chrome的pc端限制字体最小为12px,小于此值时,仍然展示为12px。 由于移动端也可能会有类似的设置,所以这里乘以一个比例,让根字体的大小大一些,不过这样在写css时,也需要除以这个值,这是唯一的弊端,不过这个问题,在后面会解决。

e.g:因数设置为100,UI图总宽度为750,则写成下面即可,这样在使用时,7.5rem 就是正好宽度100%,因为 7.5rem * 因数100 = 750px。

html {
  font-size: calc(100 * (100vw / 750));
}

js指令

下面代码直接用<script>标签,插入到html的head中即可,因数也是设置的100,UI图总宽度uiWidth设置的是750,可以修改。

(function (doc, win) {
  // 设置当前设置UI图的总宽度,直接看UI给的设计的宽度就行,固定的
  var uiWidth = 750
  var docEl = doc.documentElement
  var recalc = function () {
    // 乘以一个比例,作为rem的值,实现rem的值随着设别宽度的不同而不同
    var clientWidth = docEl.clientWidth || 0
    docEl.style.fontSize = 100 * (clientWidth / uiWidth) + 'px'
  }
  recalc() // 先自动触发一下
  win.addEventListener('resize', recalc, false) // 添加页面监听事件
})(document, window)

rem的用法

然后再使用的时候,量取了设计图的尺寸,写css时直接将这个值除以因数100,单位设置为rem。

比如在宽度为750的设计图上,量取一个按钮的宽度为125px,则写css时,宽度写为1.25rem即可,字体大小、圆角尺寸、阴影尺寸均可以以此类推。

css用法

button {
  width: 1.25rem; /* (125px / 100 = 1.25rem) */
}

使用scss封装方法(暂不推荐使用了)

但对于开发着来说,每次写css还需要计算一下,哪怕这个计算是很简单的,也是很招人烦,所以如果使用了scss,就可以使用下面scss的语法,封装一个scss方法。

// phoneSet.scss 文件
$divisor: 100; // 需要除以的除数因子(js中的因数)

// 去掉单位 把传入的带单位的值的单位去掉
@function clearUnit($number) {
  @if type-of($number) == 'number' and not unitless($number) {
    @return $number / ($number * 0 + 1);
  }
  @return $number;
}

// 传过来一个带单位的值,比如1px,返回固定rem单位的值,比如3rem
@function r($numAndUnit) {
  @if not unitless($numAndUnit) {
    $numAndUnit: clearUnit($numAndUnit);
  }
  @return ($numAndUnit / $divisor) * 1rem;
}

注:新版的scss,貌似有些数学计算方法不再支持,所以如果报错的话,就需要换种写法

// phoneSet.scss 文件
@use "sass:math";
$divisor: 100; // 需要除以的除数因子(js中的因数)

// 去掉单位 把传入的带单位的值的单位去掉
@function clearUnit($number) {
  @if type-of($number) == 'number' and not unitless($number) {
    @return math.div($number, ($number * 0 + 1));
  }
  @return $number;
}

// 传过来一个带单位的值,比如1px,返回固定rem单位的值,比如3rem
@function r($numAndUnit) {
  @if not unitless($numAndUnit) {
    $numAndUnit: clearUnit($numAndUnit);
  }
  @return calc((#{$numAndUnit} / #{$divisor}) * 1rem);
}

用法

// 其他scss文件
@import(./phoneSet.scss) // 引入scss方法文件

button {
  width: r(125); /* 直接传入测量的值即可 */
}

使用tailwindcss的问题

tailwindcss的移动端优先

tailwindcss提供sm、md、lg、xl、2xl这5个默认断点,但在开发pc端+移动端页面时,会发现 tailwindcss 有一个问题。

首先列举一下这5个断点的官方示意。

断点前缀
最小宽度
CSS

sm

640像素

@media (min-width: 640px) { ... }

md

768px

@media (min-width: 768px) { ... }

lg

1024px

@media (min-width: 1024px) { ... }

xl

1280像素

@media (min-width: 1280px) { ... }

2xl

1536px

@media (min-width: 1536px) { ... }

需要注意的是:当使用 md:bg-white 时,指的并不是 屏幕宽度小于 768px 时,而是 屏幕宽度大于等于768px时,背景色为白色!

因为 tailwindcss 是 移动端优先,当不添加前缀时的样式,是屏幕宽度大于等于0时的样式,当使用了md前缀,指的是屏幕宽度大于等于 768px 时,其他断点同理。

即使在 tailwind.config.ts 文件中添加断点:

theme: {
  extend: {
    screens: {
      pc: {'min-width': '800px'}, // 浏览器宽度大于等于800像素时,有这个前缀的生效
      mobile: {'max': '800px'}, // 浏览器宽度小于800像素时,有这个前缀的生效
      // min: '500px',
      // big: '1200px',
    },
  },
},

当是用 mo 前缀时,指的也是屏幕尺寸大于等于 500px 时会应用的样式,比较蛋疼。

tailwindcss相关文档 也有说明:不要使用sm:定位移动端设备,而是使用无前缀的类名来定位移动端样式,并在较大的断点处覆盖它们!

解决:进行自由配置

官方文档在此:自定义屏幕断点。

下面摘抄整理文档中的示例,在 tailwind.config.js 文件中配置:

/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      'sm': '200px', // 可以自定义key,也可以覆盖默认值
      // => @media (min-width: 200px) { ... }
      // 意思是生效的范围的「最小值」是「200px」,也就是大于等于200px时生效

      'pad': {'max': '900px'},
      // => @media (max-width: 900px) { ... }
      // 意思是生效的范围的「最大值」是「900px」,也就是小于等于900px时生效
      
      'md': {'min': '768px', 'max': '1023px'},
      // => @media (min-width: 768px and max-width: 1023px) { ... }
      // 意思是生效的范围是 >= 768 且 <= 1023
      
      'tall': { 'raw': '(min-height: 800px)' },
      // 完全自定义媒体查询的值
    }
  }
}

总结

下面给出最适用的配置。

例子中将要完成的效果:

  • 大于900px时认为是pc端,小于等于900px时认为是移动端

  • 当时pc端时,给html添加类名pc,当移动端时类名为mo

  • 默认样式是所有端生效,pc前缀的是pc端生效,mo 前缀的是移动端生效

  • 移动端设计图的总宽度是375px,所以设定开发移动端时,需要375rem时正好是100vw,方便开发

1. 根字体大小、行高的修改

html {
  font-size: 16px;
}

/* 小于等于900px时应用的样式 */
@media (max-width: 900px) {
  html {
    /* 设置小于等于900px时的根字体大小 */
    /* 按下面这样设置,当测量设计图的按钮宽度是100px时,开发时这个按钮的样式可以直接设置为 100rem */
    font-size: calc(100vw / 375);
  }
  body {
    font-size: 16rem;
  }
}

2. 在pc端、移动端时,给html添加不同的类名

/**
 * 获取设备宽度信息
 * @returns [宽度像素值, 是否是移动端]
 */
function getDeviceInfo(): [number, boolean] {
  const deviceWidth = document.documentElement.clientWidth
  let isMobile = false
  if (deviceWidth < screenPc) isMobile = true
  return [deviceWidth, isMobile]
}

// 监听设备宽度和处理
export function watchDevice() {
  // 处理方法
  const handle = () => {
    let result = getDeviceWidth()
    if (!result) return
    const [deviceWidth, isMobile] = result
    // 拿到了「设备宽度」和「是否是移动端」
    // 可以存储到全局状态中
		let classList = document.querySelector('html')?.classList
    if (!classList) return
    // 添加、删除类名
    if (isMobile) {
      if (classList.contains('pc')) classList.remove('pc')
      classList.add('mo')
    } else {
      if (classList.contains('mo')) classList.remove('mo')
      classList.add('pc')
    }
  }
  // 先执行一次
  handle()
  // 添加监听
  window.addEventListener('resize', handle)
}

3. 为tailwindcss添加断点

添加 pc 和 mo 的断点, tailwind.config.js 文件中配置:

/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      // 设置屏幕尺寸大于 900px 时的前缀
      // 下面的媒体查询,是:「小于等于900px的取反」,也就是大于900px
      'pc': {'raw': 'not (max-width: 900px)'},

      // 设置屏幕尺寸小于等于 900px 时的前缀
      'mo': {'max': '900px'},
    }
  }
}

css中的px自动转为rem的功能

下面这个页面的功能,是先设定 1px 等于多少 rem,然后粘贴px为单位css,把里面的px自动计算转换为rem的页面。

还是有点用处的,偶尔使用。

<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="UTF-8">
  <title>px计算转为rem</title>
  <style>
    .box {
      width: max-content;
      margin: 100px auto 0;
    }
    .tip {
      margin-bottom: 20px;
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    .tip .text {
      text-align: center;
      color: #999;
    }
    .tip .setRow {
      margin: 10px auto 0;
    }
    .tip .setRow > input {
      width: 200px;
      line-height: 2em;
      padding: 0 5px;
    }
    .tip .setRow > span {
      line-height: 2em;
      color: #999;
    }
    .inputBox {
      display: flex;
    }
    textarea {
      resize: none;
      padding: 20px 10px;
    }
    textarea + textarea {
      margin-left: 10px;
    }
  </style>
</head>
<body>
  <div class="box">
    <div class="tip">
      <h1>css 中的 px 自动计算转换为 rem</h1>
      <div class="text">左侧框贴入px为单位的代码,右侧自动计算转换为rem之后的代码,同时会自动复制。</div>
      <div class="setRow">
        <input type="text" placeholder="1px === ?rem">
        <span>输入1px等于几rem</span>
      </div>
    </div>
    <div class="inputBox">
      <textarea placeholder="请粘贴css代码" class="input" name="" id="" cols="50" rows="20"></textarea>
      <textarea placeholder="转换后代码" class="output" name="" id="" cols="50" rows="20"></textarea>
    </div>
  </div>
</body>
<script>
  let setDom = document.querySelector('.setRow input')
  let inputDom = document.querySelector('.input')
  let outputDom = document.querySelector('.output')

  let setRem = 0.01
  setDom.value = setRem

  // 监听修改了转换比例
  setDom.addEventListener('input', (e) => {
    let newSetRem = setDom.value.trim()
    if (!/[0-9.]/.test(newSetRem)) return
    setRem = Number(newSetRem)
    handler()
  })

  // focus 自动全选
  setDom.addEventListener('focus', () => {
    setDom.select()
  })
  inputDom.addEventListener('focus', () => {
    inputDom.select()
  })
  outputDom.addEventListener('focus', () => {
    outputDom.select()
  })

  // 监听修改了输入的css
  inputDom.addEventListener('input', () => {
    handler()
  })

  // 处理
  function handler() {
    let input = inputDom.value
    let result = input.replace(/[0-9.]+px/ig, (text, b) => {
      let a = parseFloat(text)
      let result = `${a * setRem}rem`
      return result
    })
    outputDom.value = result
    navigator.clipboard.writeText(result)
  }
</script>
</html>
Previous文档片段范围 RangeNext等宽字体推荐

Last updated 3 months ago

Was this helpful?