CSS → Flutter 对照手册
核心思维转变:CSS 是给元素加属性,Flutter 是用 Widget 嵌套实现布局
一、盒模型
| CSS | Flutter | 说明 |
|---|---|---|
width / height |
Container(width, height) / SizedBox |
固定尺寸 |
max-width / min-width |
ConstrainedBox(constraints) |
尺寸约束 |
padding: 16px |
EdgeInsets.all(16) |
四边相同 |
padding: 10px 20px |
EdgeInsets.symmetric(vertical:10, horizontal:20) |
上下/左右 |
padding: 10px 20px 30px 40px |
EdgeInsets.fromLTRB(40, 10, 20, 30) |
上右下左 |
margin |
Container(margin: ...) |
外边距 |
background: blue |
Container(color: Colors.blue) |
纯色背景 |
border-radius: 20px |
BorderRadius.circular(20) |
圆角 |
border-radius: 10px 20px 30px 40px |
BorderRadius.only(topLeft: ..., ...) |
单独圆角 |
border: 3px solid yellow |
Border.all(width:3, color:Colors.yellow) |
边框 |
border-top: 3px solid red |
Border(top: BorderSide(width:3, color:Colors.red)) |
单边边框 |
box-shadow |
BoxDecoration(boxShadow: [BoxShadow(...)]) |
阴影 |
overflow: hidden |
ClipRRect / ClipOval |
裁剪溢出 |
width: fit-content |
IntrinsicWidth |
包裹内容宽度 |
width: 100% |
SizedBox(width: double.infinity) / Expanded |
撑满父级 |
⚠️
Container的color与decoration互斥,用了decoration就把颜色写进BoxDecoration(color:...)里
二、Flex 布局
| CSS | Flutter | 说明 |
|---|---|---|
display: flex; flex-direction: row |
Row |
横向排列 |
display: flex; flex-direction: column |
Column |
纵向排列 |
justify-content |
mainAxisAlignment |
主轴对齐 |
align-items |
crossAxisAlignment |
交叉轴对齐 |
flex: 1 |
Expanded |
占满剩余空间 |
flex: 2 (比例) |
Expanded(flex: 2) |
按比例分配 |
flex-grow 不强制填满 |
Flexible |
弹性但不强制 |
flex-wrap: wrap |
Wrap |
自动换行 |
gap / column-gap |
Wrap(spacing: 8) |
横向间距 |
row-gap |
Wrap(runSpacing: 8) |
纵向间距 |
align-self |
Align 包裹单个子项 |
单独控制对齐 |
justify-content 对照
| CSS | Flutter |
|---|---|
flex-start |
MainAxisAlignment.start |
flex-end |
MainAxisAlignment.end |
center |
MainAxisAlignment.center |
space-between |
MainAxisAlignment.spaceBetween |
space-around |
MainAxisAlignment.spaceAround |
space-evenly |
MainAxisAlignment.spaceEvenly |
align-items 对照
| CSS | Flutter |
|---|---|
flex-start |
CrossAxisAlignment.start |
flex-end |
CrossAxisAlignment.end |
center |
CrossAxisAlignment.center |
stretch |
CrossAxisAlignment.stretch |
baseline |
CrossAxisAlignment.baseline |
三、定位
| CSS | Flutter | 说明 |
|---|---|---|
position: relative(父容器) |
Stack |
绝对定位容器 |
position: absolute; top/left/right/bottom |
Positioned(top, left, right, bottom) |
绝对定位子项 |
position: absolute; top:50%; transform:translate(-50%,-50%) |
Positioned.fill + Align(Alignment.center) |
绝对居中 |
z-index |
Stack 中越靠后的 child 层级越高 | 层叠顺序 |
position: sticky |
SliverPersistentHeader(pinned: true) |
滚动置顶 |
position: fixed |
Scaffold 的 floatingActionButton / bottomNavigationBar |
固定在屏幕 |
四、文字样式
| CSS | Flutter | 说明 |
|---|---|---|
font-size: 20px |
TextStyle(fontSize: 20) |
字号 |
color: red |
TextStyle(color: Colors.red) |
颜色 |
font-weight: bold |
TextStyle(fontWeight: FontWeight.bold) |
粗体 |
font-weight: 300 |
TextStyle(fontWeight: FontWeight.w300) |
字重 |
font-style: italic |
TextStyle(fontStyle: FontStyle.italic) |
斜体 |
letter-spacing: 2px |
TextStyle(letterSpacing: 2) |
字间距 |
line-height: 1.5 |
TextStyle(height: 1.5) |
行高 |
text-decoration: underline |
TextStyle(decoration: TextDecoration.underline) |
下划线 |
text-decoration: line-through |
TextStyle(decoration: TextDecoration.lineThrough) |
删除线 |
text-align: center |
Text(textAlign: TextAlign.center) |
对齐 |
overflow: ellipsis |
Text(overflow: TextOverflow.ellipsis, maxLines: 1) |
超出省略 |
text-transform: uppercase |
text.toUpperCase() |
大写 |
text-shadow |
TextStyle(shadows: [Shadow(...)]) |
文字阴影 |
五、背景与装饰
| CSS | Flutter | 说明 |
|---|---|---|
background: blue |
BoxDecoration(color: Colors.blue) |
纯色背景 |
background: linear-gradient(to right, red, blue) |
LinearGradient(begin: Alignment.centerLeft, end: Alignment.centerRight, colors: [...]) |
线性渐变 |
background: linear-gradient(135deg, red, blue) |
LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [...]) |
对角渐变 |
background: radial-gradient(circle, red, blue) |
RadialGradient(colors: [...]) |
径向渐变 |
background-image: url(...) |
DecorationImage(image: AssetImage(...)) |
背景图 |
background-size: cover |
DecorationImage(fit: BoxFit.cover) |
背景图填充 |
六、变换
| CSS | Flutter | 说明 |
|---|---|---|
transform: rotate(0.05rad) |
Transform.rotate(angle: 0.05) |
旋转(弧度) |
transform: rotate(45deg) |
Transform.rotate(angle: 45 * pi / 180) |
旋转(角度转弧度) |
transform: scale(1.5) |
Transform.scale(scale: 1.5) |
缩放 |
transform: translate(20px, 10px) |
Transform.translate(offset: Offset(20, 10)) |
平移 |
transform-origin |
Transform(alignment: Alignment.topLeft, ...) |
变换原点 |
七、显示与隐藏
| CSS | Flutter | 说明 |
|---|---|---|
display: none(不占位) |
Visibility(visible: false) / 三元返回 SizedBox.shrink() |
移除占位 |
visibility: hidden(占位) |
Visibility(visible: false, maintainSize: true, maintainState: true, maintainAnimation: true) |
保留占位 |
opacity: 0.5 |
Opacity(opacity: 0.5) |
透明度 |
pointer-events: none |
IgnorePointer / AbsorbPointer |
禁用触摸 |
八、滚动
| CSS | Flutter | 说明 |
|---|---|---|
overflow: scroll(单个子项) |
SingleChildScrollView |
单子滚动 |
overflow: scroll(列表) |
ListView |
列表滚动 |
overflow-x: scroll |
SingleChildScrollView(scrollDirection: Axis.horizontal) |
横向滚动 |
scroll-snap |
PageView |
分页滑动 |
| 虚拟列表 | ListView.builder |
懒加载长列表 |
| 网格滚动 | GridView |
网格列表 |
| 混合滚动 | CustomScrollView + Sliver* |
复杂滚动 |
九、响应式
| CSS | Flutter | 说明 |
|---|---|---|
@media (max-width: 600px) |
MediaQuery.of(context).size.width < 600 |
屏幕宽度判断 |
vw / vh |
MediaQuery.of(context).size.width/height |
视口尺寸 |
grid-template-columns: repeat(auto-fill, minmax(150px,1fr)) |
LayoutBuilder + 动态 crossAxisCount |
自适应列数 |
| 父级约束响应 | LayoutBuilder(builder: (context, constraints) {...}) |
获取父级约束 |
十、经典布局速查
| 布局名 | CSS 方案 | Flutter 方案 |
|---|---|---|
| 圣杯布局 | float / flex |
Column + Row + Expanded |
| 双飞翼布局 | 负 margin |
Row + Expanded(主内容优先) |
| 粘性底部 | min-height: 100vh + margin-top: auto |
Column + Expanded |
| 水平垂直居中 | flex + justify/align: center |
Center / Align |
| 瀑布流 | column-count / JS 计算 |
双列 Column 交叉填充 |
| 底部导航 | 固定定位 | BottomNavigationBar + IndexedStack |
| 侧边抽屉 | transform: translateX |
Drawer |
| 折叠头部 | position: sticky + JS |
SliverAppBar |
| 主从布局 | @media 切换 |
MediaQuery + 条件渲染 |
| 固定头尾中间滚动 | flex-column + overflow: auto |
Column + Expanded + ListView |
十一、最大的思维差异
| CSS 思维 | Flutter 思维 |
|---|---|
| 一个元素加多个属性 | 多个 Widget 嵌套组合 |
| 样式可以全局继承 | 样式靠 ThemeData 统一管理 |
| 父级影响子级布局 | 父 Widget 向子 Widget 传递约束(constraints) |
z-index 控制层级 |
Stack 中越靠后的 child 层级越高 |
| 媒体查询响应式 | MediaQuery.of(context).size 获取屏幕尺寸 |
display: none 隐藏元素 |
三元表达式直接移除 Widget |
| 全局 class 复用样式 | 封装成独立 Widget 复用 |
CSS 变量 var(--color) |
Theme.of(context).colorScheme.primary |
伪元素 ::before / ::after |
Stack + Positioned 叠加 Widget |
transition 过渡动画 |
AnimatedContainer / AnimatedOpacity 等 Animated* 系列 |
十二、Widget 选择决策树
scss
需要样式装饰(背景/圆角/边框/阴影)?
└─ 是 → BoxDecoration(放在 Container 或 DecoratedBox 里)
需要布局子元素?
├─ 横向 → Row
├─ 纵向 → Column
├─ 叠加 → Stack
└─ 网格 → GridView
需要滚动?
├─ 单个内容 → SingleChildScrollView
├─ 列表 → ListView.builder
└─ 复杂滚动(折叠头/置顶) → CustomScrollView + Sliver*
只需固定尺寸,不需要装饰?
└─ SizedBox(比 Container 更轻量)
只需内边距?
└─ Padding(比 Container 更语义化)
只需对齐?
└─ Align / Center