XHTML SVG CSS PHP

Dr. O. Hoffmann

CSS-Layout

Einfach auch mal hinter die Dinge sehen und das Staunen nicht vergessen...
Olaf Hoffmann

Bild skalieren oder Hintergrundbild an die Größe des Anzeigefensters fließend anpassen

Ein prinzipielles Problem sowohl von (X)HTML als auch CSS ist es, die Größe des Anzeigebereiches des Darstellungsprogrammes in Erfahrung zu bringen, zumal diese vom Nutzer in weiten Bereichen jederzeit variiert werden kann. java-script, sofern überhaupt aktiviert, gibt auch nur die gesamte Größe des Bildschirms in Pixeln an, ist also auch nicht weiter hilfreich. Nun, eigentlich werden die Abmessungen des Anzeigebereiches gar nicht explizit gebraucht, wenn alles richtig durchdacht wird.

Implizit sind jedoch viele Abmessungen über CSS verfügbar. Insbesondere bietet das Modul für Medienanfragen von CSS 3 Möglichkeiten, die Abmessungen des Darstellungsbereiches in den üblichen Einheiten, also insbesondere auch em und ex zu verwenden, um geeignete Stile anzubieten, ohne die Abmessungen zu kennen - bei dem Verfahren wird also umgekehrt vorgegangen, es wird festgelegt, daß eine bestimmte Stilvorlage nur für bestimmte Abmessungsbereiche des Anzeigebereiches verwendet werden soll. Prinzipiell sieht hier CSS auch entsprechende Anfragen hinsichtlich der Bildschirmgröße vor, was aber nur sehr selten relevant sein dürfte, weil der Anzeigebereich meist anders, kleiner als die Größe des Bildschirms ist.

Um bei einem Bild allerdings die gleichen Maßeinheiten verwenden zu können, wie in der Stilvorlage, also etwa em, ex oder Prozent, wäre Vektorgraphik im Format SVG (skalierbare Vektorgraphik) zu verwenden. Mit dem Format sollte es kein Problem sein, ein Bild an die Größe des Anzeigebereiches fließend anzupassen. Mit Bildern in diesem Format treten sogar nicht einmal Qualitätsverluste beim Skalieren auf. Zwar wird das Format bereits etwa seit 2006 von technisch aktuellen Darstellungsprogrammen wie den Geckos (ab Version 1.7/1.8, Firefox, SeaMonkey etc), von Opera 8 und 9 und vom Konqueror 3.3 interpretiert, zunächst allerdings nicht jedoch als CSS-Hintergrundbild, was ein bekannter Fehler all dieser Programme war. Dieser Fehler ist zuerst bei Opera mit der Version 9.50 alpha beseitigt worden - diese Version ist damit die erste, mit der SVG sinnvoll für ein CSS-Layout eingesetzt werden kann. In den folgenden Jahren wurde das Problem dann auch bei anderen gängigen Darstellungsprogrammen behoben. SVG als Hintergrundbild kann heute also verwendet werden. Allerdings haben einige Programme immer noch massive Probleme, zentrale CSS-Einheiten für Längen korrekt zu interpretieren, etwa Prozentangaben oder die besonders relevanten Angaben in em und ex, was es komplizierter macht, in solchen Programmen keine gute Präsentation zu erreichen, weil die eigentlich vorgesehene und notierte korrekte Präsentation der Größe des Hintergrundbildes aufgrund solcher Fehler bei der Interpretation von CSS-Einheiten für Längen nicht erreicht wird, stattdessen wird das Hintergrundbild dann oft in der falschen Größe dargestellt.

Anwendungsbeispiel: SVG-Hintergrundbild an die Größe des Anzeigebereiches fließend anpassen.
Die Bildgröße wird auf 100% gesetzt und das Aspektverhältnis preserveAspectRatio auf 'none'. Das Bild wird dann per CSS als Hintergrundbild des Elementes html angegeben (bei XHTML, bei HTML alternativ auch für body). Zudem wird eine passende Hintergrundfarbe angegeben, für den Fall, daß das Programm das Bild nicht darstellen kann.

