scaleで拡大した要素の位置がずれる | scale で拡大した要素の座標値の表現 - CSS

scaleされた要素の位置がずれる現象について紹介します。

現象の確認

下記のHTMLファイルとCSSファイルを作成します。
position-scale.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
  <link rel="stylesheet" href="position-scale.css" />
</head>
<body>
  <div class="ContentsFrame">
    <div id="Square1">1</div>
    <div id="Square2">2</div>
    <div id="Square3">3</div>
  </div>
</body>
</html>
position-scale.css
body {
  background-color:#A0A0A0;
}

.ContentsFrame {
  position: relative;
  left:96px;
  top:32px;
  width: 600px;
  height: 400px;
  border: solid, 1px #0094ff;
  background-color: #FFFFFF;
}

#Square1 {
  position: absolute;
  width: 32px;
  height: 32px;
  left: 0;
  top: 0;
  border: 1px solid #ff6a00;
  position: absolute;
  transform:scale(1.0,1.0);
}

#Square2 {
  position: absolute;
  width: 32px;
  height: 32px;
  left: 280px;
  top: 96px;
  border: 1px solid #098619;
  transform: scale(1.0,1.0);
}

#Square3 {
  position: absolute;
  width: 32px;
  height: 32px;
  left: 32px;
  top: 350px;
  border: 1px solid #8604b2;
  transform: scale(1.0,1.0);
}

scaleを2倍にしたCSSと3倍にしたCSSファイルも用意します。
position-scale.css (scale 2倍版)
body {
  background-color:#A0A0A0;
}

.ContentsFrame {
  position: relative;
  left:96px;
  top:32px;
  width: 600px;
  height: 400px;
  border: solid, 1px #0094ff;
  background-color: #FFFFFF;
}

#Square1 {
  position: absolute;
  width: 32px;
  height: 32px;
  left: 0;
  top: 0;
  border: 1px solid #ff6a00;
  position: absolute;
  transform:scale(2.0,2.0);
}

#Square2 {
  position: absolute;
  width: 32px;
  height: 32px;
  left: 280px;
  top: 96px;
  border: 1px solid #098619;
  transform: scale(2.0,2.0);
}

#Square3 {
  position: absolute;
  width: 32px;
  height: 32px;
  left: 32px;
  top: 350px;
  border: 1px solid #8604b2;
  transform: scale(2.0,2.0);
}
position-scale.css (scale 3倍版)
/* 中略 */

#Square1 {
  /* 中略 */
  transform:scale(3.0,3.0);
}

#Square2 {
  /* 中略 */
  transform: scale(3.0,3.0);
}

#Square3 {
  /* 中略 */
  transform: scale(3.0,3.0);
}

表示結果

上記のHTMLファイルをWebブラウザで表示します。scale 1倍の場合、下図のページが表示されます。通常の表示のため指定した座標に枠が表示されています。


scale 2倍版のCSSの場合、下図のページが表示されます。1,2,3の枠の大きさが2倍に拡大されて表示されます。表示位置は1倍の表示位置を中心にして拡大されて 表示されていることがわかります。


scale 3倍版のCSSの場合は下図の表示になります。枠の大きさは3倍に拡大され、表示位置は1倍の表示位置を中心にして拡大されて表示されます。

表示位置を左上で設定したい

先の動作結果から、scaleで拡大された枠の表示位置は拡大しない場合(1.0倍)の位置を中心にして表示されることが確認できます。
1倍の表示を下図とします。枠の幅をw、枠の高さをh とします。


scaleで2倍に拡大した例です。下図のオレンジの枠が2倍に拡大された枠です。オレンジの点線が1倍の表示位置になります。 2倍に拡大した図形の表示位置は、1倍の図形の左上の位置から左にw/2 上に h/2 ずれた位置に表示されます。~

同様にscaleで3倍に拡大した場合の例です。下図のオレンジの枠が3倍に拡大表示された枠です。オレンジの点線が1倍の枠の表示位置になります。 3倍に拡大した図形の表示位置は、1倍の図形の左上の位置から左にw 上に h ずれた位置に表示されます。


1倍の図形の幅を w 1倍の図形の高さを h 倍率を s とすると、次のように表せます。
(1倍の図形の左上座標とのずれ [left]) = ((s - 1) * w) / 2
(1倍の図形の左上座標とのずれ [top])  = ((s - 1) * h) / 2

コード

CSSファイルを下記のとおりに変更します。
scaleを三倍にする場合は --scale-ratio の値を 3.0 に設定します。
position-scale.css (scale 2倍版)
#Square1 {
  --scale-ratio: 2.0;
  --width-length: 32px;
  --height-length: 32px;

  position: absolute;
  width: var(--width-length);
  height: var(--height-length);
  left: calc( ((var(--scale-ratio) - 1) * var(--width-length) ) / 2);
  top: calc( ((var(--scale-ratio) - 1) * var(--height-length) ) / 2);
  border: 1px solid #ff6a00;
  position: absolute;
  transform: scale(var(--scale-ratio),var(--scale-ratio));
}

#Square2 {
  --scale-ratio: 2.0;
  --width-length: 32px;
  --height-length: 32px;
  position: absolute;
  width: var(--width-length);
  height: var(--height-length);
  left: calc( 280px + ((var(--scale-ratio) - 1) * var(--width-length) ) / 2);
  top: calc( 96px + ((var(--scale-ratio) - 1) * var(--height-length) ) / 2);
  border: 1px solid #098619;
  transform: scale(var(--scale-ratio),var(--scale-ratio));
}

#Square3 {
  --scale-ratio: 2.0;
  --width-length: 32px;
  --height-length: 32px;
  position: absolute;
  width: var(--width-length);
  height: var(--height-length);
  left: calc( 32px + ((var(--scale-ratio) - 1) * var(--width-length) ) / 2);
  top: calc( 350px + ((var(--scale-ratio) - 1) * var(--height-length) ) / 2);
  border: 1px solid #8604b2;
  transform: scale(var(--scale-ratio),var(--scale-ratio));
}

解説

枠の幅と高さはCSSの変数で設定しています。CSS変数の詳細についてはこちらの記事を参照してください。
  --scale-ratio: 2.0;
  --width-length: 32px;
  --height-length: 32px;

  width: var(--width-length);
  height: var(--height-length);

left, top の座標値は元の値のままでは先の実行結果の通り左上にずれて配置されますので、先ほど紹介した計算式を設定して右下にずらします。
  left: calc( 32px + ((var(--scale-ratio) - 1) * var(--width-length) ) / 2);
  top: calc( 350px + ((var(--scale-ratio) - 1) * var(--height-length) ) / 2);

表示結果

上記のCSSに変更してHTMLファイルをWebブラウザで表示します。下図の画面が表示されます。
枠の左上の位置がscaleで拡大しない場合と同じ位置になっていることが確認できます。


scaleで拡大しない場合
scaleで拡大しない場合


scaleの倍率を3.0に設定した場合の表示結果です。こちらも枠の左上の位置がscaleで拡大しない場合と同じ位置になっています。


scaleで拡大した場合の座標の位置の変化について紹介しました。
著者
iPentecのメインデザイナー
Webページ、Webクリエイティブのデザインを担当。PhotoshopやIllustratorの作業もする。
掲載日: 2021-01-17
iPentec all rights reserverd.