Joomla! Template Tutorial Teil 4 - Ein flexibles Spaltenraster

Geschrieben von Tom   
Samstag, 20. Februar 2010

Nachdem wir im dritten Teil des Joomla Template Tutorials das Template soweit umgesetzt haben, dass eine flexible Breite mit allen gestalterischen Elementen zusammenspielt und Navigation und rechte Spalte soweit waren, wollen wir uns nun als erstes überlegen wie wir das mit den Spalten angehen wollen.

Für den weiteren Verlauf des Tutorials, haben wir eine Flows Demo-Seite eingerichtet, unter der der aktuelle Stand des Templates eingesehen werden kann.

Bis jetzt war ich der Meinung, für ein Demo-Template reicht es aus, wenn wir eine Spalte auf der rechten Seite haben, bei fehlenden Modulen die rechte Spalte verschwindet und der Content über die gesamte Template Breite läuft.
Einige fleißigen Leser sind allerdings der Meinung, dass wenn ich mir schon die Arbeit mache, ein so flexibles Template zu entwickeln, ein klassisches drei Spalten Layout ja wohl das Mindeste wäre. Nun, Recht haben sie.
Deswegen werden wir nun gemeinsam überlegen, wie wir das anstellen wollen.

Teil 5 des Joomla! 1.5 Template Tutorials ist fertig!

Das Ziel ist klar. Es soll sowohl auf der linken, wie auch auf der rechten Seite des Contents eine Modulspalte möglich sein. Das heißt wir haben insgesamt vier verschiedene Layouts:

  1. Linke Spalte + Content
  2. rechte Spalte + Content
  3. beide Spalten + Content
  4. nur Content

Obwohl ich in diesem Teil auch noch Content Overrides behandeln wollte, habe ich nun meine Meinung geändert. Content Overrides sind ein Thema für sich und verdienen einen eigenen Abschnitt. Abgesehen davon, wollte ich den vierten Teil des Tutorials nicht ganz so ausarten lassen wie den dritten.

Der Ruf nach mehr Spalten

Hier ist es nochmal sehr, sehr, sehr wichtig das zugrunde liegende Konstrukt des Templates verstanden zu haben. Wir haben uns im zweiten Teil des Tutorials für das "Equal-Height-Columns"-Layout von Matthew James Taylor entschieden. Auf seiner Seite ist wunderbar beschrieben und illustriert, wie das Konstrukt genau funktioniert. Wie alle genialen Dinge ist es ausgesprochen einfach, nur dauert es ein wenig hinter die eigentliche Idee zu kommen.

Grundsätzlich müssen Sie sich das Konstrukt wie, mmmhh... eine Schultafel vorstellen! Man kann eine Tafel hochschieben und darunter liegt eine Zweite. In der Schule gibt, es soweit ich weiss, nicht drei übereinanderliegende Tafeln, bei unserem Konstrukt schon.  Was in der Schule die Tafeln, sind bei unserem Konstrukt die DIVs mit den Klassen .wrap1, .wrap2 und .wrap3. Diese werden anders als in der Schule nicht vertikal, sondern horizontal verschoben.

Welches .wrap3 werden Sie sagen. So ein DIV gibt es doch in unserem Template gar nicht? Richtig, aber um eine dritte Spalte realisieren zu können, müssen wir es einführen.

Was also vorher so aussah

...
<div class="wrap1">
   <div class="wrap2">
...
wird nun zu
...
<div class="wrap1">
   <div class="wrap2">
      <div class="wrap3">
...

Drei verschiebbare Tafeln ...äh, DIVs. Das CSS des Konstrukts hat bis jetzt die einzelnen DIVs exakt so verschoben, dass ein Zwei-Spalten Layout entstand. Der wesentliche Punkt war eigentlich nur das CSS right:250px; für das .wrap2 DIV. Genau hier wird die Tafel nach links verschoben, indem der Abstand zum rechten Rand definiert wird. Lassen Sie dies sacken und versuchen Sie das Gesamtkonstrukt zu verstehen.

