Individuelle Layouts für Unterseiten — ein Typo3-Experiment

Individuelle Layouts für Unterseiten — ein Typo3-Experiment
Von Lars Ebert am 29.04.13, 11:00
Kategorien: Content Management Systeme, PHP, Programmieren, Tutorials and Typo3

In letzter Zeit wurde ich oft von Webdesignern gefragt, was beim Gestalten einer Typo3-Layouts beachtet werden muss. Meine Antwort lautete immer, dass der Inhalt der einzelnen Seiten, den man per Typo3 pflegt, möglichst einfach gehalten sein sollte. Doch neulich viel es mir auf, dass es absurd ist, das Layout an Typo3 anzupassen. Sollte es nicht—grade bei einem so mächtigen CMS—genau anders herum sein? Sollte Typo3 sich nicht genau so konfigurieren lassen, dass sich jedes beliebige Layout und Design darstellen lässt?

Also startete ich ein Experiment: Bei meinem nächsten Auftrag verschwieg ich dem Designer, dass die Seite pflegbar sein sollte und bekam ein Design, bei dem der Inhalt jeder Unterseite individuell aufgebaut war. Ziel des Experimentes sollte es sein, den Spagat zwischen möglichst leichter Pflegbarkeit und möglichst individuellem Design zu finden. Das Ergebnis war sowohl überraschend einfach also auch überraschend gut. Wie immer bei Typo3 muss man nur wissen, wie es geht!

Das Design

Hier ist eine Auswahl von drei Unterseiten-Layouts, die ich bekommen hatte.

Ich hatte an dieser Stelle drei Anforderungen für die Umsetzung in Typo3. Erstens sollte das Design möglichst genau eingehalten werden, zweitens soll die Pflege der einzelnen Seiten möglichst simpel sein und drittens sollte die Umsetzung möglichst sauber und schnell sein.

Schaut man sich die Entwürfe an, kommen sofort einige Fragen auf. Die Team-Seite steht von der Struktur fest, aber die Team-Mitglieder und Bilder müssen ausgetauscht werden können—und das so einfach wie möglich. Auf der Standorte-Seite müssen nur die Bilder geändert werden können. Auf der Startseite ist nur der Text auf der linken Seite zu editieren, das Video sollte der Einfachheit halber statisch eingebunden sein.

Schließlich konnte ich so für jede Unterseite einen kleinen Bereich eingrenzen, der editierbar sein muss. Also entschloss ich mich, für jede Unterseite das Template individuell anzupassen.

Schritt 1: Grundstruktur der Typo3-Seite

Wir beginnen damit, das Basis-Layout der Webseite in Typo3 umzusetzen.

<body>
	<!-- ###BODY### begin -->
	<header>
		###HEADER_IMAGE###
		<h1><a href="/"><img src="/fileadmin/templates/curos/img/logo.png" alt="" id="logo" /><img src="/fileadmin/templates/curos/img/curos.png" alt="Curos" /></a></h1>
		<nav>
			<!-- ###NAV### begin -->
			<a href="#" class="active">Startseite</a>
			<a href="#">Leistung</a>
			<a href="#">Team</a>
			<a href="#">Standorte</a>
			<!-- ###NAV### end -->
		</nav>
	</header>
	<section id="content">
		<!-- ###CONTENT### begin -->
			
		<!-- ###CONTENT### end -->
	</section>
	<!-- ###BODY### end -->
</body>

Aus diesem Template können wir nun per TypoScript die Seite generieren. Ich werde hier nur kurz auf diesen Aspekt eingehen. Bei Interesse empfehle ich die Lektüre des Artikels Wie wird aus einem Design eine fertige Typo3-Seite?.

Zunächst legen wir die gewünschte Seitenbaum-Struktur an. Zunächst legen wir die gewünschte Seitenbaum-Struktur an.

