SVG-Bilder im Web: Farben ändern und animieren mit CSS

SVG-Bilder sind eine tolle Sache – besonders wenn man sie auf Webseiten einbindet: Die Speichergröße ist gering, die Images sind ohne Qualitätsverlust skalierbar und sogar der Internet Explorer 9 kann damit etwas anfangen. Im Gegensatz zu herkömmlichen Bildformaten, haben sie aber noch einen Vorteil: Mit CSS kann ihre Farbe verändert und auf Wunsch sogar animiert werden.

Das Markup

[html]<img src="logo.svg" class="svg" id="logo" />[/html]

Vorbereitung mit JavaScript

Zuerst muss via jQuery der Inhalt der .svg-Bilddatei in den Image-Tag eingefügt werden. Dies kann natürlich auch direkt im Markup erledigt werden. Beide Methoden haben Vor- und Nachteile.
[js]
$(‚img.svg‘).each(function(){
var $img = $(this),
imgID = $img.attr(‚id‘),
imgClass = $img.attr(‚class‘),
imgURL = $img.attr(‚src‘);

$.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = $(data).find(‚svg‘);

// Add replaced image’s ID to the new SVG
if(typeof imgID !== ‚undefined‘) {
$svg = $svg.attr(‚id‘, imgID);
}
// Add replaced image’s classes to the new SVG
if(typeof imgClass !== ‚undefined‘) {
$svg = $svg.attr(‚class‘, imgClass+‘ replaced-svg‘);
}

// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr(‚xmlns:a‘);


// Replace image with new SVG
$img.replaceWith($svg);
});

});
[/js]
Quelle: stackoverflow.com

Farbe des Bildes ändern

Nun kann direkt via CSS die Farbe des SVG-Bildes angepasst werden:
[css]#logo path {color: red}[/css]

Farbe animieren

Natürlich ist es jetzt auch möglich den gewünschten Farbwert via Animation zu verändern. Im folgenden Beispiel passiert das bei Mouse-Hover:
[css]#logo path {
-webkit-transition: all 1;
-moz-transition: all 1;
-ms-transition: all 1;
-o-transition: all 1;
transition: all 1;
}
#logo:hover path {color: green}
[/css]

Das ganze funktioniert in allen Browsern die mit SVG-Bildern und CSS3-Transitions etwas anfangen können.

Animation von Farbwerten mit CSS3-Transition, ohne jQuery

Das Problem ist bekannt: Mit der animate()-Methode von jQuery können lediglich numerische Style-Variablen animiert werden. Was aber machen wenn eine Farbwert-Animation benötigt wird? Beispielsweise um bei Hover die Hintergrundfarbe eines Elementes gleichmäßig zu ändern.

CSS3
Quick-Animationen: CSS3 macht’s möglich

Entweder man bindet ein Plugin ein, verwendet gleich eine große Library oder aber man nutzt die Möglichkeiten die einen CSS3 schon heute bietet. Die Transition-Eigenschaft, welche in allen modernen Browsern gut funktioniert, ist in der Lage diese Anforderung in wenigen Zeilen umzusetzen.

Beispiel: Hintergrund-Animation bei Hover

Ja wirklich, dieser Code reicht aus, um unsere Hintergrund-Animation auf das Element #foo anzuwenden.
[css]#foo {
background:red;
-webkit-transition:background 1s;
-moz-transition:background 1s;
-o-transition:background 1s;
transition:background 1s
}
#foo:hover {
background:yellow;
}[/css]
Die Transition-Eigenschaft (inkl. aller Browser-Prefixe) sorgt dafür, dass jegliche Änderung der background-Eigenschaft, mit einer 1-sekündigen-Animation durchgeführt werden. Das kann natürlich auch abgeändert werden, um zum Beispiel die Schriftfarbe (color) oder die Rahmen-Farbe (border-color) zu animieren. Natürlich bietet die Transition-Eigenschaft die Möglichkeit fast alle CSS-Werte animierend zu ändern. Ganze Animations-Abfolgen können via Keyframe-Animation realisiert werden.

Noch schneller geht es mit SCSS/SASS und Compass:
[css]#foo {background:red; @include transition(background 1s)}
#foo:hover {background:yellow}[/css]


Soll der Effekt erst ab einer bestimmten User-Interaktion starten, muss die gewünschte Zielfarbe einfach in einer Klasse gespeichert werden, welche man dem Element via JavaScript zuweist. Viel Spaß!

mySQL-Connection-Probleme mit node.js und MAMP (ECONNREFUSED)

Mit node.js ist es mit wenigen Code-Zeilen möglich eine Verbindung zu einer mySQL-Datenbank herzustellen und daraufhin Queries auszuführen. Ermöglicht wird dies durch das Modul node-mysql welches via Node Package Manager installiert werden kann (zum Beispiel: npm install mysql@2.0.0-alpha2). Wer auf seinem lokalen Rechner MAMP benutzt, kann eventuell Probleme bei der Verbindung zur mySQL-Datenbank bekommen.