Das Hintergrundbild wird aufgrund des Attributwertes 'none' von preserveAspectRatio in der Regel verzerrt. Läßt man die Angabe weg oder wählt eine andere vom Typ 'meet', so bleibt zwar das Aspektverhältnis erhalten, es entstehen aber Ränder, vermeidbar ist das mit dem Typ 'slice', besonders geeignet für ein Muster als Hintergrund, da es da nicht darauf ankommt, wenn in einer Richtung ein Stück vom Bild nicht sichtbar ist, wenn das Aspektverhältnis nicht stimmt. Folgendes Beispiel nutzt ein aperiodisches Penrose-Muster mit komplett asymmetrischen Grundformen als Hintergrundbild. Das ist aufgrund der fehlenden Periodizität und der fehlenden Skalierbarkeit von Pixelgraphik als Hintergrundbild mit einem Pixelgraphikformat gar nicht umsetzbar:
SVG-Hintergrundbild mit Muster an die Größe des Anzeigebereiches fließend anpassen.
Hier wurde preserveAspectRatio = xMidYMid slice' verwendet, um die Struktur zu zentrieren, auch um die fünfzählige Rotationssymmetrie mit dem Zentrum als Rotationszentrum deutlich sichtbar zu machen. Mit den anderen möglichen Werten kann man auch sicherstellen, daß die jeweils ausgewählte Ecke auf jeden Fall sichtbar bleibt.

Tatsächlich funktionierte die Darstellung eines SVG-Hintergrundbildes wie gesagt 2009 bei anderen Darstellungsprogrammen als Opera ab Version 9.50 alpha/beta noch nicht, in späteren Jahren wurde der Fehler bei den anderen gängigen Programmen allerdings in aktuellen Versionen beseitigt. Bei Mozilla/Gecko (Firefox) oder WebKit (Chromium, Safari etc) scheint wie bereits angedeutet die Implementierung auf niedrigem Niveau zu stagnieren und es können diverse Fehler insbesondere bei der korrekten Dimensionierung des Hintergrundbildes auftreten. Je nachdem, ob width und height explizit gesetzt sind oder auf welchen Wert, insbesondere in welcher Einheit, was für preserveAspectRatio angegeben wird, kann es da zu verschieden unsinnigen Dimensionierungen kommen oder zum Abschneiden des Bildrandes abhängig von viewBox, was die Nutzbarkeit von SVG-Hintergrundbildern bei diesen Darstellungsprogrammen immer noch stark einschränkt - teilweise gilt das auch für eingebettete SVGs.

Prinzipiell, wenn man einmal von den noch zu beseitigenden Fehlern einiger Darstellungsprogramme absieht, ist es einfach, ebenfalls bei anderen Elementen das Hintergrundbild passend zu skalieren, was bei diversen Layouts recht nützlich sein kann, wo etwa in Navigationsmenüs die Verweise oft als Knöpfe ausgebildet sind. Die Knöpfe sind oft als Hintergrundgraphik umgesetzt, was eine Skalierung oder Anpassung der Größe des Hintergrundbildes an die aktuelle Schriftgröße des Lesers notwendig macht, um die optimale Lesbarkeit des Verweistextes bei gleichzeitigem Erhalt der Layoutidee zu realisieren.

Da mit SVG auch Pixelgraphik eingebunden und transformiert werden kann, gilt das dann auch für Pixelgraphik. Da allerdings bei CSS dringend zu empfehlen ist, eine Hintergrundfarbe anzugeben, die zur Schriftfarbe passend ist, ergeben sich durch die fehlende Darstellung von SVG-Hintergrundbildern auch für Nutzer alter Programme bei der Seite keine Probleme, weswegen die Methode somit problemlos einsetzbar ist. Was leider nicht nachvollziehbar ist, ist eine alternative Angabe eines Pixelgraphikhintergrundbildes vor dem SVG-Hintergrundbild als zusätzliche Eigenschaft. Dies ist erst für CSS 3 vorgesehen. Bleibt also nur die Angabe der Hintergrundfarbe als Alternative oder der Einsatz von einem zusätzlichen Element div, welches den ganzen Anzeigebereich abdeckt. Dann wird die Pixelgraphik für das Element html verwendet und die Vektorgraphik für das div, welches html komplett verdeckt. Die Vektorgraphik sollte dann keine teiltransparenten Stellen aufweisen und html bekommt dann eine Angabe zur Hintergrundfarbe, nicht das div.

Wenn das SVG-Hintergrundbild auch mit alten, fehlerhaften Programmversionen angezeigt werden soll, bleibt also die (allerdings inhaltlich schlechte) Möglichkeit, SVG als object einzubinden oder Pixelgraphik als Bild. Pixelgraphik verfügt nur über Pixel als Maßangabe, die zum Skalieren nur schlecht geeignet ist, ein entscheidender Nachteil gegenüber SVG, der Vorteil liegt darin, daß auch alte Programme besonders JPEG/JFIF richtig darstellen können, die meisten auch PNG (selbst Netscape 4 und der MSIE bis Version 6 können das bis auf Teiltransparenz). Aufgrund der verwendeten Kompressionsmethode kann ein JPEG/JFIF sogar in gewissen Grenzen skalierbar sein, ohne daß die Qualitätsverluste zu arg auffallen.

