stylelint-taro 多端融合样式校验:基于 Stylelint 的 Taro 跨端 CSS 子集校验完全指南
【免费下载链接】taro开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/项目地址: https://gitcode.com/NervJS/taro
stylelint-taro 是 Taro 官方仓库中面向多端开发的 Stylelint 规则集合,其核心思想是根据目标适配端所支持的最小样式子集进行样式校验:开发者声明需要适配 h5、miniprogram、harmony、rn 中的哪些端,工具便会自动合并各端的能力约束,对不满足任一目标端能力范围的样式给出 warning 提示。本文将以 packages/stylelint-taro/README.md 为主线,结合仓库内规则实现与平台配置源码,完整讲解安装、配置、内置规则、VS Code 接入方式,以及各端样式属性与选择器的支持边界,帮助你在一套样式代码中提前拦截跨端不兼容问题。
安装
在项目根目录以开发依赖方式安装:
yarn add -D stylelint-taro从 package.json 可以看到该包要求 Node.js >= 18,并以stylelint@^16作为 peerDependency,即使用前需要确保项目中已经安装 Stylelint 16 及以上版本。包同时提供dist/index.cjs.js(CommonJS)与dist/index.esm.js(ESM)两种构建产物,供不同模块体系的项目引入。
快速上手:使用 mergeConfig 合并多端规则
项目根目录创建.stylelintrc.js:
// .stylelintrc.js const mergeConfig = require('stylelint-taro/lib/config') // 合并配置,填写需要适配的端:"h5", "miniprogram", "harmony", "rn" module.exports = mergeConfig(['h5', 'miniprogram', 'harmony'], { // 自定义样式规范: 支持sass的语言规范 // customSyntax: "postcss-scss" // 自定义Stylelint配置 rules: {}, })mergeConfig接收两个参数:
| 参数 | 类型 | 说明 |
|---|---|---|
platforms | ('h5' \| 'miniprogram' \| 'harmony' \| 'rn')[] | 需要适配的端列表,决定最终生效的样式约束集合 |
stylelintConfig | stylelint.Config | 自定义 Stylelint 配置,会与平台规则合并,其中rules优先级高于平台默认规则 |
mergeConfig 的底层逻辑
从源码 src/config.ts 可以看清mergeConfig做的事:
- 注入平台环境变量:将平台列表写入
process.env.__PLATFORMS__,供规则在运行时感知当前适配范围; - 插件合并:把 h5 / miniprogram / harmony / rn 各平台配置中声明的
plugins与用户自定义的plugins合并,因此平台默认会注册stylelint-taro自身; - 规则合并:各平台规则通过
taroRules(platforms)合并为规则集合,随后与用户自定义rules展开合并,用户的配置可以覆盖平台默认行为; - 统一告警级别:所有由平台生成的规则统一附加
{ severity: 'warning' }(见 src/config.ts),即不阻断构建,仅给出样式风险提示。
多端规则合并采用取交集策略(mergeRule,见 src/config.ts):当多个平台对同一规则给出数组形式的允许列表时,使用_.intersection取公共部分;对布尔型规则取并集。这意味着声明的端越多,样式约束越严格——最终校验的是所有目标端都支持的公共样式子集。
内置 Rule 详解
stylelint-taro 注册了 3 条命名空间为taro/的规则(注册入口见 src/index.ts,规则清单见 src/rules/index.ts):
| 规则 | 作用 |
|---|---|
taro/no-nested-selectors | 仅允许使用单个 class 选择器 |
taro/property-allowed-list | 允许使用的属性列表(按平台分别约束) |
taro/declaration-property-value-allowed-list | 允许的属性及其对应取值 |
taro/no-nested-selectors:仅能使用单类选择器
// .stylelintrc.js module.exports = mergeConfig(['harmony'], {})/* 通过检查 */ ✅ .hello { /* ... */ } /* 警告提示:harmony平台仅能使用单类选择器 */ ❌ #a { } ❌ .a .b { } ❌ #a .b { } ❌ .a > .b { } ❌ .a + .b { } ❌ .a ~ .b { }该规则通过正则/^[.#]?[a-zA-Z0-9_-]+$/判定选择器是否"仅由单个类(或 id)名称构成",任何包含组合器、空格嵌套、伪类的写法都会触发告警,实现见 src/rules/no-nested-selectors/index.ts。对应测试用例(src/rules/no-nested-selectors/tests/index.spec.ts)覆盖了.a .b、#a .b、.a>.b、.a+.b、.a~.b等拒绝场景以及.app的通过场景,告警消息为:"${selector}" 仅能使用单个class选择器,受限端 "harmony, rn"。
从源码看,该规则实际面向 harmony 与 rn 两个受限端(规则内platform = ['harmony', 'rn']),这也与 harmony 平台配置中的disAllowedSelectors约束一致:selector-max-id: 0、selector-max-type: 0、selector-max-attribute: 0、selector-max-universal: 0(见 src/platform/harmony.ts)。
taro/property-allowed-list:允许的属性列表
该规则按平台分别声明允许使用的 CSS 属性。启用 harmony + rn 后,平台配置会自动注入对应的允许属性集合(见 src/config.ts:仅当平台列表中包含 harmony 或 rn 时才启用属性类校验)。例如 harmony 平台在 src/platform/harmony.ts 中声明了 margin、padding、width、height、border、background 系列、font 系列、flex 布局系列、position、transform 等属性;未在列表中的属性(如float、grid等)会被提示。
taro/declaration-property-value-allowed-list:允许的属性及取值
允许针对每个平台为属性指定合法取值,值可以是布尔true(表示接受该属性的所有合法值)、字符串枚举或正则:
{ plugins: ['stylelint-taro'] rules: { 'taro/declaration-property-value-allowed-list': { harmony: { 'color': true, // 支持color属性及所有合法值 'text-align': ['left', 'right'], // 仅支持left、right 2个值 'height': [/^-?\d+(\.\d+)?(px|vw|vh|%)?$/i] // 支持匹配height为length }, rn: { 'text-align': ['left', 'center'], // 仅支持left、center 2个值 } } } }平台配置中的supportedProperties就是该规则的数据来源,其中的true、字符串数组与正则分别对应上述三种取值约束形式。底层使用的正则常量集中在 src/platform/constrant.ts:
LENGTH_REGEX = /^-?\d+(\.\d+)?(px|rem|vw|vh|%)?$/i:单一长度值;LENGTH_REGEX_SPLIT:支持以空格分隔的多段长度值(如 margin 的四个方向);NUMBER = /^-?\d+(\.\d+)?$/:数值;BACKGROUND_IMAGE = /(url\(|linear-gradient\()/:背景图片资源或线性渐变。
多端取值取交集的实际效果
同时支持 rn 与 harmony 时:
// .stylelintrc.js module.exports = mergeConfig(['harmony', 'rn'], {})/* 通过检查 */ ✅ .hello { text-align: left; } /* 警告提示 */ ❌ .hello2 { /* rn平台的text-align属性暂不支持right */ text-align: right; }原因在于:harmony 的text-align支持['center', 'left', 'right'],而 rn 侧supportedProperties为空对象(见 src/platform/rn.ts),通过 rn 平台通用规则与实际渲染能力约束后,right不在交集内,因而触发 warning。这正是"多端融合校验"的价值:在开发阶段即可发现某个取值在某一端不生效的隐患。
开启 VS Code 校验
项目空间内,建议通过修改.vscode/settings.json开启编辑器内联校验:
// .vscode/settings.json { "stylelint.enable": true, "stylelint.validate": ["css", "sass", "scss", "less", "postcss"] }配合customSyntax: "postcss-scss"(在mergeConfig的第二个参数中传入),即可让 SCSS/Less 等预处理器样式也享受同样的多端校验。
样式支持情况
值类型
| 类型 | 举例合法值 | 备注 |
|---|---|---|
| Length | 10px、10vw、10vh、100%、10rem、calc(100% - 20px) | 1rem = 16px |
| Color | #f00、rgb(0,0,0)、rgba(0,0,0,0.2)、green | 暂不支持 hsl 等方法 |
| Border | '1px solid #f00' | 符合 w3c 规范 |
通用属性
以下为所有元素都支持的样式属性(✔️ 表示支持,❌ 表示当前不支持):
| 属性 | 可选值 / 单位 | 支持情况 |
|---|---|---|
| flex | flexGrow flexShrink flexBasis | ✔️ |
| flex-grow | Number | ✔️ |
| flex-shrink | Number | ✔️ |
| flex-basis | Length | ✔️ |
| flex-direction | 'row','row-reverse','column','column-reverse' | ✔️ |
| justify-content | 'flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly' | ✔️ |
| align-content | 'flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly' | ✔️ |
| align-items | 'flex-start', 'flex-end', 'center', 'baseline', 'stretch' , 'auto' | ✔️ |
| align-self | 'flex-start', 'flex-end', 'center', 'baseline', 'stretch' , 'auto' | ✔️ |
| flex-wrap | 'nowrap', 'wrap', 'wrap-reverse' | ❌ |
| position | 'relative', 'absolute' | ✔️ |
| left | Length | ✔️ |
| top | Length | ❌ |
| right | Length | ❌ |
| z-index | Number | ✔️ |
| bottom | Length | ✔️ |
| margin | Length \ Length Length \ Length Length Length \ Length Length Length Length | ✔️ |
| margin-top | Length | ✔️ |
| margin-right | Length | ✔️ |
| margin-bottom | Length | ✔️ |
| margin-left | Length | ✔️ |
| padding | Length \ Length Length \ Length Length Length \ Length Length Length Length | ✔️ |
| padding-top | Length | ✔️ |
| padding-right | Length | ✔️ |
| padding-bottom | Length | ✔️ |
| padding-left | Length | ✔️ |
| width | Length | ✔️ |
| height | Length | ✔️ |
| min-height | Length | ✔️ |
| min-width | Length | ✔️ |
| max-height | Length | ✔️ |
| max-width | Length | ✔️ |
| background | ✔️ | |
| background-color | Color | ✔️ |
| background-image | "src('xxx')", "linear-gradient(xxx)" 支持图片资源和线性渐变 | ✔️ |
| background-size | 'cover', 'contain', Length(x y), Length(x) Length(y) | ✔️ |
| background-position | 'center', 'top', 'bottom', 'left', 'right', Length(x y), Length(x) Length(y) | ✔️ |
| background-repeat | 'repeat', 'no-repeat', 'repeat-x', 'repeat-y' | ✔️ |
| border | Border(可设置 4 个值,控制 4 个方向) | ✔️ |
| border-top | Border | ✔️ |
| border-left | Border | ✔️ |
| border-right | Border | ✔️ |
| border-bottom | Border | ✔️ |
| border-color | Color(可设置 4 个值,控制 4 个方向) | ✔️ |
| border-top-color | Color | ✔️ |
| border-right-color | Color | ✔️ |
| border-bottom-color | Color | ✔️ |
| border-left-color | Color | ✔️ |
| border-radius | Length(可设置 4 个值,控制 4 个方向) | ✔️ |
| border-top-left-radius | Length | ✔️ |
| border-top-right-radius | Length | ✔️ |
| border-bottom-left-radius | Length | ✔️ |
| border-bottom-right-radius | Length | ✔️ |
| border-style | 'dotted', 'dashed', 'solid' (4 个值,控制 4 个方向) | ✔️ |
| border-top-style | 'dotted', 'dashed', 'solid' | ✔️ |
| border-right-style | 'dotted', 'dashed', 'solid' | ✔️ |
| border-bottom-style | 'dotted', 'dashed', 'solid' | ✔️ |
| border-left-style | 'dotted', 'dashed', 'solid' | ✔️ |
| opacity | Number | ✔️ |
| display | 'flex', 'none', 'block' | ✔️ |
| display | 'inline-block', 'inline-flex', 'inline' | ❌ |
| overflow | 'hidden', 'visible' | ✔️ |
| transform | translate、translateX、translateY、translateZ、translate2d、translate3d、scale、scaleX、scaleY、scale3d、rotate、rotateX、rotateY、rotate3d | ✔️ |
| transform-origin | Length Length | ✔️ |
| content | ✔️ |
⚠️ 注意:
transform不允许连续出现 2 个同类型,如transform: translate(20px 20px) translate3d(10px, 30px, 30px)不合法;display不支持行内取值(inline / inline-block / inline-flex);- 定位不支持bottom和right(对照 harmony 平台配置,src/platform/harmony.ts 中仅声明了
top与left,position可选值为absolute | relative | fixed)。
上表描述的是一般意义上的支持边界;实际校验时以mergeConfig声明的平台对应的 harmony.ts 与 rn.ts 等平台配置为准,并取多端交集,因此不同平台组合下同一属性/取值的最终可用性可能更严格。
文本样式
| 属性 | 可选值 / 单位 | 支持情况 |
|---|---|---|
| font-size | Length | ✔️ |
| font-family | ✔️ | |
| font-style | 'normal', 'italic' | ✔️ |
| font-weight | 100~900, 'bold','bolder','light','lighter','normal' | ✔️ |
| line-height | 'XXpx' (需要指定具体指,不支持 Number) | ✔️ |
| text-align | 'center', 'left', 'right' | ✔️ |
| text-decoration | ('none', 'underline', 'line-through', 'overline') Color | ✔️ |
| text-overflow | 'ellipsis', 'clip' | ✔️ |
| color | Color | ✔️ |
| -webkit-line-clamp | Number | ✔️ |
⚠️ 注意:
- 文本样式仅对
<Text></Text>节点生效; - 文本样式不支持继承;
line-height不支持数值(即必须写成带单位的长度值,如line-height: 20px)。
以下两种情况是正确的对文本进行样式添加的案例:
- 直接将样式添加在
<Text/>上:
// ✅ 允许 <Text className="txt">hello</Text>- 样式添加到
<View/>下是一个文本内容:
// ✅ 允许 <View className="txt">hello</View>错误案例:
// ❌ hello 父级没有添加文本样式,txt的文本属性无法继承下去 <View className="txt"> <Text>hello</Text> </View>CSS 选择器
通用选择器
注意点:
- 支持类选择器;
- 不支持ID 选择器、标签选择器、属性选择器。
| 选择器 | 示例 | 示例说明 | 支持情况 |
|---|---|---|---|
| .class | .intro | 选择所有 class="intro" 的元素 | ✔️ |
| .class.class | .red.big | 选择所有 class="red big" 元素 | ✔️ |
| .class, .class | .item, .text | 选择所有 class="item" 元素和 class="text" 元素 | ✔️ |
| .class .class | .grandfather .child | 选择所有 class="grandfather" 内所有的 class="child" 的元素 | ✔️ |
| .class > .class | .parent > .child | 选择所有父级是 class="parent" 的 class="child" 元素 | ✔️ |
| .class+.class | .red+.big | 选择所有紧跟在 class="red" 元素之后的第一个 class="big" 元素 | ❌ |
| .class~.class | .red~.big | 选择所有紧跟在 class="red" 之后的每一个 class="big" 元素 | ❌ |
| #id | #firstname | 选择所有 id="firstname" 的元素 | ❌ |
| * | * | 选择所有元素 | ❌ |
| element | p | 选择所有<p>元素 | ❌ |
| [attribute] | [target] | 选择所有带有 target 属性元素 | ❌ |
| [attribute=value] | [target=blank] | 选择所有使用 target="blank" 的元素 | ❌ |
| ... | 其他 | ❌ |
伪类
- 支持before、after。
| 选择器 | 示例 | 示例说明 | 支持情况 |
|---|---|---|---|
| :before | .intro:before | 在每个 class="intro" 元素之前插入内容 | ✔️ |
| :after | .intro:after | 在每个 class="intro" 元素之后插入内容 | ✔️ |
| :nth-child() | .intro:nth-child(2) | 选择 class="intro" 元素是其父级的第二个子元素 | ❌ |
| :nth-last-child() | .intro:nth-last-child(2) | 选择 class="intro" 元素是其父级的第二个子元素, 从最后一个子项计数 | ❌ |
| :first-child | .intro:first-child | 选择 class="intro" 元素是其父级的第一个子级 | ❌ |
| :last-child | .intro:last-child | 选择 class="intro" 元素是其父级的最后一个子级 | ❌ |
| :root | :root | 选择文档的根元素 | ❌ |
| :checked | input:checked | 选择每个选中的输入元素 | ❌ |
| ... | 其他 | ❌ |
选择器层面的约束在平台配置中同样有据可查:harmony 平台通过selector-max-id、selector-max-type、selector-max-attribute、selector-max-universal四条内建规则将 id/类型/属性/通配选择器数量上限设为 0,并通过selector-pseudo-class-allowed-list: ['before', 'after']限定伪类、selector-combinator-allowed-list: ['>', ' ']限定组合器;rn 平台则额外设置了selector-max-combinators: 0(完全禁止组合器,见 src/platform/rn.ts),并允许export、root两个伪类。这些约束叠加后,代码中应尽量以"单类选择器 + before/after 伪类"的方式编写跨端样式。
平台默认规则速查
mergeConfig在生成规则时还会附带各平台的通用 Stylelint 规则(覆盖于用户rules之下),值得在排障时留意:
- harmony(src/platform/harmony.ts):禁止 vendor 前缀属性与取值;
color-named: never禁止命名颜色(应使用#f00、rgb()等);允许的单位为px, deg, %, vh, vw, s, rem;禁止min / max / clamp等函数;禁止@规则。 - rn(src/platform/rn.ts):同样禁止 vendor 前缀;允许的单位为
px, rem, deg, %, vh, vw, vmin, vmax, s(rn 额外支持 vmin/vmax);declaration-no-important: true禁止!important。
理解了这些默认约束,即可在自定义rules中按需放行或收紧,将 stylelint-taro 无缝嵌入 Taro 多端项目的日常样式开发流程。
【免费下载链接】taro开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/项目地址: https://gitcode.com/NervJS/taro
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考