基本的にはリキッドレイアウトでHTMLページを構成するのがいいと思うんだけど、場合によってはアスペクト比を保ってレイアウトしたい場合もあるかもしれない。その際内部の解像度が変わってしまうと任意の位置に要素を配置することがHTMLでは難しいので、内部的な扱いは決まった解像度になっていると楽だ。

ということをCSS transformで要素をスケールさせて実現する。

デモ

CSS

bodyのマージンを取り除く:

body {
  margin: 0;
}

念のためoverflow: hiddenを指定したほうがいいかもしれない。

HTML

body直下にdiv要素を配置して、widthheightを指定しておく:

<body>
  <div id="root" style="width: 640px; height: 480px;">
    Resolution fixed element.
  </div>
</body>

JavaScript

JavaScriptからその要素を自動的にスケーリングさせるための関数を呼び出す:

var root = document.getElementById('root')
scaleBlockAuto(root)

windowresizeされたときにCSS transformを使って、ウィンドウに長辺がフィットするようにスケールする:

function scaleBlockAuto(elem, callback) {
  const onResize = function() {
    var winWidth = window.innerWidth, winHeight = window.innerHeight
    var aspect = elem.clientWidth / elem.clientHeight
    var width, tx = 0, ty = 0
    if (winWidth / winHeight >= aspect) {
      width = winHeight * aspect
      tx = (winWidth - width) * 0.5
    } else {
      width = winWidth
      ty = (winHeight - winWidth / aspect) * 0.5
    }

    var scale = width / elem.clientWidth
    elem.style.transform = 'translate(' + tx + 'px,' + ty + 'px) scale(' + scale + ')'
    elem.style.transformOrigin = '0 0'
    if (callback)
      callback(scale)
  }

  window.addEventListener('resize', onResize, false)
  onResize()
}
  • リサイズされた時に、スケールをcallbackで受け取れるようにしている(マウスイベントなどでスケールが必要になることがあるため)