Gibt man Benutzername, Passwort, Datenbank und Port an, erhält man folgendes Fehler-Objekt:
[js]{"code":"ECONNREFUSED","errno":"ECONNREFUSED","syscall":"connect","fatal":true}[/js]

Die Angabe des Socket-Paths half mir das Problem in den Griff zu bekommen:
[js]var mysql = require("mysql");


var connection = mysql.createConnection({
user: "YOUR USERNAME",
password: "YOUR PASSWORD",
database: "YOUR DATABASE",
socketPath: ‚/Applications/MAMP/tmp/mysql/mysql.sock‘
});[/js]

Wichtig: Nach Angabe des Paths dürfen keine Werte für „host“ und „port“ mehr mitgesendet werden, da diese sonst den Socket-Path überschreiben. Der Pfad muss bei euch nicht zwingend dort sein wo er bei mir ist. Ich nutze MAMP Pro und kann via http://localhost:8888/MAMP nachsehen wo genau der Socket-Pfad ist. Sollte diese Änderung nichts bewirken kann auch folgender Socket-Path probiert werden:

[js]socketPath: ‚/var/run/mysqld/mysqld.sock'[/js]

Durch erstere Änderung konnte ich mich erfolgreich zu meiner Datenbank (eingerichtet via MAMP) verbinden.

HTML5 Iframe-Attribut seamless schon jetzt nutzen (Alle Informationen und Beispiele)

Es gibt sie auf fast jeder Internetseite und trotzdem mag sie kein Webentwickler: Iframes. Früher wurden sie verwendet um ganze Internet-Auftritte umzusetzen (Stichwort: nav.html, content.html), heute Fristen sie ein unscheinbares Dasein als Container-Elemente unzähliger Social-Media- und Werbe-Boxen. Das Arbeiten mit Iframes wird jedoch durch HTML5 bald um einiges angenehmer werden. Welche Vorteile das hat, wie man die Features teilweise schon jetzt nutzen kann und warum Iframes gar nicht so böse sind, erklärte Ben Vinegar vor einiger Zeit in einem Vortrag. Die Slides dazu gibt es hier, die eingedeutschte Zusammenfassung mit Beispielen in diesem Artikel.

Keine Zeit? Hier geht’s direkt zur Demo-Seite inkl. Code.

Sind Iframes wirklich böse? Nein!

seamless-Iframe Attribut schon jetzt nutzen
Das seamless-Attribut und seine Möglichkeiten

Iframes, also quasi Webseiten in Webseiten, sind vom Rest der Seite isoliert, bilden eine sogenannte Sandbox. Das hat Nachteile für Webentwickler: CSS wird nicht in den Frame übernommen, Links innerhalb des Iframes verweisen nicht auf die einbindende Seite und die Größe des Frame-Elements passt sich nicht an den Inhalt darin an. Doch genau dieses Sandbox-Prinzip hat Vorteile: JavaScript-Konflikte werden verhindert und Sicherheit und Datenschutz des Users gewahrt. Services wie Flattr, Google Adsense und viele Andere können und müssen via Iframe in die eigene Seite eingebunden werden.

HTML5 und das seamless-Attribut

Da derzeitige Nachteile nicht zukünftig das Arbeiten mit Iframes verhindern sollen, wurde das HTML5-Attribut seamless hinzugefügt. Ein einfaches Beispiel:

[html]<iframe seamless src="http://www.solife.cc"></iframe>[/html]

CSS-Eigenschaften werden dadurch direkt in den Frame übernommen und die Links öffnen korrekt im übergeordneten Fenster. Außerdem passt sich der Iframe mit dem Attribut der Höhe des Inhalts an und Linien sowie Scrollbalken werden standardmässig nicht angezeigt. Wie bei allen neuen Errungenschaften im Web gibt es Dinge zu beachten und Kompromisse einzugehen:

  • Es wird nur http://, nicht aber file:// unterstützt
  • Kein einziger Stable-Browser verfügt derzeit über Support
  • Nur Google Chrome Canary (Version 22 und höher) unterstüzt derzeit das Attribut
  • Die Implementierung der anderen Browser kann als oberflächlich bezeichnet werden

Schon jetzt die neuen Vorteile nutzen

Um schon jetzt die Vorteile des seamless-Attributes zu Nutzen bedarf es einiger Tricks. Zu aller erst muss sowohl auf der Hauptseite, als auch im Iframe selbst, JavaScript-Code eingefügt werden. Damit beide Bereiche kommunizieren können, wird die window.postMessage-Methode genutzt. Die Optik der “nahtlosen” Darstellung kann mit etwas CSS nachgebaut werden.

