Chapter 04

WXSS 样式系统

深入理解 rpx 自适应单位、选择器规则限制、Skyline 新样式能力与 CSS 动画在小程序中的实践

4.1 WXSS 概述

WXSS(WeiXin Style Sheets)是微信小程序的样式语言,基于 CSS 扩展,语法与 CSS 高度兼容,但有两处关键扩展:rpx 尺寸单位样式导入规则,同时对部分 CSS 选择器进行了限制。

WXSS 支持
类选择器 .class、ID 选择器 #id(不推荐)、元素选择器 view/text、伪类 :hover/:active、后代/子代选择器、Flexbox、Grid、CSS 变量、@keyframes、transition、transform 等现代 CSS
WXSS 不支持
通配符 *(性能原因,WebView 模式下部分支持)、属性选择器 [attr]、伪元素 ::before/::after(WebView 支持,Skyline 不支持)、媒体查询(有限支持)、本地字体 @font-face 本地文件

4.2 rpx 尺寸单位

rpx(responsive pixel,响应式像素)是小程序专有的自适应尺寸单位,解决了在不同分辨率手机上界面元素大小不一致的问题。

rpx 的计算原理

小程序规定:任何手机屏幕宽度都等于 750 rpx。运行时,框架会根据实际屏幕宽度自动换算:

// rpx 换算公式:
// 1 rpx = (屏幕宽度 / 750) px

// iPhone 6/7/8 (375px):1 rpx = 0.5px
// iPhone 14 Pro (393px):1 rpx ≈ 0.524px
// iPhone 14 Pro Max (430px):1 rpx ≈ 0.573px
// 小米 12 (393px):1 rpx ≈ 0.524px

// 设计稿约定:以 750px 宽度出图,1:1 对应 rpx
// 例如设计稿中 100px 的按钮 → 代码写 100rpx

使用示例

/* WXSS */

.product-card {
  width: 700rpx;          /* 几乎全屏宽(左右各留 25rpx)*/
  margin: 0 25rpx 20rpx; /* 居中显示 */
  border-radius: 16rpx;
  overflow: hidden;
}

.product-image {
  width: 700rpx;
  height: 700rpx;          /* 正方形图片,自适应屏幕 */
}

.product-title {
  font-size: 28rpx;        /* ≈ 14px on 375px screen */
  line-height: 1.5;        /* 行高用无单位值,相对于字号 */
  padding: 20rpx 24rpx;
}

.price {
  font-size: 40rpx;        /* ≈ 20px on 375px screen,突出价格 */
  font-weight: 700;
  color: #f40;
}

/* 高度建议:避免固定 rpx 高度,用 padding 撑开更灵活 */
.list-item {
  /* height: 100rpx;  ← 不推荐,内容超出会截断 */
  min-height: 100rpx;     /* 推荐:内容自然延伸 */
  padding: 20rpx 30rpx;
  display: flex;
  align-items: center;
}
💡
混用建议

文字字号建议同时用 rpx 和 rem 对比测试。字号不要用 rpx——苹果手机系统字号设置会被 rpx 固定值覆盖,导致视力不好的用户体验差。字号推荐使用 px(开发者工具会自动转换),或使用 em/rem

4.3 样式导入

/* 在任何 .wxss 文件中用 @import 导入其他样式文件 */
@import '../../styles/variables.wxss';
@import '../../styles/common.wxss';

/* 注意:@import 只支持相对路径 */
/* @import '/styles/common.wxss'; ← 不支持绝对路径 */

4.4 选择器优先级与限制

/* ✅ 支持的选择器 */
.class-name {}           /* 类选择器(推荐)*/
view.special {}          /* 元素+类 */
.parent > .child {}      /* 子代选择器 */
.ancestor .descendant {} /* 后代选择器 */
.item:active {}          /* 伪类(触摸反馈)*/
.item:nth-child(2n) {}   /* 结构伪类 */

/* ⚠️ 受限选择器(WebView 支持,Skyline 可能不支持)*/
* {}                     /* 通配符(性能差,避免使用)*/
.item::before {}         /* 伪元素(Skyline 不支持)*/
.item[data-type="hot"] {} /* 属性选择器(部分支持)*/

4.5 Flexbox 布局

小程序默认使用 display: flex 布局(尤其是 Skyline 模式下,view 默认就是 flex 容器),这与 Web 开发习惯不同。

/* Skyline 模式下 view 默认 flex,flex-direction: column */
/* WebView 模式下 view 类似 div,默认 block */

.horizontal-list {
  display: flex;
  flex-direction: row;        /* 水平排列 */
  align-items: center;
  gap: 20rpx;               /* 子元素间距(推荐用 gap)*/
  overflow-x: auto;           /* 横向滚动 */
}

.card-grid {
  display: flex;
  flex-wrap: wrap;            /* 允许换行 */
  gap: 20rpx;
}
.card-grid > .card {
  flex: 0 0 calc(50% - 10rpx); /* 两列布局,考虑 gap */
}

/* 垂直居中(常用)*/
.centered {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

4.6 Skyline 特有样式能力

Skyline 渲染引擎带来了一些 WebView 模式没有或支持不完整的样式特性:

CSS 变量(自定义属性)

/* app.wxss — 定义全局 CSS 变量 */
page {
  --primary-color: #07c160;
  --text-color: #333;
  --border-radius: 16rpx;
  --spacing-base: 24rpx;
}

/* 各 .wxss 中使用 */
.btn-primary {
  background: var(--primary-color);
  border-radius: var(--border-radius);
  padding: var(--spacing-base) calc(var(--spacing-base) * 2);
}

/* 局部变量覆盖(组件级主题化)*/
.dark-theme {
  --text-color: #ffffff;
  --bg-color: #1a1a2e;
}

CSS transition 与 animation

/* CSS 过渡(适合简单状态变化)*/
.toggle-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease-in-out;
}
.toggle-panel.open {
  max-height: 1000rpx;
}

/* CSS 动画 */
@keyframes slideInUp {
  from { transform: translateY(100%); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

.popup {
  animation: slideInUp 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* 骨架屏加载动画 */
@keyframes skeleton-loading {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
.skeleton {
  background: linear-gradient(90deg, #eee 25%, #ddd 50%, #eee 75%);
  background-size: 200% 100%;
  animation: skeleton-loading 1.5s infinite;
}

安全区域适配

/* 底部安全区域(刘海屏/全面屏)*/
.tab-bar {
  padding-bottom: env(safe-area-inset-bottom);
  padding-bottom: constant(safe-area-inset-bottom); /* iOS < 11.2 */
}

/* 顶部状态栏(自定义导航栏时需要)*/
.custom-nav {
  padding-top: env(safe-area-inset-top);
}

/* 或使用 JS 获取精确值 */
// 在 Page.onLoad 中获取系统信息
const { statusBarHeight } = wx.getSystemInfoSync()
// statusBarHeight 单位为 px,转 rpx 时 × 2
this.setData({ navHeight: statusBarHeight + 44 }) // 状态栏 + 导航栏高度
ℹ️
Skyline 模式的 display 默认值

在 Skyline 模式下(开启 defaultDisplayBlock: false,默认),view 组件的 display 默认为 flex(flex-direction: column),而不是 WebView 中的 block。迁移老项目时注意检查布局是否因此发生变化。如需保持与 WebView 一致的行为,在 app.json 中设置 rendererOptions.skyline.defaultDisplayBlock: true