如何创建适配数据量变化的弹窗式可滚动响应式表格?
解决方案:自适应高度的弹窗滚动表格(带响应式)
针对你遇到的固定高度导致数据量少时布局混乱、响应式未实现的问题,这里提供一套无需根据行数计算高度的方案,核心靠CSS的自适应属性和Grid布局实现需求。
核心修改思路
- 表格容器不设固定高度,改用
max-height限制最大可显示高度,min-height: fit-content让容器在数据少时自动收缩 - 用Grid的
grid-template-columns统一表头和表体的列宽,彻底解决列对齐问题 - 弹窗添加响应式样式,适配不同屏幕尺寸
- 表体(
tbody)仅在内容超过容器最大高度时显示滚动条
修改后的完整代码
React/JS 代码
const competitorLots = []; const Popup = () => { return ( <div className="popup"> <table className="scrollable-table popup-table"> <thead> <tr> <th>Наименование объявления</th> <th>Наименование и описание лота</th> <th>Дата окончания приема заявок</th> <th>Кол-во</th> </tr> </thead> <tbody> {competitorLots?.map((competitorLot, index) => ( <tr key={index}> <td>{competitorLot.lot_name}</td> <td>{competitorLot.lot_description}</td> <td> {moment(competitorLot.trd_buy_end_date).format("YYYY-MM-DD")} </td> <td>{competitorLot.lot_count}</td> </tr> ))} </tbody> </table> </div> ); } // mock competitors(改为10条数据测试自适应效果) for (let i = 0; i < 10; i++) { competitorLots.push({ lot_name: `name${i}`, lot_description: `description${i}`, trd_buy_end_date: new Date(Date.now() + 111586347 * i), lot_count: Math.ceil(Math.random() * 1000) }); } // mock moment const moment = (d) => ({ format: (f) => d.toLocaleDateString('en-CA') }); const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Popup />);
CSS 代码
:root { --popup-adname-column-width: 180px; --enddate-column-width: 120px; --popup-amount-column-width: 80px; --table-max-height: 80vh; /* 表格最大高度设为视口高度的80% */ } .popup { position: fixed; top: 10%; left: 10%; z-index: 1; background: white; padding: 1rem; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); /* 弹窗响应式适配 */ @media (max-width: 768px) { top: 0; left: 0; width: 100%; height: 100%; border-radius: 0; padding: 0.5rem; } } .scrollable-table { display: inline-grid; max-height: var(--table-max-height); min-height: fit-content; /* 数据少时自动收缩到内容高度 */ margin: 0; /* 统一列宽,确保表头和表体对齐 */ grid-template-columns: var(--popup-adname-column-width) var(--popup-adname-column-width) var(--enddate-column-width) var(--popup-amount-column-width); grid-template-areas: "head-fixed head-fixed head-fixed head-fixed" "body-scrollable body-scrollable body-scrollable body-scrollable"; } .scrollable-table thead { grid-area: head-fixed; background: #f5f5f5; /* 表头背景区分 */ } .scrollable-table tbody { grid-area: body-scrollable; overflow-y: auto; /* 仅内容超出时显示滚动条 */ /* 美化滚动条(可选) */ &::-webkit-scrollbar { width: 6px; } &::-webkit-scrollbar-thumb { background-color: #ccc; border-radius: 3px; } } /* 统一单元格样式,强化对齐效果 */ .popup-table th, .popup-table td { padding: 0.5rem; text-align: left; border-bottom: 1px solid #eee; } /* 列宽响应式调整 */ @media (max-width: 768px) { :root { --popup-adname-column-width: 120px; --enddate-column-width: 100px; --popup-amount-column-width: 60px; } } @media (max-width: 480px) { :root { --popup-adname-column-width: 100px; --enddate-column-width: 90px; --popup-amount-column-width: 50px; } /* 小屏幕允许单元格内容换行 */ .popup-table th, .popup-table td { white-space: normal; word-break: break-word; } }
HTML 代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script> <div id="root"></div>
关键修改说明
- 自适应高度解决布局混乱:表格容器用
max-height: 80vh限制最大高度(随视口自动调整),min-height: fit-content让容器在数据量少时自动收缩,彻底消除空白区域。 - 列对齐修复:通过
grid-template-columns统一指定四列宽度,替代原来单独给每个th/td设宽的方式,确保表头和表体的列完美对齐。 - 响应式适配:
- 弹窗在小屏幕下铺满整个视口,避免内容溢出
- 通过媒体查询动态调整列宽,极小屏幕允许单元格内容换行,保证表格不超出屏幕范围
- 滚动优化:仅当tbody内容超过容器高度时才显示滚动条,同时美化滚动条提升体验。
这套方案完全用CSS实现自适应,不需要JS计算行数,同时满足弹窗、tbody滚动、响应式的所有需求。
内容的提问来源于stack exchange,提问作者Dilia
相关产品推荐
相关产品推荐

