読み込み中...

HTMLで驚くほど簡単なドラッグ&ドロップ!5つのステップと実例

HTMLで驚くほど簡単なドラッグ&ドロップ! HTML
この記事は約25分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

📋 対応バージョン
HTML HTML5
CSS CSS3
JavaScript ES6+
Chrome 46+
Firefox 36+
Safari 10+
Edge 12+
IE 11
完全対応 一部機能制限

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

この記事を読めば、HTMLでドラッグ&ドロップ機能を実装できるようになります。ウェブサイトやアプリで、ユーザーに直感的な操作を提供することが可能です。さっそく始めてみましょう。

ドラッグ&ドロップとは

ドラッグ&ドロップは、マウスやタッチ操作で要素を選択し、別の場所に移動させる機能のことを指します。現代のウェブページやアプリでは、ファイルのアップロードや項目の並べ替えなどに広く活用されており、ユーザビリティの向上に大きく貢献している技術です。

ステップ1:HTML要素の準備

まず、ドラッグ&ドロップを実装するために必要なHTML要素を準備しましょう。以下のようなコードを記述してください。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>ドラッグ&ドロップサンプル</title>
</head>
<body>
  <div id="draggable" draggable="true">ドラッグできる要素</div>
  <div id="droppable">ここにドロップできます</div>
</body>
</html>

重要なポイントはdraggable="true"属性です。この属性を追加することで、要素がドラッグ可能になります。

ステップ2:CSSでスタイル設定

次に、ドラッグ&ドロップ機能を見やすくするため、CSSでスタイルを設定していきます。以下のコードを<head>タグ内に追加しましょう。

<style>
  #draggable {
    width: 100px;
    height: 100px;
    background-color: lightblue;
    cursor: grab;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 8px;
    user-select: none;
  }

  #droppable {
    width: 200px;
    height: 200px;
    background-color: lightgray;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 2px dashed #999;
    border-radius: 8px;
    margin-top: 20px;
  }

  .drag-over {
    background-color: #e8f5e8;
    border-color: #4CAF50;
  }
</style>

cursor: grabによってマウスカーソルが手の形になり、ドラッグ可能であることをユーザーに視覚的に伝えられます。また、.drag-overクラスは後ほどJavaScriptで使用する予定です。

ステップ3:JavaScriptでドラッグ&ドロップ機能実装

続いて、JavaScriptを使用してドラッグ&ドロップ機能を実装していきましょう。以下のコードを</body>タグの直前に追加してください。

<script>
  const draggable = document.getElementById('draggable');
  const droppable = document.getElementById('droppable');

  // ドラッグ開始時の処理
  draggable.addEventListener('dragstart', (event) => {
    event.dataTransfer.setData('text/plain', event.target.id);
    draggable.style.opacity = '0.5';
  });

  // ドラッグ終了時の処理
  draggable.addEventListener('dragend', (event) => {
    draggable.style.opacity = '1';
  });

  // ドロップ領域上でのドラッグ処理
  droppable.addEventListener('dragover', (event) => {
    event.preventDefault();
    droppable.classList.add('drag-over');
  });

  // ドロップ領域から離れた時の処理
  droppable.addEventListener('dragleave', (event) => {
    droppable.classList.remove('drag-over');
  });

  // ドロップ時の処理
  droppable.addEventListener('drop', (event) => {
    event.preventDefault();
    droppable.classList.remove('drag-over');
    const id = event.dataTransfer.getData('text/plain');
    const element = document.getElementById(id);
    droppable.appendChild(element);
  });
</script>

このコードでは、ドラッグ中の視覚的フィードバックを提供するため、要素の透明度を変更したり、ドロップ領域のスタイルを動的に変更したりしています。

ステップ4:注意点と対処法

ドラッグ&ドロップ機能を実装する際に知っておくべき重要なポイントがあります。以下に主な注意点とその対処法を示しましょう。

ブラウザサポートについて

HTML5のドラッグ&ドロップAPIは、現在すべての主要ブラウザ(Chrome、Firefox、Safari、Edge)で完全にサポートされています。過度に古いブラウザ(Internet Explorer 8以前など)を除けば、現代のウェブ開発において互換性を心配する必要はありません。

視覚的フィードバックの実装

ドラッグ中の要素の見た目を変更したい場合、CSS の :active:hover 疑似クラスは適用されないため注意が必要です。正しくは、JavaScript のイベントリスナー内でクラスを動的に追加・削除する方法や、要素のスタイルを直接変更する方法を使用します。上記のサンプルコードでは、dragstart 時に透明度を変更し、drag-over クラスを使ってドロップ領域の見た目を変更する実装例を示しています。

タッチデバイスでの対応

モバイルデバイスでのドラッグ&ドロップ機能は、デスクトップとは異なる動作をする場合があります。タッチイベントとの競合を避けるため、必要に応じて touch-action CSS プロパティを調整することを検討してください。

ステップ5:カスタマイズと応用例

ドラッグ&ドロップ機能は、様々なカスタマイズが可能です。実際の開発現場でよく使われる応用例とサンプルコードを紹介します。

応用例1:複数の要素をドラッグ&ドロップ可能にする

