第四章 WXSS 样式系统与布局
📚 系列教程:微信小程序投票系统完整开发
🔗 上一章:第三章 - WXML 表单组件全览
🔗 下一章:第五章 - JS 生命周期、事件与 API 全览
4.1 WXSS 简介与 CSS 的区别
WXSS(WeiXin Style Sheets)是小程序的样式语言,基于 CSS 扩展:
| 对比 | CSS | WXSS |
|---|---|---|
| 尺寸单位 | px / rem / vw | rpx(自适应) |
| 选择器 | 支持 * 属性选择器等 |
不支持 * 和属性选择器 |
| 全局变量 | CSS Variables | 部分支持,谨慎使用 |
| 导入 | @import |
@import(同样支持) |
| 本地字体 | @font-face | 不支持本地字体文件 |
4.2 rpx 单位深度理解
rpx 以 750rpx = 屏幕宽度 为基准,自动适配所有设备。
各设备换算关系
| 设备 | 屏幕宽度 | 1rpx 对应 px |
|---|---|---|
| iPhone SE | 320px | 0.427px |
| iPhone 6/7/8 | 375px | 0.5px(设计基准) |
| iPhone 12 | 390px | 0.52px |
| iPhone 14 Plus | 428px | 0.571px |
| 常见 Android | 360px | 0.48px |
设计稿换算规则
设计稿输出宽度:750px
换算规则:设计稿 1px = 小程序 1rpx(1:1 直接使用)
示例:
设计稿卡片宽度 = 702px → width: 702rpx
设计稿字号 = 28px → font-size: 28rpx
设计稿圆角 = 16px → border-radius: 16rpx
设计稿间距 = 24px → padding: 24rpx
最佳实践
wxss
/* 尺寸、间距、圆角 → rpx */
.card {
padding: 30rpx;
border-radius: 16rpx;
margin: 20rpx 24rpx;
}
/* 字体大小 → rpx */
.title { font-size: 36rpx; font-weight: bold; }
.body { font-size: 28rpx; }
.small { font-size: 24rpx; }
.tiny { font-size: 22rpx; }
/* 1px 细线用 1rpx(2x屏显示为0.5物理像素)*/
.border { border-bottom: 1rpx solid #eee; }
4.3 Flex 布局(小程序主流布局)
小程序中几乎所有布局都用 Flex 实现,必须熟练掌握。
核心属性速查
wxss
/* ===== 父容器属性 ===== */
/* 主轴方向 */
flex-direction: row; /* 横向(默认)*/
flex-direction: column; /* 纵向 */
/* 主轴对齐(水平方向,row时)*/
justify-content: flex-start; /* 左对齐(默认)*/
justify-content: center; /* 居中 */
justify-content: flex-end; /* 右对齐 */
justify-content: space-between;/* 两端对齐,中间均分 */
justify-content: space-around; /* 每项两侧等距 */
justify-content: space-evenly; /* 所有间距相等 */
/* 交叉轴对齐(垂直方向,row时)*/
align-items: stretch; /* 拉伸填满(默认)*/
align-items: center; /* 垂直居中 */
align-items: flex-start; /* 顶部对齐 */
align-items: flex-end; /* 底部对齐 */
/* 换行 */
flex-wrap: nowrap; /* 不换行(默认)*/
flex-wrap: wrap; /* 换行 */
/* ===== 子元素属性 ===== */
flex: 1; /* 占据所有剩余空间 */
flex: 2; /* 占据两倍剩余空间 */
flex-shrink: 0; /* 禁止压缩 */
align-self: center; /* 单独设置这个子元素的交叉轴对齐 */
常用布局模式
wxss
/* 水平居中 */
.row-center { display: flex; justify-content: center; align-items: center; }
/* 两端对齐 + 垂直居中(最常用)*/
.row-between { display: flex; justify-content: space-between; align-items: center; }
/* 垂直列表 */
.col { display: flex; flex-direction: column; }
/* 垂直列表 + 水平居中 */
.col-center { display: flex; flex-direction: column; align-items: center; }
/* 左图右文(图片固定,文字占剩余)*/
.left-img-right-text {
display: flex;
align-items: center;
}
.left-img-right-text image { flex-shrink: 0; width: 80rpx; height: 80rpx; margin-right: 20rpx; }
.left-img-right-text text { flex: 1; }
/* 标签换行排列 */
.tags { display: flex; flex-wrap: wrap; gap: 12rpx; }
4.4 定位布局
wxss
/* 相对定位 + 绝对定位(子绝父相)*/
.card { position: relative; }
.badge {
position: absolute;
top: -8rpx;
right: -8rpx;
background: #f44336;
color: #fff;
font-size: 20rpx;
padding: 4rpx 10rpx;
border-radius: 20rpx;
}
/* 固定定位(底部操作栏)*/
.footer-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 100;
background: #fff;
padding: 20rpx 40rpx;
/* iPhone X 安全区适配 */
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
box-shadow: 0 -2rpx 16rpx rgba(0, 0, 0, 0.08);
}
/* sticky 吸顶(如 Tab 栏)*/
.tab-bar {
position: sticky;
top: 0;
z-index: 10;
background: #fff;
}
4.5 投票系统完整样式规范
全局配色系统
主色 #07C160 微信绿
主色深 #0a9e4d
主色浅 #e8f5e9 用于背景/标签
文字主 #222222
文字次 #666666
文字辅 #999999
文字占位 #cccccc
页面背景 #f5f7fa
卡片背景 #ffffff
输入框背景 #fafafa
边框正常 #e8e8e8
边框浅色 #f0f0f0
通用卡片
wxss
.card {
background: #fff;
border-radius: 16rpx;
margin: 20rpx 24rpx 0;
padding: 30rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
}
通用按钮(清除小程序默认样式)
wxss
/* 主按钮 */
.btn-primary {
background: linear-gradient(135deg, #07C160, #0a9e4d);
color: #fff;
border-radius: 50rpx;
font-size: 32rpx;
font-weight: bold;
border: none;
height: 88rpx;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
}
.btn-primary::after { border: none; } /* 清除边框 */
/* 禁用态 */
button[disabled] {
background: #ccc !important;
color: #fff !important;
opacity: 1 !important;
}
/* 次要按钮 */
.btn-default {
background: #fff;
color: #666;
border: 2rpx solid #e0e0e0;
border-radius: 50rpx;
font-size: 32rpx;
height: 88rpx;
padding: 0;
}
.btn-default::after { border: none; }
状态标签
wxss
.tag { display: inline-flex; align-items: center; padding: 6rpx 18rpx; border-radius: 20rpx; font-size: 22rpx; font-weight: 500; }
.tag-green { background: #e8f5e9; color: #07C160; }
.tag-blue { background: #e3f2fd; color: #1976d2; }
.tag-orange { background: #fff3e0; color: #f57c00; }
.tag-red { background: #ffebee; color: #f44336; }
进度条
wxss
.progress-wrap {
height: 16rpx;
background: #f0f0f0;
border-radius: 8rpx;
overflow: hidden;
}
.progress-bar {
height: 100%;
background: linear-gradient(90deg, #07C160, #52c41a);
border-radius: 8rpx;
transition: width 0.6s ease;
}
骨架屏动画
wxss
@keyframes shimmer {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.skeleton {
background: #f0f0f0;
border-radius: 8rpx;
animation: shimmer 1.5s ease-in-out infinite;
}
空状态
wxss
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
padding: 100rpx 40rpx;
}
.empty-icon { font-size: 100rpx; margin-bottom: 24rpx; }
.empty-title { font-size: 32rpx; color: #666; font-weight: bold; }
.empty-desc { font-size: 26rpx; color: #999; margin-top: 12rpx; }
4.6 常见样式坑速查表
| 问题 | 原因 | 解决方案 |
|---|---|---|
* 选择器不生效 |
WXSS 不支持通配符 | 改用 page {} 设置全局基础样式 |
| button 有默认边框 | 微信默认样式 | button::after { border: none; } |
| button disabled 颜色不对 | 权重问题 | 用 !important 覆盖 |
| image 底部有空隙 | 行内元素特性 | image { display: block; } |
| 文字单行截断 | - | overflow:hidden; text-overflow:ellipsis; white-space:nowrap; |
| 文字多行截断 | - | -webkit-line-clamp:2; -webkit-box-orient:vertical; display:-webkit-box; overflow:hidden; |
| iOS 底部被遮挡 | 安全区问题 | padding-bottom: env(safe-area-inset-bottom) |
| 1px 边框太粗 | 设备像素比 | 改用 1rpx(高清屏显示为0.5px) |
| transition 不生效 | 内联样式无法过渡 | 只对 class 中的属性做 transition,动态宽度用内联 style 配合 class transition |
本章小结
✅ 深入理解了 rpx 与设计稿换算(1:1 对应 750px 设计稿)
✅ 掌握了 Flex 布局所有常用属性和典型模式
✅ 学会了 fixed/absolute/sticky 定位的使用场景
✅ 建立了投票系统完整样式规范(颜色、按钮、卡片、进度条)
✅ 整理了常见样式坑和解决方案
下一章:JS 生命周期、事件系统和所有常用 wx API 全览。
章节:4 / 15 | 更新时间:2026-05-18