Material UI 系统之 Display 工具详解:用 @mui/system 快速实现响应式显示控制
本文聚焦 Material UI(MUI)System 层的 display 样式工具,讲解如何用 sx prop 在 React 组件中快速切换元素的显示模式(inline/block)、按断点响应式隐藏元素、控制打印时的显示行为,以及处理溢出、文本截断、可见性与空白等 CSS 属性。读完本文,你将掌握 Display 工具的全部 6 个样式 prop、各断点响应式写法的完整对照表,并能从 @mui/system 源码层面理解这些 prop 是如何被解析、变换为真实 CSS 的。
从源码看 Display 工具的组成
Display 工具由 6 个基础样式函数组合而成,定义在 display.ts 中:
export const displayPrint = style({
prop: 'displayPrint',
cssProperty: false,
transform: (value) => ({
'@media print': {
display: value,
},
}),
});
export const displayRaw = style({
prop: 'display',
});
export const overflow = style({
prop: 'overflow',
});
export const textOverflow = style({
prop: 'textOverflow',
});
export const visibility = style({
prop: 'visibility',
});
export const whiteSpace = style({
prop: 'whiteSpace',
});
const display = compose(
displayPrint,
displayRaw,
overflow,
textOverflow,
visibility,
whiteSpace,
);
export default display;
从源码结构看,display 是通过 compose 把 6 个独立样式函数串联成的组合函数:每个函数由 style() 工厂创建,负责声明"监听哪个 prop、映射到哪个 CSS 属性"。例如 displayRaw 只声明 prop: 'display',当 cssProperty 缺省时默认等于 prop,因此最终直接输出 CSS 的 display 属性;而 displayPrint 显式设置了 cssProperty: false,表示不直接输出同名 CSS 属性,而是交给 transform 回调生成一个 @media print 媒体查询嵌套对象——这正是后面"打印显示"能力的底层实现。
每个样式函数最终都通过 handleBreakpoints 处理响应式取值,因此 display 相关 prop 天然支持"值对象 + 断点键"的响应式写法。
切换显示模式:inline 与 block
CSS 的 display 属性决定元素的布局类型。@mui/system 的 display prop(即源码中的 displayRaw)允许你直接改写任意 HTML 元素的默认显示模式。
Inline 示例(对应演示文件 Inline.tsx):把块级 div 改为行内显示:
<Box component="div" sx={{ display: 'inline' }}>inline</Box>
<Box component="div" sx={{ display: 'inline' }}>inline</Box>
Block 示例(对应演示文件 Block.tsx):把行内 span 改为块级显示:
<Box component="span" sx={{ display: 'block' }}>block</Box>
<Box component="span" sx={{ display: 'block' }}>block</Box>
这两种写法是布局微调中最常见的手段:display: 'inline' 可让多个块级元素并排排列,display: 'block' 可让行内元素独占一行。
响应式隐藏元素:完整的断点对照表
官方文档建议:为了更快地开发移动端友好的界面,应该使用响应式的 display 写法按设备显示或隐藏元素,而不是为同一站点维护多个完全不同的版本——针对每种屏幕尺寸做响应式隐藏即可。
完整的"隐藏/仅显示"对照表如下(xs 到 xl 依次覆盖手机到超大屏):
| Screen Size | Class |
|---|---|
| Hidden on all | sx={{ display: 'none' }} |
| Hidden only on xs | sx={{ display: { xs: 'none', sm: 'block' } }} |
| Hidden only on sm | sx={{ display: { xs: 'block', sm: 'none', md: 'block' } }} |
| Hidden only on md | sx={{ display: { xs: 'block', md: 'none', lg: 'block' } }} |
| Hidden only on lg | sx={{ display: { xs: 'block', lg: 'none', xl: 'block' } }} |
| Hidden only on xl | sx={{ display: { xs: 'block', xl: 'none' } }} |
| Visible only on xs | sx={{ display: { xs: 'block', sm: 'none' } }} |
| Visible only on sm | sx={{ display: { xs: 'none', sm: 'block', md: 'none' } }} |
| Visible only on md | sx={{ display: { xs: 'none', md: 'block', lg: 'none' } }} |
| Visible only on lg | sx={{ display: { xs: 'none', lg: 'block', xl: 'none' } }} |
| Visible only on xl | sx={{ display: { xs: 'none', xl: 'block' } }} |
对照表的逻辑值得拆解:断点键(如 xs、sm)代表"从该宽度起生效"(min-width 语义),因此"仅在某一段显示"的写法就是在该段起点置为 block,在下一段起点置为 none。例如"仅在 sm 段可见"即 xs: 'none', sm: 'block', md: 'none'。
Hiding 示例(对应演示文件 Hiding.tsx):
<Box sx={{ display: { xs: 'block', md: 'none' }}}>
hide on screens wider than md
</Box>
<Box sx={{ display: { xs: 'none', md: 'block' }}}>
hide on screens smaller than md
</Box>
默认断点值从哪里来
这套对照表依赖的主题断点默认值定义在 breakpoints.ts 中:
// The breakpoint **start** at this value.
export const values: Record<string, number> = {
xs: 0, // phone
sm: 600, // tablet
md: 900, // small laptop
lg: 1200, // desktop
xl: 1536, // large screen
};
也就是说,未自定义 theme 时,xs 从 0px 起、sm 从 600px 起、md 从 900px 起、lg 从 1200px 起、xl 从 1536px 起。当 sx 中的值是对象时,iterateBreakpoints 会逐键检查:键是合法断点(xs…xl)就包装成对应的 @media (min-width: Xpx) 查询;键不是断点键则原样作为普通 CSS 键输出。这就是为什么断点响应式写法和普通 CSS 键可以在同一个 sx 对象里混用。
打印时的显示:displayPrint
displayPrint prop 用于独立控制元素在打印输出中的显示方式,屏幕显示和打印显示可以完全解耦(对应演示文件 Print.tsx):
<Box sx={{ display: 'block', displayPrint: 'none' }}>
Screen Only (Hide on print only)
</Box>
<Box sx={{ display: 'none', displayPrint: 'block' }}>
Print Only (Hide on screen only)
</Box>
- 第一个 Box 在屏幕上显示、打印时被隐藏(典型场景:导航栏、操作按钮等打印无意义的界面元素);
- 第二个 Box 屏幕上不可见、仅打印时显示(典型场景:打印专用页眉、发票备注)。
源码层面(见 display.ts),displayPrint 的 transform 会把传入的值包装为 { '@media print': { display: value } },最终由 styled-engine 渲染为标准的 @media print 媒体查询。由于它设置了 cssProperty: false,该 prop 不会在屏幕上产生任何 display 声明,因此与 display prop 互不干扰,可以任意组合。
Overflow:溢出处理
控制容器内容超出时的行为(对应演示文件 Overflow.tsx):
<Box component="div" sx={{ overflow: 'hidden' }}>
Not scrollable, overflow is hidden
</Box>
<Box component="div" sx={{ overflow: 'auto' }}>
Try scrolling this overflow auto box
</Box>
overflow: 'hidden':内容超出容器时直接裁剪,不可滚动;overflow: 'auto':内容超出时容器出现滚动条。
overflow prop 在源码中就是 style({ prop: 'overflow' }) 的直接透传,无主题映射、无变换,取值即 CSS 的 overflow 标准取值(visible / hidden / scroll / auto / clip 等)。
Text overflow:文本溢出截断
textOverflow prop 映射到 CSS 的 text-overflow 属性(对应演示文件 TextOverflow.tsx):
<Box component="div" sx={{ textOverflow: 'clip' }}>
Lorem Ipsum is simply dummy text
</Box>
<Box component="div" sx={{ textOverflow: 'ellipsis' }}>
Lorem Ipsum is simply dummy text
</Box>
clip 为默认行为,文字在边界处直接切断;ellipsis 则在超出位置显示省略号(…)。实际使用 ellipsis 时,通常还需要配合 overflow: 'hidden' 和 whiteSpace: 'nowrap' 才能让截断效果符合预期——这几个 prop 都属于 Display 工具,可在同一个 sx 中一起声明。
Visibility:可见性
visibility prop 映射到 CSS 的 visibility 属性(对应演示文件 Visibility.tsx):
<Box component="div" sx={{ visibility: 'visible' }}>
Visible container
</Box>
<Box component="div" sx={{ visibility: 'hidden' }}>
Invisible container
</Box>
需要注意 visibility: 'hidden' 与 display: 'none' 的区别:前者元素不可见但仍占据布局空间,后者元素完全从布局中移除。当需要"占位隐藏"(例如让前后元素位置保持一致)时应选 visibility;当要彻底不渲染布局时选 display: 'none'。
White space:空白处理
whiteSpace prop 映射到 CSS 的 white-space 属性(对应演示文件 WhiteSpace.tsx):
<Box component="div" sx={{ whiteSpace: 'nowrap' }}>
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.
</Box>
<Box component="div" sx={{ whiteSpace: 'normal' }}>
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.
</Box>
nowrap 强制文本不换行(常与 overflow: 'hidden' + textOverflow: 'ellipsis' 组成单行截断三件套),normal 则恢复正常的换行行为。
API 参考
Display 工具从 @mui/system 导出:
import { display } from '@mui/system';
完整的 prop 与 CSS 属性映射关系(Theme key 均为 none,即这些 prop 不做主题映射,值直接透传):
| Import name | Prop | CSS property | Theme key |
|---|---|---|---|
displayPrint |
displayPrint |
display |
none |
displayRaw |
display |
display |
none |
overflow |
overflow |
overflow |
none |
textOverflow |
textOverflow |
text-overflow |
none |
visibility |
visibility |
visibility |
none |
whiteSpace |
whiteSpace |
white-space |
none |
使用位置
这些 prop 既可以写在 Box 等组件的顶层,也常用在 sx 对象中(如本文所有示例)。以 sx 为例,display、displayPrint 等键会被 styleFunctionSx 管线中的 display 组合函数消费,经 handleBreakpoints 展开断点后交给 styled-engine 生成 CSS。由于所有 Display prop 的 Theme key 均为 none,其取值不参与主题解析,因此可以直接书写 CSS 标准值;若值是对象,则按"断点键 → 媒体查询、非断点键 → 直接 CSS"的规则展开。
响应式能力的适用前提
- 断点键
xs/sm/md/lg/xl的默认起点为 0 / 600 / 900 / 1200 / 1536 px(见 breakpoints.ts),如需自定义,可在createTheme中改写breakpoints.values,本文对照表中的具体像素含义会随之变化; displayPrint依赖浏览器对@media print的支持,其效果只有在打印预览或实际打印时可见,屏幕渲染阶段不会有任何display声明。
小结
| 需求 | 写法 |
|---|---|
| 切换布局类型 | sx={{ display: 'inline' | 'block' }} |
| 全设备隐藏 | sx={{ display: 'none' }} |
| 某断点以上/以下隐藏 | sx={{ display: { xs: 'block', md: 'none' } }} |
| 仅打印显示/隐藏 | sx={{ displayPrint: 'block' | 'none' }}(可与 display 组合) |
| 溢出裁剪/滚动 | sx={{ overflow: 'hidden' | 'auto' }} |
| 单行省略号 | sx={{ overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }} |
| 占位隐藏 | sx={{ visibility: 'hidden' }} |
Display 工具的 6 个 prop 覆盖了日常布局中"显隐与溢出"这一高频需求:display 与 displayPrint 负责屏幕/打印双通道的显隐控制,overflow、textOverflow、visibility、whiteSpace 负责内容边界处理。所有 prop 均支持对象形式的断点响应式取值,配合默认断点即可覆盖从手机到超大屏的完整显示策略,无需编写任何手写媒体查询 CSS。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00