CSS媒体查询 + 弹性布局
/* 基准样式 - 1920x1080设计稿 */
.container {
width: 100vw;
height: 100vh;
}
/* 超宽屏适配 (2560x1440) */
@media screen and (min-width: 2400px) {
html {
font-size: 18px;
}
.chart-container {
transform: scale(1.2);
transform-origin: 0 0;
}
}
/* 宽屏适配 (1920x1080) */
@media screen and (min-width: 1800px) and (max-width: 2399px) {
html {
font-size: 16px;
}
}
/* 中等屏幕 (1600x900) */
@media screen and (min-width: 1400px) and (max-width: 1799px) {
html {
font-size: 14px;
}
}
/* 小屏适配 (1366x768) */
@media screen and (max-width: 1399px) {
html {
font-size: 12px;
}
}
缩放方案(推荐)
// utils/screenAdapter.js
export class ScreenAdapter {
constructor(options = {}) {
this.designWidth = options.designWidth || 1920
this.designHeight = options.designHeight || 1080
this.init()
}
init() {
this.updateScale()
window.addEventListener('resize', this.debounce(this.updateScale.bind(this), 300))
}
updateScale() {
const clientWidth = document.documentElement.clientWidth
const clientHeight = document.documentElement.clientHeight
// 计算缩放比例
const scaleX = clientWidth / this.designWidth
const scaleY = clientHeight / this.designHeight
const scale = Math.min(scaleX, scaleY)
// 应用缩放
const container = document.getElementById('screen-container')
if (container) {
container.style.transform = `scale(${scale})`
container.style.transformOrigin = '0 0'
container.style.width = `${this.designWidth}px`
container.style.height = `${this.designHeight}px`
// 居中显示
container.style.position = 'absolute'
container.style.left = '50%'
container.style.top = '50%'
container.style.marginLeft = `-${this.designWidth / 2}px`
container.style.marginTop = `-${this.designHeight / 2}px`
}
}
debounce(fn, delay) {
let timer = null
return function() {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, arguments)
}, delay)
}
}
}
Viewport + REM方案
// 动态设置视口和rem
function setViewportAndRem() {
const baseWidth = 1920
const baseHeight = 1080
const clientWidth = document.documentElement.clientWidth
const clientHeight = document.documentElement.clientHeight
// 计算缩放比例
const scaleX = clientWidth / baseWidth
const scaleY = clientHeight / baseHeight
// 设置视口缩放
const viewportMeta = document.querySelector('meta[name="viewport"]')
const scale = Math.min(scaleX, scaleY)
if (viewportMeta) {
viewportMeta.content = `width=${baseWidth}, initial-scale=${scale}, maximum-scale=${scale}, user-scalable=no`
}
// 设置rem基准值
const fontSize = (clientWidth / baseWidth) * 16
document.documentElement.style.fontSize = `${fontSize}px`
}
// 监听窗口变化
window.addEventListener('resize', setViewportAndRem)
setViewportAndRem()
CSS Transform + CSS Variables
:root {
--scale-factor: 1;
--screen-width: 1920px;
--screen-height: 1080px;
}
.screen-wrapper {
width: var(--screen-width);
height: var(--screen-height);
transform: scale(var(--scale-factor));
transform-origin: 0 0;
position: absolute;
left: 50%;
top: 50%;
margin-left: calc(var(--screen-width) / -2);
margin-top: calc(var(--screen-height) / -2);
}
/* 所有内部尺寸都使用rem或设计稿px */
.widget {
width: 400px; /* 设计稿尺寸 */
height: 300px;
position: absolute;
left: 100px;
top: 100px;
}
// 更新缩放因子
function updateScaleFactor() {
const designWidth = 1920
const designHeight = 1080
const clientWidth = window.innerWidth
const clientHeight = window.innerHeight
const scaleX = clientWidth / designWidth
const scaleY = clientHeight / designHeight
const scale = Math.min(scaleX, scaleY)
document.documentElement.style.setProperty('--scale-factor', scale)
}
结合Flex/Grid布局
/* 使用Flex和Grid进行弹性布局 */
.dashboard {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 20px;
padding: 20px;
}
.chart-card {
display: flex;
flex-direction: column;
background: rgba(26, 35, 52, 0.8);
border-radius: 8px;
padding: 20px;
}
.chart-title {
font-size: clamp(16px, 1.5vw, 24px);
margin-bottom: 15px;
}
.chart-container {
flex: 1;
min-height: 300px;
}
Vue/React组件适配示例
<template>
<div
class="screen-container"
:style="containerStyle"
ref="container"
>
<!-- 大屏内容 -->
<div class="dashboard-content">
<div
v-for="widget in widgets"
:key="widget.id"
class="widget"
:style="getWidgetStyle(widget)"
>
<component :is="widget.component" />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
scale: 1,
widgets: [] // 组件配置
}
},
computed: {
containerStyle() {
return {
transform: `scale(${this.scale})`,
transformOrigin: '0 0',
width: '1920px',
height: '1080px'
}
}
},
mounted() {
this.updateScale()
window.addEventListener('resize', this.updateScale)
},
methods: {
updateScale() {
const designWidth = 1920
const designHeight = 1080
const width = window.innerWidth
const height = window.innerHeight
const scaleX = width / designWidth
const scaleY = height / designHeight
this.scale = Math.min(scaleX, scaleY)
},
getWidgetStyle(widget) {
return {
position: 'absolute',
left: `${widget.x}px`,
top: `${widget.y}px`,
width: `${widget.width}px`,
height: `${widget.height}px`
}
}
}
}
</script>
最佳实践建议
-
设计稿尺寸:建议以1920x1080为基准设计

-
单位选择:
- 固定尺寸使用px(设计稿尺寸)
- 字体和间距可考虑使用rem
- 弹性布局使用flex/grid
-
图表库适配:
// ECharts适配 const chart = echarts.init(dom) window.addEventListener('resize', () => { chart.resize() }) -
性能优化:
- 使用防抖处理resize事件
- 避免频繁重绘
- 考虑使用CSS硬件加速
根据你的具体需求选择合适的方案,通常推荐使用缩放方案或CSS Transform方案,它们在保持设计比例的同时实现较好的适配效果。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。