Fügen Sie einem vorhandenen schwebenden Element wie einem Steuerfeld, einer Palette, einer Symbolleiste, einem Inspektor oder einem Dialogfeld die Möglichkeit zum Ziehen hinzu. Durch Ziehen wird nicht festgelegt, wie das Element angezeigt, geschlossen, gestapelt oder fokussiert wird.
Einen dedizierten Alias verwenden
Wenn das Element auswählbaren Text, Schaltflächen, Eingaben oder Links enthält, ziehen Sie es an einem speziellen Ziehpunkt. Der normale Inhalt bleibt so nutzbar. Machen Sie den Ziehpunkt für die Tastaturbewegung fokussierbar und geben Sie ihm einen barrierefreien Namen, der die Interaktion mit den Pfeiltasten erwähnt.
Wende role="application" nicht auf den Griff an. Die Interaktion mit Hilfstechnologien wird unnötig verändert.
Wenden Sie cursor: grab/grabbing, touch-action: none und sowohl user-select: none als auch -webkit-user-select: none auf den Ziehpunkt an, nicht auf das gesamte ziehbare Element. So bleibt Text außerhalb des Ziehpunkts auswählbar und Touch-Gesten behalten ihr übliches Verhalten bei:
.drag-handle {
cursor: grab;
touch-action: none;
-webkit-user-select: none;
user-select: none;
}
.drag-handle.dragging {
cursor: grabbing;
}
Position und Erreichbarkeit des Mauszeigers beibehalten
Verwenden Sie ein Darstellungsbereich-relatives Positionierungsmodell wie position: fixed, wenn Sie die Bewegung auf den Darstellungsbereich beschränken.
- Ziehvorgang nur für die primäre Zeigerschaltfläche (
event.button === 0) starten. - Zeiger-Offset bei
pointerdownaufzeichnen und bei jeder Bewegung verwenden, damit das Element nicht springt, wenn es nicht an der Ecke gegriffen wird. - Der Ziehvorgang bleibt aktiv, nachdem der Mauszeiger den Ziehpunkt verlassen hat. Standardmäßig auf
setPointerCapture()festgelegt und der Ziehstatus wird beilostpointercapturegelöscht. Wenn der Ziehpunkt während des Ziehens entfernt oder neu gerendert werden kann, verwenden Sie stattdessen die Listenerpointermove,pointerupundpointercancelauf Dokumentebene, da die Erfassung in diesem Fall verloren geht. - Optional können Sie warten, bis sich der Ziehpunkt um etwa 4 Pixel bewegt hat, bevor Sie den Ziehstatus aktivieren. So wird durch einen Klick auf den Ziehpunkt nicht das Zieh-Styling ausgelöst.
Mit der Zeigererfassung können die Bewegungs-Listener auf dem Ziehpunkt bleiben:
handle.addEventListener('pointerdown', (event) => {
if (event.button !== 0 || event.target.closest('button, input, select, textarea, a')) return;
const rect = draggable.getBoundingClientRect();
offsetX = event.clientX - rect.left;
offsetY = event.clientY - rect.top;
handle.setPointerCapture(event.pointerId);
});
handle.addEventListener('pointermove', (event) => {
if (!handle.hasPointerCapture(event.pointerId)) return;
handle.classList.add('dragging');
moveTo(event.clientX - offsetX, event.clientY - offsetY);
});
handle.addEventListener('lostpointercapture', () => {
handle.classList.remove('dragging');
});
function moveTo(left, top) {
const maxLeft = Math.max(0, window.innerWidth - draggable.offsetWidth);
const maxTop = Math.max(0, window.innerHeight - draggable.offsetHeight);
draggable.style.left = `${Math.max(0, Math.min(left, maxLeft))}px`;
draggable.style.top = `${Math.max(0, Math.min(top, maxTop))}px`;
}
Klemmen Sie jede Zeiger- und Tastaturposition über denselben Helfer, damit das Element erreichbar bleibt. Die aktuelle Position nach Änderungen am Darstellungsbereich oder an der Elementgröße neu festlegen. Bei Elementen mit vielen Layouts sollten Sie die Übersetzung während des Ziehens in Betracht ziehen, um ein Layout pro Frame zu vermeiden. Übernehmen Sie dann die endgültige Position beim Loslassen in left und top.
Tastaturbewegung bereitstellen
Wenn der Ziehpunkt den Fokus hat, verschieben Sie das Element mit den Pfeiltasten und rufen Sie preventDefault() für diese Tasten auf. Verwenden Sie denselben Hilfscode für die Positionierung wie für die Zeigerbewegung. Ein Schritt von 15 Pixeln ist ein guter Ausgangspunkt. Passen Sie ihn an die Größe und die Genauigkeitsanforderungen der Komponente an.
Dialogfeldspezifischer Hinweis
Ein <dialog> oder [popover] kann diesen Mechanismus mit seinem Header als Handle verwenden. Legen Sie margin: 0 fest, bevor Sie left und top zuweisen, da die Standardränder des Browsers die manuelle Positionierung beeinträchtigen. Informationen zum Verhalten beim Öffnen, Schließen, Fokussieren und Schließen von Dialogfeldern und Pop-overn finden Sie unter Deklarative Dialogfeld- und Pop-over-Steuerung und Plattformsteuerelemente zum Schließen von Dialogfeldern.
Fallback-Strategien
Wenn durch Ziehen nur die Position einer Komponente geändert wird, behandeln Sie dies als progressive Verbesserung: Ohne JavaScript sollten das Element, sein Inhalt und seine Steuerelemente an einer sinnvollen Standardposition sichtbar, lesbar und funktionsfähig bleiben. Zeigen Sie keinen nicht funktionsfähigen Ziehpunkt an: Wenn der Ziehpunkt ein eigenständiges Steuerelement ist, blenden Sie ihn standardmäßig aus und zeigen Sie ihn an, wenn JavaScript initialisiert wird. Wenn ein Header als Ziehpunkt dient, hängen Sie seine Ziehfunktionen an, wenn JavaScript initialisiert wird.
Fügen Sie -webkit-user-select: none vor user-select: none ein, damit die Textauswahl beim Ziehen in Safari unterdrückt bleibt.