position:fixed-fähige Browser erkennen
molily
- dhtml
Hallo zusammen,
In http://forum.de.selfhtml.org/archiv/2002/11/29991/ stellte ich den Artikel http://home.t-online.de/home/dj5nu/css-position-fixed.html vor, in welchem Workarounds für die Verwendung von position:fixed und Ankern diskutiert werden. Ich kam bezüglich der JavaScript-Lösung, welche an alle dokumentinternen Anker ein zusätzliches onclick mit einem window.scrollBy()-Aufruf vergibt, zu der Konklusion, dass eine möglichst serverseitige Abfrage nötig ist, welche den entsprechenden Funktionsaufruf nur einbinden darf, wenn der Benutzer einen Browser verwendet, welcher bekannt dafür ist, position:fixed zu unterstützen (siehe zweiter Absatz von "Nachteile der JavaScript-Lösungen").
Orlando kommentierte dazu:
Deine Schlussfolgerung, dass man serverseitig den Client ermitteln muss, um zu entscheiden, ob man die JS-Lösung einsetzen kann, oder nicht, kann ich nicht so recht nachvollziehen. Da du position:fixed ohnehin per Selektor einbindest (und das musst du ja), kannst du natürlich per DOM herausfinden, ob es der Browser gefunden hat, oder nicht.
Ich entgegnete:
Daran dachte ich auch schon. [...] Zwischen "der Browser interpretiert Kindselektoren" und "der Browser unterstützt position:fixed" beziehungsweise "der Browser wendet es erfolgreich an" [...] besteht meiner Vermutung nach keine zuverlässige Verbindung...
Weiterhin schlug Orlando vor:
if(document.getElementById("header").style.position == "fixed") { ...
Auf die Idee bin ich natürlich nicht gekommen, beziehungsweise ich hielt sie nicht für sehr zuverlässig, ich dachte eher daran, die top- oder left-Parameter abzufragen, sozusagen der "computed value"... oder so, da müsste es doch irgendwo ein Unterscheidungskriterium geben. Das ist aber auf den zweiten Blick Kappes.
Tatsächlich nützt es nichts, die Objekteigenschaft style.position abzufragen, sie ist entweder leer oder undefined: IE 6: leer, Opera 6.05: undefined, Opera 7: leer, Mozilla 1.2: leer.
Der Stylesheet dazu ist natürlich:
#murks {position:absolute; ...}
body > #murks {position:fixed;}
Nun habe ich versucht, den Wert zusätzlich zum Stylesheet festzulegen, um danach zu prüfen, ob er angenommen wurde:
document.getElementById('murks').style.position='fixed';
Danach lässt sich der Wert über document.getElementById('murks').style.position abrufen, jedoch interpretiert es MSIE als static (weil unbekannt), gibt aber dennoch fixed zurück. Somit ist diese Prüfung unnütz.
Wie ich vorhersagte, wäre die einzig sichere Methode getComputedStyle(), wobei dies nur von Gecko/Mozilla unterstützt wird (nicht Opera 7 :-/ ), somit kommt es für die Abfrage, ob der Browser position:fixed unterstützt, momentan nicht in Frage.
if (document.defaultView.getComputedStyle(document.getElementById('murks'), null).getPropertyValue('position')=='fixed') { ...
Das bringt mich in eine Zwickmühle, denn ich stimme Orlando im Grunde zu und würde in jedem Falle eine komplexe Browserabfrage vermeiden wollen, beziehungsweise die Empfehlung an den Leser, diese zu entwickeln.
Weitere Möglichkeiten fallen mir nicht ein, also muss anscheinend tatsächlich ein stupides Abfragen des User-Agent-Headers her... Sachdienliche Hinweise[tm] sind gewünscht.
Grüße,
Mathias
Hallo,
Weitere Möglichkeiten fallen mir nicht ein, also muss anscheinend tatsächlich ein stupides Abfragen des User-Agent-Headers her... Sachdienliche Hinweise[tm] sind gewünscht.
Spontan faellt mir der Vergleich von object.style.top mit object.offsetHeight oder object.style.left mit object.offsetLeft ein:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Test by TM 11/02</title>
</head>
<body>
<div style="position: fixed; top: 100px; left: 50px; width: 150px; height: 80px; color: #00C; background-color: #FFC" onclick="if(parseInt(this.style.top)==this.offsetTop)alert('position: fixed funktioniert.');else alert('position: fixed funktioniert nicht.')">
[Klick mich!]
</div>
</body>
</html>
Opera und Mozilla sagen ok, der IE(6) meint nein.
MfG, Thomas
Hallo, Thomas,
Spontan faellt mir der Vergleich von object.style.top mit object.offsetHeight oder object.style.left mit object.offsetLeft ein:
Es um Bereiche geht, welche sich am obersten Bildrand befinden, das heißt, sie befindet sich in jedem Fall bei top:0 und left:0 beziehungsweise right:0, unabhängig davon, ob position:absolute oder position:fixed.
Wenn ich richtig schlussfolgere, dürften dadurch auch in einem Browser, welcher position:fixed nicht kann, offset(Top|Left) und style.(top|left) gleich sein, da dieser position:absolute anzeigen sollte (siehe Selektorkonstrukt).
<div style="position: fixed; top: 100px; left: 50px; width: 150px; height: 80px; color: #00C; background-color: #FFC" onclick="if(parseInt(this.style.top)==this.offsetTop)alert('position: fixed funktioniert.');else alert('position: fixed funktioniert nicht.')">[Klick mich!]</div>
Opera und Mozilla sagen ok, der IE(6) meint nein.
Das Komische beziehungsweise mir bisher Unbekannte ist, dass sich objekt.style.top nur abfragen lässt, wenn es im style-Attribut vergeben wurde. Wenn es im vom Markup getrennten Styles festgelegt wird, ist die Objekteigenschaft leer.
Es ist jedoch unbedingt nötig ist, dass die Styles in einem dokumentweiten Stylesheet festgelegt werden, da wie Orlando sagte den Kindselektor verwenden muss, um position:fixed vor dem Internet Explorer zu verstecken.
Das allerkurioseste ist, dass Opera 6.05 den Wert liefert...
Stylesheet Wert von objekt.style.top
Opera 6.05 Inline vorhanden
Opera 6.05 global vorhanden
Opera 7 beta 1b Inline vorhanden
Opera 7 beta 1b global nicht vorhanden
Mozilla 1.2 final Inline vorhanden
Mozilla 1.2 final global nicht vorhanden
MSIE 6.0 SP1* Inline vorhanden
MSIE 6.0 SP1* global nicht vorhanden
* Plus ein paar Zerquetschte[tm] (Sicherheitsupdates), welche nicht ins Gewicht fallen dürften.
Eine Testseite gibt es unter http://home.t-online.de/home/dj5nu/fanhost/css-fixed.html...
Alles in allem hilft mir das wenig weiter - vielleicht hast du noch eine ähnliche Idee. Trotzdem vielen Dank.
Kann mir jemand erklären, wie der standardisierte Weg ist, den "computed value" des Abstands zum Fensteroberrand zu bestimmen? offset* ist anscheinend Microsoft-Syntax, wird aber breit unterstützt, und die genannte DOM-Variante unterstützt kein Browser. (Meine Informationen beruhen nur auf Selfhtml, ich habe mich nie umfassend in DHTML eingearbeitet...) Wieso lässt sich über objekt.style.position nicht der momentane Wert bestimmen, ist das beabsichtigt? Ich frage mich, wieso Opera 7 die Abfrage bei globalen Stylesheets im Gegensatz zu Inline-Styles neuerdings unterbindet, erfordert das der Standard?
Grüße,
Mathias
Hallo Mathias,
Das Komische beziehungsweise mir bisher Unbekannte ist, dass sich objekt.style.top nur abfragen lässt, wenn es im style-Attribut vergeben wurde. Wenn es im vom Markup getrennten Styles festgelegt wird, ist die Objekteigenschaft leer.
FYI: Der Konqueror 3.0.3 machts genauso falsch... :-(
Grüße,
Christian
Hallo,
Es um Bereiche geht, welche sich am obersten Bildrand befinden, das heißt, sie befindet sich in jedem Fall bei top:0 und left:0 beziehungsweise right:0, unabhängig davon, ob position:absolute oder position:fixed.
Wenn ich richtig schlussfolgere, dürften dadurch auch in einem Browser, welcher position:fixed nicht kann, offset(Top|Left) und style.(top|left) gleich sein, da dieser position:absolute anzeigen sollte (siehe Selektorkonstrukt).
Wenn fuer body margin: 0; festgelegt wurde, dann sieht es schlecht aus, mit gleichzeitigem position: absolute; des DIVs natuerlich auch.
Das Komische beziehungsweise mir bisher Unbekannte ist, dass sich objekt.style.top nur abfragen lässt, wenn es im style-Attribut vergeben wurde. Wenn es im vom Markup getrennten Styles festgelegt wird, ist die Objekteigenschaft leer.
Wenn im ersten (internen oder externen) CSS dem DIV eine Klasse bzw. ID test bekannt gemacht wurde, dann kann man Eigenschaften auch so abfragen [bzw. mit parseInt() drumherum]:
IE:
document.styleSheets.item(0).rules.item('test').style.top
Mozilla:
document.styleSheets.item(0).cssRules.item('test').style.top
Opera(7) kennt offenbar beides nicht ...
MfG, Thomas
Hallo, Thomas,
ich fasse mich kurz, da Opera Lust dazu hatte, sich aufzuhängen, während ich das Posting schrieb.
IE:
document.styleSheets.item(0).rules.item('test').style.topMozilla:
document.styleSheets.item(0).cssRules.item('test').style.top
Das hilft mir indirekt weiter, denn ich habe ein wenig in den Specs http://www.w3.org/TR/DOM-Level-2-Style/ gewühlt (ohne sie komplett zu verstehen) und bin auf selectorText gestoßen und damit auf das erste sichere Unterscheidungsmerkmal. Angenommen die zweite Styledeklaration ist body > #murks {position:fixed;} (siehe Ausgangsposting), liefert MSIE nur UNKNOWN, da dieser den Selektor nicht versteht, Mozilla hingegen liefert den richtigen Selektor. Ein Beispiel:
if (document.all)
alert(document.styleSheets.item(0).rules.item(1).selectorText);
else
alert(document.styleSheets.item(0).cssRules.item(1).selectorText);
Insgesamt bringt mich das aber nicht weiter, da diese Überprüfung nur bei MSIE vermutlich Version >=5.5 oder gar erst 6 und Mozilla möglich ist (> Netscape 6?).
Es ist offensichtlich in jedem Fall eine auf dem User-Agent basierende Selektion nötig... urg, und zwar nach Version. Also lag ich mit meiner ursprünglichen Annahme nicht falsch.
Mathias
Hallo,
Das hilft mir indirekt weiter, denn ich habe ein wenig in den Specs http://www.w3.org/TR/DOM-Level-2-Style/ gewühlt (ohne sie komplett zu verstehen) und bin auf selectorText gestoßen und damit auf das erste sichere Unterscheidungsmerkmal.
Dazu habe ich auch mal ein Beispiel gebracht: http://forum.de.selfhtml.org/archiv/2002/10/27842/#m151724.
Es ist offensichtlich in jedem Fall eine auf dem User-Agent basierende Selektion nötig... urg, und zwar nach Version. Also lag ich mit meiner ursprünglichen Annahme nicht falsch.
Das war wohl zu erwarten. Allerdings verstehe ich diesen K(r)ampf mit position: fixed nicht so richtig. Wenn das Browser nicht kennen, dann ist das doch fuer die Besucher kein Problem oder vielleicht sogar von Vorteil (IMHO) ...
MfG, Thomas