Fluid-Layout entwickeln für Typo3

Aus Debacher-Wiki
Wechseln zu:Navigation, Suche

Schon seit Typo3 8.x basieren unsere Typo3-Layouts auf der Fluid-Engine. Damit gibt es für die Gestaltung der Seite folgende Elemente:

  • PHP-Programme wie z.B. die View-Helper
  • HTML-Code in Layout, Template und Partial
  • Typoscript-Code
  • CSS

PHP

Typo3 selber ist in der Programmiersprache PHP geschrieben, wie viele andere CMS auch. Damit ist es auch abhängig von den Versionen dieser Sprache, aktuell ist 7.4. Typo3 funktioniert nicht mit jeder PHP-Version.

Normalerweise hat man für die Layout-Entwicklung eher selten direkt mit PHP zu tun. Lediglich für die Entwicklung der nettgrids habe ich z.B. PHP-Code benötigt, in Form der ViewHelper.

Hier einmal der VerzeichnisViewHelper.php

<?php
namespace Netthelp\nettgrids\ViewHelpers;
/**
  * ViewHelper zur Rückgabe einer Liste von Bildern in einem Verzeichnis
  * @author  Uwe Debacher 
  * @version 2.0.1 vom 6.10.2020 
 */

class VerzeichnisViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper {
  // output html since TYPO3 8LTS
  protected $escapeOutput = false;
  
    public function initializeArguments()
    {
        $this->registerArgument('verzeichnis', 'string', 'Verzeichnisname', true);
    }
  

  /**
   * Hole die Dateien im Pfad
   *
   * @param  verzeichnis $string mit dem Verzeichnispfad 
   * @return array  die Liste der Dateien mit Pfad 
   */
  public function render() {
    $verzeichnis = $this->arguments['verzeichnis'];
    $root=$_SERVER['DOCUMENT_ROOT'];
    $pfad=str_replace("1:", "/fileadmin", $verzeichnis);
    $dateien=array();

    $d = scandir($root.$pfad);

    foreach ($d as $eintrag) {
     if (is_file($root.$pfad.$eintrag))
      if (in_array(substr($eintrag, -3), array('png', 'PNG', 'gif', 'GIF', 'jpg', 'JPG' ) ))
      $dateien[]= $pfad.$eintrag;
    }
    return ($dateien);
  }
}

Das Programm ist stark objektorientiert, es wird eine vorhandene Klasse erweitert. Das Programm bekommt ein Verzeichnis übergeben und liefert ein Array mit allen Bild-Dateien zurück, die sich aktuell in dem Verzeichnis befinden.

Layout, Template und Partial

Hierbei handelt es sich um eine hierarchische Struktur. Zu einem Layout können mehrere Templates gehören und zu den Templates verschieden Partials. Bei meinen Gestaltungen ist das Layout fast leer, DefaultLayout.html besteht nur aus einer Zeile:

 <f:render section="inhalt" />

Die eigentliche Struktur steckt in den Templates:

  • einspaltig.html
  • zweispaltig.html
  • dreispaltig.html

Hier einmal das einfachste Template einspaltig.html

<f:layout name="DefaultLayout" />
<f:section name="inhalt">

<div id="einspaltig">

  <div class="container">

   
    <div class="row" id="header">
      <div class="col-md-12"><f:cObject typoscriptObjectPath="lib.field_headerimage" /></div>
    </div>

  <f:render partial="navbar" />
  <f:render partial="service" />
  <f:render partial="rootline" />

    <div id="inhalt" class="row equalheight">

      <div class="col-md-12 equal" id="hauptinhalt">
      <a id="content" name="content"></a>
          <!--TYPO3SEARCH_begin-->
          <f:format.raw>{hauptInhalt}</f:format.raw>
          <!--TYPO3SEARCH_end-->
      <p style="font-size:0px">&nbsp;<p> 
      </div>

    </div>  
    <f:render partial="footer" />
  </div>
 </div>
</f:section>

Die ersten beiden Zeilen stellen den Bezug zum übergeordneten Layout dar.

Die meisten Elemente der Datei sind HTML-Elemente. Lediglich die Tags die mit f: beginnen haben eine besondere Bedeutung. Die meisten dieser Tags binden weitere Elemente ein, die Partials. Dies sind hier Elemente, die in mehreren Templates benötigt werden. Es erleichtert die Pflege des Codes, wenn solche Teile nicht mehrfach geschrieben werden.

Bei meinen Templates ist jeweils das letzte Partial die Datei Footer.html

 <div class="row" id="footer">
    <div class="col-md-12"><f:cObject typoscriptObjectPath="lib.field_footer" /></div>
  </div>

Sowohl im Template, als auch im Partial tauchen dann Elemente auf, wie

<f:cObject typoscriptObjectPath="lib.field_footer" />
oder
<f:cObject typoscriptObjectPath="lib.field_headerimage" />

Hierbei handelt es sich um Aufrufe von Typoscript, die wir im nächsten Abschnitt betrachten.

