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' }
相关推荐
沐言人生17 小时前
ReactNative 源码分析11——Native View创建流程setChildren和manageChildren
android·react native
沐言人生2 天前
ReactNative 源码分析10——Native View创建流程createView
android·react native
坏小虎2 天前
【聊天列表组件选型建议】FlashList、FlatList、LegendList三种列表组件
javascript·react native·react.js
sealaugh323 天前
react native(学习笔记第五课) 英语打卡微应用(4)- frontend的列表展示
笔记·学习·react native
沐言人生4 天前
ReactNative 源码分析9——Native View初始化
android·react native
接着奏乐接着舞4 天前
react native expo打包
javascript·react native·react.js
jxm_csdn5 天前
Expo Go 本地命令行编译 apk(Ubutnu22.04)
react native
红尘散仙5 天前
一套 Rust 核心,跑通 Tauri + React Native
react native·react.js·rust
诚实可靠王大锤6 天前
React Native 输入框与按钮焦点冲突解决方案(rn版本0.70.3)
前端·javascript·react native·react.js
sealaugh3210 天前
react native(学习笔记第四课) 英语打卡微应用(3)-ocr的文字转化成语音文件(tts)
笔记·学习·react native