Hinweis
Um das Konstrukt besser zu verstehen, führt kein Weg am Firefox-Plugin Firebug vorbei. Darin können Veränderungen am CSS mit sofortigem Feedback direkt auf der Webseite durchgeführt werden. Googles Chrome Browser hat ebenfalls so ein Entwicklerwerkzeug.

Gut. Wir müssen also die DIVs abhängig von der Anzahl und Kombination der darzustellenden Spalten (Modulpositionen left und right) aktivieren und deaktivieren.

Da wir IMMER Content darstellen werden, dieser also nicht wie die Spalten aktiviert oder deaktiviert wird, benötigen wir auf jeden Fall ein DIV für den Content. Wir lassen also das DIV mit der Klasse .wrap1 unberührt.
Beim .wrap2 DIV ist das schon anders. Dieses benötigen wir für eine Spalte, egal ob die linke oder die rechte. Wir passen die index.php also wie folgt an:

<?php if($this->countModules('left') || $this->countModules('right')) : ?>
   <div class="wrap2">
<?php endif ?>

Damit stellen wir sicher, dass das DIV dargestellt wird, wenn, entweder in der linken oder in der rechten Modulposition, Module dargestellt werden sollen. Anders formuliert: Das DIV wird ausgegeben, wenn mindestens eine Modulposition Module beinhaltet.

Ähnlich sieht es mit dem neuen .wrap3 DIV aus. Dieses benötigen wir allerdings nur, wenn wirklich beide Spalten dargestellt werden sollen. Aus einem ODER wird also ein UND.

<?php if($this->countModules('left') && $this->countModules('right')) : ?>
   <div class="wrap3">
<?php endif ?>

Das Gleiche müssen wir natürlich noch bei den schließenden DIV-Tags weiter unten in der index.php machen:

<?php if($this->countModules('left') || $this->countModules('right')) : ?>
   </div>
<?php endif ?>

Jetzt haben wir das nötige HTML um entsprechend der darzustellenden Modulpositionen (Spalten) dass CSS so zu formulieren, dass diese passend verschoben werden. Schauen Sie sich zu diesem Zeitpunkt bloß nicht das Frontend an. Es ist ein Chaos.

Ein gutes Template bringt eigene Werkzeuge mit

Um Herr über das Chaos zu werden, gibt es nur einen Weg: Mathematik!
Wir haben in unserer index.php im letzten Tutorial ein wenig inline-CSS definiert, welches sich darum kümmert, passende CSS-Anweisungen zu formulieren, abhängig von der gesamten Template Breite, welche im Backend über Parameter angegeben werden kann.

<style type="text/css">
    .wrapper {width: <?php echo $this->params->get('width');  ?>px;}
    #main {width:<?php echo $this->params->get('width')-270;  ?>px;}
    .page {min-width:<?php echo $this->params->get('width');  ?>px;}
</style>

Das ist im Prinzip die einfache Version von dem was wir benötigen, um unsere Spalten so flexibel wie gewünscht darzustellen.

Um unsere index.php jetzt allerdings nicht mit PHP-Anweisungen zu überfrachten, betreiben wir ein wenig Outsourcing. Ich werde die nötigen Abfragen und die daraus resultierenden Anweisungen in eine separate PHP-Datei auslagern, welche uns vielleicht an späterer Stelle noch weitere Hilfsarbeiten rund um das Template abnehmen kann. Eine kleine Werkzeugkiste für das Flows-Template wenn Sie so wollen. Wir erzeugen im Template Verzeichnis eine leere PHP-Datei namens flowtools.php. Darin erstellen wir erstmal eine Basis Hilfsklasse:

