IE, überlagerte Elemente und Mausereignisse
dedlfix
- browser
0 Axel Richter0 dedlfix0 Axel Richter0 dedlfix
Hi!
Gegeben sei der nachfolgende Beispiel-Code. Im Container #images befinden sich eine Bilderliste (#thumbs) und ein weiterer Container (#areas). Letzterer soll die Thumbs-Liste überlagern. Zu erkennen ist #areas am roten Rahmen. Darin befinden sich weitere Elemente (.area), denen ich einen blauen Rand gegeben habe. Nun möchte ich, dass der Mauszeiger beim Ein- und Austreten in eines der .area-Elemente eine Aktion auslöst (onmouseover, onmouseout). Mein Problem mit den Internet Explorern (getestet IE6 und IE8) ist, dass in leeren .area-Elementen nur deren Rand, nicht aber deren nicht vorhandenes Inneres zum Element zu zählen scheint. Sprich: wenn die Maus auf rot oder blau ist, ist sie over, sonst ist sie out. (Firefox 3.0 macht es so wie ich das möchte, andere Browser hab ich (noch) nicht probiert.)
Die linken beiden .area-Elemente habe ich zum Test präpariert, das möchte ich aber eigentlich nicht so haben. Ganz links ist ein transparentes GIF flächenfüllend eingefügt, da wird das over so erkannt, wie ich das möchte. Im zweiten von links habe ich "XXX" als Inhalt eingefügt. Wenn die Maus nicht direkt darüber ist, wird sie nicht als over erkannt.
Die Event-Handler onmouseover und onmouseout habe ich #areas zugefügt. Es ändert sich am Verhalten nichts, wenn man sie stattdessen jeweils den einzelnen .area-Elementen gibt. Auch onmousemove ergibt das gleiche Verhalten. Mein eigentliches Ziel ist, dass in den blau gekennzeichneten Bereichen jeweils unterschiedliche Aktionen ausgeführt werden (und das auch unabhängig von den darunter liegenden Bildern). Dazu müsste ich onmouseover und onmouseout sowieso den einzelnen .area-Elementen zuweisen. Natürlich könnte ich auch #images "anzapfen" und anhand der X-Position die jeweilige Aktionen auslösen. Doch ich dachte, dass es vielleicht auch so geht. Vermutlich werde ich die X-Position-Lösung weiterverfolgen, aber bekommt man es auch auf diese Weise und ohne Pseudo-Inhalt hin?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Test</title>
<style type="text/css">
a img { border-style: none; }
#thumbs {
position: absolute;
list-style-type: none;
margin: 0;
padding:0;
z-index: 1;
}
#thumbs li {
float: left;
width: 120px;
height: 96px;
}
#areas {
position: absolute;
z-index: 3;
width: 470px;
height: 86px;
border: 5px solid red;
}
.area {
float: left;
width: 84px;
height: 76px;
border: 5px solid blue;
}
</style>
<script type="text/javascript">
function over() {
document.getElementById('content').innerHTML = "Ich hab die Maus über.";
}
function out() {
document.getElementById('content').innerHTML = "Sie ist weg.";
}
</script>
</head>
<body>
<div id="content">Inhaltsplatzhalter</div>
<div id="images">
<ul id="thumbs">
<li><a href="#"><img src="http://de.selfhtml.org/grafik/anzeige/thumbnails/thumb1.jpg" /></a></li>
<li><a href="#"><img src="http://de.selfhtml.org/grafik/anzeige/thumbnails/thumb2.jpg" /></a></li>
<li><a href="#"><img src="http://de.selfhtml.org/grafik/anzeige/thumbnails/thumb3.jpg" /></a></li>
<li><a href="#"><img src="http://de.selfhtml.org/grafik/anzeige/thumbnails/thumb4.jpg" /></a></li>
</ul>
<div id="areas" onmouseover="over()" onmouseout="out()">
<div class="area"><img src="http://de.selfhtml.org/layouts/nr03/vorlage/images/transp.gif" width="100%" height="100%" alt="" /></div>
<div class="area">XXX</div>
<div class="area"></div>
<div class="area"></div>
<div class="area"></div>
</div>
</div>
</body>
</html>
Lo!
Hallo,
(Firefox 3.0 macht es so wie ich das möchte, andere Browser hab ich (noch) nicht probiert.)
Dass die Links der Thumbs aber nicht mehr aufrufbar sind, weil #areas darüber liegt, stört nicht?
aber bekommt man es auch auf diese Weise und ohne Pseudo-Inhalt hin?
Ja, die .area müssen nur einen definierten Hintergrund abweichend von transparent haben.
.area {
float: left;
width: 84px;
height: 76px;
border: 5px solid blue;
background-image: url("http://de.selfhtml.org/layouts/nr03/vorlage/images/transp.gif");
}
viele Grüße
Axel
Hi!
(Firefox 3.0 macht es so wie ich das möchte, andere Browser hab ich (noch) nicht probiert.)
Dass die Links der Thumbs aber nicht mehr aufrufbar sind, weil #areas darüber liegt, stört nicht?
Doch schon, deswegen habe ich den Weg auch nicht weiter verfolgt, sondern nun wie angedeutet die Eventhandler auf #images gelegt und #areas ganz weggelassen. Jedoch verfolgte mich das Problem weiter. Ich lasse #thumbs über ein mit Javascript geändertes marginLeft nach links und rechts verschieben. Das soll in Abhängigkeit von der über #images positionierten Maus geschehen. #thumbs ist(/soll) durch seinen Inhalt breiter als der Viewport (sein), #images hingegen 100% vom Viewport. Das Beispiel hatte ich auf nur vier Bilder beschränkt, denn der beanstandete Effekt tritt da auch schon auf. Nun ist es auch so, dass bei bestimmten Werten von marginLeft links oder rechts keine Bilder mehr sind. Am Ende wird das nicht so sein, weil ich die Bilder "hintenrum" holen und wieder anfügen will, so dass ein endloses Band entsteht. Aber bevor ich soweit bin, war da erst einmal nichts und eben die Maus nicht mehr über #images obwohl sie innerhalb dessen Grenzen war.
Beim Nachvollziehen eben stellte ich fest, dass das Phänomen nur dann auftritt, wenn #images mit position: absolute; behandelt wird. Ohne dies füllt sich #images quasi von selbst, mit diesem hilft es nur einen (transparenten) Hintergrund zu verwenden. Oder vielleicht irgend ein anderer (unsichtbarer) Trick, der ohne zusätzlichen Request auskommt.
aber bekommt man es auch auf diese Weise und ohne Pseudo-Inhalt hin?
Ja, die .area müssen nur einen definierten Hintergrund abweichend von transparent haben.
Naja, das war im Prinzip auch nichts anderes als mein Workaround-Versuch im linken .area, nur dass dein Vorschlag den transparenten Pseudo-Inhalt in ein Hintergrundbild verlagert. Trotzdem danke ich dir für deine Antwort.
Wie auch immer. Im Grunde soll das Problem in der fertigen Lösung aufgrund des Endlosbandes gar nicht auftauchen. Es interessiert mich aber noch aus akademischen Gründen, warum der IE sich so verhält.
Anbei der geänderte Versuchsaufbau. Zum Nachvollziehen fahre man mit der Maus über den freien Bereich rechts (innerhalb von rot aber außerhalb von blau), sie ist/bleibt over. Man lasse position: absolute; wirken - weg ist sie. Und mit Hintergrundbild ist sie wieder da.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Test</title>
<style type="text/css">
a img { border-style: none; }
#images {
/* background-image: url("http://de.selfhtml.org/layouts/nr03/vorlage/images/transp.gif"); */
/* position: absolute; */
width: 800px;
border: 5px solid red;
}
#thumbs {
list-style-type: none;
margin: 0;
padding:0;
z-index: 1;
width: 480px;
border: 5px solid blue;
}
#thumbs li {
float: left;
width: 120px;
height: 96px;
}
</style>
<script type="text/javascript">
function over() {
document.getElementById('content').innerHTML = "Ich hab die Maus über.";
}
function out() {
document.getElementById('content').innerHTML = "Sie ist weg.";
}
</script>
</head>
<body>
<div id="content">Inhaltsplatzhalter</div>
<div id="images" onmouseover="over()" onmouseout="out()">
<ul id="thumbs">
<li><a href="#"><img src="http://de.selfhtml.org/grafik/anzeige/thumbnails/thumb1.jpg" /></a></li>
<li><a href="#"><img src="http://de.selfhtml.org/grafik/anzeige/thumbnails/thumb2.jpg" /></a></li>
<li><a href="#"><img src="http://de.selfhtml.org/grafik/anzeige/thumbnails/thumb3.jpg" /></a></li>
<li><a href="#"><img src="http://de.selfhtml.org/grafik/anzeige/thumbnails/thumb4.jpg" /></a></li>
</ul>
</div>
</body>
</html>
Lo!
Hallo,
Es interessiert mich aber noch aus akademischen Gründen, warum der IE sich so verhält.
*g* Weil seine rendering engine im Zusammenhang mit JavaScript so programmiert ist.
Da MS den IE nicht quelloffen legt, kann man das allerdimgs nicht wirklich genau prüfen. Es sieht so aus als ob sichergestellt werden soll, dass JavaScript mouseover immer das Eelment trifft, welches unter der Mausposition tatsächlich _zu sehen_ ist.
Immer wenn sich Elemente überlappen und transparent sind, wird mouseout/mousover auch dann gefeuert, wenn ein Teil eines überlappten Elements, welcher eigentlich im Hintergrund liegt, aber sichtbar ist, unter der Maus steht. Das trifft auch für ein Element mit position:absolute zu, welches scheinbar nichts überlappt, denn es überlappt ja das HTML-Element.
Testcase:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>IE mouseover/out bei überlappenden Elementen</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<style type="text/css">
#d1 {
width: 100px;
height: 100px;
border: 20px solid red;
}
#d2, #d4 {
position: absolute;
width: 100px;
height: 100px;
border: 20px solid green;
}
#d3 {
position: relative;
left: 50px;
top: -50px;
width: 100px;
height: 100px;
border: 20px solid blue;
}
</style>
</head>
<body>
<div id="monitor">Monitor</div>
<div id="d1" onmouseover="document.getElementById('monitor').innerHTML='over '+this.id" onmouseout="document.getElementById('monitor').innerHTML='out '+this.id"></div>
<div id="d2" onmouseover="document.getElementById('monitor').innerHTML='over '+this.id" onmouseout="document.getElementById('monitor').innerHTML='out '+this.id"></div>
<div id="d3" onmouseover="document.getElementById('monitor').innerHTML='over '+this.id" onmouseout="document.getElementById('monitor').innerHTML='out '+this.id"></div>
<div id="d4" onmouseover="document.getElementById('monitor').innerHTML='over '+this.id" onmouseout="document.getElementById('monitor').innerHTML='out '+this.id"></div>
</body>
</html>
viele Grüße
Axel
Hi!
Es interessiert mich aber noch aus akademischen Gründen, warum der IE sich so verhält.
*g* Weil seine rendering engine im Zusammenhang mit JavaScript so programmiert ist.
Das erklärt natürlich alles :-)
Testcase:
Der verhält sich für mich nicht erklärbar.
d1 ist im normalen Elementefluss und die Maus over.
d2 und d4 sind beide absolute positioniert, bei d2 ist sie over, bei d4 nicht. Und es ändert auch nichts daran, wenn man d3 über d2 und d4 statt d1 und d2 schiebt sowie einen z-index: 2 hinzufügt, damit es über beiden liegt.
d3 verhält sich noch eigenwilliger. Liegt es über d1 und d2, so ist man over, es sei denn, man ist über dem in d3 liegenden und sichtbaren Teil der Ränder von d1 oder d2.
Schiebt man d3 nach unten (plus z-index) über d2 und d4, so das sich in d3 drei weiße Flächen ergeben (oben, unten und rechts), so ist man sowohl rechts als auch oben (also in d2) über d3, unten jedoch über gar nichts (vom d3-Rand kommend: out d3, vom d4-Rand kommend: out d4).
Ich gebe es auf, dieses unterschiedliche Verhalten verstehen zu wollen.
Lo!