Auf der Root-Seite (zu erkennen an der Weltkugel) legen wir nun ein neues Template an. Ich habe hier alles Irrelevante entfernt, sodass wir uns auf den Kern der Sache konzentrieren können.

page = PAGE
page {
  10 = TEMPLATE
  10 {
    template = FILE
    template.file = fileadmin/templates/curos/index.html
    workOnSubpart = BODY
    
    subparts {
      CONTENT = COA
      CONTENT {
        10 < styles.content.get
        10.wrap = <div class="grid6"> | </div>
      }
    }
  }
}

Wir laden also das eben erstellte HTML-Template und erstellen daraus die Seiten in Typo3. Mit Zeile 12 sorgen wir dafür, dass im Inhaltsbereich der Seite der Inhalt der Hauptspalte angezeigt wird. Die Grundstruktur der Seite steht damit, jetzt kann es mit dem individuellen Design der Unterseiten weiter gehen.

Schritt 2: HTML-Struktur der Unterseite

Als nächstes modifizieren wir unsere Template-Datei ein wenig:

<body>
	<!-- ###BODY### begin -->
	<header>
		###HEADER_IMAGE###
		<h1><a href="/"><img src="/fileadmin/templates/curos/img/logo.png" alt="" id="logo" /><img src="/fileadmin/templates/curos/img/curos.png" alt="Curos" /></a></h1>
		<nav>
			<!-- ###NAV### begin -->
			<a href="#" class="active">Startseite</a>
			<a href="#">Leistung</a>
			<a href="#">Team</a>
			<a href="#">Standorte</a>
			<!-- ###NAV### end -->
		</nav>
	</header>
	<section id="content">
		<!-- ###CONTENT### begin -->
		
		<!-- ###PAGE_STARTSEITE### begin -->
		<div id="startseite">
			<section class="grid3">
				###PAGE_CONTENT###
			</section>
			<section id="vContainer">
				<div id="video"><embed width="334" height="281" align="middle"
					type="application/x-shockwave-flash" salign=""
					allowscriptaccess="sameDomain" allowfullscreen="true"
					menu="true" name="vPlayer" bgcolor="#ffffff" devicefont="false"
					wmode="window" scale="noscale" loop="true" play="true"
					pluginspage="http://www.adobe.com/go/getflashplayer_de"
					quality="high" src="http://GelbeSeiten.v4all.de/vPlayer.swf"
					flashVars="clipID=//v128/85/80V11485/80V11485&TAF=&linkURL="
				/></div>
			</section>
		</div>
		<!-- ###PAGE_STARTSEITE### end -->
		
		<!-- ###CONTENT### end -->
	</section>
	<!-- ###BODY### end -->
</body>

Wir haben nun einen HTML-Abschnitt definiert, der nur auf der Startseite sichtbar sein soll. In Zeile 21 befindet sich ein Marker, der später durch den editierbaren Inhalt ersetzt werden soll. Darum kümmern wir uns jetzt.

Auf der Startseite legen wir über das Template-Modul nun ein Erweiterungs-Template an. Mit Erweiterungs-Templates kann man zusätzliches TypoScript definieren, das nur auf der jeweiligen Seite (und deren Unterseiten) ausgeführt wird. Dies machen wir uns jetzt zunutze, um die Struktur der Seite zu Überschreiben.

page.10.subparts {
  CONTENT >
  CONTENT = TEMPLATE
  CONTENT {
    template = FILE
    template.file = fileadmin/templates/curos/index.html
    workOnSubpart = PAGE_STARTSEITE
    
    marks {
      PAGE_CONTENT < styles.content.get
    }
  }
}

