molily: position:fixed-fähige Browser erkennen

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

--
Remember: KING KONG Died For Your Sins!
"ich belle ich fauche ich keife ich röchle ich knurre ich schreie ich wimmer ich bibber ich zitter ich ICH!"
Naïve Nonsens-Poesïe http://home.t-online.de/home/dj5nu/lit-nonsens.html
  1. 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

    1. 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

      --
      Remember: KING KONG Died For Your Sins!
      "ich belle ich fauche ich keife ich röchle ich knurre ich schreie ich wimmer ich bibber ich zitter ich ICH!"
      Naïve Nonsens-Poesïe http://home.t-online.de/home/dj5nu/lit-nonsens.html
      1. 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

        --
        Sollen sich alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen und nicht mehr davon erfasst haben als eine Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst.
                              -- Albert Einstein
      2. 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

        1. 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.top

          Mozilla:
          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

          --
          Remember: KING KONG Died For Your Sins!
          "ich belle ich fauche ich keife ich röchle ich knurre ich schreie ich wimmer ich bibber ich zitter ich ICH!"
          Naïve Nonsens-Poesïe http://home.t-online.de/home/dj5nu/lit-nonsens.html
          1. 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