Icon für RSS-Feed Link zum XING-Profil
Wählen Sie eine Hintergrundfarbe:
Schwarzer Hintergrund Blauer Hintergrund Hellblauer Hintergrund Rose Hintergrund Grüner Hintergrund Grüner Hintergrund Olivfarbener Hintergrund Gelber Hintergrund Sandfarbiger Hintergrund Beiger Hintergrund Weisser Hintergrund
Texthintergrund:
Schwarzer Hintergrund Weisser Hintergrund Transparenter Hintergrund


Ladebild
Brick in the Wall

Dynamisches Stylesheet (Dynamic CSS)

Von Matu am 14. Juni, 2009 (21:35 Uhr) unter Kategorie: CSS, PHP, WordPress

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
Im Gegensatz zu einer normalen Stylesheet-Datei, die der jeweilige Browser direkt durch den angegebenen Pfad im Head-Bereich der Webseite „annektiert“, wird die neue PHP-CSS-Datei zuerst vom Server (auf Grund der .php-Endung!) durch den PHP-Parser geschickt.
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 Icon Evil in Dynamisches Stylesheet (Dynamic CSS) -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'; ?>;
	}
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

4 Antworten zu “Dynamisches Stylesheet (Dynamic CSS)”

  1. Diablo sagt:

    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

  2. Matu sagt:

    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

  3. vastolorde sagt:

    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? :)

  4. Matu sagt:

    Hallo,

    ich denke es ist besser, wenn ich Dir noch ein Beispiel für Dein Anliegen aufzeige.

    < ?php
    session_start(); //Session starten
    
    header('Content-type: text/css'); // Mime-Type setzen
    
    /* Wenn noch keine Session-Variable mit Zufallsbild angelegt wurde */
    if(!isset($_SESSION['headerbild'])){ 
    
    /* Erzeuge ein Array mit allen Header-Bildern aus dem Ordner, in dem die Bilder liegen (dieser Ordner kann auch z.B.
    mit der php-Funktion 'glob' eingelesen werden) */
    $mehrere_header_bilder = array('pfad_zum_bilderordner/header1.jpg','../header2.jpg','../header3.jpg','../header4.jpg');
    
    /* Wähle aus diesem Array ein zufälliges aus */
    $ein_zufaelliges_headerbild = array_rand($mehrere_header_bilder);
    
    /* Und weise dieses zufällige Bild als aktuell anzuzeigendes Bild einer Session-Variable zu */
    $_SESSION['headerbild']= $ein_zufaelliges_headerbild;
    }
    
    /* Nun muss dem header-div der Webseite der Inhalt der Session-Variable noch als background-image übergeben werden.
    * Dies geschieht nun weiter unten in der eigentlichen CSS-Datei
     */
    
    /* PHP-Block beenden */
    ?>
    
    /* CSS-Definitionen */
    
    /* ... */
    
    div#header {
    	width: 700px; /* Breite und Höhe sind nur ein Beispiel */
    	height: 200px;
            /* Hier wird das Zufalls-Bild gesetzt */
    	background: transparent url(< ?php echo $_SESSION['headerbild']?>)
    	/* ... hier können weitere CSS-Definitionen stehen (position, float ...) */
    }
    
    /* ... */
    

    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

Deine Meinung ist mir wichtig!

Es besteht die Möglichkeit, Kommentare nachträglich innerhalb einer Zeitspanne von 5 Minuten zu ändern (Keine werblichen Kommentare)
Jeder 1. Kommentar muss freigeschaltet werden!

Smileys:spy:

Nach oben