uwe: Höhe eines Elements abfragen und ändern

Hallo,

es kann noch nicht so schwer sein, die Höhe eines Elements um einen bestimmten Wert zu ändern, oder?

Bisher finde ich nur diese eine Möglichkeit, um die Höhe eines Elements zu setzen:

Element.style.height = 100 + 'px'; 

Um die Höhe eines Elements nun um bspw. 100px zu erhöhen, muss erst die aktuelle Höhe des Elements ermittelt werden, um dann die 100px hinzu addieren zu können.

Element.style.height = AktuelleHöhe + 100 + 'px'; 

Aber wie kommt man an die aktuelle Höhe? Die erste Idee wäre style.height auszulesen:

AktuelleHöhe = Element.style.height; 

Das funktioniert jedoch nicht richtig. Bei Elementen, die per Klasse formatiert sind, liefert diese Abfrage keinen Wert.

AktuelleHöhe = Element.scrollHeight;

Liefert einen Wert. Dieser ist jedoch unbrauchbar, da er zusätzlich zur Höhe auch noch die Größe es inneren Abstands enthält.
Alle anderen von mit versuchten Abfragen liefern ebenfalls nicht die reine Höhe.

Beispiel:

<html>
<head>

<style>

 .style1,
 .style2 { padding: 10px; border: 2px solid black; width: 200px; }

 .style1 { height: 50px; }

</style>

</head>
<body>

  <div class="style1" id="box1"                      >Box 1</div>
  <div class="style2" id="box2" style="height: 60px;">Box 2</div>

  <button id="werte">Werte anzeigen</button>

<script>
  document.querySelector('#werte').addEventListener('click',werte_anzeigen);

  function werte_anzeigen() {
    box1 = document.getElementById("box1");
    box2 = document.getElementById("box2");

    werte = '';
    werte += 'box1 - style.height: ' + box1.style.height + '\n';
    werte += 'box2 - style.height: ' + box2.style.height + '\n';

    werte += 'box1 - offset: ' + box1.offsetHeight + '\n';
    werte += 'box1 - scroll: ' + box1.scrollHeight + '\n';
    werte += 'box1 - client: ' + box1.clientHeight + '\n';
    werte += 'box1 - bound : ' + box1.getBoundingClientRect().height;

    alert(werte);
}
</script>

</body>
</html>

Nur box2.style.height liefert einen Wert, da height direkt im Element angegeben wurde.

box1.style.height bleibt dagegen leer.

Keines der Abfragen für box1 liefert den benötigten Wert 50px. Der ist aber nötig, um diesen dann mit +100 in box1.style.height schreiben zu können, um die box1 um genau 100px in der Höhe vergrößern zu können.

box1.scrollHeight = box1.scrollHeight + 100 oder ähnliches funktioniert leider nicht.

Was übersehe ich, wie kann man die 50px auslesen und dann 100px dazu addieren, wenn ein Element per class formatiert ist und keine direkte style Formatierung enthält?

Vielen Dank.

