使い方と目的
この四角は、Web 上で動かせる「仮のコンテンツ箱」です。学習や HTML / CSS / JavaScript の練習、ブラウザでのレイアウト試作に使えます。
中にテキストや画像、ボタンなどを入れて、端や角をドラッグしてサイズを調整できます。実際に動かすことで、配置やサイズ感の確認ができます。
「リサイズ可能な四角」 デモ
デモは、実物ページ「リサイズ可能な四角」を iframe 内に表示しています。
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
<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
<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アプリや便利なツールを作る上では、ユーザーへの「おもてなし(使いやすさ)」を形にするための重要な技術です。 今はただの「四角形」ですが、この仕組み(部品)を応用すると、以下のような一歩進んだアプリやツールが作れるようになります。
- 自由自在なメモ帳やチャット欄
日記やメモをたくさん書くとき、入力欄が狭くてイライラしたことはありませんか?このコードを使えば、ユーザーが自分の書きたい量に合わせて「好きなサイズに広げられる入力欄」が作れます。 - 画像編集・デザインツール
写真やスタンプの大きさを自由に変える操作。プロの世界では「バウンディングボックス」と呼びますが、今回作ったコードはその基礎そのものです。自分だけのデザインツールを作る第一歩になります。 - 自分好みの管理画面(ダッシュボード)
カレンダーや TODO リスト、天気予報など、たくさんの情報を並べる画面で、「見たいものだけ大きく、他は小さく」と、ユーザーが自由にレイアウトをカスタマイズできる機能を提供できます。 - ブラウザの中の「小さな窓」
ゲームのステータス画面やヘルプ画面のように、ブラウザの中にさらに「動かせる窓」を作る高度なサイトでは、この機能が欠かせません。 「邪魔だから小さくしよう」「もっと詳しく見たいから広げよう」というユーザーのわがままに応えることができます。
「自分専用ツール」を作る最強の武器に
もしあなたが将来、「自分専用の便利な Webツール」を作りたいと思ったなら、このコードは心強い味方になります。
- 画像比較ツール:2 つの画像を並べて、サイズを変えながら細部をチェック!
- マルチ窓ブラウザ:好きなサイズの窓をたくさん作って、複数の動画を同時視聴!
中身を textarea(入力欄)や img(画像)に変えるだけで、一気に実用的なアプリへと進化します。 「いつかあのリサイズの仕組みが必要になるかも!」そんなときのために、このコードをあなたの引き出しに大切に保管しておいてください。
技術は進歩しますが、この『座標の計算』という基本は、時代が変わっても色褪せない Web の基礎知識です。
このページは、解説も含めてほぼ ChatGPT が作り、修正と仕上げは Gemini が担当しました。私はそれらをまとめただけです。
