jQuery: Gleiche Höhe für Elemente
In diesem Beitrag findet ihr jQuery-Snippets um Elementen eine einheitliche Höhe zuzuweisen.
Die in diesem Artikel beschriebene Technik funktioniert noch, sollte heute jedoch mit CSS Flexbox oder CSS Grid realisiert werden.
In flexiblen Web-Layouts kann die Höhe von Elementen eine Herausforderung darstellen. Beispielsweise findet man auf vielen Websites nebeneinander angeordnete Teaser-Elemente mit Text und einem »Weiterlesen«-Button. Redaktionell sollte man natürlich darauf achten, dass die Texte gleich lang sind, aber je nach Breite des Displays brechen die Wörter anders um, was wiederum dazu führt, dass die Buttons nicht immer auf gleicher Höhe sitzen. Mit CSS lässt sich das Problem nur schwer lösen, daher möchte ich in diesem Beitrag ein praktisches jQuery-Snippet archivieren.
Gleiche Höhe von Elementen mit jQuery erzwingen
Mit Hilfe einer each
-Schleife in jQuery könnt ihr die Höhe von Teasern oder anderen Elementen angleichen. Im folgenden Beispiel erhalten alle Elemente mit dem Selektor .teaser
eine Höhe von 300 Pixeln.
// Suche alle Elemente mit der Klasse ».teaser«.
$('.teaser').each( function(){
// Ändere bei diesen Elementen die Höhe auf 300 Pixel
$(this).css('height', '300px');
});
Elemente ansprechen die höher/niedriger als X Pixel sind
Im vorherigen Beispiel wurde die Höhe generell auf 300 Pixel erhöht. Im responsive Design und in flexiblem Weblayouts ändert sich jedoch sowohl die Höhe als auch die Breite von Elementen. Erst ab einem bestimmten Punkt tritt i.d.R. ein Darstellungsfehler auf. Mit folgendem Snippet werden alle .teaser
angesprochen und grün eingefärbt, die niedriger als 150 Pixel sind.
$('.teaser').each( function(){
if ($(this).height() < 150) { // Prüfe ob die Höhe eines Teasers niedriger als 150 Pixel ist
$(this).css('background', 'lime'); // Wenn ja, färbe den Hintergrund grün ein.
}
});
Elemente an der Höhe des höchsten Elements ausrichten
Wenn alle Elemente automatisch so hoch wie das höchste Element werden sollen, verwendet folgendes Snippet. Hierbei wird die Schleife zwei mal durchlaufen: Im ersten Durchlauf wird in Erfahrung gebracht welcher .teaser
am höchsten ist. Im zweiten Durchlauf wird allen Elementen diese Höhe zugewiesen.
var highest_element = 0;
// Prüfe, welches Element am höchsten ist
$('.teaser').each(function() {
if ($(this).height() > highest_element) {
highest_element = $(this).height();
}
});
// Weise diese Höhe allen Elementen zu.
$('.teaser').each(function() {
$(this).height(highest_element);
});
Alle Elemente neu berechnen, wenn die Größe des Browserfensters verändert wird
In den oben gezeigten Beispielen wird die Höhe einmalig beim Seitenaufruf berechnet. Wenn sich die Höhe der Elemente jedoch ändern kann – beispielsweise weil das Layout flexibel ist und die Höhe der Elemente von der Breite des Viewports abhängig ist – sollte die Berechnung erneut stattfinden, sobald das Browserfenster verändert wird. Um die Performance etwas zu schonen, wird ein Timeout eingerichtet.
function kb_equal_height() {
var highest_element = 0;
// Lösche die Höhe
$('.teaser').each(function() {
$(this).removeAttr('style');
}); // Prüfe, welches Element am höchsten ist
$('.teaser').each(function() {
if ($(this).height() > highest_element) {
highest_element = $(this).height();
}
}); // Weise diese Höhe allen Elementen zu.
$('.teaser').each(function() {
$(this).height(highest_element);
});
}; window.onload = kb_equal_height; var resizeTimer;
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(kb_equal_height, 100);
});
Werkle gerade mit joomla 3 local am Template. Generell sind doch in joomla unterschiedliche und verschachtelte divs vorhanden. Kurzum kann man dein Script beim Beitrag „Elemente an der Höhe des höchsten Elements ausrichten“ dahingehend abändern? Also nicht nur für eine Klasse sondern 3. Bei mir sind es von links nach rechts: div.moduletable_ibl, div.blog_start, div.moduletable_ibr. Naja bin kein Profi in Sachen Javascipt. Hab‘ dein Script probiert und .teaser durch .blog_start ersetzt (meine höchste Ausrichtung). Klappte nicht und liegt wohl an joomla durch die erwähnte Verschachtelung? Versuchte css-Lösungen. Die einzigste was bei mir gehen würde ist mit hohen padding-bottom und negativen margin-bottom Werten und dann overflow der umfassenden #wrapper-id. Leider wird unten dann das Design zerschossen. Viele Grüße und danke Karin
super unkompliziert. Gefällt mir. Danke!
Hier mal ein Versuch in CSS/SCSS mit modifizierter Table-cell Methode:
http://codepen.io/randolfm/pen/qNdxpy
Mir ging es darum, durch Abstände getrennte Boxen zu erhalten, die sich aber an den Seitenrändern ausrichten und einen unteren Rand besitzen.
(Bisher nur mit einigermaßen aktuellen Browsern getestet)
Ich habe den Script, der bei einer Größenanderung des Browser die Höhe neu berechnet, in mein Testseite eingebaut und bin begeistert.
Leider habe ich noch ein Problem. Wenn man das Browserfenster weit zusammenschiebt landen die einzelnen Spalten direkt untereinander. Dies ist so gewünscht. Jetzt sollten die Spalten direkt untereinander stehen, hier ist aber auch ein Abstand entsprechnd der längsten Spalte vorhanden.
Der Script sollte deshalb erst bei einer Browerbreite von z.B. 600px aktiv werden.
Kann diese Abfrage noch eingebaut werden? Leider kenne ich mich mit Java überhaupt nicht aus.
Grüße Roland
Hallo das Skript funktioniert super. Hab blos ein kleines Problem mit Eltern div. Das Eltern div hat dadurch keine Höhe. Aus diesem Grund kann ich das nachfolgende Div sehr schwer formatieren.
Flexbox (mit display: table/-cell; Fallback). Dafür braucht man kein JavasScript.
Bei Geschwister-Elementen in der gleichen Zeile funktioniert Flexbox bzw. Display Table gut, aber sobald der Aufbau verschachtelt ist oder die Elemente nicht direkt nebeneinander liegen kommt man um JS kaum herum. Ich hatte beispielsweise letztens den Fall, dass alle Überschriften in meinen Teasern gleich hoch sein mussten.
das ist ein Designfehler ;) Wenn man im „nachhinein“ die Höhe der Überschriften anpassen muss, dann geht das nur mit JS, das stimmt. Dein Beispiel ist aber über Teaserblöcke, die nebeneinander liegen. ;)
Haha, ist klar! :) Ich hatte etwa einen Anwendungsfall wie diesen hier im Kopf als ich den Beitrag verfasst habe: Drei Teaser mit drei Überschriften, drei Texten und drei Buttons. Sowohl die Länge der Überschriften, als auch die Länge der Texte können sehr unterschiedlich ausfallen. Trotzdem sollen die Texte und die Buttons immer auf einer Höhe anfangen, egal wie breit das Display ist. Das Beispiel reagiert jetzt noch nicht auf resize, aber ich denke es ist klar was ich meine.
Hey Jonas,
Der Artikel ist wie immer Super! Es ist auf jeden Fall mal eine Variante, die ich mir anschauen werde.
Bei dem Beispiel, dass du Sven geschickt hattest wird das Div-Element .container nicht geschlossen. ;-)
Liebe Grüße
Katja
Vielen Dank. Ebenso richtig wie jetzt behoben :)
Hey, tolle Snippets!
Ich persönlich benutze immer folgendes Script:
http://brm.io/jquery-match-height/
LG Nicolas
https://github.com/FlorianKoerner/equalHeight.js
Ich habe mit diesem Script gute Erfahrungen bei unserer aktuellen responsive-Umstellung gemacht. Eigentlich suchen wir aber immer noch nach einer Lösung, die ohne Javascript auskommt und ich dachte, Flexbox könnte bei dem Problem an einigen Stellen behilflich sein.
Hallo Michael,
Ein reine CSS-Lösung (die JS als Fallback für ältere Browser benutzt), gibt es im YAML-Framework. Schau mal hier: http://www.yaml.de/docs/index.html#yaml-grids. Scroll dort ein wenig runter bis Du links „Equal Heights Grids“ siehst. Wenn Du mit Chromebug, Firebug, o.ä. den Quelltext der Beispielboxen untersuchst, erkennst Du auch schon die Lösung. Auf jede der Boxen wird ein padding-bottom von 10000px und ein margin-bottom von -10000px angewendet. Der Wrapper-Container für beide Boxen braucht dann wohl noch ein overflow: hidden.
Den Pixel-Wert von 10000 bzw. -10000 kann man sicherlich auch kleiner halten, je nachdem wie viel Content die Boxen enthalten sollen. Es reicht wahrscheinlich in den meisten Fällen schon 2000px bzw. -2000px.
Ich weiß nicht, ob ich in meiner Schilderung was übersehen habe, da es schon länger her ist, dass ich diesen Trick benutzt habe, funktioniert, aber eben auch ganz gut ohne das YAML-Framework und ohne JS.
Weiß leider nicht mehr, wo ich die Funktion im Netz gefunden habe, doch finde ich ganz clever.
Damit sich die Elemente auch in ihrer eigenen Reihe auf die selbe Höhe bringen, kann man das ja auch so erweiteren.
„Alle Kind-Div-Elemente von Eltern-Div auf eine Höhe bringen – Funktion“:
$.fn.eqHeights = function(options) {
var defaults = {
child: false
};
var options = $.extend(defaults, options);
var el = $(this);
if (el.length > 0 && !el.data(‚eqHeights‘)) {
el.data(‚eqHeights‘, true);
}
if( options.child && options.child.length > 0 ){
var elmtns = $(options.child, this);
} else {
var elmtns = $(this).children();
}
var prevTop = 0;
var max_height = 0;
var elements = [];
elmtns.height(‚auto‘).each(function() {
var thisTop = this.offsetTop;
if (prevTop > 0 && prevTop != thisTop) {
$(elements).height(max_height);
max_height = $(this).outerHeight();
elements = [];
}
max_height = Math.max(max_height, $(this).outerHeight());
prevTop = this.offsetTop;
elements.push(this);
});
$(elements).height(max_height);
};
Aufruf: $(‚.DEINE_KLASSE‘).eqHeights();
Hmhm .. interessante Lösung, vielen Dank!
—
Ich überlege gerade, ob man das Problem Elemente an der Höhe des höchsten Elements ausrichten nicht mit display: flex im Elternelement lösen könnte?
http://codepen.io/5202/pen/PqzggV
Spricht was dagegen?
Hallo Oliver, in diesem konkreten Fall hast du vollkommen Recht. Das würde auch mit Flexbox wunderbar funktionieren (wie deine Demo zeigt). Bei komplexeren Elemente wird es manchmal etwas schwieriger.
Problem aktuell bei Flexbox ist, dass es erst ab IE10 funktioniert. Darunter muss man Fallbacks einbauen.
Anstatt eine fixe Höhe zu vergeben, wäre es praktischer, wenn sich die Höhe am längsten Element innerhalb eines Containers ausrichtet, wie bspw. bei Foundation Equalizer http://foundation.zurb.com/docs/components/equalizer.html
Sehr guter Einwand. Meinst du so etwas hier?
var highest_element = 0;
// Prüfe, welches Element am höchsten ist
$('.teaser').each(function() {
if ($(this).height() > highest_element) {
highest_element = $(this).height();
}
});
// Weise diese Höhe allen Elementen zu.
$('.teaser').each(function() {
$(this).height(highest_element);
});
Beispiel anschauen
genau :)
Ich habe den Beitrag um das Beispiel ergänzt. Vielen Dank für deinen Input!
Oder mit Math.max: http://www.hansspiess.de/elemente-per-jquery-und-math-max-gleiche-hohe-zuweisen/247/