Dimensionamento via Unidades de Viewport (vw/vh)
A conversão direta de valores fixos para unidades relativas à janela de visualização garante que os elementos ocupem percentuais consistentes do espaço disponível, independentemente da resolução. A lógica baseia-se na proporção entre o layout de referência e o viewport atual.
Para um projeto definido em 1920 x 1080, a conversão matemática segue:
// Cálculo base
largura_em_vw = (valor_px / 1920) * 100vw
altura_em_vh = (valor_px / 1080) * 100vh
Helpers em Pré-processadores CSS
Configuração para SCSS:
@use "sass:math";
$BASE_W: 1920;
$BASE_H: 1080;
@function calc-vw($val) {
@return math.div($val, $BASE_W) * 100vw;
}
@function calc-vh($val) {
@return math.div($val, $BASE_H) * 100vh;
}
Configuração para Less:
@base-w: 1920;
@base-h: 1080;
.to-vw(@prop, @val) {
@{prop}: (@val / @base-w) * 100vw;
}
.to-vh(@prop, @val) {
@{prop}: (@val / @base-h) * 100vh;
}
Para aplicar globalmente no ecossistema Vue, injete os arquvios de utilitários no processador de CSS via configuração de compilação (vue.config.js):
module.exports = {
css: {
loaderOptions: {
sass: {
additionalData: `@import "@/styles/helpers.scss";`
},
less: {
additionalData: `@import "@/styles/helpers.less";`
}
}
}
};
Alternativa via JavaScript
Caso a manipulação deva ocorer em runtime ou em estilos inline, a conversão pode ser centralizada:
const REF_WIDTH = 1920;
const REF_HEIGHT = 1080;
export const toVw = (px) => `${(px * 100) / REF_WIDTH}vw`;
export const toVh = (px) => `${(px * 100) / REF_HEIGHT}vh`;
Ajuste Automático de Componentes Gráficos
Bibliotecas como o ECharts não recalculam automaticamente o conteúdo quando apenas a janela redimensiona, exigindo monitoramento direto do container. Uma diretiva Vue isola essa responsabilidade:
import ERD from 'element-resize-detector';
import echarts from 'echarts';
import Vue from 'vue';
const INSTANCE_KEY = '_chart_erd_handler';
Vue.directive('auto-resize-chart', {
bind(el, binding) {
const handler = binding.value || (() => {
const chart = echarts.getInstanceByDom(el);
chart && chart.resize();
});
el[INSTANCE_KEY] = handler;
ERD({ strategy: 'scroll' }).listenTo(el, el[INSTANCE_KEY]);
},
unbind(el) {
if (el[INSTANCE_KEY]) {
ERD().removeListener(el, el[INSTANCE_KEY]);
delete el[INSTANCE_KEY];
}
}
});
Para métricas internas do gráfico (fontes, sombras, margens), que aceitam apenas números, crie uma função de adaptação:
export const adaptMetric = (rawVal, refW = 1920) => {
const currentW = window.innerWidth || document.documentElement.clientWidth;
if (!currentW) return rawVal;
return parseFloat(((rawVal * currentW) / refW).toFixed(2));
};
// Uso em opções do ECharts
const config = {
grid: {
top: adaptMetric(24),
bottom: adaptMetric(12)
}
};
Escala Global via CSS Transform
Esta abordagem mantém a proporção exata do layout original. O contêiner é centralizado e recebe um fator de escala calculado pela comparação das proporções (aspect ratio) entre a tela atual e o mockup.
.viewport-container {
width: 100%;
height: 100%;
position: relative;
}
.scalable-content {
position: absolute;
top: 50%;
left: 50%;
transform-origin: top left;
/* Dimensões fixas do design */
width: 1920px;
height: 960px;
}
O cálculo da transformação ocorre em montagem e redimensionamento:
const REF_W = 1920;
const REF_H = 960;
function applyGlobalScale() {
const viewW = document.documentElement.clientWidth;
const viewH = document.documentElement.clientHeight;
const refRatio = REF_W / REF_H;
const viewRatio = viewW / viewH;
// Determina o limitador (largura ou altura) para manter proporção sem corte
const factor = viewRatio < refRatio
? viewW / REF_W
: viewH / REF_H;
const target = document.getElementById('canvas-root');
target.style.transform = `scale(${factor}) translate(-50%, -50%)`;
}
window.addEventListener('resize', applyGlobalScale);
// Chamar na montagem do componente
Essa técnica gera barras pretas (letterbox/pillarbox) quando as proporções divergem, garantindo integridade visual absoluta. Para implementação acelerada, bibliotecas como v-scale-screen encapsulam essa matemática e o posicionamento.
Unidade rem com Recálculo Dinâmico da Raiz
A unidade rem depende do valor de font-size no elemento raiz (html). Ao manipular esse valor dinamicamente conforme a largura da tela, todos os elementos marcados com rem se ajustam proporcionalmente.
A conversão de px para rem pode ser automatizada durante o build com postcss:
// .postcssrc.js
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 192, // 1920px / 10 divisões
unitPrecision: 3,
propList: ['*', '!border'],
mediaQuery: false,
minPixelValue: 2
}
}
};
O script de recalibração da raiz deve rodar no carregamento e nas mudanças de viewport:
(function bootstrapRem(baseRatio = 16 / 9) {
const html = document.documentElement;
const recalculate = () => {
const vw = html.clientWidth;
const vh = html.clientHeight;
const currentRatio = vw / vh;
// Mantém escala estável até cruzar a proporção alvo
const scaleFactor = currentRatio > baseRatio ? (baseRatio / currentRatio) : 1;
const rootSize = (vw * scaleFactor) / 10;
html.style.fontSize = `${rootSize.toFixed(2)}px`;
};
recalculate();
window.addEventListener('resize', recalculate);
})();
A inclusão deste módulo no ponto de entrada da aplicação habilita o redimentionamento contínuo. Para elementos de gráficos vetoriais que ignoram CSS, a função de adaptação métrica apresentada na primeira abordagem pode ser reutilizada para ajustar espaçamentos e fontes internas.