<?php
    // unsere Hilfsklasse
    class flowtools { 
        
        // ein Klassenattribut
        var $tmpl = null;
               
        // Konstruktor der Klasse. Weist dem Klassenattribut tmpl das aktuelle Template zu
        function flowtools(&$tmpl) {            
            $this->tmpl = $tmpl;
        }
        
        // Funktion generiert nötiges inline CSS
        function genInlineCSS() {        
       
            $css = array();
            $css[] = '<style type="text/css">';
            $css[] = '.wrapper {width: ' . $this->tmpl->params->get('width') . 'px;}';
            $css[] = '#main {width:<?php echo $this->params->get('width')-270;  ?>px;}';
            $css[] = '.page {min-width: ' . $this->tmpl->params->get('width') . 'px;}';            
           
            $css[] = '</style>';            
        
            // liefert das inline CSS. Durch Zeilenumbrüche getrennt ums leserlicher zu machen
            return implode("\n", $css);
        }        
    }
    // Erzeugt das flowtools Objekt und übergibt dem Konstruktor das aktuelle Template
    $ftools = new flowtools($this);
?>

In der index.php wo vorher unser inline CSS stand ersetzen wir dieses mit <?php echo $ftools->genInlineCSS(); ?> Mit ein wenig PHP-Kenntnissen erkennt jeder was hier passiert. Im Grunde genau das Gleiche wie vorher im inline-CSS. Nur dass wir uns jetzt in der eigens angelegten Funktion genInlineCSS austoben können und die index.php übersichtlich bleibt. genInlineCSS soll übrigens "generiere das inline CSS" heissen...

Ein wenig Mathe muss sein

As nächsten Schritt gilt es, die oben genannten vier verschiedenen Layoutfälle (linke Spalte hier, rechte Spalte da, usw.) in unserer Klasse abzufragen und entsprechendes inline CSS zu generieren. Fangen wir mit dem einfachsten Fall an. Dieser wäre das Layout ohne Spalten, also nur Content über die gesamte Breite. Da wir das #main DIV abhängig vom aktuellen Layout definieren müssen, nehmen wir es in die Abfragen hinein. Der erste Fall sieht dann so aus: 

// keine Spalten + Content
if(!($this->tmpl->countModules('left') || $this->tmpl->countModules('right'))) {
    $css[] = '#main {';
    $css[] = 'width:' . ($this->tmpl->params->get('width')-20) .'px;';
    $css[] = 'left:0px;';
    $css[] = '}';
    $css[] = '.wrap1 {background-color:#fff;}';
}

Spaltenraster ohne SpaltenDas war recht einfach. Wenn keine Module in Position left oder right sind, wird die Breite des #main DIV auf die komplette im Backend angegebene Template Breite gesetzt, fertig. Da bei vorhandenen Spalten das .wrap1 DIV auch mal für eine Spalte genutzt wird, müssen wir ihm hier eine Hintergrundfarbe zuweisen, um die Farbe aus den Farbvariation CSS (aus Teil zwei des Tutorials) zu überschreiben. Die index.php kümmert sich darum, siehe oben, dass die DIVs .wrap2 und .wrap3 gar nicht erst ausgegeben werden.

Machen wir weiter mit der Layoutvariante, bei der nur die rechten Spalte dargestellt werden soll. Dabei müssen wir beachten, dass die Spalten eine feste Breite von 250px haben sollen.

// rechte Spalte + Content
if((!$this->tmpl->countModules('left') && $this->tmpl->countModules('right'))) {
    $css[] = '#main {';
    $css[] = 'width:' . (($this->tmpl->params->get('width')-270)) .'px;';
    $css[] = 'left:250px;';
    $css[] = '}';
    $css[] = '#right {';
    $css[] = 'left: 250px;';
    $css[] = 'width: 250px;';
    $css[] = '}';
    $css[] = '.wrap2 {background-color:#fff;right: 250px; }';
}

Spaltenraster mit Spalte rechtsIm Prinzip war dies der Standard Fall im Verlauf des Tutorials. das #main DIV wird um die Breite der Modulspalte, also um 250px schlanker. Die 270px kommen durch die 10px padding auf jeder Seite zu Stande. Die restlichen Anweisungen sind das übliche "Tafelschieben" für diese Layoutvariante.

 

Die Layoutvariante mit nur einer linken Spalte sieht nicht viel anders aus. Der einzige Unterschied liegt in der Art, wie wir die DIVs verschieben, also den Pixelangaben.