Trotzdem gibt es bei den Formaten JPEG oder PNG keine Möglichkeit, eine Größe von hundert Prozent anzugeben, so daß sich Bilder in dieses Formaten nicht allein als Hintergrundgraphilk mit CSS 2 an den Anzeigebereich anpassen lassen. Somit gibt es für dieses Problem keine Lösung bei der Verwendung von Pixelgraphik, die nicht in ein SVG eingebunden ist. Es ist nicht möglich, allein mit XHTML und CSS2 eine Pixelgraphik als Hintergrundbild an die Größe des aktuellen Anzeigebereiches des Darstellungsprogrammes anzupassen.

Allerdings ist es mit CSS möglich, ein Bild auf die Größe des Anzeigebereiches zu skalieren, ohne diese überhaupt absolut zu kennen. Dies kann als Ersatzlösung des Problems verwendet werden. Fraglich bleibt es allerdings, ob es wirklich Situationen gibt, wo es sinnvoll ist, ein Vordergrundbild derart zu skalieren. Als kleine CSS-Übung ist die Aufgabenstellung allerdings ideal. Was wichtiger und relevant für eine eigene Seite ist, ist Bilder allgemein relativ zu ihrem umgebenden Kasten skalieren zu können, damit sie nicht seitlich aus einem CSS-Bereich definierter Breite herausragen. Etwa kann angegeben werden in XHTML:


<p>
Sonstiger Inhalt<br />
<img class="skaliere" ... /><br />
Weiterer Inhalt
</p>

und dann in der CSS-Datei:


img.skaliere
{
max-width: 100%;
height: auto;
}

Nachdem damit die korrekte Lösung mit SVG und CSS und das allgemein Nützliche abgehandelt ist, kommen wir nun zu dem Teil, der in meinen Augen für die Praxis nicht nützlich ist, aber Spaß beim Basteln macht - jedenfalls würde ich das nie ernsthaft auf einer Seite einsetzen: Ein Bild als XHTML-Element als 'Hintergrundbild' nutzen und an die Größe des Anzeigebereiches anpassen.

Um dieses zu bewerkstelligen, ist es erst einmal notwendig, das Element body über den gesamten Anzeigebereich erstrecken zu lassen. Dies ist ebenfalls mit CSS möglich, indem margin und padding auf 0 gesetzt werden, Höhe und Breite aber jeweils auf hundert Prozent gesetzt werden. Vorsorglich sollte dann auch overflow: hidden gesetzt werden.

Das spätere Bild, welches als Hintergrund verwendet werden soll, ist nun als normales Bild mit dem Element img oder object in den body-Bereich einzufügen. Da img oder object selbst inzeilige Elemente sind, muß man es zusätzlich in ein Blockelement setzen. Da das keine spezifische Bedeutung hat, wird dafür ein div-Element verwendet. Wenn dies direkt hinter dem Element body erfolgt, sind später nicht die Schichtpositionen mit z-index festzulegen. Nachteil dieser Position im XHTML-Quelltext ist allerdings die Anzeige des Bildes an dieser Stelle, wenn das Darstellungsprogramm kein CSS aktiviert hat.
Dem kann mit eimem Trick entgegengewirkt werden, indem die XHTML-Attribute für Höhe und Breite auf 1 Pixel gesetzt werden. Anschließend sind Höhe und Breite des Bildes mit einer direkten CSS-Formatierung auf hundert Prozent zu setzen.

Der eigentliche Inhalt der Seite wird anschließend in einem weiteren div-Element eingefügt. Dieses div-Element wird absolut positioniert und zwar mit top, bottom, left und right jeweils auf 0. Um gegebenenfalls notwendige Rollbalken zu bekommen, muß dieses div-Element mit overflow: auto ausgestattet werden.
Damit der eigentliche Inhalt noch einen Randabstand bekommt, ist dieser mit padding anzugeben.

