开发课程 | 支付宝小程序开发中CSS中的“单位”

简介: 本文将从概念着手,辅以实例说明,将各常用单位的含义、用法进行讲解

小程序.jpg

作者简介:雪庭,来自蚂蚁金服支付宝,曾就职于 MathWorks、网易,具有丰富的软件开发、前端开发经验;从零到一打造支付宝电子发票、信用卡还款等小程序,支撑千万级PV应用;蚂蚁金服技术大学金牌讲师,所授课程均获得近乎满分评价。现推出支付宝小程序开发系列课程,将前端基础、小程序开发等知识与业务中沉淀的最佳实践相结合,深入浅出带你快速了解必要的前端基础,并掌握如何开发支付宝小程序

CSS units

单位是 css 中最基本的内容,常用的有 px,em,rem,以及和 viewport 相关的vw,vh 等,本文将从概念着手,辅以实例说明,将各常用单位的含义、用法进行讲解。

让我们开始吧!

px

绝对长度单位,非常熟悉,概念不再赘述。优点在使用简单,但是设置的属性值不会根据屏幕的大小变化而变化,也不会根据用户设置的字体大小发生改变

常用在设置固定尺寸、位置上,例如:

border: 1px solid black;
border-radius: 3px;

em

1 em 等于当前元素父元素的 font-size,例如父元素的 font-size 为 20px,则 1rem = 20px 。如果父元素未显式设置 font-size,则向上继承,直至 body 元素

基础示例

举个例子

<div class="parent">
  parent
  <div class="child">
    child1
    <div class="child">
      child2
    </div>
  </div>
</div>
.parent {
   
  font-size: 15px;
}

.child {
   
  font-size: 2em;
}

image.png

原理分析:

  • parent 元素设置了 font-size,它的字体大小是 15px
  • child1 元素 font-size 是 2em,即 2 倍于父元素(parent)的字体大小,为 15px * 2 = 30px
  • child2 元素 font-size 是 2em,即 2 倍于父元素(child1)的字体大小,为 30px * 2 = 60px

逐层递进

em 的定义中,有一个关键点:父元素,即 em 的值的大小与直系父元素的 font-size 息息相关,这可以很方便的做出逐层递进的效果,比如说,sidebar!

<div class="sidebar">
  <div class="sidebar-item">foo</div>
  <div class="sidebar-item">bar
    <div class="sidebar-item">aa</div>
    <div class="sidebar-item">bb
      <div class="sidebar-item">x</div>
      <div class="sidebar-item">y</div>
    </div>
  </div>
  <div class="sidebar-item">baz</div>
</div>
.sidebar {
   
  font-size: 60px;
}

.sidebar-item {
   
  border-left: 1px solid blue;
  font-size: 0.6em;
  margin-left: 1em;
}

image.png

原理分析:

  • 每层 sidebar-item 设置的 font-size 为 0.75em,即为父元素字体大小的 0.75 倍,那么随着层级的加深,每层 sidebar-item 的字体大小会越来越小
  • 每层 sidebar-item 设置的 margin-left 为 1em,即左边距设置为父元素字体大小,随着层级的加深,margin-left 也呈递减态势(例子中利用 border-left 来辅助展示 margin-left)

屏幕自适应

em 是相对长度单位,不同于 pxem 的值是动态的,是可变的,只要调整父元素的字体大小,就可以改变 em 的值,这为不同屏幕宽度自适应布局提供了解决方案:

如果我们想在更宽的屏幕上显示更大的字体、更大的图片,只需要根据屏幕宽度设置父元素的 font-size 即可

来看如下例子,例子中使用顶部滚动条来模拟不同宽度屏幕下动态设置父元素 font-size 的过程,例子中 title 的字体大小是固定的,可借此对比 pxem 的区别

<div>拖动滚动条,模拟屏幕宽度变化</div>
<input type="range" id="range" min="1" max="6" step="0.1" value="2" oninput="onChange()" />
<div class="container">
  <div class="title">TITLE</div>
  <div class="content">
    <div class="logo"></div>
    <div class="text">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vitae convallis felis. Quisque egestas lorem ligula, vel facilisis velit maximus a. Pellentesque gravida vestibulum odio. Suspendisse sagittis viverra arcu vel convallis. Duis magna felis, blandit eu nisl sollicitudin, lobortis varius odio. Pellentesque rhoncus at ante et vestibulum. Pellentesque et elit eu sapien vehicula euismod id vitae velit. Donec eleifend ligula eu nulla vulputate, sed porttitor velit mattis. Fusce scelerisque volutpat cursus. Phasellus eleifend, quam nec mollis blandit, nisi felis hendrerit dui, vitae efficitur urna est vitae dui. Vivamus vel pretium tellus. Vestibulum lobortis quam ac quam lobortis, sit amet fermentum purus lobortis. Cras rutrum ultricies lacus ac faucibus.
    </div>
  </div>
</div>
.container {
   
  width: 600px;
  font-size: 30px;
  border: 1px solid #108EE9;
  padding: 20px;
}

