开发课程 | 支付宝小程序开发中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 元素

基础示例

举个例子

(codepen 链接:https://codepen.io/yu-xueting/pen/byQxYZ?editors=1100#0

<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!

(codepen 链接:https://codepen.io/yu-xueting/pen/eaxvXN

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

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

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

(codepen链接:https://codepen.io/yu-xueting/pen/zQeEmE

<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

em 与 rem 很相似,区别在于 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/a 和y*r/a 都是常数,进而导出结论,元素定位信息中的 left 和 top 可以使用固定值来设置

以下是示例

(codepen 链接:https://codepen.io/yu-xueting/pen/wbQmLX

<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 - vw 和 vh 中较大的值
  • vmin - vw 和 vh 中较小的值

来个例子

(codepen 链接:https://codepen.io/yu-xueting/pen/byzOBL

<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

目录
相关文章
|
4小时前
|
小程序
开发小程序只要几百块?
开发小程序只要几百块?
21 0
|
4小时前
|
Web App开发 数据采集 移动开发
开发uniapp过程中对app、微信小程序与h5的webview调试
开发uniapp过程中对app、微信小程序与h5的webview调试
11 1
|
4小时前
|
移动开发 前端开发 JavaScript
:掌握移动端开发:HTML5 与 CSS3 的高效实践
:掌握移动端开发:HTML5 与 CSS3 的高效实践 “【5月更文挑战第6天】”
26 1
|
4小时前
|
缓存 前端开发 JavaScript
【专栏:HTML与CSS移动端开发篇】移动端网页性能优化策略
【4月更文挑战第30天】本文探讨了移动端网页性能优化的重要性,并提出了优化策略。HTML方面,建议精简结构、使用语义化标签、异步加载脚本和压缩文件;CSS优化包括精简样式、使用CSS3动画、媒体查询和压缩文件。其他策略涉及图片和字体压缩、缓存利用、数据压缩、减少HTTP请求及根据网络状态调整加载。综合运用这些策略能提升网页性能和用户体验。
|
4小时前
|
前端开发 JavaScript UED
【专栏:HTML与CSS移动端开发篇】移动端触摸事件与手势识别
【4月更文挑战第30天】本文探讨了移动端触摸事件和手势识别在网页开发中的重要性。介绍了基础触摸事件如`touchstart`, `touchmove`, `touchend`, `touchcancel`及相关属性。文章列举了处理触摸事件的方法,包括单点触摸、多点触摸、滑动、长按、捏合缩放、旋转检测和事件代理。建议使用第三方库如Hammer.js简化手势处理,并分享了最佳实践,如避免意外触摸、提供视觉反馈、考虑性能和跨设备测试。理解并有效利用这些技术能提升用户交互体验。
|
4小时前
|
编解码 前端开发 UED
【专栏:HTML 与 CSS 移动端开发篇】CSS 媒体查询与移动端特定样式
【4月更文挑战第30天】CSS媒体查询在移动端开发中至关重要,它基于设备特性(如屏幕尺寸、分辨率、方向)应用特定样式,实现响应式设计。通过`@media`规则定义条件,如`(max-width: 600px)`,当屏幕宽度小于或等于600px时应用相应样式。常见条件包括屏幕宽度、高度、方向和分辨率。媒体查询可用于响应式布局、导航菜单优化、图片加载及字体调整。在实践中,需注意保持查询简洁,充分测试,渐进增强,并提前规划。掌握媒体查询能提升移动端用户体验,创造更优秀的网页设计。
|
4小时前
|
编解码 移动开发 前端开发
【专栏:HTML与CSS移动端开发篇】使用Viewport Meta标签优化移动端显示
【4月更文挑战第30天】本文介绍了HTML的Viewport Meta标签在移动端网页优化中的作用。Viewport Meta标签定义了视口属性,如宽度、高度、初始缩放等,解决移动设备因屏幕尺寸差异导致的显示问题。主要属性包括width(常用device-width)、initial-scale、maximum-scale、minimum-scale和user-scalable。
|
4小时前
|
编解码 缓存 前端开发
【专栏:HTML与CSS移动端开发篇】移动端网页布局与适配
【4月更文挑战第30天】本文探讨了如何使用HTML和CSS优化移动端网页布局与适配,强调响应式设计、灵活布局和媒体查询的重要性。针对移动设备的屏幕尺寸、操作方式、网络速度和性能差异,提出了断点选择、触摸优化、图像和性能优化等最佳实践。测试和调试、框架工具的应用也是关键步骤,以确保在多设备上提供优秀用户体验。开发者需持续学习新趋势和工具,以适应移动端发展。
|
4小时前
|
编解码 前端开发 数据挖掘
【专栏:HTML 与 CSS 移动端开发篇】移动优先的网页设计理念
【4月更文挑战第30天】本文探讨了移动优先的网页设计在HTML和CSS移动端开发中的重要性。随着移动设备普及,移动优先设计理念旨在首先满足移动端用户需求,提供良好体验。通过响应式设计、简洁布局、优化资源和触摸友好交互,确保网站在移动设备上的表现。实施步骤包括分析用户需求、设计原型、编写代码和测试优化。注意避免过度设计,保持一致性,关注性能,并适应不同平台。移动优先设计是提升用户体验和竞争力的关键,随着技术发展,这一理念将持续演进。
|
4小时前
|
编解码 前端开发 UED
【专栏:HTML与CSS实践篇】响应式网站开发实战
【4月更文挑战第30天】本文探讨了响应式网站开发,它能根据用户设备自动调整布局,提供最佳浏览体验。通过HTML和CSS,利用媒体查询、Flexbox和百分比宽度等技术实现响应式设计。媒体查询按屏幕尺寸定义CSS规则,Flexbox处理元素排列。文章通过新闻网站首页设计实例,展示了如何应用这些理论,包括使用Flexbox设计导航栏,使用媒体查询调整轮播图和内容区域,以及创建自适应页脚。遵循移动优先原则,关注性能优化和用户体验,响应式设计是前端开发的关键,为多设备用户提供优质浏览体验。