Web 2.0 ist in aller Munde. Nachrichten werden zwischen einzelnen Webseiten ausgetauscht (Stichwort Abonnementdienste wie RSS/Atom). Weblogs schießen wie Pilze aus den Boden. Dynamische Webseiten (DHTML) sowie DOM-Scripting sind in der heutigen Zeit zum Standard geworden. Menüs klappen auf, Texte werden eingeblendet, Seiteninhalte lassen sich einfach verschieben … überall bewegt sich etwas.
Es werden Techniken eingesetzt, die Web-Anwendungen wie Desktop-Anwendungen aussehen lassen (Stichwort Ajax). Rein statische Seiten fristen in den Weiten des Internet nur noch ein Schatten-Dasein.
Und wenn wir ehrlich sind, haben wir uns daran gewöhnt.
Wir erwarten, das Webprogrammierer -und Designer die Seiten so gestalten, das sie attraktiv und „usability“ daher kommen. Das Webseiten auch körperlich beeinträchtigten Menschen zugänglich sind (Stichwort Barrierefreiheit) und nach Möglichkeit in jedem Browser … zumindest einigermaßen … ähnlich aussehen.
Es können Videos und Fotos betrachtet, Musik gehört und Spiele gespielt werden. Animationen, erstellt mit Java, Flash, Javascript oder als GIF-Bild, lassen Webseiten „leben“ (wenn sie uns nicht gerade stören).
Und da ich von diesen Dingen einfach fasziniert bin, habe ich mich daran gesetzt, dem Stylesheet meines Blogs mit Hilfe von PHP ebenfalls etwas Dynamik einzuhauchen.
Anleitung dynamisches Stylesheet
Zuerst muss die Endung der normalen Stylesheet-Datei …
style.css
… durch …
style.css.php
… ersetzt werden.
Eingebunden wird die neue dynamische Stylesheet-Datei wie gewohnt im Head-Bereich der Seite:
<!DOCTYPE html PUBLIC …
<html>
<head>
<link rel="stylesheet" type="text/css" href="pfad_zur_datei/style.css.php" />
</head>
<body>
...
</body>
</html>
Nun wird im neuen Stylesheet innerhalb eines PHP-Blocks der Content-type angegeben, da der Server beim Parsen sonst davon ausgeht, dass es sich hierbei um eine gewöhnliche HTML-Datei handelt. Dazu wird im Kopf der css.php-Datei folgendes deklariert:
<?php header('Content-type: text/css'); /* An dieser Stelle wird der Quellcode eingefügt. Mehr dazu später … */ ?> /* Begin Typography & Colors */ body { font-size: 62.5%; /* Resets 1em to 10px */ font-family: Arial, Helvetica, Sans-Serif; background: #063164; color: #999; text-align: center; } …
Nun „weiß“ der Server Bescheid, gibt die PHP-Datei als CSS-Datei an den Browser und dieser kann die Datei anschließend richtig interpretieren.
Erklärung
Dieser erkennt den eingefügten PHP-Block
<?php … ?>
und arbeitet den dort eingefügten Quellcode ab. Erst danach wird die (inhaltlich geänderte) Datei zurückgeschickt und steht nun dem jeweiligen Browser zur Verfügung. Dieser erkennt, genau wie der Besucher der Seite, durch die explizite Angabe des Content-Types eine ganz normale CSS-Datei. Der PHP-Code kann dagegen nicht eingesehen werden!
Da mir diese Webseite neben dem Bloggen auch als „Bastelstube“ dient (siehe auch mein Kolophon), um Webtechniken anzuwenden, hatte ich mir überlegt, die Hintergrundfarbe beim ersten Aufruf der Seite zufällig aus einem Pool von Hintergrundgrafiken generieren zu lassen. Diese sind bereits als PNG-Dateien auf dem Webspace hinterlegt und werden über den Name eingebunden.
bg_hellgruen.png bg_blau.png bg_beige.png ...
Dazu legte ich zunächst ein Array an, in das die Namen derjenigen Grafiken einfügte wurde, die später angezeigt werden sollen.
$farben = array('weiss', 'schwarz', 'blau', 'gruen', 'beige', 'hellblau', 'hellgruen', 'rose', 'sand', 'grau_gruen');
Aus diesem wird ein zufälliges ausgewählt
$zufall = array_rand($farben, 1);/* ... die 1 kann bei einem
Wert auch weggelassen werden */
$zufalls_farbe = $farben[$zufall];
und danach in einem switch-Kontrollblock die Textfarbe an die jeweilige Hintergrundfarbe angepasst, um einen ausreichenden Kontrast zu garantieren.
switch ($zufalls_farbe) { case 'weiss': $_SESSION['textcolor'] = '#222'; break; case 'beige': $_SESSION['textcolor'] = '#222'; break; case 'hellblau': $_SESSION['textcolor'] = '#222'; break; case 'oliv': $_SESSION['textcolor'] = '#222'; break; case 'rose': $_SESSION['textcolor'] = '#222'; break; case 'hellgruen': $_SESSION['textcolor'] = '#222'; break; case 'sand': $_SESSION['textcolor'] = '#222'; break; case 'grau_gruen': $_SESSION['textcolor'] = '#222'; break; default: $_SESSION['textcolor'] = '#aaa'; break; }
Anstatt des switch-Kontrollblocks kann natürlich auch eine if-Abfrage eingesetzt werden. Ich habe dies lediglich auf diese Art gelöst, um wieder mal mit der switch-Syntax zu arbeiten. Hinsichtlich der Geschwindigkeit dürften sich beide Möglichkeiten (auch bei größeren Datenmengen) nicht wesentlich unterscheiden (unter Programmierern führt dieser Aspekt gern zu ausufernden Diskussionen –> kürzer, schneller …).
Um die einmal ausgewählte Hintergrundfarbe während des Besuchs beizubehalten, wird noch eine Session-Variable erstellt. In dieser wird beim ersten Einlesen der css.php-Datei ebenfalls die zufällig generierte Hintergrundfarbe gespeichert.
$_SESSION['color'] = $zufalls_farbe;
Dies wurde für die Textfarbe bereits schon im switch realisiert.
Normalerweise legt der Browser die CSS- Datei (und noch einige andere Dateien, z.B. Grafiken) im eigenen Cache-Speicher ab und ein erneutes Einlesen ist bei Seitenwechsel nicht mehr nötig. Dadurch kann die Webseite nach dem ersten Aufruf schneller geladen werden.
Da dies aber nicht garantiert ist (was mir meine Erfahrungen auch bestätigen), wird bei jedem Einlesen überprüft, ob diese Session-Variable existiert. Sollte dies der Fall sein, erfolgt keine erneute Auswahl der Hintergrundfarbe, sondern es wird dann der gespeicherte Wert der Session-Variable verwendet. Dafür wird der gesamte Quellcode in eine Abfrage eingeschlossen, welche direkt überprüft, ob die Session-Variable bereits existiert.
if(!isset($_SESSION['color'])) {
...
}
/* Nur wenn die SESSION-Variable noch nicht (!)
existiert, wird eine neue Farbe ausgewählt
*/
Nun werden die gefüllten Variablen an den jeweiligen Stellen im normalen Stylesheet-Bereich eingefügt und mit dem echo-Befehl ausgegeben.
#header { background: transparent url('images/layout/bg_<?php if(isset($_SESSION['color'])) echo $_SESSION['color']; else echo 'bg_weiss'; ?>.png') repeat-y top center; /* Der else-Block dient nur als Beispiel und dürfte nicht ausgeführt werden*/ } ... #content { font-size: 1.35em; color:<?php if(isset($_SESSION['textcolor'])) echo $_SESSION['textcolor']; else echo '#222'; ?>; } ...
Durch diese Maßnahme bekommt jeder Besucher der Seite beim ersten Aufruf eine zufällige Hintergrundfarbe, die auch bei Seitenwechsel erhalten bleibt (es sei denn, es wird ein anderer Hintergrund über den Einstellungen-Button gewählt).
Aber anstatt der Hintergrundfarbe könnte auch der body-Hintergrund geändert werden. In dem PHP-Bereich kann das ganze Potenzial dieser Scriptsprache eingesetzt werden, um das Stylesheet den eigenen Bedürfnissen dynamisch anzupassen.
Auch eine Darstellung, welche an die jeweilige Tageszeit angepasst wird bzw. von dieser abhängig ist, kann so leicht realisiert werden (time-Funktion von PHP).
/* H - Stunde im 24-Stunden-Format (00-23 ) */
if (date("H")>8 && date("H")<20){
$background = "#ffffff";
$color = "#000000";
} else {
$background = "#000000";
$color = "#ffffff";
}
Doch es traten auch Probleme auf. Die Stylesheet-Anpassungen für die -Browser der Redmonder habe ich direkt im Stylesheet stehen und nicht wie sonst üblich über eine Browserweiche (Conditional Comments ) als zusätzliches Stylesheet eingebunden.
Die Separierung erfolgt über die “Holzhammer-Methode” mit dem !important-Hack:
/* Beispiel */ .navigation { display: block; text-align: center; /* 'Normale' Browser führen diese Zuweisung aus ... */ margin-top: 10px !important; /* ... während der IE !important nicht kennt und diese Zuweisung interpretiert */ margin-top:0px; /* Dies wird dann wieder von allen ausgeführt */ margin-bottom: 60px; }
Diese Art, IE-Bugs zu beheben, sollte eigentlich nicht verwendet werden ( … um das Grund-Stylesheet sauber zu halten). Da ich jedoch bisher nicht viele Anpassungen vornehmen mußte, habe ich es auf diese (nicht besonders elegante Weise) gelöst.
Nach Umänderung meines Stylesheets zu einer PHP-CSS-Datei mit Content-Type-Deklaration wurde ich auch sofort bestraft und der Hack funktionierte aus mir unerklärlichen Gründen nicht mehr. Als Folge wurde meine Seite 3 Tage lang etwas “zerissen” im IE angezeigt, bis ich es als Firefox-Nutzer endlich gemerkt hatte. Dadurch wurde ich mal wieder daran erinnert, dass in der Programmierung umfangreiche Tests unabdingbar sind.
Nun hätte ich mein Grund-Stylesheet ändern und die IE-Anweisungen auslagern können. Ich entschied mich aber dafür, den PHP-Teil in eine separate Datei zu schreiben und zusätzlich in die Seite einzufügen. So können zukünftige weitere Schritte überschaubarer realisiert werden.
Ich hoffe, diese Einführung in dynamische Stylesheets war hilfreich für eigene Projekte.
Hier noch mal der gesamte Quellcode
<?php session_start(); /* ... muss am Anfang eingefügt werden */ /* error_reporting(E_ALL) und ini_set('display_errors', 'On') zur Fehlersuche */ error_reporting(E_ALL); ini_set('display_errors', 'On'); header('Content-type: text/css'); /* Zufallshintergrund */ if(!isset($_SESSION['color'])) { $farben = array('weiss', 'schwarz', 'blau', 'gruen', 'beige', 'hellblau', 'hellgruen', 'rose', 'sand', 'grau_gruen'); $zufall = array_rand($farben, 1);/* ... die 1 kann bei einem Wert auch weggelassen werden */ $zufalls_farbe = $farben[$zufall]; switch ($zufalls_farbe) { case 'weiss': $_SESSION['textcolor'] = '#222'; break; case 'beige': $_SESSION['textcolor'] = '#222'; break; case 'hellblau': $_SESSION['textcolor'] = '#222'; break; case 'oliv': $_SESSION['textcolor'] = '#222'; break; case 'rose': $_SESSION['textcolor'] = '#222'; break; case 'hellgruen': $_SESSION['textcolor'] = '#222'; break; case 'sand': $_SESSION['textcolor'] = '#222'; break; case 'grau_gruen': $_SESSION['textcolor'] = '#222'; break; default: $_SESSION['textcolor'] = '#ccc'; break; } $_SESSION['color'] = $zufalls_farbe; } ?> #header { background: transparent url('images/layout/bg_<?php if(isset($_SESSION['color'])) echo $_SESSION['color']; else echo 'bg_weiss'; ?>.png') repeat-y top center; } #container_inside { background: transparent url('images/layout/bg_<?php if(isset($_SESSION['color'])) echo $_SESSION['color']; else echo 'bg_weiss'; ?>.png') repeat-y top center; } #content { font-size: 1.35em; color:<?php if(isset($_SESSION['textcolor'])) echo $_SESSION['textcolor']; else echo '#222'; ?>; }
Ich tendiere dazu, immer eine extra IE6.css anzulegen.
Die Idee mit der Tageszeit ist ganz nett, doch es macht eigentlich mehr sinn, wenn man die Client-Zeit nimmt. Grad bei internationalen Blogs stimmt die ja selten mit der Serverzeit überein.
Gruß aus Marl
Martin
Hallo Martin,
da hast Du sicherlich Recht. Eine Möglichkeit, die mir da in den Sinn kommen würde: Man müßte den Referrer auslesen und dann dementsprechend zur lokalen Serverzeit etwas hinzuaddieren oder abziehen. Oder per Javascript die Zeit auslesen (so wie auf dieser Seite oben links) und dann an die css.php weiterleiten …
Gruß Matu
Hi Martin,
ich habe versucht auf die selbe Art und Weise wechselnde Headergrafiken hinzubekommen. Aber, da meine Kenntnisse in PHP, HTML und eigentlich allem was Webdesign/-Programmierung angeht gerade mal auf niedrigstem Anfänger-Niveau liegen bin ich mir sicher das ich beim “adaptieren” deines Codes irgendeinen Mist verzapft habe.
Ein Stück weiter unten in der style.css.php wo die Header-Sektion anfängt habe ich z.b. folgendes eingetragen:
$headers = 3;
#header {
background-image: url(../images/header.jpg);
}
Theoretisch richtig oder falsch?
Hallo,
ich denke es ist besser, wenn ich Dir noch ein Beispiel für Dein Anliegen aufzeige.
Die Header-Bilder sollten die Maße des header-div haben. Dieser Code ist kurz runtergetippt und ungetestet, sollte aber funktionieren.
Viele Grüße
Matu