ぱたぱたアニメ館

リサイズ可能な四角

使い方と目的

この四角は、Web 上で動かせる「仮のコンテンツ箱」です。学習や HTML / CSS / JavaScript の練習、ブラウザでのレイアウト試作に使えます。 中にテキストや画像、ボタンなどを入れて、端や角をドラッグしてサイズを調整できます。実際に動かすことで、配置やサイズ感の確認ができます。

「リサイズ可能な四角」 デモ

デモは、実物ページ「リサイズ可能な四角」を iframe 内に表示しています。

HTML

HTML

<div class="resizable" id="box">
  ドラッグしてサイズ変更
  <div class="resizer resizer-ew"></div>
  <div class="resizer resizer-ew-left"></div>
  <div class="resizer resizer-ns"></div>
  <div class="resizer resizer-ns-top"></div>
  <div class="resizer resizer-nwse"></div>
  <div class="resizer resizer-nesw"></div>
  <div class="resizer resizer-nwse-tl"></div>
  <div class="resizer resizer-nesw-tr"></div>
</div>

CSS

CSS

<style>
/* iframe 内で「画面の真ん中」を正しく計算するために、
  土台となる html と body の高さ(100%)を確保しています。*/
html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden; /* 余計なスクロールバーを出さない */
  position: relative;
}

.resizable {
  width: 200px;
  height: 150px;
  border: 2px solid #333;
  position: absolute;
  padding: 10px;
  box-sizing: border-box;
  background: #fdfdfd;
  text-align: center;
  user-select: none;
}
.resizer { position: absolute; background: rgba(0,0,0,0.1); }

/* 各ハンドルのカーソルと位置 */
.resizer-ew { width: 10px; height: 100%; top:0; right:0; cursor: ew-resize; }
.resizer-ew-left { width:10px; height:100%; top:0; left:0; cursor: ew-resize; }
.resizer-ns { height:10px; width:100%; bottom:0; left:0; cursor: ns-resize; }
.resizer-ns-top { height:10px; width:100%; top:0; left:0; cursor: ns-resize; }
.resizer-nwse { width:15px; height:15px; bottom:0; right:0; cursor:nwse-resize; }
.resizer-nesw { width:15px; height:15px; bottom:0; left:0; cursor:nesw-resize; }
.resizer-nwse-tl { width:15px; height:15px; top:0; left:0; cursor:nwse-resize; }
.resizer-nesw-tr { width:15px; height:15px; top:0; right:0; cursor:nesw-resize; }
</style>

見た目やハンドルの位置・カーソルを設定。

JavaScript

JavaScript

<script>
const box = document.getElementById('box');
let currentResizer = null;
let startX, startY, startWidth, startHeight, startLeft, startTop;
const minSize = 50; // 最小サイズ制限

// 中央に配置する関数
function centerBox() {
  const parentWidth = window.innerWidth;
  const parentHeight = window.innerHeight;
  box.style.left = (parentWidth - box.offsetWidth) / 2 + 'px';
  box.style.top = (parentHeight - box.offsetHeight) / 2 + 'px';
}

// 読み込み完了時とリサイズ時に中央へ
window.addEventListener('load', centerBox);
window.addEventListener('resize', centerBox);

box.querySelectorAll('.resizer').forEach(resizer => {
  resizer.addEventListener('mousedown', e => {
    e.preventDefault();
    currentResizer = resizer;
    const rect = box.getBoundingClientRect();
    startX = e.clientX;
    startY = e.clientY;
    startWidth = rect.width;
    startHeight = rect.height;
    startLeft = rect.left;
    startTop = rect.top;
    document.addEventListener('mousemove', resize);
    document.addEventListener('mouseup', stopResize);
  });
});

