尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
响应式布局的5种实现方式:从媒体查询到现代CSS方案
响应式布局说实话是前端绕不开的一个话题。不管你是做企业官网、电商活动页还是后台管理系统的嵌套界面只要你的产品需要被手机、平板、笔记本同时访问就得面对“同一套代码在不同宽度屏幕下怎么展示”这个问题。今天我要聊的这五种实现方式不是让你从里挑一个用到死而是帮你把每一种的思路、适用场景、坑点都理清楚在做技术选型的时候心里有底。本文适合刚接触响应式的前端新手也适合那些写过很多页面但从来没有系统梳理过适配方案的开发者。1. 响应式布局到底是解决什么问题1.1 从“一套设计稿”到“无数种屏幕”很多刚入行的同学会有一个误区觉得响应式布局就是“加几个媒体查询断点”屏幕变小了就换个样式。但实际做项目你会发现真正的难点在于设计师只给你一张1920宽的设计稿你却能变出手机、平板、笔记本、大屏电视都能看的页面。响应式布局的核心不是“适配”而是“重新组织信息”。同一个页面在桌面上可能是一行五列的卡片列表在手机上就得变成一列上下滑动在桌面上导航栏可以完整展开在手机上就得收进汉堡菜单。这些变化不是单纯把字号缩小、把图片缩小就完了而是信息密度、交互方式、阅读顺序的整体调整。所以理解响应式布局首先要建立“宽度不是唯一变量”的思维。除了宽度还要考虑触屏和鼠标的交互差异、网络环境差异、浏览器默认字体大小差异。这也是为什么后面五种方式各有侧重没有一种方案能包打天下。1.2 五种方式并不是“五选一”而是组合拳这五种实现方式——媒体查询、百分比布局、Flexbox、CSS Grid、视口单位与clamp()——很多人会误以为它们是对立的选了媒体查询就不能用Flex用了Grid就不需要百分比。实际上它们解决的问题维度完全不同。媒体查询解决的是“在特定宽度区间内切换布局形态”百分比解决的是“容器宽度跟随父级变化”Flexbox 解决的是“一维方向上元素如何排列、伸缩、对齐”Grid 解决的是“二维平面上行和列如何同时控制”而视口单位和clamp() 解决的是“字号、间距、尺寸如何随视口连续变化”。你可以在一个项目里同时用上全部五种最外层用 Grid 搭骨架网格内部的横向排列用 Flexbox容器宽度用百分比断点切换用媒体查询标题字号用 clamp()。它们不是地图上并列的五条路而是工具箱里功能各异的五把工具。明白这一点后面看每个方案的时候思路会清晰很多。2. 五种实现方式逐个拆解2.1 方式一媒体查询Media Queries媒体查询是响应式布局最经典、最基础的方式也是大多数人接触到的第一种方式。核心原理很简单通过media规则监听视口宽度、高度、屏幕方向等条件当条件满足时应用一段覆盖样式。/* 基础样式手机优先 */ .card-list { display: block; } /* 屏幕宽度大于等于 768px 时 */ media (min-width: 768px) { .card-list { display: flex; flex-wrap: wrap; gap: 16px; } }这种方式的优点是直观、可控性强——你能精确知道在某个宽度区间内页面长什么样断点之间的过渡都是你自己设计的。调试的时候开着开发者工具拖动视口样式能立刻变化非常方便。但媒体查询也有明显的坑。第一断点怎么定很多人喜欢照搬常见的 768px、1024px 这几个数字但这是从历史设备尺寸来的经验值不代表你的内容会在这些宽度自然换行。正确的做法是先写内容然后慢慢拖浏览器宽度找到内容变拥挤或者变空旷的位置把断点定在那里。第二媒体查询只是“切换开关”不解决连续变化的问题。假设你在手机上设了font-size: 14px在桌面上设了font-size: 18px那么中间宽度区间字号会突然从 14px 跳到 18px没有过渡。如果产品需求是“字号随屏幕平滑变化”媒体查询就不够用了需要配合clamp()或视口单位。第三媒体查询里面的样式覆盖层级容易混乱写多了之后很难维护所以现在更推荐用min-width从小到大写移动优先的样式后面的断点只覆盖需要变化的部分。2.2 方式二百分比布局流式布局百分比布局是一种很朴素的思路元素的宽度不用固定的px而是用父容器宽度的百分比来表示。比如一个两栏布局左侧 30%右侧 70%不管屏幕多宽比例始终不变。.container { width: 100%; max-width: 1200px; margin: 0 auto; } .sidebar { width: 30%; float: left; } .main { width: 70%; float: left; }这种方式的优点是代码简单没有断点任何宽度下都能自动伸缩。对于文字密集的内容型页面比如文档、博客百分比布局往往比媒体查询更平滑因为文本在任意宽度下都能重新换行不会出现“页面变窄了但容器还是固定宽度导致内容被挤爆”的问题。不过百分比布局的坑也不少。最经典的是“百分比到底是相对于谁计算的”——大多数 CSS 属性里width的百分比是相对于父元素的内容宽度的但padding、margin的百分比是相对于父元素的宽度的而height的百分比要求父元素有一个明确的高度否则会被忽略。很多新手在这里翻车设置了height: 50%发现根本不起作用就是因为父元素只有height: auto。还有一个问题是“百分比不能解决设计稿上的固定尺寸需求”。比如一个按钮需要有最小宽度 48px 保证可点击区域你用百分比设width: 20%在窄屏上按钮可能缩到 30px根本没法点。所以百分比布局通常要配合min-width、max-width、calc()一起用。这也是为什么说它很少单独作为方案更多是作为其他布局方式的辅助手段。2.3 方式三Flexbox 弹性盒子Flexbox 的出现可以说是一次革命。它专门解决一维排列问题——无论是水平方向还是垂直方向你只需要告诉容器“子元素该怎么排列、是否换行、如何伸缩”剩下的交给浏览器计算。.card-list { display: flex; flex-wrap: wrap; gap: 16px; } .card-list .item { flex: 1 1 200px; min-width: 0; }上面这段代码的意思是每个卡片在主轴方向上可以伸缩初始尺寸是 200px空间足够时放大空间不足时缩小一行放不下就换行。这个效果如果只用浮动或者百分比你得手写一堆nth-child选择器去控制每行最后一个元素的 margin而 Flexbox 一行代码就搞定了。Flexbox 解决响应式问题的核心优势在于“比例伸缩”。比如一个头部区域左边是 logo中间是导航右边是按钮你希望 logo 固定 100px按钮固定 80px导航在中间自适应。用 Flexbox 可以这样实现.header { display: flex; align-items: center; } .logo { flex: 0 0 100px; } .nav { flex: 1; min-width: 0; } .action-btn { flex: 0 0 80px; }flex: 1表示导航占据剩余空间当屏幕变窄时导航先被压缩logo 和按钮不动。如果导航内容太多可以配合overflow: hidden处理截断而不是让整个布局崩掉。这个能力是百分比布局很难做到的。但 Flexbox 的短板也很明显它只擅长一维。如果要做完整的页面骨架比如“左侧边栏固定宽度右侧内容区域分为上中下三块”用 Flexbox 嵌套也能做但代码会非常冗余而且行和列的关系不够直观。这时候就要看 Grid 了。2.4 方式四CSS Grid 网格布局CSS Grid 是真正意义上为二维布局而生的。它可以同时在行和列两个方向上定义网格轨道然后把内容直接放进网格区域里。.page { display: grid; grid-template-columns: 220px 1fr; grid-template-rows: 60px 1fr 60px; grid-template-areas: header header sidebar main footer footer; min-height: 100vh; } .page .header { grid-area: header; } .page .sidebar { grid-area: sidebar; } .page .main { grid-area: main; } .page .footer { grid-area: footer; }这个代码实现了一个经典的后台布局头部横跨整行左侧固定宽度的侧边栏右侧可伸缩内容区底部页脚。如果要变成移动端布局只需要在媒体查询里重新定义grid-template-columns为单列grid-template-areas重新排列模块顺序media (max-width: 768px) { .page { grid-template-columns: 1fr; grid-template-areas: header main footer; } .sidebar { display: none; } }Grid 对响应式的价值在于你不需要在 HTML 里调整模块顺序只需要通过grid-template-areas修改区域位置。比如在桌面上侧边栏在内容左边在手机上想让它跑到内容下面只需要调整 areas 的字符串排列就行HTML 结构完全不用动。还有一个特别实用的特性是minmax()。比如写grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))网格会自动计算能放下多少个 250px 的列剩余空间均分给每一列。这个效果用来做卡片列表简直完美它不需要媒体查询就能实现“宽度够就多放几列不够就自动换行”这是前面几种方式都实现起来很麻烦的。Grid 的主要缺点是学习曲线比 Flexbox 陡峭而且对于一维布局写 Grid 反而显得繁琐。另外要注意浏览器对grid-template-areas的拼写很敏感区域名称必须对应准确否则整个布局就会失效。2.5 方式五视口单位 clamp() 现代流式方案视口单位vw、vh、vmin、vmax以及 CSS 函数clamp()是最近几年越来越流行的一套组合。它的思路是彻底放弃“断点切换”让元素尺寸随视口宽度连续变化。1vw等于视口宽度的 1%。如果一个标题字号是5vw那么视口 375px 时字号是 18.75px视口 1920px 时字号是 96px。但直接用vw做字号有个问题在特别窄或特别宽的屏幕上字号会变得不可读。所以需要clamp()来限位。.title { font-size: clamp(16px, 3vw 10px, 48px); }clamp(最小值, 首选值, 最大值)的意思是字号永远在 16px 到 48px 之间首选值为3vw 10px。视口宽度 375px 时3vw是 11.25px加上 10px 就是 21.25px大于 16px视口宽度 800px 时是 34px视口宽度 1266px 时是 48px之后就不再增加了。这样字号既平滑变化又不会超出可读范围。这个方案特别适合处理间距、字号、图标大小这类“连续变化”的需求。比如卡片的内边距如果你用固定 20px在 320px 的屏幕上会显得很局促用padding: clamp(12px, 4vw, 20px)就能让它在小屏自动收紧。还可以配合calc()做更复杂的计算比如width: calc(100% - clamp(10px, 5vw, 40px))。不过要提醒一句视口单位是相对于整个浏览器视口的不是相对于父容器。如果你在一个宽度 500px 的侧边栏里用width: 50vw它会按整个视口宽度计算而不是侧边栏宽度结果很容易超出父容器。在这种场景下新型的容器查询Container Queries才是更准确的方案。容器查询允许你基于“元素所在的容器”的尺寸来做样式调整而不是整个视口。虽然目前浏览器支持已经比较普及但它在项目中的应用还不够广泛如果你是做组件库或者卡片类通用组件可以优先考虑。3. 实操搭建一个响应式卡片页面的完整过程3.1 项目需求与方案选型我们拿一个常见的案例来串一遍五个方案。假设要做一套商品卡片列表页要求是在桌面端每行显示 4 张卡片平板每行 2 张手机上每行 1 张。卡片内部有图片、标题、描述和一个操作按钮需要整个页面在任何宽度下都美观可用。如果只用媒体查询可以这样写默认手机单列min-width: 600px时双列min-width: 992px时四列。但这样断点切换比较生硬而且每一列的宽度是固定的 25% 或 50%如果中间有个 700px 的屏幕双列会显得很宽。如果我们用Grid minmaxauto-fill这个问题就能平滑解决让网格自动决定列数。我最终采用的方案是外层用 Gridrepeat(auto-fill, minmax(240px, 1fr))自动生成列卡片内部用 Flexbox 布局图片宽度用百分比标题字号用clamp()同时保留一个媒体查询用于在小屏上调整卡片的边距和内边距。这就是五者的组合。3.2 关键代码与实现步骤HTML 结构保持简单不为了布局特意包一层多余的容器div classproduct-grid article classproduct-card img srcpic.jpg alt商品图片 h2 classproduct-title无线蓝牙耳机黑色/h2 p classproduct-desc这是一段商品描述文字可能会比较长需要换行。/p button classproduct-btn查看详情/button /article !-- 重复若干卡片 -- /divCSS 核心部分如下.product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; width: 100%; max-width: 1200px; margin: 0 auto; padding: clamp(12px, 3vw, 24px); } .product-card { display: flex; flex-direction: column; /* 让按钮始终在底部 */ background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.06); } .product-card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; } .product-title { font-size: clamp(16px, 2vw 8px, 24px); margin: 12px 16px 8px; } .product-desc { flex: 1; font-size: 14px; color: #666; margin: 0 16px 16px; line-height: 1.6; } .product-btn { margin: 0 16px 16px; padding: 10px 16px; border: none; background: #3478f6; color: #fff; border-radius: 6px; cursor: pointer; } media (max-width: 520px) { .product-grid { gap: 12px; } .product-desc { font-size: 13px; } }解释一下几个关键选择repeat(auto-fill, minmax(240px, 1fr))自动填充列数每列最小 240px如果父容器足够宽就多放几列剩余空间由1fr均分。这样不需要手动写“平板两列、手机一列”的断点因为 240px 已经隐含了“如果容器宽度小于 240px 就只能一列”的判断。卡片内部用flex-direction: column并给描述文字flex: 1这样当卡片高度不齐时按钮能自动对齐到底部视觉更整齐。图片width: 100%是百分比布局的思路让图片跟随卡片宽度aspect-ratio: 4/3固定宽高比防止图片在加载过程中布局抖动。标题用clamp()平滑缩放字号避免在 520px 到 900px 这个区间里感到字号突然变化。3.3 适配验证与参数调整写完样式后我在浏览器开发者工具里把宽度分别调到 320px、375px、768px、1024px、1440px 检查效果。发现了两个问题第一个问题是 240px 的列最小宽度在 320px 屏幕上会溢出。因为 320px 的屏幕去掉左右 paddingclamp(12px, 3vw, 24px)在 320px 下约等于 12px两遍共 24px实际内容宽度只有 296px大于 240px所以还可以放一列。但如果卡片有边框和阴影视觉效果已经撑得很满。于是我把最小列宽调成 220px并给.product-grid加了一句grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr))。这里min(220px, 100%)是一个很关键的技巧——如果容器宽度比 220px 还小就让列宽等于容器宽度避免溢出。第二个问题是aspect-ratio: 4/3在图片原始比例不是 4/3 时会裁掉一部分但设计稿要求图片横竖比例统一所以保留裁切。如果有的图片想完整显示就不能用object-fit: cover而是contain但那样会留下空白背景取舍要看具体产品要求。经过调整后的网格可以很好地做到大屏自动四列中屏三列或两列窄屏一列而且没有任何一个媒体查询硬编码断点。这就是 Grid 加现代 CSS 的威力。4. 常见问题与排查技巧实录4.1 断点怎么选才科学很多人纠结“移动端用 375px 还是 480px”。我的建议是不要从设备尺寸出发而是从内容出发。你先写一个没有媒体查询的流式布局然后慢慢在开发者工具里拉宽视口观察页面在哪些宽度开始变得别扭——比如卡片变得太宽导致文字阅读体验差或者导航栏的点击区域被压缩到难以操作。在这些“临界点”设置断点而不是盲目照着大众设备尺寸表抄。另外如果你的项目是桌面优先可以用max-width向下覆盖如果是移动优先就用min-width向上覆盖。我建议大多数新项目用移动优先因为基准样式简单性能也更好——手机上不会加载桌面端的额外样式。4.2 百分比嵌套后溢出怎么办百分比布局最常见的坑是“父元素宽度 100%子元素又设置了宽度 100%再算上 padding 或 border就溢出”。比如.parent { width: 100%; } .child { width: 100%; padding: 20px; }在标准盒模型下.child的实际宽度是100% 40px必然溢出。两种解决方法一是给所有元素设box-sizing: border-box这是最推荐的全局默认二是不要用width: 100%对块级元素让它默认占满父容器宽度只要加 padding 就不会撑破因为块级元素的width: auto会自动减去 padding。还有一个容易被忽略的点Flex 或 Grid 的子项默认会超出容器因为它们的min-width默认是auto内容再长也不会换行收缩。如果你发现一个长英文单词把卡片撑爆了给子项加min-width: 0或者在容器上写overflow: hidden往往能解决。4.3 Flex 子项压缩与换行问题Flexbox 有三个比例概念经常让人搞混flex-grow放大、flex-shrink缩小、flex-basis基准尺寸。很多人直接写flex: 1但不知道它其实是flex: 1 1 0%。这表示基准尺寸为 0所有元素均分剩余空间。如果你希望元素按内容尺寸伸缩应该写flex: 1 1 auto或者flex: 0 1 auto。还有一个常见问题是flex-wrap没设置时子项会把容器撑破或者被压缩得不成样子。如果你想要“放不下自动换行”一定要加flex-wrap: wrap。如果是导航栏里的菜单项一般不希望换行那就用flex-wrap: nowrap但要注意给容器加overflow: hidden或者让菜单项内部省略号不然内容会溢出。4.4 移动端 1px 边框和字号适配细节移动端响应式不只是布局视觉细节也很容易被忽视。最典型的是“1px 边框”在手机上看起来像 2px 甚至更粗因为普通设备的物理像素比是 2 或 3CSS 的 1px 等于物理像素的 2px 或 3px。解决方案有几种用transform: scale(0.5)模拟细线用box-shadow: 0 0 0 0.5px或者用border-image。但从现代浏览器的兼容性来看最省事的其实是直接接受这个像素差异很多设计团队已经不再纠结。字号适配我一直坚持“优先用 rem clamp()而不是把所有字号都写死 px”。如果你使用了视口单位做字号记得要给根元素设置一个基准字号并且在媒体查询里调整根字号这样页面上所有用 rem 的地方都能跟着变维护起来更方便。但是要注意字体大小用视口单位有一个用户体验问题在窄屏上字号会变得很小影响可读性所以一定要用clamp()加下限不要纯vw。5. 我的个人取舍经验5.1 在不同项目里的组合策略我在实际项目里很少只用单一方案。做后台管理系统我第一选择是 Grid 搭整体骨架因为后台通常有侧边栏、顶栏、内容区之间的固定比例关系Grid 的grid-template-areas让模块重新排列非常省心。做官网营销页我倾向于 Flexbox 加媒体查询因为页面结构相对线性而且视觉评审经常要求精确控制每个断点下的效果Flexbox 更容易精细调整。做移动端 H5我会大量使用clamp()和百分比让页面在任意尺寸的全面屏手机上都能平滑拉伸不像媒体查询那样只能在几个固定断点之间跳跃。还有一个很实用的经验是能用 Grid 自动布局实现的就不要写一堆断点。像repeat(auto-fit, minmax(200px, 1fr))这种写法已经包含了“窄屏一列、宽屏多列”的自动判断省掉了几百行媒体查询代码。但也要注意auto-fit和auto-fill的行为有细微差别——容器宽到能放 4 列的时候auto-fill会保留空的轨道占用空间而auto-fit会把空轨道折叠。如果只有 3 个卡片你想让它们占满整行而不是靠左排列应该用auto-fit如果你想每列宽度恒定就用auto-fill。5.2 你不需要一开始就用 Grid 或容器查询聊到这里我想泼一点冷水。现在各种新特性层出不穷容器查询也确实很好用但并不是所有项目都必须上。如果你们的项目只需要适配几个明确的目标设备比如企业内部系统只跑在 1920 的办公机和 iPad 上那写几个媒体查询就够了不用为了“高级”而把简单问题复杂化。响应式布局的目的是让用户在任何合理尺寸下都能顺畅阅读和操作不是为了让代码看起来炫技。我见过有些团队把页面改成纯 Grid 之后发现旧浏览器的兼容问题一大堆最后不得不回退反而浪费了工时。反过来如果你在做的是一个组件库或者你的页面要在各种不确定的容器里被嵌套使用那容器查询就很有价值。因为常规媒体查询只能感知视口大小无法感知组件所在容器的大小一个卡片组件在侧边栏里和在主内容区里需要完全不同的排版只有容器查询能同时满足。你可以用container来写.card { container-type: inline-size; } container (max-width: 300px) { .card { display: block; } }这个知识点可以作为你后面进阶的方向但我还是建议先把前面五种基本功练扎实再考虑容器查询。我在实际使用中最大的体会是响应式布局没有一个万能钥匙。你理解得越深就越知道在某个具体界面里该用哪个工具而不是一招鲜吃遍天。多写几个不同场景的项目把每种方式的优势和毛病都亲手踩一遍比看一百篇教程都有用。
RELATED

相关推荐

PCA9422与PIC18F87J11的完整电源管理设计实战

PCA9422与PIC18F87J11的完整电源管理设计实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/24 1:05:43
Tomcat三个默认端口详解:8080、8005、8009的作用与配置避坑指南

Tomcat三个默认端口详解:8080、8005、8009的作用与配置避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/24 1:05:43
基于PCA9422与ATmega324PA的嵌入式电源管理方案设计

基于PCA9422与ATmega324PA的嵌入式电源管理方案设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/24 1:05:43
MORE NEWS

更多资讯

📰

Vue3.0项目创建步骤

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

半导体基础知识和组合电路分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

windows 域控-共享设置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

基于FPGA实现Aurora协议,概念

FPGA实现Aurora协议完整指南 Aurora协议是Xilinx开发的一种轻量级、可扩展的高速串行通信协议,专为FPGA之间的点对点数据传输而设计。本文将极其详细地讲解如何基于FPGA实现Aurora协议,从原理到实战,让你彻底掌握这一关键技术。 一、Aurora协…

📰

Install docker and presearch

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

上位机程序设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