<div id="draggable1" draggable="true" class="draggable">ドラッグできる要素1</div>
<div id="draggable2" draggable="true" class="draggable">ドラッグできる要素2</div>
<div id="draggable3" draggable="true" class="draggable">ドラッグできる要素3</div>
<div id="droppable">ここにドロップできます</div>

<script>
  const draggables = document.querySelectorAll('.draggable');
  const droppable = document.getElementById('droppable');

  draggables.forEach((draggable) => {
    draggable.addEventListener('dragstart', (event) => {
      event.dataTransfer.setData('text/plain', event.target.id);
      event.target.style.opacity = '0.5';
    });

    draggable.addEventListener('dragend', (event) => {
      event.target.style.opacity = '1';
    });
  });

  droppable.addEventListener('dragover', (event) => {
    event.preventDefault();
    droppable.classList.add('drag-over');
  });

  droppable.addEventListener('dragleave', (event) => {
    droppable.classList.remove('drag-over');
  });

  droppable.addEventListener('drop', (event) => {
    event.preventDefault();
    droppable.classList.remove('drag-over');
    const id = event.dataTransfer.getData('text/plain');
    const element = document.getElementById(id);
    droppable.appendChild(element);
  });
</script>

この実装では、querySelectorAll を使用して複数の要素に一括でイベントリスナーを設定しています。コードの保守性が向上し、新しい要素を追加する際も簡単に対応できるでしょう。

応用例2:複数のドロップ領域を設定する

<div id="draggable" draggable="true">ドラッグできる要素</div>
<div id="droppable1" class="droppable">ここにドロップできます1</div>
<div id="droppable2" class="droppable">ここにドロップできます2</div>
<div id="droppable3" class="droppable">ここにドロップできます3</div>

<script>
  const draggable = document.getElementById('draggable');
  const droppables = document.querySelectorAll('.droppable');

  draggable.addEventListener('dragstart', (event) => {
    event.dataTransfer.setData('text/plain', event.target.id);
    event.target.style.opacity = '0.5';
  });

  draggable.addEventListener('dragend', (event) => {
    event.target.style.opacity = '1';
  });

  droppables.forEach((droppable) => {
    droppable.addEventListener('dragover', (event) => {
      event.preventDefault();
      droppable.classList.add('drag-over');
    });

    droppable.addEventListener('dragleave', (event) => {
      droppable.classList.remove('drag-over');
    });

    droppable.addEventListener('drop', (event) => {
      event.preventDefault();
      droppable.classList.remove('drag-over');
      const id = event.dataTransfer.getData('text/plain');
      const element = document.getElementById(id);
      droppable.appendChild(element);
    });
  });
</script>

この例では、複数のドロップ領域を設定することで、より柔軟なユーザーインターフェースを実現できます。

応用例3:ドラッグ&ドロップでリストの順序変更

<ul id="sortable-list">
  <li draggable="true" data-id="1">項目1</li>
  <li draggable="true" data-id="2">項目2</li>
  <li draggable="true" data-id="3">項目3</li>
  <li draggable="true" data-id="4">項目4</li>
</ul>

<style>
  #sortable-list {
    list-style: none;
    padding: 0;
  }

  #sortable-list li {
    padding: 10px;
    margin: 5px 0;
    background-color: #f0f0f0;
    border: 1px solid #ddd;
    cursor: move;
  }

  .dragging {
    opacity: 0.5;
  }
</style>

<script>
  const sortableList = document.getElementById('sortable-list');
  let draggedElement = null;

  sortableList.addEventListener('dragstart', (event) => {
    draggedElement = event.target;
    event.target.classList.add('dragging');
  });

  sortableList.addEventListener('dragend', (event) => {
    event.target.classList.remove('dragging');
    draggedElement = null;
  });

  sortableList.addEventListener('dragover', (event) => {
    event.preventDefault();
    const afterElement = getDragAfterElement(sortableList, event.clientY);
    if (afterElement == null) {
      sortableList.appendChild(draggedElement);
    } else {
      sortableList.insertBefore(draggedElement, afterElement);
    }
  });

  function getDragAfterElement(container, y) {
    const draggableElements = [...container.querySelectorAll('li:not(.dragging)')];
    
    return draggableElements.reduce((closest, child) => {
      const box = child.getBoundingClientRect();
      const offset = y - box.top - box.height / 2;
      
      if (offset < 0 && offset > closest.offset) {
        return { offset: offset, element: child };
      } else {
        return closest;
      }
    }, { offset: Number.NEGATIVE_INFINITY }).element;
  }
</script>

この応用例では、リスト項目の順序をドラッグ&ドロップで変更できる機能を実装しています。実際のToDoアプリやタスク管理システムなどでよく見られる機能です。

まとめ

この記事では、HTMLでドラッグ&ドロップ機能を実装する方法を初心者向けに詳しく解説しました。5つのステップを踏むことで、基本的なドラッグ&ドロップ機能を実現できるでしょう。

技術的な注意点やカスタマイズの方法、実践的な応用例も紹介しているため、実際のプロジェクトでも活用していただけるはずです。現代のウェブ開発において、ドラッグ&ドロップ機能はユーザビリティを大幅に向上させる重要な技術となっています。

この知識を活用して、ウェブサイトやアプリに直感的で使いやすい操作を提供してみてください。