uwe

  1. Hallo uwe,

    es kann noch nicht so schwer sein, die Höhe eines Elements um einen bestimmten Wert zu ändern, oder?

    Je nach Ausgangsposition ist es einfacher oder schwerer.

    Zu den verfügbarern Quellen:

    element.clientHeight
    Integerwert in Pixeln. Es ist der Innenbereich eines Elements, inklusive Padding, aber ohne einen eventuellen Scrollbar. Eine Eigenschaft für die reine Innenhöhe ohne Padding kenne ich gar nicht.
    element.offsetHeight
    Integerwert in Pixeln. Es ist clientHeight plus Breite von top- und bottom-border, und der Höhe eines eventuell vorhandenen Scrollbars.
    element.scrollHeight
    Integerwert in Pixeln. Es ist die Höhe des Element-Inhalts. Der kann höher als das Element sein.
    element.style.height
    Zeichenkette als 1:1 Abbild der height-Eigenschaft im style-Attribut. Liefert den Wert des height-Attributs, der im style-Attribut des Element gesetzt wurde. Die Einheit kann hier alles mögliche sein - px, em, vh, %. Wenn Du im style-Element mit calc() gearbeitet hast, bekommst Du den calc-Ausdruck, nicht dessen Ergebnis!
    cStyle = window.getComputedStyle(element)
    Liefert ein style-Objekt mit den aktuellen, vom Browser errechneten Werten. Ein calc-Ausdruck wurde ausgerechnet. Die Einheit von height ist hier px.

    Was Du dort an height findest, entspricht dem clientHeight-Wert, wenn box-sizing auf content-box steht (dem Default), und dem offsetHeight-Wert, wenn box-sizing auf border-box steht. Brrrr.

    Aber damit kannst Du arbeiten. Denn genau diesen height-Wert musst Du anpassen, um ihn dann am Element-Style zu setzen.

    Umständlich daran ist, dass die height-Werte die Einheit enthalten. Die musst Du erstmal abtrennen, den neuen Betrag ausrechnen und dann die Einheit wieder ankleben. Und das Rechnen wird deutlich umständlicher, wenn die Einheit nicht in px gegeben ist. Sondern in %. Oder em. Oder vh. Die Houdini-Erweiterungen von CSS bieten hier einige Hilfsfunktionen an, die Dir den Umgang mit einheitenbehafteten Werten erleichtern, aber wenn Du die verwendest, schließt Du im Moment noch den Firefox aus.

    Es könnte einfachere Lösungen für Dein Problem geben. aber dazu müsstest Du verraten, was Du mit deinen Höhenveränderungen eigentlich bezweckst. Vielleicht kann der Browser das, was Du willst, bereits von ganz alleine, wenn man ihn nur lieb danach fragt.

    Ich denke da an Grid, Flexbox, calc-Ausdrücke, Custom Propertys - irgendwas könnte vielleicht dein Leben erleichtern.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      vielen Dank für Deine ausführliche Hilfe.

      box-sizing: border-box; hab ich inzwischen auch gefunden. Habs noch nicht ausprobiert, aber damit passen wohl element.offsetHeight und element.style.height zusammen.

      Nebenbei bleibt da aber noch die Frage, wie sich grundsätzlich style Eingenschaften auslesen lassen, die per Klasse definiert wurden. element.style.height kann scheinbar nur den Text aus dem style-Attribut des Elemenst auslesen.

      <style> .style1 { height: 50%; } </style>
      <div class="style1" id="box1">Box 1</div>
      

      Wie kommt man hier ausgehend von document.getElementById("box1"); an "height: 50%"? Oder ist das gar nicht vorgesehen?

      Sehe, daß man mit element.className zumindest den Klassenname auslesen kann. Aber wie kommt man dann von da aus weiter zu "height: 50%"?
      Und wie ist das bei komplexen CSS Struckturen. Wie finden man heraus, was letztlich gültigt ist?

      Mir get es weniger um eine öffentliche Webseite, sondern um eine interne Anwendung, wo der Benutzer die einzelnen Anzeigebereiche innerhalb des Browserfensters flexibel verschieben kann. Bspw. so wie man in Tabellen die Spalten und Zeilen verschieben kann. So wie man in xls die obere Eingabezeile einfach in der Höhe ändern kann. Wenn ich mich recht erinnere, funktionierte das früher beim <frameset> Element automatisch.

      Gruß
      uwe

      1. Hallo uwe,

        wie sich grundsätzlich style Eingenschaften auslesen lassen, die per Klasse definiert wurden

        Schrieb ich doch: getComputedStyle. Damit kriegst Du den Wert, der nach Anwendung aller Styles gilt.

        Wenn Du die CSS Regeln finden willst, die für ein bestimmtes Element gelten, und dort die gesetzten Eigenschaften auslesen - lass es. Lass den Browser die Styles integrieren.

        Wenn Du so etwas wie Split-Panels realisieren willst, bau Deine Seite als Grid auf, setze ein schmales Element als Split-Mover in die Lücke und verschiebe das an Hand seiner Position (offsetLeft/offsetTop). An Hand der Elementposition konfigurierst Du dann die Spalten oder Zeilen des Grid um. Ich bin gerade nicht wirklich online und kann kein Beispiel machen…

        Aber Grid ist deutlich einfacher als alle betroffenen Element von Hand zu resizen und zu platzieren.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Hallo Rolf,

          getComputedStyle gibt nur den berechneten aktuellen Wert in Pixel wieder, nicht bspw. 10%.

          Ok, werd mich dann mal mit Grid beschäften.

          Vielen Dank.
          uwe

          1. Hallo Uwe,

            getComputedStyle gibt nur den berechneten aktuellen Wert in Pixel wieder, nicht bspw. 10%.

            Ja. Was bis jetzt nicht angesprochen wurde: In einem Stylesheet können mehrere CSS-Regelsätze auf ein Element wirken. Gerade bei Prozentwerten musst du ja neben dem Prozentwert auch den oder die Ausgangswerte kennen/berücksichtigen.

            im SELF-Wiki:

            Ok, werd mich dann mal mit Grid beschäften.

            Das ist sehr interessant:

            Herzliche Grüße

            Matthias Scharwies

            --
            Eigentlich hatte ich heute viel vor - jetzt habe ich morgen viel vor!
      2. Hallo uwe,

        Wie kommt man hier ausgehend von document.getElementById("box1"); an "height: 50%"? Oder ist das gar nicht vorgesehen?

        Gestern abend hatte ich nicht so viel Zeit.

        Nein, das ist nicht direkt vorgesehen. Es gibt keine Programmierschnittstelle, mit der man sagen könnte: gib mir alle CSS Regeln, die auf das konkrete Element xy, auf alle Elemente mit Klasse "foo", mit id "bar", mit Tagname "div" oder mit sonst welchen Selektormöglichkeiten zutreffen.

        Das kannst Du im CSSOM (CSS Object Model) selbst programmieren. Aber dafür müsstest Du dann wirklich ganz low-level die CSS Selektoren selbst analysieren. Und das sollte man sein lassen. Denn es ist ja nicht mit dem Parsen von Selektoren getan, und der Prüfung, ob sie auf das aktuelle Element zutreffen. Danach muss man die gefundenen Selektoren noch gemäß der Regeln für Kaskade und Spezifität ordnen, um herauszufinden, welche Regel nun für welche Eigenschaft Vorfahrt hat.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Hi,

          Das kannst Du im CSSOM (CSS Object Model) selbst programmieren. Aber dafür müsstest Du dann wirklich ganz low-level die CSS Selektoren selbst analysieren. Und das sollte man sein lassen. Denn es ist ja nicht mit dem Parsen von Selektoren getan, und der Prüfung, ob sie auf das aktuelle Element zutreffen. Danach muss man die gefundenen Selektoren noch gemäß der Regeln für Kaskade und Spezifität ordnen, um herauszufinden, welche Regel nun für welche Eigenschaft Vorfahrt hat.

          Und bis man das fertig programmiert hat, sind 17 neue Selektoren-Typen hinzugekommen usw.

          cu,
          Andreas a/k/a MudGuard

          1. Hallo MudGuard,

            damit es nicht nochmal überlesen wird, habe ich den wichtigsten Satz des zitierten Abschnitts im Original und im Zitat fett nachmarkiert.

            Rolf

            --
            sumpsi - posui - obstruxi
  2. Hallo uwe,

    für Split-Panels habe ich diese Lib gefunden. In einer einfachen Version für Panels, und in einer Grid-Version.

    Dort steht auch, wie man die Lib einbindet, über Tools wie Yarn oder NPM, oder direkt von einem Content-Server (CDN). Falls mal Du eine öffentliche Seite anbieten willst: Kopiere jegliche CDN-Quellen auf deinen Server, das erspart Dir DSGVO-Kopfschmerzen in der Datenschutzerklärung.

    Eine Einsatzdemo ist auf der CSS Script Seite verlinkt. Hier ist eine von mir.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      wow, mit so vielen Tipps hatt ich nicht gerechnet.
      😃😃😃😃😃😃😃😃😃

      Da ist das Wochenende gelaufen.

      Das script werden ich mal einbauen. Aber um das zu verstehen ist das zu viel.

      Gruß uwe