derkps: Scrollbalken, position

Hallo,

der Scrollbalken startet immer oben und kann dann nach unten verschoben werden.

.scollen {
  height: 400px;
  overflow-y: scroll;
}

Wie erreiche ich, dass er in der Mitte startet und dann nach oben/unten verschoben werden kann?

vG derkps

  1. @@derkps

    Wie erreiche ich, dass er in der Mitte startet und dann nach oben/unten verschoben werden kann?

    Was soll die Mitte sein? Die Mitte der Seitenhöhe? Dann kannst du per JavaScript dorthin scrollen:

    window.scrollTo({
    	top: (document.documentElement.offsetHeight - window.innerHeight)/2,
    });
    
    

    Oder ein bestimmtes Element, das sich in der Mitte der Seite befindet und eine ID (bspw. id="middle") hat?

    Dann kommst du per location.hash = 'middle'; dorthin. Oder ohne JavaScript, wenn du gleich dorthin verlinkst: https://example.net/path#middle.

    ☞ Beispiel

    Kwakoni Yiquan

    --
    Ad astra per aspera
    1. Hi,

      Wie erreiche ich, dass er in der Mitte startet und dann nach oben/unten verschoben werden kann?

      Was soll die Mitte sein? Die Mitte der Seitenhöhe? Dann kannst du per JavaScript dorthin scrollen:

      Aufgrund der Tatsache, daß derkps eine Klasse verwendet, vermute ich, daß er mehrere scrollbare Bereiche auf seiner Seite haben will - und da soll sich vermutlich die Mitte des jeweiligen Inhalts im sichtbaren Bereich befinden.

      cu,
      Andreas a/k/a MudGuard

  2. Hallo, ich habe mein Anliegen nicht gut formuliert, sorry! Hier ein Link http://test.derkps.de/

    Es gibt einen Beitrag mit <iframe> und einem über großen Bild. Das ist gesetzt!

    <div class="scroll"><iframe src="/images/stories/eslohe.jpg" width="3000px" height="925px"></iframe></div>
    
    

    Die Klasse "scroll" setzt Scroll-Bars

    .scroll {
        height: 300px;
        overflow-y: scroll;
        width: 1000px;
        overflow-x: scroll;
        }
    

    Gewünscht ist, dass der Scroll-Bar in der Mitte steht und nicht in der Ecke.

    Ich arbeite mit Joomla, in css scheint es nichts zu geben und im Browser kann ich den scroll-container nicht identifizieren.

    vG

    1. Hi,

      Es gibt einen Beitrag mit <iframe> und einem über großen Bild. Das ist gesetzt!

      <div class="scroll"><iframe src="/images/stories/eslohe.jpg" width="3000px" height="925px"></iframe></div>
      
      

      Du packst also ein Element, das an sich schon Scrollbalken anbietet, in ein weiteres Element, um dort Scrollbalken anzubieten?

      cu,
      Andreas a/k/a MudGuard

    2. Hallo derkps,

      Es gibt einen Beitrag mit <iframe> und einem über großen Bild. Das ist gesetzt!

      Magst Du uns erläutern, warum das gesetzt ist? Nur damit wir ausschließen können, in die XY-Problem-Falle getappt zu sein.

      Denn für das Beispiel ist der iframe überhaupt nicht nötig. Der ist genau so groß wie das Bild, d.h. man könnte das Bild auch direkt in den Scrollcontainer setzen. Rechtfertigung für den iframe kann sein, dass statt des Bildes ein HTML Dokument gezeigt werden soll - aber dann hast Du ganz andere Probleme, weil die Höhe dieses Dokuments nicht a priori bestimmbar ist.

      Aber nehmen wir mal an, es ginge nicht anders.

      in css scheint es nichts zu geben

      Wenn der Scoll-Container nur dazu da ist, den mittleren Ausschnitt herauszufinden und nicht, um nachher auch zu scrollen, gäbe es schon Möglichkeiten (transforms oder margin). Wenn Du wirklich scrollen können willst und eine anfängliche Scrollposition setzen musst, dann brauchst Du JavaScript.

      und im Browser kann ich den scroll-container nicht identifizieren.

      Nimm querySelector. Wenn Du nicht weißt, was CSS Kombinatoren sind, folge dem Link in unser Wiki.

      Wichtig: Der iframe braucht noch ein display:block ODER ein vertical-align:bottom, andernfalls lässt der Browser darunter ein paar Pixel für Unterlängen frei. Das äußert sich bei mir darin, dass die scrollHeight des div.scroll 931px beträgt und nicht die 925px des iframe.

      Wenn das gefixt ist, kann man die Scrollposition auf diese Weise setzen (was Gunnar eigentlich schon geschrieben hatte):

      const scrollFrame = document.querySelector(".com-content-article__body .scroll");
      const y_excess = scrollFrame.scrollHeight - scrollFrame.clientHeight;
      const x_excess = scrollFrame.scrollWidth - scrollFrame.clientWidth;
      scrollFrame.scrollTo(x_excess/2, y_excess/2);
      

      querySelector(".com-content-article__body .scroll") sucht ein Element mit der Klasse com-content-article__body und darin ein Element mit der Klasse scroll.

      scrollWidth/scrollHeight ist die Größe des gescrollten Inhalts, also des iframes. clientWidth/clientHeight ist die Größe des sichtbaren Bereichs, also die Größe von div.scroll minus die Scrollbalken. Damit ist y_excess und x_excess der Größenüberschuss des Inhaltes. Teilt man den durch 2, weiß man, wieviel vom Größenüberschuss an jede Seite muss, und das kann man als Scrollposition verwenden. scrollTo() kann man in 2 Varianten aufrufen. Entweder mit einem Objekt als Argument wie bei Gunnar - dann kann man auch sanft scrollen, oder einfach mit den Koordinaten für linke obere Ecke des gewünschten Ausschnitts.

      Wenn Du nur vertikal zentrieren willst, brauchst Du x_excess nicht und kannst scrollTo dort eine 0 übergeben. Aber wenn doch, weißt Du jetzt, wie man auch horizontal in die Mitte scrollt.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. problematische Seite

        Hallo, in der Endversion wird ein 'panorama.svg' benutzt und das bedingt ein iframe. Vorerst nur ein breites 'panorama.jpg' mit overflow-x auf SEITE1 Das beiläufige overflow-y mit langem Beitrag habe ich jetzt auf SEITE2 gesetzt.

        Vorhandener JS-Code funktioniert in einer user.js Datei. Z.B.

        HTML
        <div><button id="goBack"> <img src="images/stories/module/zurueck01.jpg" alt="zurück" /> </button></div>
        
        JS
        document.addEventListener("DOMContentLoaded", function() { 
            if (document.getElementById("goBack")) { 
              document.getElementById("goBack").addEventListener("click", Back);
            }
          }
        );
        function Back() {
           window.history.back();
        }
        

        Für SEITE2 benutze ich aktuell

        JS
        window.scrollTo({
        	top: (document.documentElement.offsetHeight - window.innerHeight)/2,
        });
        

        Es zeigt keine Wirkung und ich verstehe auch nicht, wie der Code der SEITE2 zugeordnet wird. 'window' gilt doch für alle, auch ohne y-overflow.

        Für SEITE1 benutze ich aktuell

        HTML
        <div class="scroll"><iframe src="/images/stories/seiten/panorama.jpg" width="3000px" height="400px"></iframe></div>
        
        CSS
        .scroll {
          width: 1500px;
          overflow-x: scroll;
        }
        
        JS
        window.scrollTo (
        const scrollFrame = document.querySelector(".com-content-article__body .scroll");
        const y_excess = scrollFrame.scrollHeight - scrollFrame.clientHeight;
        const x_excess = scrollFrame.scrollWidth - scrollFrame.clientWidth;
        scrollFrame.scrollTo(x_excess/2, y_excess/2);
        );
        

        Es zeigt keine Wirkung und ich verstehe auch nicht, wie der Code der SEITE1 zugeordnet wird. Über die Klasse '.scroll'? Und 'scrollFrame' bezieht sich immer auf das iframe?

        Ich habe von 20Jahre mal ernsthaft mit JS gearbeitet, da ist vieles weg 😞 VG

        1. problematische Seite

          Hallo derkps,

          Hallo, in der Endversion wird ein 'panorama.svg' benutzt und das bedingt ein iframe.

          Öhm. Warum? Welches Problem verursacht <img src="panorama.svg" alt="Panorama von Hengasch"> an Stelle eine iframe?

          Es zeigt keine Wirkung

          Weil du einen Syntaxerror drin hast, der zum Abbruch des Scripts führt.

          Verwende die Entwicklerwerkzeuge des Browsers, da steht's in rot geschrieben!

          Dein Code hat einen Kopierrest, der weg muss. Es sieht so aus, als wolltest Du für Seite 1 window.scrollTo aufrufen. In den Funktionsklammern dieses Aufrufs sollten dann zwei Zahlen folgen (bzw. zwei Variablen mit diesen Zahlen drin). Aber statt dessen folgen Anweisungen. Das ist syntaktisch falsch.

          Wenn Du auf Seite 1 mit scrollFrame.scrollTo arbeiten willst, dann nimm diesen Überrest von window.scrollTo weg (Zeile 2 und Zeile 7)

          Zweitens: Dein CMS lädt die user.js im <head> Bereich der Seite. Es ist eine BLÖDE Eigenschaft der Browser, bei Antreffen eines script-Elements erstmal anzuhalten, das Script zu laden, auszuführen und dann erst die Seite weiter aufzubauen. Heißt: document.querySelector(".com-content-article__body .scroll") greift ins Leere, weil der Body noch gar nicht aufgebaut ist.

          Der nachfolgende Code, der eine vorhandene Browserfunktionalität sinnlos nachbaut (der goBack-Button), zeigt Dir eine Lösungsmöglichkeit: Ein DOMContentLoaded Eventhandler. Der Code, der in der Funktion steht, die da als Eventhandler registriert wird, läuft dann, wenn das HTML der Seite fertig verarbeitet ist (Bilder sind eventuell noch nicht geladen).

          Eine andere Möglichkeit wäre, dem <script> Element das defer-Attribut zu geben, aber ich weiß nicht, ob dein CMS dir das ermöglicht. Scripte mit defer laufen direkt vor den Funktionen, die für DOMContentLoaded registriert sind.

          ich verstehe auch nicht, wie der Code der SEITE1 zugeordnet wird.
          ich verstehe auch nicht, wie der Code der SEITE2 zugeordnet wird.

          Kannst Du auch nicht verstehen. Weil es keine Zuordnung gibt.

          Es ist ja nett, dass Du JavaScript mit Kommentaren mitteilen möchtest, dass manche Codeteile für Seite 1 und andere Codeteile für Seite 2 gelten sollen. Aber das ist JavaScript total schnuppe, es führt stur alles aus, was nach richtigem Code aussieht.

          Wenn Du möchtest, dass ein Teil Code nur auf Seite 1 läuft und ein anderer Teil Code nur auf Seite 2, dann musst Du entweder für Seite 1 und Seite 2 getrennte .js Dateien vorsehen, oder Du musst ein Merkmal der Seite finden, woran Du erkennen kannst, ob Seite 1 oder Seite 2 geladen ist. Dieses Merkmal kannst Du abfragen, und damit erreichen, dass Code für Seite 1 nur auf Seite 1 läuft, und entsprechend für Seite 2. In deiner Demo könntest Du beispielsweise location.pathname verwenden, da steht der Teil der URL drin, der auf deinem Server liegt (also z.B. '/ueber-mich'. Alternativ kannst Du auch mit querySelector schauen, ob bestimmte Seitenelemente vorhanden sind. Für Seite 1 könntest Du abfragen, ob der querySelector was gefunden hat (d.h. ob in scrollFrame was drinsteht), und nur dann die Zentrierung machen.

          So in etwa:

          const scrollFrame = document.querySelector(...);
          if (scrollFrame) {
             const excess_y = ...
             scrollFrame.scrollTo...
          }
          

          Auf Seite 2 ist so wenig spezifisches, da muss wohl tatsächlich der pathname ran. Oder deine reale Seite bietet bessere Möglichkeiten, keine Ahnung, die kenne ich ja nicht.

          Ich habe von 20Jahre mal ernsthaft mit JS gearbeitet, da ist vieles weg

          Offensichtlich, und vor 20 Jahren gab's vieles von dem, was heute üblich ist, noch gar nicht. Statt DOMContentLoaded hast Du damals das load-Event nehmen müssen, meine ich, und für EventListener musste man zwischen IE und Rest der Welt unterscheiden. Weshalb jQuery auch damals so erfolgreich war. Heute ist das meiste standardisiert.

          Aber auch damals galt: wenn Code nur auf der Seite X laufen soll, dann darf er entweder nur dort geladen werden, oder er muss prüfen, ob Seite X gerade vorhanden ist.

          Und damals galt auch schon: Bau nicht nach, was der Browser eh schon kann. Einen Back-Button zu bauen, der einfach in der History zurück geht, ist sinnfrei. Es gibt Formularketten, bei denen man das Zurückgehen in der History ausdrücklich verhindern will (weil man sonst am Server durchdreht) und dem User sagt: Verwende unbedingt die "Zurück" und "Weiter" Buttons. Diese führen dann aber auch als Form-Elemente oder Links auf entsprechende Seiten und verwenden nicht die History.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Vielen Dank für die Erläuterungen.