5. Dez. 2009
Grundlinienraster-Bildhöhenausgleich mit jQuery
Wenn man bei Layout einer Webpage ein Grid System benutzt, ist es auch oft sinnvoll, die Typografie an einem Grundlinienraster auszurichten. Das bedeutet, dass man die Grundlinien der Schrift in ihrer vertikalen Ausrichtung so anpasst, dass sie mit dem Grundlinienraster übereinstimmen. Da in den CSS-Spezifikationen keine speziellen Methoden vorgesehen sind, um die Grundlinie von Schrift automatisch an einem Raster auszurichten, wie es z.B. in einem DTP-Programm wie InDesign möglich ist, muss man sich mit vertikalem padding und margin behelfen, indem man damit alle erforderlichen HTML-Elemente so anpasst, dass Schrift-Grundlinie und Grundlinienraster übereinstimmen.
Sobald man jedoch Bilder in den Fließtext einfügt, macht man sich dadurch mit hoher Wahrscheinlichkeit einen Strich durch die Rechnung. Im Normalfall passt man ein Bild durch proportionales Skalieren an die vom Layout vorgegebene Breite an. Die Höhe des Bildes resultiert aus den ursprünglichen Proportionen des Bildes und kann daher ganz unterschiedliche Werte annehmen.
Angenommen, das Grundlinienraster beträgt 20 Pixel, dann müsste jedes Bild als Höhe ein Vielfaches von 20 haben. Da jedoch beim Skalieren die Anpassung an eine bestimmte Breite erfolgt, ist es gut möglich, dass sich eine Höhe von z.B. 256 Pixeln ergibt. Damit die dem Bild nachfolgenden Elemente auch mit dem Grundlinienraster übereinstimmen, müsste das Bild aber stattdessen 240 oder 260 Pixel hoch sein.
Da es jedoch zusätzliche Arbeit machen würde, jedes Bild nach dem Skalieren auch noch auf ein Vielfaches von 20 zu beschneiden, ist es sinnvoll, „unpassende“ Bildhöhen einfach durch Hinzufügen eines unteren vertikalen Abstands auf den nächsthöheren durch 20 teilbaren Wert zu erhöhen und damit die Differenz zum Grundlinienraster auszugleichen.
Links: Ohne Bildhöhenausgleich; rechts: mit Bildhöhenausgleich
Damit dies aber auch wirklich keine zusätzliche Arbeit macht und man den erforderlichen Abstand nicht bei jedem Bild selbst ausrechnen und per CSS zuweisen muss, ist es sinnvoll, diese Ausgabe von einem Script erledigen zu lassen. Da ich kein Programmierer bin, greife ich auf die JavaScript-Library jQuery zurück. Da jQuery auf dieser Seite sowieso schon im Einsatz ist, erzeuge ich also keinen zusätzlichen Datentransfer, wenn ich es auch für den Bildhöhenausgleich einsetze (außer den wenigen Zeilen Script für den Höhenausgleich selbst).
Das folgende Script wendet den Grundlinienausgleich auf alle Bilder und object-Elemente innerhalb aller Artikel an (Zeile 6).
Dazu wird die Bildhöhe ermittelt, durch den vorher festgelegten Wert für die Zeilenhöhe des Grundlinienrasters (Zeile 3) geteilt, das Ergebnis wird auf die nächsthöhere ganze Zahl gerundet und das gerundete Ergebnis wieder mit der Zeilenhöhe multipliziert. Nun hat man die erforderliche Höhe, um das Grunlinienraster einzuhalten. Davon wird die tatsächliche Bildhöhe wieder subtrahiert und übrig bleibt der dem Bild zuzuweisende untere Abstand (alles in Zeile 9).
In Zeile 10 wird abgeglichen, ob der berechnete Abstand nicht den festgelegten minimalen unteren Bildabstand (Zeile 4) unterschreitet und falls ja, werden einfach weitere 20 Pixel addiert, um die nachfolgenden Elemente eine weitere Zeile im Grundlinienraster nach unten zu verschieben.
Die if-Schleife von Zeile 11 bis 15 ist dafür verantwortlich, dem Elter-Element des Bildes den Abstand zuzuweisen – denn hier ist jedes Bild von einem p-Element umschlossen – beziehungsweise dem Elter-Elter-Element den Abstand zuzuweisen, sofern das Bild von einem a-Element umschlossen ist.
$(document).ready(function(){
var line_height = 20; // line-height of the vertical grid
var min_margin = 5; // smallest acceptable margin-bottom of an image
$('div.article img, div.article object').each(function() {
var $this = $(this); // prefixed variable name with $ to remind it's a jQuery object
var img_height = $this.height();
var img_margin = ((Math.ceil(img_height / line_height)) * line_height) - img_height;
img_margin = (img_margin < min_margin)? img_margin + line_height : img_margin;
if ($this.parent('a').length) {
$this.parent().parent().css({'margin-bottom' : img_margin + 'px'});
} else {
$this.parent().css({'margin-bottom' : img_margin + 'px'});
}
});
});
Das Skript lässt sich durch Anpassen der Werte line_height und min_margin sowie des Selektors div.article img, div.article object und der if-Schleife an die Gegebenheiten anderer Websites anpassen.