.logo {
   
  width: 2em;
  height: 2em;
  background: #108EE9;
}

.title {
   
  text-align: center;
  font-size: 50px;
  color: #108EE9;
}

.text {
   
  font-size: 0.5em;
}
function onChange () {
   
  const range = document.getElementById("range").value;
  document.querySelector('.container').style.fontSize= 15 * range + 'px';
}

image.png

原理分析:

  • logo(蓝色方块)和 text(段落文字)使用 em 为单位设置宽、高、字体大小
  • 拖动滚动条,动态设置 container 的字体大小
  • 根据 em 的定义,container 元素是 logo 和 text 的父元素,改变 container 的字体大小会改变 em 的值,进而改变 logo 的大小及段落文字的字体大小

rem

1rem 等于根元素(html 元素)的字体大小,例如 html 元素的 font-size 为 20px,则 1rem = 20px

em vs rem

emrem 很相似,区别在于 rem 的值是 html 元素字体大小决定的,对于页面中各个层级的元素均相同,修改 rem 会动态更改所有以 rem 为单位的元素对应的属性值,不需要考虑层级结构

没有好坏之别,各有适用的场景

rem 适用于整体的屏幕自适应布局,只需修改 html 元素 font-size,即可全局调整页面样式
em 如上文所述,适用于写出逐层递进的效果,和部分区域自适应布局

rem 版本的屏幕自适应例子与 em 非常相似,这里不再赘述,让我们看一个更复杂的例子

固定元素在背景图片上

在不同的屏幕尺寸下,我们希望页面展示的效果是相同的,对于背景图比较好处理,通常设置背景图宽度与屏幕宽度保持一致,并保持背景图比例不变。但是除背景图外,有些元素会设置动画效果(例如呼吸的气泡),有些元素会设置操作热区供用户操作(例如刮刮卡的刮开区)。这些元素需要固定在背景图片的某个位置上,不能因为屏幕尺寸改变而移动,要如何固定呢?

举个例子,我们用图中蓝色方块来代表需要固定的元素,如何让它始终固定在 KEEP 的左上角?

image.png

其实这是一个数学问题,示意图如下(图中大矩形为背景图,小矩形为定位元素)

image.png

图中 w 代表屏幕宽度(背景图宽度),h 代表背景图高度,x 代表定位的位置距离背景图左边缘占比背景图宽度的大小,例如 20%,30%,y 代表定位的位置距离背景图上边缘占比背景图高度的大小

定位元素的位置信息为:

left: x * w;
top: y * h;

背景图随屏幕宽度变化而变化时,w,h 都会变化,也就是按照现有公式,left 和 top 需要设置的值始终在变,有没有什么办法可以让我们设置 left 和 top 的值是固定的,但是让变化自动进行呢?

有的,这个中间桥梁就是 rem

关键的步骤是, 将 html 的 font-size 与屏幕宽度进行关联,进而使得以 rem 为单位的 left 和 top 的值随屏幕宽度变化而变化,来看看具体细节:

  1. 设置 html 的 font-size 为屏幕宽度 w 乘以某个系数,假设为 a,即为 a*w
  2. 根据定义可得, 1rem = a*w
  3. w = 1rem / a => w = 1/a rem
  4. 由于背景图始终保持原比例,假设比例为 r,则 h = w*r => h = (1/a rem)*r => h = r/a rem

现在,定位元素的位置信息为:

left: x * w => x * (1/a rem) => x/a rem;
top: y * h => y * (r/a rem) => y*r/a rem;

注意,在上述的公式中,x, y, r, a 都是常数,所以 x/ay*r/a 都是常数,进而导出结论,元素定位信息中的 left 和 top 可以使用固定值来设置

以下是示例

<div>蓝色块表示需要固定的元素,它一直固定在图片 keep 文字的左上角</div>
<input type="range" id="range" min="1" max="6" step="0.1" value="3" oninput="onChange()" />
<div class="container">
  <div class="content">
    <div class=icon></div>
  </div>
</div>
html {
   
  font-size: 60px;
}
body {
   
  font-size: 16px;
}

.container {
   
  position: relative;
  width: 300px;
  height: 600px;
  border: 1px solid black;
}
.content {
   
  position: relative;
  width: 100%;
  height: 100%;
  background-image: url('https://cdn.shopify.com/s/files/1/1272/9011/files/1_6614eeeb-262e-4d53-99e6-b8cf6cac767e_1024x1024.png?v=1520891132');
  background-repeat: no-repeat;
  background-size: 100% auto;
  background-position: top center;
  overflow: hidden;
}

.icon {
   
  width: 30px;
  height: 30px;
  background-color: #108EE9;
  position: absolute;
  top: 3.5rem;
  left: 1.16rem;
  text-align: center;
}
function onChange () {
   
  const range = document.getElementById("range").value;
  document.querySelector('.container').style.width = 100*range + 'px';
  document.querySelector('html').style.fontSize = 20*range + 'px';
  document.querySelector('.icon').style.width = 10*range + 'px';
  document.querySelector('.icon').style.height = 10*range + 'px';
}

