Zielsetzung / Problembeschreibung

Häufig hat man z.B. in Webshops auf Kategorie- oder Produktauswahlseiten diese als Tableau mit Vorschaubildern angezeigt. Hierbei reiht sich Vorschaubild an Vorschaubild jeweils in kleinen Blöcken. Bei einem tabellenfreien und in der Breite flexiblen Layout läßt man diese Vorschaubildblöcke einfach floaten.

Hierbei will man der schönen Optik wg. gerne zwei Dinge erreichen:

  • die Container für die Vorschaubilder sollen alle gleich groß sein
  • und die Bilder darin auch bei unterschiedlicher physikalischen Größe untereinander vertikal zentriert ausgerichtet sein.

Wer sich schon mal mit einer solchen Aufgabenstellung befasst hat, wird erfahren haben, dass dies per HTML und CSS so nicht möglich ist. Neuerdings findet man in Foren dazu eine Lösung die mit display:table, display:table-cell und vertikal-align:middle als Styleanweisungen arbeitet. Jedoch hat diese Formatierung als Tabellenzellen den Nachteil, dass Bilder die physikalisch größer abgelegt wurden als im Layout vorgesehen mit 100% angezeigt werden und dann einfach über den Tabellenrand hinausragen.

Wer sich jetzt fragt, warum ich dann nicht einfach die Bilder in der Breite korrekt skaliert auf den Server schiebe, der kennt meine Kunden nicht. Die sind dazu nicht in der Lage und erwarten einfach dass es trotzdem schick aussieht.

 



 

Die Lösung

Die Umsetzung erfolgt mit jQuery. Im Wesentlichen wird mit der jQuery die Höhe vereinheitlicht, wozu man gleich mal die Bibliothek syncHeight verwenden kann (oder man schreibt dazu schnell einen eigene jQuery-Methode) und per margin-top wird das Verschieben der Vorschaubilder nach unten abhängig von ihrer eigenen Höhe und der Höhe des umgebenden Containers erreicht.

Dazu speichert man sich z.B. folgendes JavaScript:

 

var jQSyncHeight = '.category-view ';

  

jQuery(window).load(function () {
	if (jQSyncHeight != '') {
		// vertikale Höhensynchronisierung für Vorschaubilder
		jQuery(jQSyncHeight+' .slider-img').syncHeight();
		jQuery(jQSyncHeight+' .category').syncHeight(); 
		// vertikale Zentrierung
		height = jQuery(jQSyncHeight+' .slider-img').first().height();
		jQuery(jQSyncHeight+' .slider-img img').each(function(i){
			jQuery(this).css( {'margin-top': (height - jQuery(this).height())/2 + "px"}	);
		});
	}
});

 

Der Bsp.-Selector .category-view wurde von mir in eine JavaScript-Variable ausgegliedert, damit auf Wunsch auch weitere Gruppen z.B. Produkt-Vorschaubilder mit dem gleichen Script formatiert werden könnten. Der Inhalt dieser Variablen wird dann quasi über das php-Template-Script für diese Seite befüllt.

Der PHP-Block zur Ausgabe der Kategorie-Vorschaublöcke kann vereinfacht dann etwa so aussehen (am Bsp. von VirtueMart 2.x in Joomla):

 

<h2>
  <a href="#" title="<?php echo $category->category_name ?>">
    <?php if (!empty($category->images)) : ?>
    <div class="slider-img">
      <?php echo $category->images[0]->displayMediaThumb("", false); ?></div>
    <?php endif; ?>
    <div><?php echo $category->category_name ?></div>
  </a>
</h2>

 

Der in der Höhe syncronisierte, das Bild umgebende Block wird angesprochen über den selector .slider-img. Margin-top wird dann gesetzt für das das Vorschaubild in diesem Block. Wie groß Margin-top ist, ergibt sich aus der syncronisierten Blockhöhe minus der Höhe des jeweiligen Bildes geteilt durch 2. Über die Methodes each() wird diese Berechnung und margin-top-Zuweisung für jedes Kategoriebild durchlaufen.

Ein Nachteil dieser Methode sei aber auch noch genannt. Dieser ganze Synchronisierungsprozess kann natürlich erst durchlaufen werden, wenn alle Bilder durch den Browser geladen wurden. Erst wenn ich die Höhe des größten Bildes kenne, kann ich die Höhen der Bildcontainer vereinheitlichen und auch erst dann das margin-top für die Bilder berechnen. D.h. beim Laden der Seite werden die Bilder zunächst unformiert angezeigt und rutschen erst dann auf ihre korrigierte Position.