Beispiel: Hintergrundbild an die Größe des Anzeigebereiches fließend anpassen
Zu sehen ist, daß das normale Seitenverhältnis des Bildes in der Regel nicht erhalten bleibt. Ist dies erwünscht, sollte nur die Breite des Bildes auf hundert Prozent festgelegt werden. Auch die Höhenangabe im XHTML-Attribut muß dann wegfallen, beziehungsweise wird die Höhenangaben per CSS auf 'auto' gesetzt.
Dann bleibt das Seitenverhältnis des Bildes erhalten. Das Bild wird aber je nach dem Seitenverhältnis des Anzeigebereiches nur teilweise sichtbar sein oder es wird den Anzeigebereich nur teilweise abdecken - man kann eben nicht alles haben.
Nun kann das gleiche Prinzip verwendet werden, um mittels object statt img eine SVG einzubinden:
SVG-Hintergrundbild an die Größe des Anzeigebereiches fließend anpassen.
Da die oben beschriebene Methode besser ist, sollte diese Möglichkeit nur als Spielerei verstanden werden. Bei einer ernsthaften Anwendung sollte auch eine Möglichkeit vorgesehen werden, CSS explizit abzuschalten oder Nutzer älterer Programme zur Darstellung von SVG und XHTML vorzuwarnen. Mit Opera 9 funktioniert es bereits, erweist sich aber als unnötig in diesem Zusammenhang, weil ab Opera 9.50 alpha/beta auch die Einbindung als SVG-Hintergrundbild bereits funktioniert. Konqueror+KSVG1, Konqueror+Adobe-plugin, MSIE+Adobe-plugin und Opera 8 haben einen Fehler, daß das SVG immer im Vordergrund zeigt, weswegen da der eigentliche Inhalt nicht mehr sichtbar ist. Gecko 1.8 (SeaMonkey 1, Firefox 2) stellt es nach lägerer Wartezeit ebenfalls dar, friert aber nahezu ein und ist kaum noch nutzbar. Amaya 9.5 stellt das Bild nicht dar. Programme, die gar kein SVG darstellen können, werden die leere Alternative des verwendeten Elementes object verwenden und keine Probleme haben.

Beispiel 2: Hintergrundbild an die Größe des Anzeigebereiches fließend anpassen
Hier wird der gleiche Effekt mit etwas anderen Mitteln erreicht. Die Positionierung und Skalierung erfolgt hier komplett mit einer CSS-Angabe im Stilbereich, nicht durch Direktformatierung.
Die SVG-Version:
SVG-Hintergrundbild an die Größe des Anzeigebereiches fließend anpassen.
Nun, 2009 ergab auch das nur mit Opera 9 das gewünschte korrekte Ergebnis, was wohl einmal mehr zeigt, daß Opera technologisch eine Spitzenposition einnimmt, was die Unterstützung von SVG oder gemischten Formaten SVG+XHTML anbelangt. Eine weitere Variante wäre, SVG und XHTML direkt in einem Dokument zu mischen.

Mängel und Probleme von Darstellungsprogrammen (bei den Pixelgraphikversionen)

1. Netscape 4 beherrscht das Skalieren der Bilder nicht richtig. Da wir aber das Bild per XHTML auf einen Pixel gesetzt haben, ist praktisch gar kein Bild statt des Hintergrundbildes zu sehen. Man sollte sowieso immer eine passende Hintergrundfarbe angeben.

2. Microsoft internet explorer (msie, Version 6 getestet) hatte kleinere Probleme mit dem Rollbalken für den eigentlichen Inhalt. Daher wird overflow: hidden für das Element body mit dem üblichen Trick vor ihm versteckt: das Element body bekommt eine id und die CSS-Zuweisung nutzt einfach 'body[id]'. Nun wird das Bild korrekt skaliert, wird aber fälschlich mitgerollt. Im Bedarfsfalle sollte man eine passende Hintergrundfarbe angeben. Im zweiten Falle beherrscht der msie natürlich auch position: fixed nicht, was aber hier nicht so gravierend ist, da er dafür fälschlich position: static interpretiert, was auch dazu führt, daß das Bild mitrollt.

3. Konqueror (Version 3.2 getestet) zeigt bei derartig positionierten Elementen für den body (?) immer einen Rollbalken an, egal was man für CSS-Anweisungen gibt. Aber damit kann man leben. Spätere Versionen (3.3.2 getestet) sind hingegen komplett in Ordnung.
Der ältere Konqueror (Version 2.2 getestet) skaliert hingegen nur die Breite des Bildes und rollt ebenso verkehrt wie der msie.

4. Geckos wie Mozilla, SeaMonkey oder Firefox funktionieren problemlos (getestet mit rev 1.5 - 1.8), ebenso Opera (getestet mit 7, 8, 9)