// nur linke Spalte
if((!$this->tmpl->countModules('right') && $this->tmpl->countModules('left'))) {
    $css[] = '#main {';
    $css[] = 'width:' . ($this->tmpl->params->get('width')-270) .'px;';
    $css[] = 'left:' . ($this->tmpl->params->get('width')-270) .'px;';
    $css[] = '}';
    $css[] = '#left {';
    $css[] = 'left: ' . ($this->tmpl->params->get('width')-270) .'px;';
    $css[] = 'width:250px;';
    $css[] = '}';
    $css[] = '.wrap1 {background-color:#fff;}';
    $css[] = '.wrap2 {right:' . ($this->tmpl->params->get('width')-270) .'px;}';
}  

Spaltenraster mit zwei Spalten Als letztes folgt noch der Fall, in dem ein Drei-Spalten-Layout möglich sein soll. Dies ist der einzige Fall, in dem alle drei Tafeln bzw. DIVs (.wrap1, wrap2 und wrap3) zum Einsatz kommen. Dementsprechend müssen wir hier etwas mehr CSS definieren.

// beide Spalten
if($this->tmpl->countModules('right') && $this->tmpl->countModules('left')) {
    $css[] = '#main {';
    $css[] = 'width:' . ($this->tmpl->params->get('width')-520) .'px;';
    $css[] = 'left:' . ($this->tmpl->params->get('width')-270) .'px;';
    $css[] = '}';
    $css[] = '#left {';
    $css[] = 'left:' . ($this->tmpl->params->get('width')-270) .'px;';
    $css[] = 'width: 250px;';
    $css[] = '}';
    $css[] = '#right {';
    $css[] = 'left:' . ($this->tmpl->params->get('width')-270) .'px;';
    $css[] = 'width: 250px;';
    $css[] = '}';
    $css[] = '.wrap2 {background-color:#fff;right:250px;}';
    $css[] = '.wrap3 {right:' . ($this->tmpl->params->get('width')-520) .'px;}';
}

Die Breite des #main DIVs wird um die Breiten der beiden Spalten reduziert (250px + 250px + 20px padding). Der Rest ist die übliche Schieberei, die bei drei DIVs nötig ist.

Warum nicht variable Spaltenbreiten?

Wenn man sich das layoutabhängige inline CSS dort oben anschaut, kommt man als Templatebauer nicht um eine Frage herum: Warum ersetzen wir diese ganzen Konstanten nicht durch definierbare Parameter? Mit anderen Worten: Warum lassen wir den Webseitenbetreiber nicht über die Spaltenbreite per Templateparameter entscheiden. Und zwar für jede separat...Muahahaa! Schließlich haben wir eine flexible Templatebreite und da macht es Sinn in machen Fällen die rechte Spalte auf eine Breite von z.B. 400px zu setzen.

Parameter zu Spaltenbreiten Gesagt, getan. Wie im vorigen Teil des Tutorials beschrieben, erstellen wir zwei weitere Template Parameter für die linke und rechte Spalte. Diese Parameter habe ich width-left und width-right genannt. Das ganze sieht im Backend dann wie im Bild links aus.

So, nun müssen wir nur noch zusehen, dass die Parameterwerte auch ihren Weg in das inline CSS finden. In der genInlineCSS Funktion holen wir uns zunächst die Werte aus dem Parameter Objekt.