Mit diesem TypoScript überschreiben wir den Inhalt des CONTENT-Subpart, den wir im Haupttemplate definiert haben. In Zeile 2 setzen wir den Inhalt wieder auf Null, danach definieren wir, dass für diesen Subpart-Marker ein neues Template herangezogen wird und öffnen somit das Template, in dem wir den HTML-Abschnitt definiert haben. Hier geben wir als aktiven Subpart-Marker PAGE_STARTSEITE und fügen den Inhalt der Hauptspalte in den Marker PAGE_CONTENT ein. Das Resultat ist, dass der Inhalt der Seite, den wir in Typo3 definieren, nun in der linken Spalte eingefügt wird. Rechts steht das Video, was automatisch im Template eingebunden wird.

Die Startseit der Webseite hat nun ein indivduelles Design. Die Startseit der Webseite hat nun ein indivduelles Design. Der in pink markierte Bereich ist editierbar.

Schritt 3: Backend-Layout

Um es dem Redakteur der Seite noch einfacher zu machen, legen wir nun ein neues Backend-Layout an. Backend-Layouts sind die neue, bessere Methode, um die angezeigten Spalten im Backend anzupassen. Über ein Backend-Layout können wir Typo3 mitteilen, welche editierbaren Bereiche es im Frontend-Layout gibt und wie diese angeordnet sind.

Da unser Grundlayout nur eine Spalte hat, macht es Sinn, im Backend auch nur eine Spalte zur Verfügung zu stellen. So spart man sich, dem Redakteur zu erklären, warum er nur in der einen Spalte Inhalte eintragen kann.

Um ein Backend-Layout anzulegen, schauen wir uns die Wurzelseite mit dem Listen-Modul an und klicken oben auf das Icon, um einen neuen Datensatz zu erstellen. Hier wählen wir unter Systemdatensätze den Punkt Backend-Layout. Als Titel geben wir hier »Standard« ein, da dies unser Standard-Layout werden soll. Unter Konfiguration können wir jetzt die Bereiche definieren.

backend_layout {
	colCount = 1
	rowCount = 1
	rows {
		1 {
			columns {
				1 {
					name = Hauptspalte
					colPos = 0
				}
			}
		}
	}
}

Da wir nur eine Spalte brauchen, reicht dieser Code, um die Spalten zu definieren. Wichtig ist, dass wir in Zeile 9 als colPos 0 eintragen. Diese Zahl steht für die ID der Spalte, wobei 0 für die Hauptspalte, 1 für die linke Spalte, 2 für die rechte Spalte und 3 für die Randspalte steht. Dies hat nichts mit der tatsächlichen Position der Spalte im Front- oder Backend zu tun. Es definiert lediglich, wie wir im TypoScript auf die Spalten zugreifen können. So greifen wir auf die 0 zum Beispiel mit styles.content.get, auf 1 mit styles.content.getLeft usw.

Nun können wir das Layout speichern und müssen in den Seiteneigentschaften der Wurzelseite nur noch definieren, dass dieses Backend-Layout standardmäßig verwendet werden soll.

Hier können wir defnieren, dass für dies Seite und alle Unterseiten das gewählte Backend-Layout verwendet wird. Hier können wir defnieren, dass für dies Seite und alle Unterseiten das gewählte Backend-Layout verwendet wird.

Bearbeiten wir nun die Wurzelseite, sehen wir den Effekt des Backend-Layouts. Bearbeiten wir nun die Wurzelseite, sehen wir den Effekt des Backend-Layouts.

Auf der Startseite brauchen wir das Backend-Layout nicht weiter anpassen, denn auch hier gibt es nur eine Spalte. Nun widmen wir uns exemplarisch einigen anderen Unterseiten, um das eben getestete weiter zu vertiefen.

Die Unterseite »Team«

Auf der Unserseite »Team« müssen die Mitarbeiter und Fotos austauschbar sein. Hier können wir die individuellen Templates und Backend-Layouts wunderbar weiter anwenden. Wieder erweitern wir zuerst unser HTML-Template.

