概要: このチュートリアルでは、JavaScript ドラッグ&ドロップ API について、そしてそれを用いてシンプルなドラッグ&ドロップアプリケーションを実装する方法を学びます。
JavaScript ドラッグ&ドロップ API入門
HTML5 はドラッグ&ドロップ仕様を正式に導入しました。 ほとんどのモダン Web ブラウザは、HTML5 仕様に基づいたネイティブのドラッグ&ドロップを実装しています。
デフォルトでは、画像とテキストのみドラッグ可能です。 画像をドラッグするには、マウスボタンを押したまま移動するだけです。 テキストをドラッグするには、テキストをハイライトして、画像をドラッグするのと同じ方法でドラッグする必要があります。
HTML5 仕様では、ほぼすべての要素がドラッグ可能であると規定されています。 要素をドラッグ可能にするには、HTML タグに値が true
の draggable
プロパティを追加します。 例:
<div class="item" draggable="true"></div>
Code language: HTML, XML (xml)
ドラッグ可能要素のイベント
要素をドラッグすると、以下の順序でイベントが発生します。
dragstart
drag
dragend
マウスボタンを押したままマウスを動かし始めると、ドラッグしているドラッグ可能要素で dragstart
イベントが発生します。 カーソルは、要素を自身にドロップできないことを示すドロップ不可記号(線で斜線を引いた円)に変わります。
dragstart
イベントが発生した後、要素をドラッグしている間、drag
イベントが繰り返し発生します。
そして、要素のドラッグを停止すると、dragend
イベントが発生します。
すべてのイベントのターゲット (e.target
) は、ドラッグされている要素です。
デフォルトでは、ブラウザはドラッグされた要素の外観を変更しません。 したがって、好みに基づいて外観をカスタマイズできます。
ドロップターゲットのイベント
要素を有効なドロップターゲットにドラッグすると、以下の順序でイベントが発生します。
dragenter
dragover
dragleave
またはdrop
dragenter
イベントは、要素をドロップターゲットにドラッグするとすぐに発生します。
dragenter
イベントが発生した後、ドロップターゲットの境界内で要素をドラッグしている間、dragover
イベントが繰り返し発生します。
要素をドロップターゲットの境界外にドラッグすると、dragover
イベントの発生が停止し、dragleave
イベントが発生します。
ターゲットに要素をドロップした場合、dragleave
イベントの代わりに drop
イベントが発生します。
dragenter
、dragover
、dragleave
、および drop
イベントのターゲット (e.target
) は、ドロップターゲット要素です。
有効なドロップターゲット
ほぼすべての要素がドロップターゲットイベント (dragenter
、dragover
、dragleave
、および drop
) をサポートしています。 ただし、デフォルトではドロップは許可されていません。
ドロップを許可しないドロップターゲットに要素をドロップした場合、drop
イベントは発生しません。
要素を有効なドロップターゲットにするには、対応するイベントハンドラで event.preventDefault()
メソッドを呼び出すことにより、dragenter
イベントと dragover
イベントの両方のデフォルトの動作をオーバーライドできます。 (詳細は例セクションを参照)
dataTransfer オブジェクトを使用したデータ転送
ドラッグ&ドロップアクションでデータを転送するには、dataTransfer
オブジェクトを使用します。
dataTransfer
オブジェクトは、イベントのプロパティです。 ドラッグされた要素からドロップターゲットにデータを転送することができます。
dataTransfer
オブジェクトには、setData()
と getData()
の 2 つのメソッドがあります。
setData()
を使用すると、ドラッグ操作のデータを指定された形式とデータに設定できます。
dataTransfer.setData(format, data)
Code language: CSS (css)
形式は text/plain
または text/uri-list
です。 また、データは、ドラッグオブジェクトに追加するデータを表す文字列です。
getData()
メソッドは、setData()
メソッドによって保存されたドラッグデータを取得します。
getData()
は 1 つの引数を受け入れます。
dataTransfer(format)
形式は text/plain
または text/uri-list
です。 getData()
は、setData()
メソッドによって保存された文字列、またはドラッグ操作にデータが含まれていない場合は空の文字列を返します。
JavaScript ドラッグ&ドロップの例
JavaScript ドラッグ&ドロップ API を説明するために、次の シンプルなドラッグ&ドロップアプリケーション を開発します。
プロジェクト構造の作成
まず、drag-n-drop-basics
という新しいフォルダを作成します。 このフォルダ内に、css
と js
という 2 つのサブフォルダを作成します。
次に、js
フォルダに app.js
という新しいファイル、css
フォルダに style.css
、drag-n-drop-basics
フォルダに index.html
を作成します。
3 番目に、style.css
へのリンクと app.js
にリンクするスクリプトタグを index.html
ファイルに次のように配置します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript - Drag and Drop Demo</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script src="js/app.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
CSS については、ここから入手できます。
index.html ファイルの構築
次のコードを index.html
ファイルに配置します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript - Drag and Drop Demo</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<h1>JavaScript - Drag and Drop</h1>
<div class="drop-targets">
<div class="box">
<div class="item" id="item">
</div>
</div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
<script src="js/app.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
この index.html ファイルでは、.container
要素を使用して、見出しと drop-targets
要素を配置しました。
drop-targets
要素内に、同じクラス box
を持つ 3 つの div
要素を配置しました。 そして、クラス item
を持つ別の div 要素を最初のボックスに配置しました。
index.html
を開いて黄色のボックスをドラッグしようとすると、ドラッグできないことを示すカーソルが表示されます。