function resize(e) {
  if (!currentResizer) return;
  const dx = e.clientX - startX;
  const dy = e.clientY - startY;

  // 右・下方向のリサイズ
  if (currentResizer.classList.contains('resizer-ew') || 
      currentResizer.classList.contains('resizer-nwse') || 
      currentResizer.classList.contains('resizer-nesw-tr')) {
    box.style.width = Math.max(minSize, startWidth + dx) + 'px';
  }
  if (currentResizer.classList.contains('resizer-ns') || 
      currentResizer.classList.contains('resizer-nwse') || 
      currentResizer.classList.contains('resizer-nesw')) {
    box.style.height = Math.max(minSize, startHeight + dy) + 'px';
  }

  // 左・上方向のリサイズ(座標の移動も伴う)
  if (currentResizer.classList.contains('resizer-ew-left') || 
      currentResizer.classList.contains('resizer-nesw') || 
      currentResizer.classList.contains('resizer-nwse-tl')) {
    const width = Math.max(minSize, startWidth - dx);
    if (width > minSize) {
      box.style.width = width + 'px';
      box.style.left = startLeft + dx + 'px';
    }
  }
  if (currentResizer.classList.contains('resizer-ns-top') || 
      currentResizer.classList.contains('resizer-nwse-tl') || 
      currentResizer.classList.contains('resizer-nesw-tr')) {
    const height = Math.max(minSize, startHeight - dy);
    if (height > minSize) {
      box.style.height = height + 'px';
      box.style.top = startTop + dy + 'px';
    }
  }
}

function stopResize() {
  document.removeEventListener('mousemove', resize);
  document.removeEventListener('mouseup', stopResize);
  currentResizer = null;
}
</script>

端や角のハンドルをドラッグして四角のサイズを変える処理です。最小サイズ制限を追加し、iframe 内での中央配置にも対応させています。

[注] この「ドラッグリサイズ」操作は PC(マウス操作)向けに最適化されています。 スマホやタブレットで動かすには、指の動きを感知する「タッチイベント」への対応や、指でも掴みやすい大きなハンドルへの調整が必要になります。

この技術の活用アイデア

この「リサイズ機能」は、単に四角を動かすだけの遊びではありません。Webアプリや便利なツールを作る上では、ユーザーへの「おもてなし(使いやすさ)」を形にするための重要な技術です。 今はただの「四角形」ですが、この仕組み(部品)を応用すると、以下のような一歩進んだアプリやツールが作れるようになります。

  1. 自由自在なメモ帳やチャット欄
    日記やメモをたくさん書くとき、入力欄が狭くてイライラしたことはありませんか?このコードを使えば、ユーザーが自分の書きたい量に合わせて「好きなサイズに広げられる入力欄」が作れます。
  2. 画像編集・デザインツール
    写真やスタンプの大きさを自由に変える操作。プロの世界では「バウンディングボックス」と呼びますが、今回作ったコードはその基礎そのものです。自分だけのデザインツールを作る第一歩になります。
  3. 自分好みの管理画面(ダッシュボード)
    カレンダーや TODO リスト、天気予報など、たくさんの情報を並べる画面で、「見たいものだけ大きく、他は小さく」と、ユーザーが自由にレイアウトをカスタマイズできる機能を提供できます。
  4. ブラウザの中の「小さな窓」
    ゲームのステータス画面やヘルプ画面のように、ブラウザの中にさらに「動かせる窓」を作る高度なサイトでは、この機能が欠かせません。 「邪魔だから小さくしよう」「もっと詳しく見たいから広げよう」というユーザーのわがままに応えることができます。

「自分専用ツール」を作る最強の武器に

もしあなたが将来、「自分専用の便利な Webツール」を作りたいと思ったなら、このコードは心強い味方になります。

  • 画像比較ツール:2 つの画像を並べて、サイズを変えながら細部をチェック!
  • マルチ窓ブラウザ:好きなサイズの窓をたくさん作って、複数の動画を同時視聴!

中身を textarea(入力欄)や img(画像)に変えるだけで、一気に実用的なアプリへと進化します。 「いつかあのリサイズの仕組みが必要になるかも!」そんなときのために、このコードをあなたの引き出しに大切に保管しておいてください。

技術は進歩しますが、この『座標の計算』という基本は、時代が変わっても色褪せない Web の基礎知識です。

このページは、解説も含めてほぼ ChatGPT が作り、修正と仕上げは Gemini が担当しました。私はそれらをまとめただけです。

上に戻る