<body>
	<!-- ###BODY### begin -->
	<header>
		###HEADER_IMAGE###
		<h1><a href="/"><img src="/fileadmin/templates/curos/img/logo.png" alt="" id="logo" /><img src="/fileadmin/templates/curos/img/curos.png" alt="Curos" /></a></h1>
		<nav>
			<!-- ###NAV### begin -->
			<a href="#" class="active">Startseite</a>
			<a href="#">Leistung</a>
			<a href="#">Team</a>
			<a href="#">Standorte</a>
			<!-- ###NAV### end -->
		</nav>
	</header>
	<section id="content">
		<!-- ###CONTENT### begin -->
		
		<!-- ###PAGE_STARTSEITE### begin -->
		<div id="startseite">
			<section class="grid3">
				###PAGE_CONTENT###
			</section>
			<section id="vContainer">
				<div id="video"><embed width="334" height="281" align="middle"
					type="application/x-shockwave-flash" salign=""
					allowscriptaccess="sameDomain" allowfullscreen="true"
					menu="true" name="vPlayer" bgcolor="#ffffff" devicefont="false"
					wmode="window" scale="noscale" loop="true" play="true"
					pluginspage="http://www.adobe.com/go/getflashplayer_de"
					quality="high" src="http://GelbeSeiten.v4all.de/vPlayer.swf"
					flashVars="clipID=//v128/85/80V11485/80V11485&TAF=&linkURL="
				/></div>
			</section>
		</div>
		<!-- ###PAGE_STARTSEITE### end -->
		
		<!-- ###PAGE_TEAM### begin -->
		<div id="team">
			<h2 class="grid2">Lebensläufe unserer Ärzte</h2>
			<h3 class="grid4 aRight">Das sind unsere Ärzte in <span class="green">Wesseling</span>, <span class="blue">Köln-Rodenkirchen</span> und <span class="red">Bornheim</span></h3>
			<div class="clear"></div>
			<section id="doctors">
				###PAGE_DOCTORS###
			</section>
			<section id="teams">
				###PAGE_TEAMS###
			</section>
		</div>
		<!-- ###PAGE_TEAM### end -->
		
		<!-- ###CONTENT### end -->
	</section>
	<!-- ###BODY### end -->
</body>

Als nächstes fügen wir auf der Seite »Team« ein neues Extension-Template hinzu.

page.10.subparts {
  CONTENT >
  CONTENT = TEMPLATE
  CONTENT {
    template = FILE
    template.file = fileadmin/templates/curos/index.html
    workOnSubpart = PAGE_TEAM
    
    marks {
      PAGE_DOCTORS < styles.content.get
      PAGE_TEAMS < styles.content.getLeft
    }
  }
}
Diese beiden Bereiche auf der Team-Seite sind jetzt getrennt voneinander editierbar. Diese beiden Bereiche auf der Team-Seite sind jetzt getrennt voneinander editierbar.

So weit so gut. Da die beiden Bereiche vertikal untereinander angeordnet sind, macht es Sinn, das in einem neuen Backend-Layout auch so darzustellen. Dazu legen wir ein neues Backend-Layout auf der Seite »Team« an.

backend_layout {
	colCount = 1
	rowCount = 2
	rows {
		1 {
			columns {
				1 {
					name = Ärzte
					colPos = 0
				}
			}
		}
		2 {
			columns {
				1 {
					name = Teams
					colPos = 1
				}
			}
		}
	}
}

Wenden wir dieses Backend-Layout auf die Team-Seite an, können wir auf der Team-Seite auch zwei übereinanderliegende »Spalten« oder eher Zeilen bearbeiten. Nun müssen wir es dem Redakteur noch möglichst einfach machen, die Mitarbeiter einzupflegen. Meiner Meinung nach, ist es hier am einfachsten, wenn die Mitarbeiter jeweils als einzelnes Bild-Inhaltselement eingepflegt werden. Der Redakteur kann als Überschrift den Namen des Mitarbeiters, als Link den Link zum Lebenslauf und als Bild eben das Bild des Mitarbeiters einpflegen. Hier ergibt sich jetzt nur ein Problem.

