In den letzten Wochen und Monaten habe ich diverse Skins für Templavoila Framework und Sitemgr entwickelt. Diese Skins hatten die Anforderung, dass die Farben und andere Eigenschaften im CSS änderbar sein müssen.
Irrwege beim Erzeugen von dynamischem CSS
Eine der ersten Ideen war es, dass CSS direkt mit TYPOScript zu erzeugen, leider ist der Code schlecht pflegbar und nicht wirklich gut lesbar. Also wurde fluid_css entwickelt, diese Extension nutzt die Vorzüge von Fluid-ViewHelpern und bildet Funktionen, die aus LESSCSS bekannt waren nach. Nachteil des Ansatzes ist der schlecht lesbare Code.
{namespace fcss = Tx_FluidCss_ViewHelpers} <fcss:AddCssAsFile> <fcss:RemoveWhitespace compress="1"> /* setup some dynamic variables, please do not use it to modify assignments! */ <f:if condition="{fcss:CssModify.lightness(color:main-color)} < 50"> <f:then> <fcss:Assign name="contrast1" value="{fcss:CssModify.lighten(color:main-color, delta:'50%')}" /> </f:then> <f:else> <fcss:Assign name="contrast1" value="{fcss:CssModify.darken(color:main-color, delta:'50%')}" /> </f:else> </f:if> a:hover { color: {contrast2}; } </fcss:RemoveWhitespace> </fcss:AddCssAsFile> |
Da auch Grafikdesigner in den Prozess eingebunden wurden, bestand das Problem, regelmäßig die Dateien aus CSS in fluid_css umzuwandeln.
CSS Präprocessoren in TYPO3 – Backend
Folglich konnte dies nicht der letzte Evolutionsschritt sein. Während der weiteren Nachforschungen stellten sich LESS, SASS, SCSS und Turbine als übliche CSS Präprozessoren heraus. Außerdem gibt es für alle diese Sprachen PHP-Bibliotheken, sodass die Umsetzung nicht allzu schwer sein dürfte – also wurde die Idee von DynCSS geboren.
DynCSS ist ein Wrapper, der Hooks im Core nutzt, um die Nutzung von CSS Präprozessoren zu vereinfachen. Werfen wir doch mal einen Blick auf ein Beispiel aus dyncss_test.
@color: red; @textColor: hsl(hue(@color), saturation(@color), 80%); #typo3-logo h1 { color: @textColor!important; } |
Dieses Beispiel kann also die Farbe der Überschrift neben dem TYPO3 Logo ändern. Die Farbe steht in der Less-Datei, sodass der Designer mit seinen bekannten Werkzeugen arbeiten kann.
Die Wrapper für die Parser haben jedoch einen Präprozessor, sodass die Farben auch dynamisch geändert werden können, dazu muss nur der entsprechende Code in den Hook
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'][] |
zum Einfügen der CSS Datei eingefügt werden:
$overrides = t3lib_div::makeInstance('tx_Dyncss_Configuration_BeRegistry'); $options = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dyncss_test']); $overrides->setOverride('color', $options['baseColor']); |
Nun kann wie in der Extension dyncss_test gezeigt, die Farbe des Backends mit einer Einstellung im Extensionmanager geändert werden.
Intern passiert folgendes:
- Über einen Hook im Pagerenderer wird über alle CSS Dateien iteriert, beim Auffinden einer registrierten Dateiendung, wird die Datei an den zuständigen Parser übergeben
- Wie bereits vorhin aufgeführt, ist dies auch mit dynamischen Variablen in der jeweiligen Sprache möglich, dies wiederum wird über einen Präprozessor realisiert, der die Dateien entsprechend anpasst und das Präkompilat in typo3temp/cache/Data/DynCss ablegt
- Im vorletzten Schritt wird die Datei an die Library übergeben, die dann das „dynamische CSS“ in CSS umwandelt
- Am Ende werden dann Statements wie „url(pfad)“ korrigiert, damit diese wieder auf die korrekten Dateien verweisen (ist noch nicht komplett implementiert).
Außerdem wird über filemtime und diverse Hashs sichergestellt, dass eine Konfiguration von Overrides zusammen mit einer Datei jeweils nur einmal kompiliert wird.
CSS Präprozessoren in TYPO3 – Frontend
Eigentlich war ja das Ziel die Nutzung des dynamischen CSS im Frontend, das ist nun relativ einfach möglich.
Um eine CSS Datei einzubinden, wird im TYPOScript der Seite Folgendes definiert:
page.includeCSS.file1 = {$templavoila_framework.skinPath}contrib/less/main.less plugin.tx_dyncss { overrides { color = TEXT color.value = {$main-color} } } |
Hier wird also eine LESS Datei eingebunden und kompiliert, außerdem wird die Variable „color“ mit dem Inhalt der TYPOScript-Konstante {$main-color} überschrieben. Damit ist es möglich, mit einem Stylesheet diverse Optionen abzubilden.
Hier können mit imgResource auch Bilder dynamisch in die CSS Datei eingebunden werden.
Für die Nutzung einer Turbine Datei wird eben diese angegeben, ansonsten bleibt der Code unverändert.
Einschränkungen
Die Erweiterung dyncss bietet diverse Optionen, durch die Optimierung auf Geschwindigkeit hat die Erweiterung aber auch gewisse Einschränkungen:
- Dynamisch änderbare Variablen müssen in der Wurzeldatei definiert werden (gilt bei Nutzung von include, @import, etc.
- Änderungen werden nur bei invalidiertem PageCache oder mit deaktiviertem Cache sofort übernommen, wenn der Präprozessor keine eigene Cacheverwaltung hat (analog SCSS), werden Änderungen nur in der Wurzeldatei erkannt.
- Aufgrund eines Bugs in t3lib_pagerenderer wird das Ergebnis des Hooks zum Manipulieren der CSS Dateien nicht im Cache genutzt, folglich wird für das Frontend ein anderer gecachter Hook mit XMLDOM verwendet.
Roadmap
Bis zum neuen Jahr ist es geplant, die letzten Unschönheiten zu beseitigen und die Dokumentation zu vervollständigen, danach wird die Extension im TER verfügbar sein.
Die Extension läuft sowohl im der aktuellen TYPO3 CMS 6.0 als auch in TYPO3 CMS 4.5, die Versionen 4.6 und 4.7 wurden nicht getestet.
Ich freue mich über euer Feedback und eventuelle weitere CSS-Präprozessoren an typo3@kay-strobach.de