Einrichten von postMessage und CSS

Code der Hauptseite:

[js]<iframe seamless id="myFrame" src="iframe.html"></iframe>

<script>
var iframe = document.getElementById("myFrame");
// Erste Test-Nachricht an den Iframe
iframe.onload = function() {
iframe.contentWindow.postMessage(‚Hallo Iframe!‘, "*" );
};
</script>[/js]

Da die Nachricht erst gesendet werden soll, wenn der Iframe schon geladen ist, verwende ich den onload-Event-Handler.

JavaScript-Code für den Iframe:

[js] // Wird aufgerufen bei einer neuen Nachricht
function listener(e){
alert(e.data);
}

// Listener für alle Browser
if (window.addEventListener){
window.addEventListener("message", listener, false);
} else {
window.attachEvent("onmessage", listener);
}
[/js]
Wir haben nun die erste Test-Nachricht via Hauptseite an den Iframe gesendet. Die Vorteile von postMessage können wir nun nutzen, um unterschiedliche Werte an den Frame zu übermitteln und das seamless-Attribut teilweise zu simulieren.

CSS für die Hauptseite (Nahtloser Iframe-Effekt):

[css]iframe[seamless]{
background-color: transparent;
border: 0 none transparent;
padding: 0;
overflow: hidden;
}[/css]

Um Links innerhalb des Iframes korrekt zu öffnen, könnte man bei jedem Link das Attribut target="_parent" hinzufügen. Das ist allerdings Wartungsintensiv und überladet das Markup. Dank des <base>-Tags und etwas Java-Script kann dies automatisiert werden.

Im <head>-Bereich des Iframes einfügen:

[html]<base href="http://www.solife.cc/" target="_parent">[/html]

Die angegebene URL des href-Attributes ist nicht zwingend notwendig, da sie mittels Javascript gleich mit der dynamischen Seiten-URL getauscht wird.

Im JavaScript (onLoad-Bereich) der Hauptseite einfügen:

[js] // Schicke aktuelle URL an Iframe
iframe.contentWindow.postMessage([‚referrer‘, window.location.href], ‚*‘);
[/js]

Javascript des Iframes empfängt Nachricht und ändert Base-URL:

[js] // Neue Listener-Funktion
function listener(e){

var eventName = e.data[0],
data = e.data[1];

switch (eventName) {
case ‚referrer': setNewBase(data); break;
}

}

// Aktualisiere Base-URL
function setNewBase(url) {
document.getElementsByTagName(‚base‘)[0].href = url;
}
[/js]

Styles in den Iframe übernehmen

Es ist keine perfekte Lösung, aber es können beliebige Style-Eigenschaften wie Schriftart, Schriftgröße und Schriftfarbe via Nachricht dem Iframe übergeben werden. In diesem Beispiel wird dies Mithilfe von jQuery gelöst:

[js] iframe.onload = function() {

….
// Style-Eigenschaften an Iframe senden
iframe.contentWindow.postMessage([‚styles‘, getIframeStyles(iframe)], ‚*‘);

};

// Styles auslesen (Dazu wird ein leeres span-Element erstellt)
function getIframeStyles(iframe) {

var $span = $(‚<span>‘).appendTo(iframe.parentNode);

var styles = {
color: $span.css(‚color‘),
fontFamily: $span.css(‚font-family‘),
fontSize: $span.css(‚font-size‘)
};

$span.remove(); // Cleanup
return styles;

}
[/js]

Natürlich können beliebig viele Styles an den Iframe übergeben werden. Auch ist es möglich ganze CSS-File-URL’s zu versenden, um sie später einzufügen. Wir bleiben bei der einfachen Methode der Werte-Übermittlung.

Beim Iframe selbst nun folgenden Code einfügen:

[js]function listener(e){

….

switch (eventName) {
case ‚referrer': setNewBase(data); break;
case ‚styles': injectStyles(data); break;
}

}

function injectStyles(styles) {
$(document.body).css(styles);
}
[/js]
Wie oben beschrieben gibt es viele Wege die gewünschten Style-Eigenschaften in den Frame zu bekommen. Dem Webworker ist überlassen wie er diesen Prozess umsetzt.

Höhe des Iframes automatisch anpassen

Jeder Coder der bereits einmal ein Gästebuch oder ähnliches via Iframe einbinden musste, kennt das Problem: Welche Höhe definiert man dem Iframe-Element? Gerade bei dynamischen Seiten ist diese Frage schwer zu beantworten – die Lösung ist meist eine Höhe von weit über 1000 Pixel zu wählen. Dank postMessage kann die korrekte Höhe nun direkt übertragen werden.