Schritt 4: Anpassen des Content-Renderings

Mit dieser HTML-Struktur werden Bildelemente in Typo3 standardmäßig ausgeben. Mit dieser HTML-Struktur werden Bildelemente in Typo3 standardmäßig ausgeben.

Leider ist die HTML-Struktur, die Typo3 uns standardmäßig für Bild-Elemente vorgibt, nicht sonderlich geeignet für unser Vorhaben. Deshalb werden wir nun die Ausgabe dieser Elemente wieder etwas verändern.

tt_content.image {
  10 >
  10 = CASE
  10 {
    key.field = colPos
    0 = COA
    0 {
      10 = TEXT
      10 {
        field = header
        noTrimWrap = |<h4>Dr. med. <div class="name">|</div></h4><div class="clickMe">Mit <strong>Klick</strong> zum Lebenslauf</div>|
      }
      stdWrap.typolink {
        parameter {
          field = header_link
        }
      }
    }
    1 = COA
    1 {
      10 = TEXT
      10 {
        field = header
        noTrimWrap = |<h3>Team <span class="name">|</span></h3>|
      }
    }
  }
  20 {
    addClassesImage >
    borderClass >
    addClassesCol >
    imageStdWrap >
    imageColmnStdWrap >
    layout >
    stdWrap >
    rendering >
    
    layout = TEXT
    layout.value = ###IMAGES###
  }
  wrap = <figure> | </figure>
}

Über tt_content können wir die Ausgabe von Elementen beeinflussen. Es macht Sinn, sich das ganze mal im TypoScript-Objekt-Browser anzuschauen, dann ergibt der Großteil des Scripts Sinn.

Kurz gesagt sorgen wir mit diesem TypoScript dafür, dass alle unnötigen HTML-Tags verschwinden und jedes Bild in ein Figure-Element eingeschlossen wird. Interessant ist die Zeile 3 und folgende Zeilen, denn hier sorgen wir dafür, dass die Elemente aus Spalte 0 und 1 getrennt angesprochen werden. So können wir den Team-Fotos eine andere Struktur geben als den Ärzten. Folgende HTML-Struktur haben wir nun für die Ärzte definiert:

<figure>
	<a href="team/albert-heidrich/">
		<h4>Dr. med. <div class="name">Albert Heidrich</div></h4>
		<div class="clickMe">Mit <strong>Klick</strong> zum Lebenslauf</div>
	</a>
	<img src="fileadmin/media/team/albert-heidrich2.jpg" alt="" height="165" width="110">
</figure>

Das sieht doch schon viel besser aus! Wir können also für beliebige Seiten und sogar nach Spalten getrennt das Aussehen der Content-Elemente beeinflussen. Auf dieser Seite war das durchaus praktisch.

Die Unterseite »Standorte«

Unter Standorte sollen dem Nuter drei Bildergalerien präsentiert werden. Dazu benutze ich meine eigene Extension lightboxgallery. Aber konzentrieren wir uns wieder auf unsere individuellen (Backend-)Layouts. Wieder fügen wir einen neuen Abschnitt zu unserem HTML-Template hinzu.

