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' }
相关推荐
Flynt10 小时前
Shopify 弃 React Native 上了 HN 1272 分,我复现了它给 Agent 用的那套无头架构
react native·前端框架·agent
嵩风抚5 天前
一款HK银行APP的业务+技术
android·flutter·react native·html5
杉氧6 天前
RN 性能调优指南:重渲染(Re-renders)控制与长列表(FlatList)优化
android·前端·react native
光影少年6 天前
react navite process.nextTick 和 Promise.then 的执行顺序
前端·react native·react.js
光影少年7 天前
react navite浏览器 Event Loop 和 Node Event Loop 的区别
前端·javascript·react native·react.js·前端框架
做前端的娜娜子8 天前
施工蓝图:vite.config.js —— 项目的指挥中心
前端·react native·vite
光影少年9 天前
RN首屏加载速度优化全方案
react native·react.js·掘金·金石计划
光影少年10 天前
如何实现RN 多环境、多渠道打包
前端·react native·react.js