要素をドラッグ可能にするには、HTML タグに値が true
の draggable
プロパティを次のように追加します。
<div class="item" id="item" draggable="true">
Code language: JavaScript (javascript)
これで、index.html
を保存してブラウザで再度開くと、次のように item
要素をドラッグできることがわかります。

ドラッグ可能要素のイベント処理
style.css
ファイルには、要素を非表示にする .hide
クラスがあります。
.hide {
display: none;
}
Code language: CSS (css)
app.js
ファイルに、次のコードを追加します。
// select the item element
const item = document.querySelector('.item');
// attach the dragstart event handler
item.addEventListener('dragstart', dragStart);
// handle the dragstart
function dragStart(e) {
console.log('drag starts...');
}
Code language: JavaScript (javascript)
仕組み
- まず、
querySelector()
を使用してドラッグ可能要素を選択します。 - 次に、ドラッグ可能要素に
dragstart
イベントハンドラをアタッチします。 - 3 番目に、
dragstart
イベントを処理するdragStart()
関数を定義します。
index.html ファイルを開いてドラッグ可能要素のドラッグを開始すると、コンソールに「ドラッグ開始...」メッセージが表示されます。
dragStart
イベントハンドラでは、ドラッグ可能要素の id
を格納する必要があります。 そして、それを非表示にする必要があります。
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
e.target.classList.add('hide');
}
Code language: JavaScript (javascript)
要素をドラッグすると、ドラッグを開始するとすぐに要素が消えることがわかります。
これを解決するには、setTimeout()
関数を使用します。
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
setTimeout(() => {
e.target.classList.add('hide');
}, 0);
}
Code language: JavaScript (javascript)
これで、ドラッグ可能要素を元の位置からドラッグできます。

