首页
/ Material UI 系统之 Display 工具详解:用 @mui/system 快速实现响应式显示控制

Material UI 系统之 Display 工具详解:用 @mui/system 快速实现响应式显示控制

2026-09-06 17:46:44作者:胡易黎Nicole

本文聚焦 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/systemdisplay 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' } }}

对照表的逻辑值得拆解:断点键(如 xssm)代表"从该宽度起生效"(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 会逐键检查:键是合法断点(xsxl)就包装成对应的 @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),displayPrinttransform 会把传入的值包装为 { '@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 为例,displaydisplayPrint 等键会被 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 覆盖了日常布局中"显隐与溢出"这一高频需求:displaydisplayPrint 负责屏幕/打印双通道的显隐控制,overflowtextOverflowvisibilitywhiteSpace 负责内容边界处理。所有 prop 均支持对象形式的断点响应式取值,配合默认断点即可覆盖从手机到超大屏的完整显示策略,无需编写任何手写媒体查询 CSS。

登录后查看全文
热门项目推荐
相关项目推荐