...
function genInlineCSS() {
    $leftw = $this->tmpl->params->get('width-left');
    $rightw = $this->tmpl->params->get('width-right');
    ...

Nun haben wir die im Backend definierten Breiten der beiden Spalten in den Variablen $leftw und $rightw. Diese können wir recht einfach in das inline CSS einbauen.

Was also vorher so aussah:

// rechte Spalte + Content
if((!$this->tmpl->countModules('left') && $this->tmpl->countModules('right'))) {
    $css[] = '#main {';
    $css[] = 'width:' . (($this->tmpl->params->get('width')-270)) .'px;';
    $css[] = 'left:250px;';
    $css[] = '}';
    $css[] = '#right {';
    $css[] = 'left: 250px;';
    $css[] = 'width: 250px;';
    $css[] = '}';
    $css[] = '.wrap2 {background-color:#fff;right: 250px; }';
}

wird nun zu

// rechte Spalte + Content
if((!$this->tmpl->countModules('left') && $this->tmpl->countModules('right'))) {
    $css[] = '#main {';
    $css[] = 'width:' . (($this->tmpl->params->get('width')-$rightw-20)) .'px;';
    $css[] = 'left:'.$rightw.'px;';
    $css[] = '}';
    $css[] = '#right {';
    $css[] = 'left: '.$rightw.'px;';
    $css[] = 'width: '.$rightw.'px;';
    $css[] = '}';
    $css[] = '.wrap2 {background-color:#fff;right: '.$rightw.'px; }';
}

Trivial, nicht wahr? Die ganze Funktion mit Parametern ersetzt, erspare ich mir hier einzufügen. Wichtig ist das Ergebnis, und das kann sich sehen lassen.

Hinweis
Bis jetzt haben wir die verschiedenen Tutorial-Schritte als statische Seiten zum Ansehen bereitgestellt und im Download Bereich als nicht installierfähige Templates angeboten.
Da das Template nun einen Grad an Funktionalität bekommen hat, bei dem dies keinen Sinn mehr macht, haben wir eine Demo Seite zum Flows-Template eingerichtet. Unter dieser kann jeweils der aktuelle Fortschritt des Templates begutachtet werden. Die einzelnen Tutorial-Schritte werden ab jetzt als installierfähiges Template im Download-Bereich angeboten. Bedenken Sie allerdings, dass das Template bis zu diesem Zeitpunkt in keinem Fall produktiv eingesetzt werden sollte.

Das Flows Template wird installationsfähig

Wozu die templateDetails.xml da ist und was sie beinhaltet, haben wir bereits besprochen. Nun erweitern wir sie derart, dass unser Template nicht mehr manuell in das Template Verzeichnis kopiert werden muss, sondern wie jedes andere Template installiert werden kann. Dazu führen wir direkt hinter dem Description Tag ein neuen Bereich names Files hinzu:

...
<description>Flows template</description>    
    <files>
    ...
    </files>
...

Hier listen wir nun alle Dateien auf, welche zu unserem Template gehören und bei der Installation beachtet werden müssen. Das Joomla Framework kümmert sich darum, dass diese an die richtige Stelle kopiert werden.
Anders als noch unter Joomla 1.0.x müssen wir nicht jede Datei einzeln aufzählen, sondern können komplette Verzeichnisse mit folder angeben. Was für eine Erleichterung!

<files>
    <filename>templateDetails.xml</filename>
    <filename>template_thumbnail.png</filename>
    <filename>params.ini</filename>
    <filename>flowtools.php</filename>
    <filename>index.php</filename>
    <filename>index.html</filename>
    <filename>favicon.ico</filename>
    <folder>images</folder>
    <folder>html</folder>
    <folder>css</folder>    
</files>

Das sollte alles sein (bis jetzt). Es sind zwei neue Dateien hinzugekommen: template_thumbnail.png und favicon.ico. Das PNG-Bild ist eine kleine Vorschaugrafik unseres Templates und wird nur im Backend bei der Templateauswahl angezeigt. Der Begriff Favicon sollte bekannt sein. Es dient der Darstellung eines kleinen Identifizierungssymbols in der Adresszeile der meisten Browser oder bei deren Favouritenverwaltung.

Jetzt müssen wir nur noch das ganze Template Verzeichnis zu einem ZIP-Archiv zusammenpacken und schon haben wir ein installierbares Joomla Template.

Flows-Template mit flexiblem Raster:
Ansehen: Flows Template Step 9
Download: Flows Template Step 9

Teil 5 des Joomla! 1.5 Template Tutorials ist fertig!

 

Im nächsten Schritt des Tutorials wollen wir uns dann mit den Content Overrides beschäftigen. Wer sich vorab darüber informieren möchte, kann das über einen Artikel zum Thema Overrides tun, den ich vor einer Weile für ein Schweizer Joomla Portal geschrieben habe.

feed9 Kommentare
Sago
April 22, 2010
Stimmen: +0

Wie barrierefrei wird dieses Template am Ende sein? Die Nutzung von Tabellen wird in der Welt der Barrierefreiheit in Frage gestellt, bei diesem Beispiel wird der Content Bereich via Tabellenlayout positioniert, lässt sich das nicht auch ausschließlich mit CSS realisieren?

Insgesamt ist das ein super Tut, besonders die flexible Spaltengestaltung hat meinen, doch kleinen ;-), Horizont erweitert!

