Simples Grid Layout Skript

Simples Grid Layout Skript

Wichtiger Hinweis: Dieser Artikel ist ursprünglich von 2017. Inzwischen existieren wesentlich bessere Alternativen, wie display: flex; und display: grid;, welche auch in allen modernen Browsern unterstützt werden.

Zweispaltiges Layout

Im Netz existieren viele diverse Javascript Bibliotheken für Grid Layouts, allerdings sind die meisten überladen und funktionieren selten wie gewünscht. Aus diesem Grund habe ich ein simples Skript geschrieben um ein einfaches Grid Layout zu realisieren.

Das Problem mit dem guten alten float Attribut

float.png

Das float Attribut war schon immer Freund und Helfer, bringt aber falsch angewendet auch oft Chaos mit sich. In diesem Fall bringt uns das float Attribut nur bis zu einem gewissen Punkt weiter. Das Problem ist schnell ersichtlich, wenn man sich das Bild ansieht. Es kommt zu unerwünschte Abständen, wegen der verschiedenen Höhen der Boxen.

Die moderne Alternative "Flexbox"

Mit display: flex; kann man ein Grid Layout schnell realisieren. Der Browser Support ist inzwischen auch ganz gut. Allerdings hatte ich persönlich merkwürdige Darstellungsfehler mit display: flex;, die mich auf Dauer gestört haben. (Stand: 2017) Trotzdem rate ich jedem sich vorher einmal mit der Materie zu beschäftigen, denn display: flex; ist die Zukunft von komplexen und vor allem responsiven Layouts.

Das Skript

Wer trotz allem das Grid Layout mit Javascript realisieren möchte, der kriegt jetzt hier einen Lösungsweg:

var grid = null;
var gridHeight = 0;
var penX = 0, penY = 0;
var lastDivLeft = null, lastDivRight = null;
var gutter = 15;
var elemID = '';

function childrens(e, type)
{
	 var childs = new Array();
	 for(var i = 0; i < e.childNodes.length; i++) if(e.childNodes[i].tagName == type.toUpperCase()) childs[childs.length] = e.childNodes[i]; 
	 return childs;
}

function updatePens(elem)
{
	 if(penX == 0) 
	 {
		  penX += elem.offsetWidth + gutter;
		  gridHeight += elem.offsetHeight + gutter;

		  if(lastDivRight != null)
		  {
				penY = parseInt(lastDivRight.offsetTop + lastDivRight.offsetHeight + gutter);    
		  }

		  lastDivLeft = elem;
	 }
	 else 
	 {
		  penX = 0; 
		  penY = parseInt(lastDivLeft.offsetTop + lastDivLeft.offsetHeight + gutter);
		  lastDivRight = elem;
	 }
}

function gridIt(elem)
{
	 if(elem !== undefined) elemID = elem;
	 
	 penX = 0;
	 penY = 0;
	 lastDivLeft = null;
	 lastDivRight = null;
	 gridHeight = 0;

	 grid = document.getElementById(elemID);					
	 var childs = childrens(grid, "div");
 
	 for(var i = 0; i < childs.length; ++i)
	 {
		  childs[i].style.position = "absolute";
		  childs[i].style.left = penX + "px";
		  childs[i].style.top = penY + "px";
		  updatePens(childs[i]);
	 }   

	 grid.style.height = gridHeight + "px";
}

window.onresize = function(event) { gridIt("content"); };

var called = false;

document.addEventListener("DOMContentLoaded", function() {
         if(!called) gridIt();
	 called = true;
});

document.onreadystatechange = function () {
	 if(!called) gridIt();
	 called = true;
};

window.onload = function() {
	 gridIt();
};

Der dazugehörige HTML Teil sollte in diese Richtung gehen:

Vielleicht auch interessant
Weiterleitung mit .htaccess: HTTPS, mit und ohne www
Weiterleitung mit .htaccess: HTTPS, mit und ohne "www"

Wie man eine Weiterleitung mit .htaccess von http://***.tld auf https://www.***.tld einrichtet.

<div id="content">
     <div>Box 1</div>
     <div>Box 2</div>
</div>

Das war schon die ganze Zauberei. Das Skript wurde auf das nötigste reduziert, damit das Prinzip ersichtlich ist und das Anpassen einfacher fällt.

Eine kurze Erklärung

Die childrens Funktion gibt die Kind Elemente eines bestimmten Types (div, span, p, ...) zurück. Die updatePens Funktion berechnet die Position für das nächste Kind Element. Die gridIt Funktion ist das Herz dieses Skripts und verbindet die vorherigen Funktionen mit Logik zusammen. Alles weitere ist dafür zuständig, dass das Grid Layout beim fertig Laden der Inhalte sowie beim Verändern der Fenstergröße sich anpasst.

Hinterlasse gerne einen Like oder Kommentar (~‾▿‾)~
Name Text
Kommentare
Mr. A> 2 JIch möchte die modernste Variante, ein Grid-Layout mit CSS herzustellen, nicht unerwähnt lassen: display: grid; Dieses wird seit März dieses Jahres in allen gängigen Browsern unterstützt. Natürlich muss man sich je nach gewünschter Darstellung entscheiden, welche Technik man benutzt. Von float würde ich heute in den meisten Fällen abraten, da es mehr Probleme macht als löst. Flexbox eignet sich gut, wenn die Inhalte nur in eine Richtung verlaufen. Wenn Inhalte sowohl vertikal als auch horizontal verlaufen, eignet sich das neue CSS3-Grid am besten. Das von dir gewünschte Zwei-Spalten-Layout ist aber derzeit wirklich nicht ohne Javascript realisierbar.

Zum CSS3-Grid noch ein paar Wörtchen, da es relativ neu ist (auch wenn es hier nicht anwendbar ist): Es ist besonders gut für das Layout einer gesamten Seite geeignet. Beispielsweise kann man seine gesamte Seite in drei Zeilen und zwei Spalten teilen. Die linke Spalte könnte beispielsweise 20% der Gesamtbreite der Seite oder 200px Breite haben, was auch immer größer ist (siehe die CSS-Funktion minmax()). Die zweite Spalte erhält den Rest. Man hat die Möglichkeit, sogenannte Grid Areas zu definieren. Das sind benannte Bereiche des Grids. Beispielsweise können die beiden Zellen der oberen Zeile als "header", die unteren beiden als "footer", die linke Zelle der mittleren Zeile als "navigation" und die rechte Zelle als "content" definiert werden. Jetzt braucht man nur noch vier divs, denen man mit der CSS-Eigenschaft grid-area mitteilt, in welchem Bereich sie angezeigt werden sollen.

Doch warum das alles? Ganz einfach: Möchte man die Seite auf Mobilgeräten anders darstellen, muss man im Media Query jetzt nur noch das Grid neu definieren (z.B. eine Spalte, vier Zeilen: header, navigation, content, footer). Die Grid Areas sind den divs ja bereits zugewiesen.

Wer mehr wissen will, dem empfehle ich zum Einstieg das Lernspiel CSS Grid Garden (gleichnamige Website). Übrigens gibt es etwas Ähnliches auch für Flexbox: Flexbox Froggy.