Flexbox 在 RN 中的行为差异 & css注意

RN 的样式系统是 CSS 的子集 + 变体:基于 Flexbox 布局,但默认值、继承规则、支持的属性与 Web CSS 均有差异。核心原则是不要假设 Web 写法能直接移植,遇到问题优先查阅对应组件的官方文档确认属性是否受支持。


一、Flexbox 与 Web CSS 的差异

默认值

属性 Web CSS React Native
flexDirection row column
alignContent stretch flex-start
flexShrink 1 0
position static relative

flex 简写

  • Web 的 flex: 1 等价于 flex-grow: 1; flex-shrink: 1; flex-basis: 0
  • RN 底层由 Yoga 引擎计算,行为接近但边界情况与 W3C 规范略有出入,且不支持三值写法
jsx 复制代码
// ❌ RN 不支持
{ flex: '1 1 auto' }

// ✅ 分开声明
{ flexGrow: 1, flexShrink: 1, flexBasis: 'auto' }

不支持的属性 📢

  • float
  • display: inline-flex
  • flex-flow(需分别写 flexDirectionflexWrap
  • grid 系列属性

RN 特有属性

  • gap / rowGap / columnGap:RN 0.71+ 支持
  • aspectRatio:接受数字(1)而非字符串("1/1"

常见陷阱 📢

子 View 若未声明尺寸或 flex,高度默认为 0,不可见:

jsx 复制代码
// ❌ 子 View 高度为 0
<View style={{ flex: 1 }}>
  <View style={{ backgroundColor: 'red' }} />
</View>

// ✅ 正确
<View style={{ flex: 1 }}>
  <View style={{ flex: 1, backgroundColor: 'red' }} />
</View>

二、样式系统规范

StyleSheet API

  • RN 没有真正的 CSS,样式是 JavaScript 对象,属性名用 camelCase。
  • 推荐用 StyleSheet.create() 而非内联对象(样式会被 ID 化,减少跨线程传输开销):
jsx 复制代码
import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: '#fff' },
});

无 CSS 继承与选择器

RN 不支持 CSS 选择器,样式不会自动继承(Text 嵌套是例外:colorfontSize 等文字样式会从父 Text 继承):

jsx 复制代码
// ❌ View 没有 color 属性,子 Text 不会继承
<View style={{ color: 'red' }}>
  <Text>不会变红</Text>
</View>

// ✅ 每个组件单独设置
<Text style={{ color: 'red' }}>会变红</Text>

组件与样式绑定

不是所有属性对所有组件都有效:

组件 支持 不支持
View backgroundColorbordershadow colorfontSize
Text colorfontSizefontWeight overflow: scroll
Image widthheightresizeMode borderRadius(部分平台有问题)

单位规则

jsx 复制代码
// ✅ 无单位数字 = dp(与屏幕密度无关的像素)
{ width: 100, fontSize: 16 }

// ✅ 部分属性支持百分比字符串
{ width: '50%', height: '100%' }

// ❌ 不支持 px、rem 等单位
{ width: '100px', fontSize: '1rem' }

// ❌ 不支持 margin/padding 简写字符串
{ margin: '10 20' }

// ✅ 用 marginVertical / marginHorizontal
{ marginVertical: 10, marginHorizontal: 20 }

不支持的 CSS 功能

CSS 功能 RN 替代方案
::before / ::after 额外的 View / Text 组件
:hover / :focus PressableonHoverIn / onPressIn
transition / animation Animated API 或 react-native-reanimated
box-shadow shadow*(iOS)+ elevation(Android)
渐变背景 expo-linear-gradient 等三方库

平台差异

jsx 复制代码
import { Platform, StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  box: {
    shadowColor: '#000',      // iOS 阴影
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.3,
    shadowRadius: 4,
    elevation: 5,             // Android 阴影
  },
});

// 按平台差异化样式
const textStyle = Platform.select({
  ios: { fontSize: 14 },
  android: { fontSize: 13 },
});

overflow 行为

Android 默认 hidden,iOS 默认 visible。需要裁剪内容时,应明确声明以避免平台差异:

jsx 复制代码
{ overflow: 'hidden' }
相关推荐
leeyi15 小时前
Graph 编排:不只是 ReAct 的通用 DAG
react native·agent·graphql
不爱吃糖的程序媛17 小时前
React Native 三方库 react-native-version-number 鸿蒙适配实战:从零到版本信息展示
react native·react.js·harmonyos
Dragon Wu18 小时前
React Native 配置自定义字体
react native·react.js
不爱吃糖的程序媛2 天前
小白实战手记:React Native 应用部署到鸿蒙设备全流程详解
react native·鸿蒙
不爱吃糖的程序媛2 天前
React Native 三方库 react-native-share 的 HarmonyOS 适配实战
react native·react.js·harmonyos
不爱吃糖的程序媛2 天前
React Native 应用适配鸿蒙PC 实战:从白屏到成功运行
react native·react.js·harmonyos
jt君424263 天前
Bridge vs JSI,发生了什么变化以及为什么重要
react native
小书房4 天前
移动开发跨平台方案之RN/Flutter/KMP/CMP
flutter·react native·react·跨平台·rn·kmp·cmp
浩风祭月7 天前
React 18 并发特性实战:用 useTransition 和 useDeferredValue 优化列表搜索体验
前端·react native
老王以为7 天前
单仓库下的四十模块 —— React Monorepo 工程架构拆解
前端·react native·react.js