ドロップターゲットのイベント処理
style.css ファイルには、ドロップターゲットの境界線スタイルを破線と赤に変更する .drag-over
という CSS クラスもあります。
.drag-over {
border: dashed 3px red;
}
Code language: CSS (css)
app.js では、ドロップターゲット要素を選択し、これらの要素の dragenter
、dragover
、dragleave
、および drop
イベントを処理する必要があります。
const boxes = document.querySelectorAll('.box');
boxes.forEach(box => {
box.addEventListener('dragenter', dragEnter)
box.addEventListener('dragover', dragOver);
box.addEventListener('dragleave', dragLeave);
box.addEventListener('drop', drop);
});
function dragEnter(e) {
}
function dragOver(e) {
}
function dragLeave(e) {
}
function drop(e) {
}
Code language: JavaScript (javascript)
ドロップターゲットの境界線スタイルは、dragenter
イベントと dragover
イベントが発生したときに変更する必要があります。 dragleave
イベントと drop
イベントが発生したときにスタイルを復元する必要があります。
これを行うには、次のようにドロップターゲットに drag-over
クラスを追加および削除します。
function dragEnter(e) {
e.target.classList.add('drag-over');
}
function dragOver(e) {
e.target.classList.add('drag-over');
}
function dragLeave(e) {
e.target.classList.remove('drag-over');
}
function drop(e) {
e.target.classList.remove('drag-over');
}
Code language: JavaScript (javascript)
これで、ドラッグ可能要素を別のドロップターゲットにドラッグすると、次の図に示すように、ドロップターゲットの境界線が変更されます。

ドロップターゲットを有効にするには、次のように dragenter
イベントハンドラと dragover
イベントハンドラで event.preventDefault()
を呼び出す必要があります。
function dragEnter(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
Code language: JavaScript (javascript)
これを行わないと、div
要素はデフォルトでは有効なドロップターゲットではないため、drop
イベントは発生しません。
ドラッグ可能要素をドロップターゲットにドラッグすると、要素をドロップできることを示すカーソルが変更されます。

ここで、item
要素をドロップすると、すぐに消えることがわかります。
この問題を解決するには、drop
イベントを処理する必要があります。
- まず、
dataTransfer
オブジェクトのgetData()
メソッドを使用して、ドラッグ可能要素のid
を取得します。 - 次に、ドラッグ可能要素をドロップターゲット要素の子要素として追加します。
- 3 番目に、
draggable
要素からhide
クラスを削除します。
次のコードは、完全な drop
イベントハンドラを示しています。
function drop(e) {
e.target.classList.remove('drag-over');
// get the draggable element
const id = e.dataTransfer.getData('text/plain');
const draggable = document.getElementById(id);
// add it to the drop target
e.target.appendChild(draggable);
// display the draggable element
draggable.classList.remove('hide');
}
Code language: JavaScript (javascript)
これで、ドラッグ可能要素をドラッグアンドドロップすると、期待どおりに動作するはずです。
以下は、完全な app.js ファイルです。
/* draggable element */
const item = document.querySelector('.item');
item.addEventListener('dragstart', dragStart);
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
setTimeout(() => {
e.target.classList.add('hide');
}, 0);
}
/* drop targets */
const boxes = document.querySelectorAll('.box');
boxes.forEach(box => {
box.addEventListener('dragenter', dragEnter)
box.addEventListener('dragover', dragOver);
box.addEventListener('dragleave', dragLeave);
box.addEventListener('drop', drop);
});
function dragEnter(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragLeave(e) {
e.target.classList.remove('drag-over');
}
function drop(e) {
e.target.classList.remove('drag-over');
// get the draggable element
const id = e.dataTransfer.getData('text/plain');
const draggable = document.getElementById(id);
// add it to the drop target
e.target.appendChild(draggable);
// display the draggable element
draggable.classList.remove('hide');
}
Code language: JavaScript (javascript)
そして、こちらがデモへのリンクです。
まとめ
- 要素をドラッグ可能にするには、値が true の
draggable
プロパティを追加します。 dragstart
、drag
、およびdragend
イベントは、ドラッグ可能要素で発生します。dragenter
、dragover
、dragleave
、またはdrop
イベントは、ドロップターゲットで発生します。- 要素を有効なドロップターゲットにするには、
dragenter
イベントハンドラとdragover
イベントハンドラでevent.preventDefault()
を呼び出します。 - ドラッグアンドドロップ操作でデータを転送するには、
setData()
メソッドとgetData()
メソッドを備えたevent.dataTransfer
オブジェクトを使用します。