Will man etwas an der Struktur einer Seite verändern, so erfolgt das hier im Template. Manchmal soll z.B. das Partial Service.html nicht oben auf der Seite eingebunden werden, sondern im Bereich des Footers. Solche Struktur-Änderungen der Seite nimmt man hier vor.

Typoscript

Am Typoscript sind vermutlich schon viele Leute verzweifelt. Es handelt sich hierbei um eine eigene Programmiersprache im Kontext von Typo3. Typosrcipt bietet enorme Möglichkeiten, ist aber aus meiner Sicht nicht optimal dokumentiert bzw. schwer nachvollziehbar. CMS-Systeme wir Wordpress verzichten auf eine eigene Programmiersprache, hier erfolgt die Gestaltung direkt mit PHP.

# Dieser Code wird vom Partial footer angesprungen
 lib.field_footer = TEXT
 lib.field_footer {
    data = date : Y
    wrap (
     {$plugin.nettemplate.FooterText} (|)
    )
 }


Der Code sagt folgendes. Der Footer ist ein Element vom Typ TEXT und bekommt als erzeugten Inhalt eine Datumsangabe. In diesem Fall nur das aktuelle Jahr. Dieser Text wird umgeben (gewrappt) von den runden Klammern und dem Inhalt der Variablen $plugin.nettemplate.FooterText. Wraps spielen bei Typoscript eine große Rolle, wenn erzeugte Daten von konstantem Text umgeben werden sollen. Teile des Wraps können vo bzw. hinter den Daten stehen. Die Position der Daten im Wrap wird durch den senkrechten Strich markiert, der hier zwischen den runden Klammern kaum auffällt.

Die Variable stammt übrigens aus dem Konstanten-Editor von Typo3. Hier gibt es Einstellmöglichkeiten für nettemplate, u.a. das Feld FooterText.

Etwas aufwändiger ist das Listing für das HeaderImage:

 # Dieser Code wird von den Templates aus angesprungen
 lib.field_headerimage = IMG_RESOURCE
 lib.field_headerimage {
  file.import.data = levelmedia:2, slide
  file.treatIdAsReference = 1
  file.import.listNum = 0
  stdWrap.wrap (
     <div id="skiplink">
      <a class="skip" title="Direkt zur Navigation springen" href="#navigation">Zur Navigation springen</a><br>
      <a class="skip" title="Direkt zum Content springen" href="#content">Zum Content springen</a>
     </div>
     <div id="headerimage" style="background-image:url('/|'); "><a href="/">
      <img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAO2lmDQ==" alt="Zur Startseite" width="135" height="135">
     </a></div>
  )
 }

Auch hier wird ein Element erzeugt, diesmal eine IMG_RESOURCE, kein Image sondern dessen Pfad und Name. Als Quelle für dieses Bild dient das Feld levelmedia aus dem Tab Ressourcen der aktuellen Seite. Sollte sich auf der aktuellen Seite kein Eintrag finden, so wird durch das slide bei den Elternseiten gesucht. Die Zahl 2 gibt die Ebene an, bis zu der gesucht wird. Ebene 1 ist die root-Seite, auf Ebene 2 befindet sich die Ausgangsseite, bis zu der aufwärts gesucht wird.

Dann kommt wieder ein WRAP, im Prinzip reines HTML davor und dahinter ein transparentes Bild, das einen Rücklink auf die Startseite bildet. Dieses Bild wird nicht als Datei eingebunden, sondern als data-Image. Die kryptische Zeichenkette ergibt im Browser das entsprechende Bild. Damit kann man das zusätzliche Laden für ein Bild verhindern. Grundsätzlich lassen sich alle Bilder so einbinden, man kann seine Bilder online konvertieren lassen. Bei großen Bildern lohnt sich das aber nicht.

CSS

Nachdem durch die bisherigen Etappen die Struktur der Seite geregelt wurde, kommt jetzt die Gestaltung ins Spiel, dafür ist das CSS zuständig. CSS war lange Zeit ein schwieriges Thema, da viele Details nicht exakt vorgeschrieben sind und die Browser daher manche Dinge unterschiedlich gehandhabt haben. Das hat sich gebessert, seit es Systeme wie Bootstrap gibt. Bootstrap, wir benutzen die Version 3, vereinheitlicht die grundlegenden Einstellungen für die CSS-Elemente und stellt Elemente zur Verfügung, die immer wieder benötigt werden.

Die Einstellungen aus dem Bootstrap-Paket können dann von eigenen Einstellungen überschrieben bzw. ergänzt werden. Die Verknüpfung erfolgt über die IDs und Klassen aus den HTML-Elementen.

Die Klasse .row ist z.B. im Bootstrap-Paket definiert:

.row {
    margin-right: -15px;
    margin-left: -15px;
}

Hier werden nur Abstände zu den Seiten gesetzt.

Die ID #footer ist in der Datei anpassung.css zu finden

#footer {
 background-color:#000033; 
 text-align: center; 
 color:white; 
 height:auto;
 border: 0; 
 border-top:1px solid #DDDDDD;
 padding-bottom: 12px;
}

Hier werden u.a. die Farben gesetzt, ein Blau für den Hintergrund und Weiß als Textfarbe.