Cascading Style Sheets ::Artikel
Serverseitige Konstanten für CSS
Die Erstellung von Webseiten ist durch die Verbreitung von Stylesheets deutlich einfacher geworden. Viele Webentwickler vermissen aber immer noch die Möglichkeit, Variablen wie in Programmiersprachen zu definieren. Diese CSS-Funktionalität hat das W3C uns bisher verwehrt und das wird sich auch in absehbarer Zukunft nicht ändern. Gründe dafür gibt es einige:
- Ein Server hat mit dem Inhalt von Stylesheets nichts zu tun, sie werden erst durch den Browser abgearbeitet. Die dazu nötigen Abläufe sind bereits heute so komplex, dass einige Browserhersteller es für wirtschaftlicher halten, sich den Programmieraufwand zu sparen und bestimmte Anforderungen erst gar nicht zu unterstützen. Diese Anforderungen werden durch CSS 3 noch deutlich steigen.
- Jede Art von Scripting ist eine potentielle Sicherheitslücke für den Browser.
- Ebenso wie HTML ist CSS keine Programmiersprache, sondern wurde von Anfang an als Präsentationssprache konzipiert. Deshalb sind auch die üblichen Merkmale einer Script- oder Programmiersprache wie Abfragen, Schleifen und natürlich Konstanten und Variablen in CSS nicht vorhanden.
Um was geht es?
Sicher kennen Sie die Situation, dass dieselben Werte für Text, Links, Hintergründe etc. in verschiedenen Sektionen einer Website auftreten. So können Buttons in allen Containern dieselbe Farbe, dieselbe Schrift usw. haben. Das kann insbesondere bei längeren und komplexen Stylesheets dazu führen, dass in vielen Regeln dieselben Werte deklariert werden müssen. Will man dann das Design auch nur geringfügig ändern, müssen diese Werte an allen Stellen ihres Auftretens angepasst werden.
Wie hat man das bisher gelöst?
- Man arbeitet mit 'Suchen und Ersetzen' und ändert dieselben Werte an allen Stellen im Stylesheet gleichzeitig. Diese Arbeitsweise bietet nur eine indirekte Kontrolle der durchgeführten Ersetzungen, indem man das Webdokument am Bildschirm betrachtet. Auch ist es nicht möglich, Deklarationen getrennt voneinander zu behandeln, die denselben Wert haben, z. B. 'Submit'- und 'Reset'-Button mit demselben Hintergrund werden durch diese Vorgehensweise immer gleich behandelt.
- Gruppierungen werden schnell unübersichtlich und sind in diesem Fall nur eingeschränkt verwendbar.
Als Lösung bietet sich hier die Verwendung von Konstanten an, die wir in das Stylesheet einfügen und für die beim Aufruf die jeweils aktuellen Werte eingesetzt werden. Bei Änderung des Designs brauchen wir nur einmal die Konstanten zu ändern, nicht aber verschiedene Werte längs durch das gesamte Stylesheet. Dies wird dann zum besonderen Vorteil, wenn mehrere Personen am selben Projekt arbeiten.
Lösung per Script durch PHP
Im August 2005 stellte Shaun Inman eine Lösung des Problems vor (siehe Hinweis unten).
Funktionsweise
'Aber ... Moment mal! CSS erlaubt gar keine Konstanten,' wird spätestens jetzt jeder einwenden. Das ist völlig richtig, denn wenn wir ein Stylesheet mit derartigen Konstanten an einen Browser schicken, passiert im besten Fall gar nichts, im schlimmsten Fall gibt der Browser die gesamte Seite so aus, wie wir sie gerade nicht haben wollten.
Das Verfahren ist so einfach wie genial: zunächst definieren wir unsere Konstanten im Kopf des Stylesheets und setzen dann für alle Werte, die wir so definieren wollen, die entsprechenden Konstantenwerte ein. Anschließend lassen wir unser Stylesheet durch eine serverseitige Verarbeitung laufen, bevor wir es an die Browser schicken.
Die Definition der Konstanten erfolgt in derselben Syntax, die wir von den @-Regeln bereits kennen:
@server constants { konstantenName: konstantenWert; }
Die dazu gehörenden Deklarationen definieren wir genauso wie alle anderen Eigenschaften:
selektor { eigenschaft: konstantenName; }
Wird dieses Stylesheet nun von einem Browser aus abgerufen, dann ersetzt die serverseitige Verarbeitung den Wert konstantenName
in der Deklaration durch den im Konstantenbereich definierten Wert konstantenWert
.
Hier ist ein einfaches praktisches Beispiel (der Website von Shaun Inman entnommen):
@server constants { linkColor: #ab6666; linkColorHover: #710101; } a { color: linkColor; } a:hover { color: linkColorHover; }
Nach der Verarbeitung wird daraus dieses:
a { color: #ab6666; } a:hover { color: #710101; }
Hier sehen wir schon, dass ein langer Konstantenname auch den Namen einer kürzeren Konstanten enthalten kann, beide werden trotzdem richtig aufgelöst. Ein etwas komplizierteres Beispiel könnte so aussehen:
@server constants { generalBodyFont: Georgia,"Times New Roman",serif; generalTablesFont: "Trebuchet MS",Verdana,sans-serif; } #main p { font-family: generalBodyFont; font-size: 1em; } #main td { font-family: generalTablesFont; } #navigation a { font-family: generalBodyFont; font-size: 0.9em; }
Daraus wird:
#main p { font-family: Georgia,"Times New Roman",serif; font-size: 1em; } #main td { font-family: "Trebuchet MS",Verdana,sans-serif; } #navigation a { font-family: Georgia,"Times New Roman",serif; font-size: 0.9em; }
Dies zeigt schon ein wenig auf, welche Vereinfachungen möglich sind. Als Namen der Konstanten dürfen wir jedoch keine der bekannten CSS-Eigenschaften oder Schlüsselworte verwenden - es sei denn, wir wollten unsere Kunden nachhaltig verärgern.
Ebenfalls möglich ist, die Konstanten in einer Extra-Datei vorzuhalten und in jede CSS-Datei zu importieren. Das funktioniert analog der @import
-Syntax:
@server url(constants.css);
Installation
Die Vorbereitungen zur Nutzung dieser Technik sind relativ einfach. Alles, was wir brauchen, ist ein kurzes PHP-Script, das in das CSS-Verzeichnis auf dem Server hochgeladen wird. Dieses Script dient dazu, das Stylesheet serverseitig zu verarbeiten und alle Konstanten in valides CSS umzusetzen. Die Zip-Datei dafür können Sie hier ohne Beispiele und hier mit Beispielen herunterladen (auch für Mac OS X). Entfernen Sie im Script bitte nicht die Hinweise auf den Urheber. Shaun Inman hat das Script in seiner Freizeit entwickelt und stellt es gratis zur Verfügung.
Damit das PHP-Script unsere CSS-Datei überhaupt verarbeitet, müssen wir noch ein paar Zeilen in der Datei .htaccess
auf dem Server einfügen:
RewriteEngine on RewriteCond %{REQUEST_URI} \.css$ RewriteRule ^(.+)$ css-ssc.php?css=%{REQUEST_URI}
Da die CSS-Konstanten mit mod_rewrite
arbeiten, brauchen wir den Dateityp '.css' nicht per AddType
als PHP-geparste Datei zu definieren.
Weitere Vorteile
Das Script läuft relativ schnell: es benötigt zur Abarbeitung, auch für einige Dutzend Konstanten in mehreren Stylesheets, nur einige Tausendstelsekunden.
Die CSS-Dateien werden bei jedem Aufruf durch den Browser neu erzeugt. Deshalb stimmt die Datumsinformation niemals mit der im Browser-Cache gespeicherten überein. CSS-SSC speichert aber das Datum der letzten Änderung jeder Datei und sendet dementsprechend die korrekten Headerinformationen an den Browser. Dadurch wird vermieden, dass der Server dieselbe Datei bei jedem Aufruf neu verarbeiten muss.
Einschränkungen
- Import anderer CSS-Dateien ist nur vom selben Verzeichnis möglich. Der Grund dafür ist, dass Shaun Inman das Script kürzer und einfacher halten wollte.
- Die verwendeten Konstanten dürfen nicht mit bekannten CSS-Eigenschaften oder Schlüsselworten identisch sein. Bezeichnungen wie
NavColor
, die Namen von Eigenschaften enthalten, sind aber verwendbar. Am besten umgeht man das Problem, indem man seinen Konstanten deutsche Namen gibt. - Prinzipbedingt sind auch Berechnungen per
calc()
nicht möglich. Da das Script serverseitig abläuft, sind die clientseitigen Bedingungen nicht bekannt und Ausdrücke wiecalc(50%-10px)
nicht lösbar. Die einfache Angabe von50%
oder1em
funktioniert aber problemlos. - Und letztlich ist auch der Disclaimer wichtig, dass es keine Garantie geben kann. Jeder ist für Schäden, die durch Anwendung dieser Technik entstehen, selbst verantwortlich.
Lösung ohne Script durch Server-Side Includes
Server-Side Includes sind schon relativ alt, sie stammen bereits aus der Vor-PHP-Ära. Heute kommen sie nur noch selten zum Einsatz, da ihr Funktionsumfang relativ gering ist. Wer aber nicht mehr will als einzelne Konstanten oder Variablen zu ersetzen, kann mit SSI durchaus gut klarkommen.
Funktionsweise
Die grundsätzliche Vorgehensweise ist hier dieselbe wie oben: zuerst werden Variablen definiert, denen wir anschließend Werte zuordnen. (Wir verwenden sie hier auch mit konstanten Werten, sie werden dennoch 'Variablen' genannt.)
Die Syntax zur Definition der Variablen sieht so aus:
<!--#set var="VariablenName" value="VariablenWert" -->
Für die Ausgabe von Variablen ist die SSI-Direktive #echo
zuständig. Mit folgender Syntax werden die Variablen in die CSS-Deklarationen eingesetzt:
selektor { eigenschaft: <!--#echo var="variablenName" -->; }
Diese Syntax wenden wir nun auf das von oben bereits bekannte Beispiel an:
<!--#set var="linkColor" value="#ab6666" --> <!--#set var="linkColorHover" value="#710101" --> a { color: <!--#echo var="linkColor" -->; } a:hover { color: <!--#echo var="linkColorHover" -->; }
Et voilà, auch hier wird dasselbe CSS an den Browser geschickt:
a { color: #ab6666; } a:hover { color: #710101; }
Auch das zweite oben genannte Beispiel können wir leicht per SSI nachvollziehen:
<!--#set var="generalBodyFont" value="Georgia,'Times New Roman',serif;" --> <!--#set var="generalTablesFont" value="'Trebuchet MS',Verdana,sans-serif;" --> #main p { font-family: <!--#echo var="generalBodyFont" -->; font-size: 1em; } #main td { font-family: <!--#echo var="generalTablesFont" -->; } #navigation a { font-family: <!--#echo var="generalBodyFont" -->; font-size: 0.9em; }
Daraus wird:
#main p { font-family: Georgia,'Times New Roman',serif; font-size: 1em; } #main td { font-family: 'Trebuchet MS',Verdana,sans-serif; } #navigation a { font-family: Georgia,'Times New Roman',serif; font-size: 0.9em; }
Hier folgt noch der Link zu einem Funktionsbeispiel:
Beispiel 1
Installation
Zur Verwendung von Server-Side Includes benötigen wir kein Script, denn SSI werden bereits vom Server zur Verfügung gestellt. Aber auch hier müssen wir einige Server-Einstellungen anpassen, um diese Technik für Stylesheets zu nutzen. Diese Ergänzungen tragen wir in die Datei .htaccess
ein, für lokalen Betrieb können wir auch die Konfigurationsdatei httpd.conf
ändern.
Zuerst ermöglichen wir die SSI-Verarbeitung durch die Anweisung
Options +Includes
oder
Options All
Wenn in der 'conf'-Datei bereits die Option All
gesetzt ist, dann sollte das so bleiben, um nicht andere Optionen des Servers einzuschränken.
Dann müssen wir dem Server mitteilen, dass CSS-Dateien auch auf SSI untersucht werden sollen. Dies geschieht durch die Direktive AddHandler
. Vom Server auf SSI analysierte HTML-Dateien werden in der Regel durch die Endung '.shtml' mit vorangestelltem 's' kenntlich gemacht. Analog dazu können wir die zu analysierenden Stylesheet-Dateien mit der Endung '.scss' benennen, wir können aber auch jede CSS-Datei untersuchen lassen:
AddHandler server-parsed .scss
oder
AddHandler server-parsed .css
Schließlich müssen wir nur noch dem MIME-Typ definieren, damit der Browser diese Dateien auch als Stylesheet-Dateien erkennt:
AddType text/css .scss
Das ist nur dann nötig, wenn wir die neue Endung '.scss' eingeführt haben.
Vor- und Nachteile
- Nicht alle Hostingpakete, besonders im unteren Preissegment erlauben PHP-Funktionalität, sodass man hier eher die SSI-Lösung anwenden würde. Andererseits werden Websites von einem Umfang, der CSS-Konstanten rentabel macht, nur in seltenen Fällen in diesem Segment gehostet.
- Arbeitet man mit den SSI-Konstanten, ist keine Extra-Anweisung notwendig, um ein Script auf die Konstanten aufmerksam zu machen. Das erledigt der Server. Die
@constants
-Anweisung der PHP-Lösung ist aber anwenderfreundlicher als die SSI-Syntax. - Es ist nicht möglich, beide Verfahren zu mischen, um das Beste von beiden zu bekommen.
Ausblick
Da die CSS-SSC-Technik relativ neu ist und eine einfache Lösung für ein bekanntes Problem bietet, sind hier sicherlich noch weitere Entwicklungen zu erwarten.
TOP
Hinweis:
Der PHP-Teil dieses Artikels basiert auf den Veröffentlichungen von Shaun Inman (CSS-SSV, CSS Server-Side Constants und Quick CSS SSC Update) und den Beiträgen von Eric Meyer auf Meyerweb und bei css.discuss. Er inspirierte mich zu dem Versuch, etwas ähnliches mit Server-Side Includes zu realisieren.