image.png

viewport 相关

viewport 即视窗,可以理解为无须滚动时可见的浏览器窗口范围

  • vw - 视窗宽度的 1%,如视窗宽度为 500px,则 1vw = 5px
  • vh - 视窗高度的 1%,如视窗高度为 500px,则 1vh = 5px
  • vmax - vwvh 中较大的值
  • vmin - vwvh 中较小的值

来个例子

<div class="tip">改变结果窗口的大小,观察各 viewport 相关值的变化:</div>
<div class="test-vw">test vw</div>
<div class="test-vh">test vh</div>
<div class="test-vmax">test vmax</div>
<div class="test-vmin">test vmin</div>
body {
   
  font-size: 30px;
}

.tip {
   
  font-size: 20px;
  margin-bottom: 20px;
}

.test-vw {
   
  width: 30vw;
  border: 1px solid #108EE9;
}

.test-vh {
   
  width: 30vh;
  border: 1px solid #108EE9;
}

.test-vmax {
   
  width: 30vmax;
  border: 1px solid #108EE9;
}

.test-vmin {
   
  width: 30vmin;
  border: 1px solid #108EE9;
}

image.png

Have fun! :D

Ref

生活号+钉钉群.png

目录
相关文章
|
5月前
|
人工智能 小程序 前端开发
一个小程序轻量AR体感游戏,开发实现解决方案
针对青少年运动兴趣不足问题,AR体感游戏凭借沉浸式互动体验脱颖而出。结合小程序“AI运动识别”插件与WebGL渲染技术,可实现无需外设的轻量化AR健身游戏,如跳糕、切水果等,兼具趣味性与锻炼效果,适用于儿童健身及职工团建,即开即玩,低门槛高参与。
|
5月前
|
移动开发 小程序 前端开发
小程序开发平台有哪些?哪个好
小程序的开发方式丰富多元,开发团队可根据自身的技术背景、项目具体需求以及资源状况,灵活挑选最为适宜的开发路径。以下将详细介绍几种主流的小程序开发方式。
575 1
|
5月前
|
运维 小程序 数据可视化
小程序开发平台有哪些?SaaS小程序制作平台哪个好
小程序开发模式详解:自主开发、SaaS小程序制作平台与外包全对比 选择合适的小程序开发模式,是项目成功的基石。这三种模式在成本、周期、控制力和灵活性上各有千秋,适用于不同阶段和不同类型的企业。下面我们将逐一深入剖析。
484 8
|
5月前
|
移动开发 小程序 前端开发
小程序快速开发平台有哪些?
小程序开发并非“一刀切”,需结合技术储备、资金预算、时间规划及功能需求等多维度因素综合考量。以下为您详细拆解五种主流开发方案及其适用场景,助您精准匹配开发路径。
350 3
|
5月前
|
移动开发 小程序 前端开发
小程序开发平台有哪些?小程序开发制作软件推荐
小程序开发方案全解析:5种主流方式与选择指南 小程序开发需根据技术能力、预算、时间及功能需求综合决策。以下为5种主流开发方案及适用场景分析:
26099 0
|
7月前
|
小程序 JavaScript API
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
这篇文章介绍了使用uni-halo框架进行微信小程序开发的过程,包括选择该框架的原因、开发目标以及项目配置和部署的步骤。
404 0
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
|
10月前
|
人工智能 前端开发 JavaScript
【CodeBuddy】三分钟开发一个实用小功能之:CSS代码瘦身专家
本文展示了AI编程从概念到实践的革命性突破,以一个CSS代码优化工具为例,说明AI如何在3分钟内完成传统开发需2天的任务。文章详细解析了AI在垂直领域工具开发、高频技术场景覆盖及代码维护优化中的应用,并探讨了智能上下文感知、模式识别优化等核心功能。同时,面对语义理解与逻辑验证等挑战,AI结合开发者补充规则,实现人机协同。最终总结指出,AI编程并非取代开发者,而是助力效率提升,推动“需求即代码”的未来方向,开启软件开发新纪元。
201 4
【CodeBuddy】三分钟开发一个实用小功能之:CSS代码瘦身专家
|
10月前
|
人工智能 前端开发 JavaScript
【CodeBuddy】三分钟开发一个实用小功能之:CSS渐变背景生成器
这是一个由AI生成的完整CSS渐变生成器项目,具备可视化交互、实时预览和代码生成功能。通过HTML、CSS和JavaScript实现,支持线性与径向渐变,提供随机生成和复制代码功能。项目展示了AI编程助手在快速原型开发、教学辅助和设计系统集成中的应用价值。其智能上下文感知、全链路代码生成和决策能力,为开发者提供了高效工具支持,助力从样板代码中解放创造力。附带优化方向如增强渐变类型、智能推荐系统及工程化改进,进一步拓展了应用场景。
233 2
【CodeBuddy】三分钟开发一个实用小功能之:CSS渐变背景生成器