report abuse
vote down
vote up
Tom
April 22, 2010
Stimmen: +0

Hallo Sago,
wie am Ende dieses Teils des Tutorials steht, kommen Content Overrides in Teil 5 zur Sprache.

report abuse
vote down
vote up
Ashi
Juli 03, 2010
Stimmen: +0

Hallo Tom,

wie bekomme ich die runden Ecken im Template Bereich hin?

Danke!

report abuse
vote down
vote up
Ashi
Juli 03, 2010
Stimmen: +0

Sorry ich meinte im Content Bereich...

report abuse
vote down
vote up
Tom
Juli 05, 2010
Stimmen: +0

Welche runden Ecken meinen Sie? Im Flows Content Bereich gibt es keine runden Ecken: http://flows.bohacek.de/
Oder meinen Sie die auf der Frontpage?

report abuse
vote down
vote up
Gast
August 13, 2010
Stimmen: +1

Sehr schönes Template, ein großes Lob an Tom.

Ein Problem habe ich allerdings. Habe alles bis hier her (Teil 4) nachvollzogen, funktioniert auch, nur nicht mit dieser ausgelagerten Datei flowtools.php. Da bekomme ich nur eine weiße Seite. Im Quelltext steht auch nicht drin, is komplett leer. Der Fehler muss irgendwo in der Klasse stecken, ich finde ihn aber nicht.

Hast jemand einen Tipp für mich?

Vielen Dank

report abuse
vote down
vote up
Eumel
Oktober 01, 2010
Stimmen: +1

meiner einer ist begeistert
ich wollte schon immer ein eigenes Template erstellen
mit deiner hilfe hier schaffe ich es bestimmt ;-))
Danke
Gruss Eumel

report abuse
vote down
vote up
Cristina
Januar 02, 2012
Stimmen: +1

Kompliment, ein sehr gut verständliches Tutorial. Endlich fange ich an durchzublicken :-) !! Herzlichen Dank!
Ich habe das gesamte Tut nachgebaut. Habe nur noch die Frage, ob man das template für eigene Projekte als Grundstruktur verwenden darf? Insbesonder die Nutzung der flowtools.php?

report abuse
vote down
vote up
Tom
Januar 02, 2012
Stimmen: +1

Vielen Dank. Ja, Sie können das Template und die flowtools.php Datei nutzen. Alles steht unter GPL Lizenz. Bedenken Sie aber, dass dieses Tutorial für Joomla 1.5 Templates geschrieben wurde. Joomla 1.7 bzw. 2.5 Templates unterscheiden sich nicht sehr stark, jedoch gibt es kleine Abweichungen.
Falls wir es noch schaffen diese Seite zu relaunchen, wird das Tutorial für Joomla 2.5 Templates umformuliert.

report abuse
vote down
vote up

Kommentar schreiben
 
  kleiner | groesser
 

security image
Bitte den folgenden Code eintragen


busy
 

B01 realisiert zeitgenössische Online-Kommunikationsmittel.
Wir sind spezialisiert auf OSCMS und unterstützen unsere Kunden vom Konzept bis zum Launch mit Erfahrung und exklusiven Komponenten zur Umsetzung von Communitys, Shops, Portalen und Webseiten.

B01 Kunden

Unsere Ideen, unsere Produkte, unsere Kunden.

B01 empfiehlt:

ZOO Content Construktion Kit

ZOO CCK

Virtuemart Shopsystem

E-Commerce

Joomla SEO

SEO

Joomla Content Editor

Content Editor

Joomla Social Networking

JomSocial