Da in diesem Schritt die Hauptseite, nicht wie bisher, Nachrichten sendet, sondern auch empfängt, muss ein ähnlicher Code wie im Iframe eingebunden werden.
[js] // Wird aufgerufen bei einer neuen Nachricht
// Auf Hauptseite nur um Höhe anzupassen
function listener(e){

var eventName = e.data[0],
data = e.data[1];

switch (eventName) {
case ‚setHeight': $(iframe).height(data); break;
}

}

// Listener für alle Browser
if (window.addEventListener){
window.addEventListener("message", listener, false);
} else {
window.attachEvent("onmessage", listener);
}
[/js]

Das JavaScript des Iframes aktualisieren:
[js] // Resize-Funktion zum Ermitteln der Höhe
function resize() {
window.parent.postMessage([‚setHeight‘, $(‚html‘).height()], ‚*‘);
}
[/js]
Jetzt muss die resize()-Funktion nur noch aufgerufen werden. Auch hier gibt es mehrere Möglichkeiten der Umsetzung:

  • Die Funktion wird permanent via Interval alle 500 Millisekunden odgl. aufgerufen
  • Die Funktion feuert erst wenn ein bestimmtes Event eingetreten ist
  • Wie Ben Vinegar in seinem Vortrag, mit der Debounce-Methode (Code)

Zur einfacheren Vorstellung verwende ich für dieses Beispiel die Interval-Methode.
[js] // Alle 500 Millisekunden die Höhe des Frames anpassen
window.setInterval(resize, 500);
[/js]
Das Iframe passt sich nun immer der Höhe des Inhalts darin an.

Resume

Mit diesen wenigen Code-Zeilen ist es möglich das Arbeiten mit Iframes erheblich zu verbessern und das seamless-Attribut zumindest teilweise nachzubauen. Die window.postMessage-Methode wird in allen Browser, bis auf Internet Explorer 6 und 7 unterstützt. Bis alle Browser nachgerüstet haben bleibt dieser Workflow eine passable Alternative.

Zur Demo-Seite inkl. Code.

4 Tipps um den Admin- und Login-Bereich von WordPress anzupassen

Login Admin Bereich WordPress
Sieht doch gleich besser aus!

Vor drei Tagen erschien auf Smashing Magazine ein toller Artikel von Aurélien Denis. Er beschrieb darin wie man mit wenigen Code-Zeilen den Administrations-Bereich von WordPress individueller gestalten kann. Denn gerade bei Backend-Lösungen für Kunden wäre es ratsam den Login-Bereich im „Look and feel“ der restlichen Website zu gestalten.

Das vordefinierte WordPress-Logo des Login-Bereiches kann in wenigen Handgriffen mit dem des Kunden ersetzt werden. Dazu muss die Datei functions.php geöffnet werden. Sie befindet sich im Ordner des gerade aktiven Themes unter /wp-content/themes/DEIN-THEME. Ganz am Ende, vor dem schließenden PHP-Tag, einfach folgenden Code einfügen:

function login_css() {
    wp_enqueue_style('login_css', get_template_directory_uri() . '/admin.css');
}
add_action('login_head', 'login_css');

Nun wird im Login-Bereich von WordPress ein neues Stylesheet mit dem Namen admin.css eingebunden, welches ebenfalls im aktuellen Theme-Ordner abgelegt wird (URL ist frei wählbar). In dieser CSS-Datei muss nun einfach die Background-Eigenschaft von #login h1 a überschrieben werden (Achtung: !important ist notwendig). Natürlich können auch weitere Änderungen am Stylesheet durchgeführt werden, um den Login-Bereich beispielsweise im CI des Kunden zu gestalten.

Leider verlinkt das gerade angepasste Logo noch auf die WordPress-Website. Der Link kann mit ein paar Zeilen in der functions.php geändert werden.

function wpc_url_login(){
    return "http://solife.cc";
}
add_filter('login_headerurl', 'wpc_url_login');

Und da auch ein WordPress-Copyright-Vermerk im Footer des Backends nicht perfekt aussieht, kann auch dieser mit einer einfachen Methode in der functions.php abgeändert werden.

function remove_footer_admin () {
    echo '© 2012 - solife.cc - marmot stuff';
}
add_filter('admin_footer_text', 'remove_footer_admin');

URL zum Admin-Bereich ändern

Abschließend kann noch die URL des Administrations-Bereiches angepasst werden. Die eher umständlichen Standard-Adressen /wp-admin bzw. /wp-login.php können mit einer Zeile in der .htaccess-Datei geändert werden. Achtung: Die Datei befindet sich im Root der WordPress-Instanz und ist eventuell nicht sichtbar – einfach im FTP-Programm die versteckten Inhalte darstellen. Danach folgende Zeile einfügen:

RewriteRule ^admin$ http://DEINE_SEITE.com/wp-login.php [NC,L]

Die neue URL zum Admin-Bereich lautet nun /admin.