<body>
	<!-- ###BODY### begin -->
	<header>
		###HEADER_IMAGE###
		<h1><a href="/"><img src="/fileadmin/templates/curos/img/logo.png" alt="" id="logo" /><img src="/fileadmin/templates/curos/img/curos.png" alt="Curos" /></a></h1>
		<nav>
			<!-- ###NAV### begin -->
			<a href="#" class="active">Startseite</a>
			<a href="#">Leistung</a>
			<a href="#">Team</a>
			<a href="#">Standorte</a>
			<!-- ###NAV### end -->
		</nav>
	</header>
	<section id="content">
		<!-- ###CONTENT### begin -->
		
		<!-- ###PAGE_STARTSEITE### begin -->
		<div id="startseite">
			<section class="grid3">
				###PAGE_CONTENT###
			</section>
			<section id="vContainer">
				<div id="video"><embed width="334" height="281" align="middle"
					type="application/x-shockwave-flash" salign=""
					allowscriptaccess="sameDomain" allowfullscreen="true"
					menu="true" name="vPlayer" bgcolor="#ffffff" devicefont="false"
					wmode="window" scale="noscale" loop="true" play="true"
					pluginspage="http://www.adobe.com/go/getflashplayer_de"
					quality="high" src="http://GelbeSeiten.v4all.de/vPlayer.swf"
					flashVars="clipID=//v128/85/80V11485/80V11485&TAF=&linkURL="
				/></div>
			</section>
		</div>
		<!-- ###PAGE_STARTSEITE### end -->
		
		<!-- ###PAGE_TEAM### begin -->
		<div id="team">
			<h2 class="grid2">Lebensläufe unserer Ärzte</h2>
			<h3 class="grid4 aRight">Das sind unsere Ärzte in <span class="green">Wesseling</span>, <span class="blue">Köln-Rodenkirchen</span> und <span class="red">Bornheim</span></h3>
			<div class="clear"></div>
			<section id="doctors">
				###PAGE_DOCTORS###
			</section>
			<section id="teams">
				###PAGE_TEAMS###
			</section>
		</div>
		<!-- ###PAGE_TEAM### end -->
		
		<!-- ###PAGE_STANDORTE### begin -->
		<div id="standorte">
			<h2 class="grid2">Unsere Standorte</h2>
			<h3 class="grid4 aRight">Ein Einblick unserer Standorte in <span class="green">Wesseling</span>, <span class="blue">Köln-Rodenkirchen</span> und <span class="red">Bornheim</span></h3>
			<div class="clear"></div>
			<section class="branch green">
				###PAGE_WESSELING###
			</section>
			<section class="branch blue">
				###PAGE_KOELN_RODENKIRCHEN###
			</section>
			<section class="branch red">
				###PAGE_BORNHEIM###
			</section>
		</div>
		<!-- ###PAGE_STANDORTE### end -->
		
		<!-- ###CONTENT### end -->
	</section>
	<!-- ###BODY### end -->
</body>

Diesmal muss es drei horizontal angeordnete Spalten geben. Darum kümmern wir uns nun wieder in unserem Backend-Layout.

backend_layout {
	colCount = 3
	rowCount = 1
	rows {
		1 {
			columns {
				1 {
					name = Wesseling
					colPos = 0
				}
				2 {
					name = Köln-Rodenkirchen
					colPos = 1
				}
				3 {
					name = Bornheim
					colPos = 2
				}
			}
		}
	}
}

Schließlich müssen wir der Seite nur noch ein eigenes Extension-Template verpassen:

page.10.subparts {
  CONTENT >
  CONTENT = TEMPLATE
  CONTENT {
    template = FILE
    template.file = fileadmin/templates/curos/index.html
    workOnSubpart = PAGE_STANDORTE
    
    marks {
      PAGE_WESSELING < styles.content.get
      PAGE_KOELN_RODENKIRCHEN < styles.content.getLeft
      PAGE_BORNHEIM < styles.content.getRight
    }
  }
}
Jetzt können wir in drei Spalten die drei Standorte bearbeiten. Jetzt können wir in drei Spalten die drei Standorte bearbeiten.

Fazit: Typo3 muss nicht immer im Einheitsbrei enden!

Wie man sieht, kann man auch mit Typo3 jede Unterseite einzeln gestalten, ohne dafür Abstriche bei der Editierbarkeit machen zu müssen. Ich finde das gut, für mich ist Typo3 damit noch praktischer geworden.

Was sagst du? Kanntest du diese Technik schon oder machst du das anders? Wie findest du diese Technik? Hinterlass mir am besten sofort einen total kontroversen Kommentar weiter unten!