Wie kann man einen Mouseover-Effekt bei Touchgeräten einsetzen? Diese Frage habe ich mich bei der Optimierung der Kellertheater.de Seite gestellt. Hier meine Lösung dafür.

Ursprünglich wurde der Mouseover-Effekt für die Desktop-Umgebung entworfen, bei der man üblicherweise eine Maus als Pointing-Device einsetzt. Der Mouseover-Effekt signalisiert dem Nutzer seit jeher eine Aktion, die durch einen Klick auf das Element ausgeführt werden kann.

Seit etwa 2007 steigt die Verbreitung von Geräten mit Touchscreens - meist mobile Geräte, wie Smartphones und Tablet PCs - rasant an 1 2 3. Das Problem: mausspezifische Effekte wie der Mouseover-Effekt funktionierten nicht mehr so wie erwartet. Bei Touch-Geräten führt dieser Effekt sogar zu unliebsamen Verzögerungen und unschönen visuellen Effekten.

Ein Lösungsvorschlag für mobile Webseiten

Die Lösung sieht folgendermaßen aus: der Mouseover-Effekt wird auf Touchscreens erst angezeigt, wenn der Nutzer anfängt das jeweilige Element zu tippen. Gleichzeitig soll aber auch der Mouseover-Effekt für die Bedienung mit der Maus weiterhin funktionieren.

Der Plan: wir müssen via JavaScript den Mouseover-Effekt manuell bei den jeweiligen Events touchstart und mouseover auslösen.

Der übliche Weg, um einen Mouseover-Effekt zu gestalten ist, ihn über die CSS Pseudo-Klasse :hover zu gestalten:

a:hover {
   /* Dein CSS-Code */
}

Für unsere Lösung können wir die Pseudoklasse nicht nutzen, denn sie kann über JavaScript Events nicht einem HTML-Element zugewiesen werden. Dafür ersetzen wir einfach den Doppelpunkt durch einen Punkt.

a.hover {
   /* Dein CSS-Code */
}

Nun können wir dem jeweiligen HTML-Element die .hover-Klasse via JavaScript zuweisen und ebenso entfernen, sobald die Events touchstart und mouseover auftreten.

Der JavaScript-Code

Mit der JavaScript Bibliothek jQuery sieht das folgendermaßen aus:

/**
   * Mouseover-Fix für Touchscreens
 */
$('a, button').bind ('touchstart mouseover', function(){
    $(this).addClass("hover");
});

Dieser kleine Codeschnipsel bindet an den HTML-Elementen a und button eine Funktion bei 'touchstart mouseover'. Diese Funktion weist den jeweiligen Elementen die CSS-Klasse hover zu, auf denen diese jeweiligen Events touchstart und mouseover zutreffen.

Wir benötigen allerdings noch eine weitere Funktion, die die Klasse wieder entfernt, sobald die Events nicht mehr stattfinden. Dafür nutzen wir die Events touchend und mouseout. Mit jQuery sieht das also folgendermaßen aus:

$('a, button').bind ('touchend mouseout', function(){
    $(this).removeClass("hover");
});

In JavaScript sieht das mithilfe von jQuery-ähnlichen Hilfsfunktionen4 dann so aus:

/* 
 * jQuery-ähnliche Funktionen
 */

// Klassenfunktionen
// Quelle: http://toddmotto.com/creating-jquery-style-functions-in-javascript-hasclass-addclass-removeclass-toggleclass/

function hasClass(elem, className) {
  if(elem === null) {return;}
  return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
}

function addClass(elem, className) {
  if(elem === null) {return;}
  if (!hasClass(elem, className)) {
    elem.className += ' ' + className;
  }
}

function removeClass(elem, className) {
  if(elem === null) {return;}
  var newClass = ' ' + elem.className.replace( /[\t\r\n]/g, ' ') + ' ';
  if (hasClass(elem, className)) {
    while (newClass.indexOf(' ' + className + ' ') >= 0 ) {
      newClass = newClass.replace(' ' + className + ' ', ' ');
    }
    elem.className = newClass.replace(/^\s+|\s+$/g, '');
  }
}

/*
 * JavaScript für den Mouseover-Effekt
 */

function onHoverStart(ev) {
  addClass(ev.target, 'hover');
}

function onHoverEnd(ev) {
  removeClass(ev.target, 'hover');
}

var elements = document.querySelectorAll("a, button");
for (var i = 0, ii = elements.length; i < ii; ++i) {
  var element = elements[i];
  element.ontouchstart = onHoverStart;
  element.onmouseover = onHoverStart;

  element.ontouchend = onHoverEnd;
  element.onmouseout = onHoverEnd;
}

In JavaScript müssen die Events jedem einzelnen HTML-Element zugewiesen werden. Durch document.querySelectorAll haben wir aber eine ziemlich einfache Lösung, die gesamte Menge der zutreffenden HTML-Elemente zu bekommen. Über eine for-Schleife wird jetzt über jedes Element iteriert und beim jeweiligen Event die jeweilige Funktion onHoverStart oder onHoverEnd aufgerufen, die dann die CSS-Klasse hover zuweist oder entfernt.

Noch ein Kommentar

Man sollte in jedem Falle gut abwägen, ob man jQuery oder JavaScript als Skriptsprachen für die Entwicklung nutzt. jQuery ist sicherlich einfacher zu verstehen, benötigt allerdings eine über 80kb große Code-Bibliothek, die ebenfalls von den mobilen Geräten bei jeglicher Verbindungsqualität geladen und interpretiert werden muss.

Ich nutze gerne jQuery fürs Prototyping von Interaktionsideen. So kann ich sie schnell überprüfen und bereits wichtige Parameter für die Logik überprüfen. Am Ende wird idealerweise der jQuery-Code dann in reines JavaScript5 umgesetzt. Nur so kann ich eine optimale Performanz meines Codes garantieren.

  1. Mobile Geräte machen mittlerweile 5,4% des Besucher-Traffics auf W3Schools aus. W3Schools: Browsing-Verteilung der Betriebssysteme
  2. Die Zahl der Smartphones in den Vereinigten Staaten stieg bereits zwischen 2010 und 2013 auf über das Doppelte an. Statista: Number of smartphone users in the U.S. from 2010 to 2018 (in millions popup: yes)
  3. Bereits im ersten Quartal 2014 waren laut Statista 31,2% Mobile Nutzer im Internet unterwegs. Statista: Mobile phone internet user penetration worldwide from 2012 to 2017
  4. aus Todd Motto: Creating jQuery-style functions in JavaScript, hasClass, addClass, removeClass, toggleClass
  5. Entwickler bezeichnen reines JavaScript auch scherzweise als VanillaJS