<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Notes | Olaf Gleba</title>
    <link>http://olafgleba.de/notes/</link>
    <description/>
    <language>de-DE</language>
    <generator>Welcompose 0.9.6 (http://welcompose.de/)</generator>
    <atom:link href="http://olafgleba.de/notes/Rss20/" rel="self" type="application/rss+xml" />

    
        <item>
      <title>SVG Icon Sprites, Nunjucks, Gulp</title>
      <link>http://olafgleba.de/notes/2017/03/09/svg-icon-sprites-nunjucks-gulp/</link>
      <description>
                              &lt;p&gt;Für die Einbindung von Icons nutze ich aus &lt;a  href=&quot;https://css-tricks.com/icon-fonts-vs-svg/&quot;&gt;vielerlei Gründen&lt;/a&gt; extern referenzierte SVG Sprites, deren Fragmente im HTML über das &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; Attribut des &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; Elements inline referenziert werden. Um redundante Schreibarbeit zu vermeiden und die Pflege deutlich zu erleichtern, bietet sich der Einsatz einer Template Engine an.&lt;/p&gt;
                    &lt;h2&gt;Worum es geht&lt;/h2&gt;

&lt;p&gt;Im folgenden Beitrag dreht sich alles um die Einbindung von Referenzen eines SVG-Sprites und wie man sich das (Arbeits)Leben durch Einsatz einer Template Engine (&lt;a href=&quot;https://mozilla.github.io/nunjucks/&quot;&gt;Nunjucks&lt;/a&gt;) und einem &lt;a href=&quot;http://gulpjs.com/&quot;&gt;Gulp&lt;/a&gt; Workflow einfacher machen kann.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Nicht&lt;/i&gt; explizit beschrieben wird die Erstellung von SVG-Sprites (wäre was für einen weiteren Beitrag), Sinn und Zweck von Template Engines und/oder die Arbeit mit Gulp. &lt;/p&gt;


&lt;h2&gt;Wie es ist&lt;/h2&gt;

&lt;p&gt;Referenziert man ein SVG-Sprite im HTML Markup, kann das u.a. schon mal einiges an Tipparbeit (&lt;i&gt;pro Referenz&lt;/i&gt;) bedeuten. Zumal, wenn wir - was obligatorisch sein sollte - Wert auf &lt;a href=&quot;https://www.sitepoint.com/tips-accessible-svg/&quot;&gt;größtmögliche Zugänglichkeit&lt;/a&gt; des SVG legen.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot; id=&quot;macro-output&quot;&gt;&lt;code&gt;HTML Markup:

&amp;lt;svg class=&quot;icon icon--huge icon-twitter&quot; role=&quot;img&quot; aria-labelledby=&quot;title-1668 desc-1668&quot;&amp;gt;
  &amp;lt;title id=&quot;title-1668&quot;&amp;gt;Titel...&amp;lt;/title&amp;gt;
  &amp;lt;desc id=&quot;desc-1668&quot;&amp;gt;Beschreibung...&amp;lt;/desc&amp;gt;
  &amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-twitter&quot; /&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Das ist eine ganze Menge Markup für die Darstellung eines kleinen Icons.&lt;/p&gt;

&lt;p&gt;Ja, aber: Ob und welche Attribute des oben gezeigtes Beispiel für ein Icon sinnvoll sind, bestimmt allein der Kontext, in dem sie verwendet werden.&lt;/p&gt;

&lt;p&gt;In meinen bisherigen Projekten gab es bislang folgende Arten von Kontext:&lt;/p&gt;

&lt;ol style=&quot;list-style: decimal outside; margin-left: 1.1em;margin-bottom: 3%;&quot;&gt;
  &lt;li&gt;Icon, das inhaltliche Bedeutung hat (nicht verlinkt)&lt;/li&gt; 
  &lt;li&gt;Icon, das dekorativer Natur ist + Text (nicht verlinkt)&lt;/li&gt;
  &lt;li&gt;Icon, das dekorativer Natur ist (verlinkt)&lt;/li&gt;
  &lt;li&gt;Icon, das dekorativer Natur ist + Text (verlinkt)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Das bedingt sehr unterschiedliche Arten der Referenzierung, resp. welche Attribute wie und ob überhaupt gesetzt werden sollten:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot; id=&quot;kontext-1&quot;&gt;&lt;code&gt;1.) HTML Markup: Icon, das inhaltliche Bedeutung hat (nicht verlinkt)

&amp;lt;svg class=&quot;icon icon-smartphone&quot; role=&quot;img&quot; aria-labelledby=&quot;title-1668 desc-1668&quot;&amp;gt;
  &amp;lt;title id=&quot;title-1668&quot;&amp;gt;Smartphone&amp;lt;/title&amp;gt;
  &amp;lt;desc id=&quot;desc-1668&quot;&amp;gt;Optimierte Darstellung für mobile Geräte&amp;lt;/desc&amp;gt;
  &amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-smartphone&quot; /&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre class=&quot;prettyprint&quot; id=&quot;kontext-2&quot;&gt;&lt;code&gt;2.) HTML Markup: Icon, das dekorativer Natur ist + Text (nicht verlinkt)

&amp;lt;svg class=&quot;icon icon-success&quot; role=&quot;img&quot; aria-hidden=&quot;true&quot;&amp;gt;
  &amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-success&quot; /&amp;gt;
&amp;lt;/svg&amp;gt; 
Ihre Eingaben wurden erfolgreich gespeichert
&lt;/code&gt;&lt;/pre&gt;

&lt;pre class=&quot;prettyprint&quot; id=&quot;macro-output&quot;&gt;&lt;code&gt;3.) HTML Markup: Icon, das dekorativer Natur ist (verlinkt)

&amp;lt;a href=&quot;#0&quot; title=&quot;Titel...&quot; aria-label=&quot;Labeltext...&quot;&amp;gt;
  &amp;lt;svg class=&quot;icon icon-twitter&quot; role=&quot;img&quot;&amp;gt;
    &amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-twitter&quot; /&amp;gt;
  &amp;lt;/svg&amp;gt;
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre class=&quot;prettyprint&quot; id=&quot;macro-output&quot;&gt;&lt;code&gt;4.) HTML Markup: Icon, das dekorativer Natur ist + Text (verlinkt)

&amp;lt;a href=&quot;#0&quot; aria-label=&quot;Labeltext...&quot;&amp;gt;
  &amp;lt;svg class=&quot;icon icon-twitter&quot; role=&quot;img&quot;&amp;gt;
    &amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-twitter&quot; /&amp;gt;
  &amp;lt;/svg&amp;gt;
  Twitter
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;h2&gt;Was wir wollen&lt;/h2&gt;

&lt;p&gt;Wie die vorigen Beispiele zeigen, müssen wir ggf. sehr unterschiedliches Markup schreiben. Je nach Kontext des Icons. Das bedeutet viel Tipparbeit, Anfälligkeit für Fehler und es wird mit zunehmenden Anzahl der Referenzen schwierig den Überblick zu behalten. Das muss anders gehen...&lt;/p&gt;

&lt;p&gt;Eine Möglichkeit ist der Einsatz einer Template Engine*. Alle mir bekannten Engines beinhalten - teilweise unterschiedlich benannt - ähnliche Funktionalitäten:  &lt;code&gt;Partials&lt;/code&gt;, &lt;code&gt;Includes&lt;/code&gt; und &lt;code&gt;Macros&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Diese können wir nutzen, um das Markup der SVG-Sprite Referenzen in einer eigenen Template-Datei auszulagern und dann mit unterschiedlichen Parametern in unser Haupt-Template einzubinden.&lt;/p&gt; 

&lt;p&gt;&lt;a href=&quot;http://hugogiraudel.com/&quot;&gt;Hugo Giraudel&lt;/a&gt; hatte diese Idee &lt;a href=&quot;https://www.sitepoint.com/a-working-svg-workflow-for-accessible-icons/#creating-an-icon-component&quot;&gt;letztes Jahr schon beschrieben&lt;/a&gt;. Da ich nicht mit dem von ihm genutzten Static Site Generator &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jeckyll&lt;/a&gt; arbeite, musste ich mich nach einer Alternative umschauen. Und habe mich für &lt;a href=&quot;https://mozilla.github.io/nunjucks/&quot;&gt;Nunjucks&lt;/a&gt; als Template Engine entschieden.&lt;/p&gt;

&lt;p&gt;Jeckyll erlaubt in &lt;code&gt;Includes&lt;/code&gt; eine Parameterübergabe, Nunjucks nicht. Mit den &lt;code&gt;Macros&lt;/code&gt;, die Nunjucks bereitstellt, erreichen wir - wenn auch auf einem leicht anderen Weg - das gleiche Ziel.&lt;/p&gt; 

&lt;p style=&quot;font-size: 80%&quot;&gt;*) Alternativ sind lokale Lösungen wie Snippets für den Lieblings-Editor denkbar&lt;/p&gt;


&lt;h2&gt;Macro anlegen, importieren und anwenden&lt;/h2&gt;

&lt;p&gt;Ein &lt;code&gt;macro&lt;/code&gt; besteht aus einer Datei, die eine oder mehrere  Funktionen enthält, welche dann beliebig oft im Haupt-Template genutzt werden können.&lt;/p&gt;

&lt;p&gt;Für unser Anliegen reichen zwei Funktionen: &lt;code&gt;mean&lt;/code&gt; und &lt;code&gt;loose&lt;/code&gt;. Mit den beiden können wir die o.g. Szenarien abdecken (s. auch nächster Abschnitt). 

&lt;pre class=&quot;prettyprint&quot; id=&quot;macro-template&quot;&gt;&lt;code&gt;Nunjucks Template: Macro (Datei: templates/macros/icon.nunjucks)

// s. 1. Icon, das inhaltliche Bedeutung hat (nicht verlinkt)

{% macro mean(file, title, desc, size, uid = randomHash()) -%}
&amp;lt;svg class=&quot;icon {% if size %}icon--{{ size }} {% endif %}icon-{{ file }}&quot; role=&quot;img&quot; {% if title or desc %}aria-labelledby=&quot;{% if title %}title-{{ uid }}{% endif %}{% if desc %} desc-{{ uid }}{% endif %}&quot;{% endif %}&amp;gt;
{%- if title -%}
&amp;lt;title id=&quot;title-{{ uid }}&quot;&amp;gt;{{ title }}&amp;lt;/title&amp;gt;
{%- endif -%}
{%- if desc -%}
&amp;lt;desc id=&quot;desc-{{ uid }}&quot;&amp;gt;{{ desc }}&amp;lt;/desc&amp;gt;
{%- endif -%}
&amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-{{ file }}&quot; /&amp;gt;&amp;lt;/svg&amp;gt;
{%- endmacro %}


// s. 2. Icon, das dekorativer Natur ist + Text (nicht verlinkt)
// s. 3. Icon, das dekorativer Natur ist (verlinkt)
// s. 4. Icon, das dekorativer Natur ist + Text (verlinkt)

{% macro loose(file, ariaHiddenStatus, size) -%}
&amp;lt;svg class=&quot;icon {% if size %}icon--{{ size }} {% endif %}icon-{{ file }}&quot; role=&quot;img&quot;{% if ariaHiddenStatus %} aria-hidden=&quot;{{ ariaHiddenStatus }}&quot;{% endif %}&amp;gt;&amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-{{ file }}&quot; /&amp;gt;&amp;lt;/svg&amp;gt;
{%- endmacro %}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Um die Funktionen des Macros einsetzen zu können, müssen wir die Macro-Datei zuerst in das Haupt-Template importieren (&lt;i&gt;vor&lt;/i&gt; dem Aufruf der Funktionen):&lt;/p&gt; 

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Nunjucks Template: Macro importieren (Datei: templates/index.nunjucks)

{% import &#039;macros/icon.nunjucks&#039; as icon %}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Anschließend stehen die Funktionen des Macros zur Verfügung.&lt;/p&gt; 

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Nunjucks Template: Macro Funktionen anwenden (Datei: templates/index.nunjucks)

// Beispiele...

// s. 1. Icon, das inhaltliche Bedeutung hat (nicht verlinkt)
{{ icon.mean(&quot;smartphone&quot;, &quot;Smartphone&quot;, &quot;Optimierte Darstellung für mobile Geräte&quot;) }}

// s. 2. Icon, das dekorativer Natur ist + Text (nicht verlinkt)
{{ icon.loose(&quot;success&quot;, &quot;true&quot;) }} Ihre Eingaben wurden erfolgreich gespeichert
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wird das Template nun gerendert, entspricht das generierte Markup dem HTML aus den Beispielen &lt;a href=&quot;#kontext-1&quot;&gt;1(eins)&lt;/a&gt; und &lt;a href=&quot;#kontext-2&quot;&gt;2(zwei)&lt;/a&gt;.&lt;/p&gt; 



&lt;h2&gt;Die beiden Macro-Funktionen im Detail&lt;/h2&gt;

&lt;p&gt;Aber der Reihe nach. Wann nutze ich welche Funktion (&lt;code&gt;mean()&lt;/code&gt;, &lt;code&gt;loose()&lt;/code&gt;) und was für Parameter stehen zur Verfügung?&lt;/p&gt;

&lt;h3&gt;icon.mean()&lt;/h3&gt; 

&lt;p&gt;Es gibt für die Funktion &lt;code&gt;mean()&lt;/code&gt; nur einen sinnvollen Anwendungsfall: Wenn ein allein stehendes Icon eine Aussage transportieren soll und nicht nur der Dekoration dient. Hier muss sichergestellt werden, dass assistive Geräte/Anwendungen die Bedeutung auch erfassen können (durch den Einsatz von &quot;title&quot; und &quot;description&quot;).&lt;/p&gt;

 
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Nunjucks Template: Macro Funktion mean()

// Mögliche Parameter
{{ icon.mean(&quot;[file]&quot;, &quot;[title]&quot;, &quot;[description]&quot;, &quot;[size]&quot;) }}

// Es muss mindestens der Fragment ID (Parameter &#039;file&#039;) definiert sein (SVG-Sprite: &amp;lt;symbol id=&quot;[x]&quot;&amp;gt;)
{{ icon.mean(&quot;smartphone&quot;) }}

// Beispiele

// Parameter: file, title, description
{{ icon.mean(&quot;smartphone&quot;, &quot;Smartphone&quot;, &quot;Optimierte Darstellung für mobile Geräte&quot;) }}

// Parameter: file, title, description, size (Icon size modifier class (.`icon--huge`))
{{ icon.mean(&quot;smartphone&quot;, &quot;Smartphone&quot;, &quot;Optimierte Darstellung für mobile Geräte&quot;, &quot;huge&quot;) }}

// Parameter: file, title, keine(!) description, size (Icon size modifier class (.`icon--large`))
{{ icon.mean(&quot;smartphone&quot;, &quot;Smartphone&quot;, &quot;&quot;, &quot;large&quot;) }}

// Parameter: file, title
{{ icon.mean(&quot;smartphone&quot;, &quot;Smartphone&quot;) }}
&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;icon.loose()&lt;/h3&gt; 

&lt;p&gt;Die Funktion &lt;code&gt;loose()&lt;/code&gt; hingegen setzen wir in allen anderen Szenarien ein. In diesen (s. Beispiele) kann auf Titel und Beschreibung verzichtet werden, ohne das die Zugänglichkeit leidet.

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Nunjucks Template: Macro Funktion loose()

// Mögliche Parameter
{{ icon.loose(&quot;[file]&quot;, &quot;[ariaHiddenStatus]&quot;, &quot;[size]&quot;) }}

// Es muss mindestens der Fragment ID (Parameter &#039;file&#039;) definiert sein (SVG-Sprite: &amp;lt;symbol id=&quot;[x]&quot;&amp;gt;)
{{ icon.loose(&quot;smartphone&quot;) }}

// Beispiele

// Parameter: file, ariaHiddenStatus
{{ icon.loose(&quot;success&quot;, &quot;true&quot;) }}

// Parameter: file, ariaHiddenStatus, size (Icon size modifier class (.`icon--huge`))
{{ icon.loose(&quot;success&quot;, &quot;true&quot;, &quot;huge&quot;) }}

// Parameter: file, size (Icon size modifier class (.`icon--huge`))
{{ icon.loose(&quot;smartphone&quot;, &quot;&quot;, &quot;huge&quot;) }}

// Parameter: file
&amp;lt;a href=&quot;#0&quot; title=&quot;Gehe zur Twitter Seite&quot; aria-label=&quot;Gehe zur Twitter Seite&quot;&amp;gt;
  {{ icon.loose(&quot;twitter&quot;) }}
&amp;lt;/a&amp;gt;

// Parameter: file
&amp;lt;a href=&quot;#0&quot; aria-label=&quot;Gehe zur Twitter Seite&quot;&amp;gt;
  {{ icon.loose(&quot;twitter&quot;) }}
  Twitter
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;






&lt;h2&gt;Nunjucks installieren und in Gulp integrieren&lt;/h2&gt;

&lt;p&gt;Das Module wird über über den Node.js Package Manager installiert, &lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Bash: Plugin installieren

$ npm install gulp-nunjucks-render --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;dann im Gulpfile.js in einer Variable gespeichert,&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Gulpfile: Plugin einbinden

var nunjucksRender = require(&#039;gulp-nunjucks-render&#039;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;die dann im neu anzulegenden Gulp Task genutzt wird.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Gulpfile: Der (vereinfachte) Gulp Task für das Templates Rendering

gulp.task(&#039;process:templates&#039;, function() {
  return gulp.src(&#039;templates/*.nunjucks&#039;)
    ...   
    .pipe(nunjucksRender({
      path: &#039;templates/&#039;,
      manageEnv: expandEnv
    }))
    .pipe(gulp.dest(&#039;app/&#039;));
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wenn wir den Task jetzt allerdings über die Bash aufrufen würden (&lt;code&gt;$ gulp process:templates&lt;/code&gt;), würde es eine Fehlermeldung hageln - schauen wir uns die Pipe Aufruf für &lt;code&gt;nunjucksRender&lt;/code&gt; an, sehen wir, dass es einen Parameter mit Namen &lt;code&gt;manageEnv&lt;/code&gt; gibt, dem eine Variable (&lt;code&gt;expandEnv&lt;/code&gt;) zugewiesen ist. Eine Variable, die zum jetzigen Zeitpunkt weder initialisiert noch gefüllt ist.&lt;/p&gt;

&lt;p&gt;Das holen wir jetzt in zwei Schritten nach: Zuerst fügen wir dem &lt;code&gt;Gulpfile&lt;/code&gt; (&lt;i&gt;vor&lt;/i&gt; dem Aufruf des Tasks) die folgende Funktion hinzu:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Gulpfile: Funktion erstellen/einfügen

/**
 * Generates random number
 * @return {string} random number
 */
function randomHash() {
    return Math.random()*0xfff|0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Anschließend erweitern wir in einem zweiten Schritt die Laufzeitumgebung von Nunjucks mit der eben eingefügten Funktion:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Gulpfile: Die Laufzeitumgebung von Nunjucks mit der zuvor erstellten Funktion (`randomHash`) erweitern 

/**
 * Enhance nunjucks environment
 * @param {object} environment
 */
var expandEnv = function(environment) {
  environment.addGlobal(&#039;randomHash&#039;, randomHash);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wozu brauchen wir das? Diese - jetzt global für Nunjucks verfügbare - Funktion erlaubt es eindeutige Element-IDs (&lt;code&gt;uid&lt;/code&gt;) für jede Funktionsinstanz des Macros zu generieren (s. &lt;a href=&quot;#macro-template&quot;&gt;Quelltext des Macros&lt;/a&gt;, &lt;a href=&quot;#macro-output&quot;&gt; Markup-Ausgabe&lt;/a&gt;). Was zwingend erforderlich ist, um die Zugänglichkeit für assistive Geräte/Anwendungen zu gewährleisten.&lt;/p&gt;

&lt;h2&gt;Was es bringt&lt;/h2&gt;

&lt;p&gt;Deutlich weniger Aufwand in der Deklaration von SVG-Sprite Referenzen im Markup. Ein Blick auf die Quellcode-Beispiele sagt mehr als tausend Worte...&lt;/p&gt;

&lt;p&gt;Vorher:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;...
&amp;lt;svg class=&quot;icon icon-smartphone&quot; role=&quot;img&quot; aria-labelledby=&quot;title-1668 desc-1668&quot;&amp;gt;
  &amp;lt;title id=&quot;title-1668&quot;&amp;gt;Smartphone&amp;lt;/title&amp;gt;
  &amp;lt;desc id=&quot;desc-1668&quot;&amp;gt;Optimierte Darstellung für mobile Geräte&amp;lt;/desc&amp;gt;
  &amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-smartphone&quot; /&amp;gt;
&amp;lt;/svg&amp;gt;

...

&amp;lt;a href=&quot;#0&quot; aria-label=&quot;Gehe zur Twitter Seite&quot;&amp;gt;
  &amp;lt;svg class=&quot;icon icon-twitter&quot; role=&quot;img&quot;&amp;gt;
    &amp;lt;use xlink:href=&quot;assets/img/icon-sprite.svg#icon-twitter&quot; /&amp;gt;
  &amp;lt;/svg&amp;gt;
  Twitter
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nachher:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot; id=&quot;macro-output&quot;&gt;&lt;code&gt;...
{{ icon.mean(&quot;smartphone&quot;, &quot;Smartphone&quot;, &quot;Optimierte Darstellung für mobile Geräte&quot;) }}

...

&amp;lt;a href=&quot;#0&quot; aria-label=&quot;Gehe zur Twitter Seite&quot;&amp;gt;
  {{ icon.loose(&quot;twitter&quot;) }}
  Twitter
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
              </description>
      <pubDate>Thu, 09 Mar 2017 08:41:00 +0100</pubDate>
      <guid>http://olafgleba.de/notes/2017/03/09/svg-icon-sprites-nunjucks-gulp/</guid>
    </item>
        <item>
      <title>Workflow beschleunigen mit Browsersync</title>
      <link>http://olafgleba.de/notes/2015/12/16/workflow-beschleunigen-mit-browsersync/</link>
      <description>
                              &lt;p&gt;Für den Adventskalender der &lt;a href=&quot;http://webkrauts.de&quot;&gt;webkrauts&lt;/a&gt; habe ich einen zweiteiligen Artikel beigesteuert, der das Tool &lt;a href=&quot;http://www.browsersync.io/&quot;&gt;Browsersync&lt;/a&gt; vorstellt und dessen Einsatz in der Webentwicklung beschreibt.&lt;/p&gt;
                    &lt;p&gt;Hier geht es zu &lt;a href=&quot;http://webkrauts.de/artikel/2015/browsersync-teil-1&quot;&gt;Teil 1&lt;/a&gt;, hier zu &lt;a href=&quot;http://webkrauts.de/artikel/2015/browsersync-teil-2&quot;&gt;Teil 2&lt;/a&gt; des Artikels.&lt;/p&gt;
              </description>
      <pubDate>Wed, 16 Dec 2015 22:29:00 +0100</pubDate>
      <guid>http://olafgleba.de/notes/2015/12/16/workflow-beschleunigen-mit-browsersync/</guid>
    </item>
        <item>
      <title>Das Ruby Begriffsuniversum kurz erklärt</title>
      <link>http://olafgleba.de/notes/2015/11/24/das-ruby-begriffsuniversum-kurz-erklaert/</link>
      <description>
                              &lt;p&gt;&lt;code&gt;RVM&lt;/code&gt;, &lt;code&gt;gem&lt;/code&gt;, &lt;code&gt;RubyGems&lt;/code&gt;, &lt;code&gt;rbenv&lt;/code&gt;, &lt;code&gt;Bundler&lt;/code&gt; etc.: Es gibt viele Begrifflichkeiten, die beim Kennenlernen von &lt;code&gt;Ruby&lt;/code&gt; den Weg kreuzen. Ein kurzer Überblick über die wichtigsten Begriffe.&lt;/p&gt;
                    &lt;p&gt;Ein &lt;a href=&quot;https://rubygems.org/gems&quot;&gt;Gem&lt;/a&gt; ist eine einzelne Ruby Bibliothek, die eine bestimmte Funktionalität bereitstellt und aus mehreren Dateien besteht. Weshalb im Zusammenhang mit &lt;code&gt;gems&lt;/code&gt; oftmals auch von sog. &lt;em&gt;Paketen&lt;/em&gt; die Rede ist. Ein Gem entspricht in etwa dem, was ein Modul für Node.js ist. In einem &lt;code&gt;gem&lt;/code&gt; findet sich der Programmcode (.rb) sowie ggf. Testdateien. In einer &lt;a href=&quot;http://guides.rubygems.org/specification-reference/&quot;&gt;gemspec&lt;/a&gt;-Datei werden allgemeine Informationen wie Name, Version, Lizenz etc. des &lt;code&gt;gems&lt;/code&gt; definiert und der Inhalt der Bibliothek beschrieben. Im &lt;a href=&quot;http://bundler.io/v1.2/man/gemfile.5.html&quot;&gt;Gemfile&lt;/a&gt; wiederum werden die Bibliotheken gelistet, die ggf. für ein bestimmtes Projekt oder eine dezidierte Ruby Bibliothek zwingend erforderlich sind. Zusammen genommen sind die beiden Dateien (gemspec, Gemfile) mit einer &lt;code&gt;package.json&lt;/code&gt; Datei im Node.js Kosmos vergleichbar.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://rubygems.org/&quot;&gt;RubyGems&lt;/a&gt; ist der Name des Package Managers für Ruby Bibliotheken. Mit ihm können &lt;code&gt;gems&lt;/code&gt; installiert/entfernt werden (&lt;code&gt;$ gem install &amp;lt;gem name&amp;gt;&lt;/code&gt;). RubyGems ist Teil von Ruby. Die unter RubyGems verlinkte Seite ist zugleich auch die erste Anlaufstelle, um installierbare Bibliotheken zu finden.&lt;/p&gt; 

&lt;p&gt;&lt;a href=&quot;http://bundler.io/&quot;&gt;Bundler&lt;/a&gt; erleichtert die Installation und Verwaltung von gems und deren Abhängigkeiten. Basierend auf einem vorhandenen &lt;code&gt;Gemfile&lt;/code&gt; lädt und installiert Bundler mit &lt;code&gt;$ bundle install&lt;/code&gt; alle in dem Gemfile aufgelisteten gems. Bundler ist kein Teil von Ruby, sondern wird als &lt;code&gt;gem&lt;/code&gt; installiert (&lt;code&gt;$ gem install bundler&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://rvm.io/&quot;&gt;RVM&lt;/a&gt; und &lt;a href=&quot;https://github.com/rbenv/rbenv&quot;&gt;rbenv&lt;/a&gt; sind beides Tools, um unterschiedliche Versionen von Ruby auf einem Rechner zu installieren und zu verwalten. Sie haben nichts mit der Installation und Aktualisierung von &lt;code&gt;gems&lt;/code&gt; zu tun.&lt;/p&gt;

&lt;p&gt;Man sollte Anfangs nicht zuviel wollen. Um erste Schritte zu machen, reicht dass Verständnis für &lt;code&gt;gems&lt;/code&gt; und &lt;code&gt;RubyGems&lt;/code&gt; vollkommen aus. Alles weitere kommt sowieso mit der Zeit.&lt;/p&gt;
              </description>
      <pubDate>Tue, 24 Nov 2015 12:19:00 +0100</pubDate>
      <guid>http://olafgleba.de/notes/2015/11/24/das-ruby-begriffsuniversum-kurz-erklaert/</guid>
    </item>
        <item>
      <title>Augenfreundliche NPM Informationen</title>
      <link>http://olafgleba.de/notes/2015/11/23/augenfreundliche-npm-informationen/</link>
      <description>
                              &lt;p&gt;Jeder, der sich einen Überblick über bspw. installierte Node-Module verschaffen will und dies mit &lt;code&gt;$ npm ls&lt;/code&gt; versucht, wird erschlagen von Informationen, da &lt;code&gt;ls&lt;/code&gt; ohne Parameter sämtliche abhängig installierten Module ebenfalls anzeigt. Das lässt sich leicht eingrenzen.&lt;/p&gt;
                    &lt;p&gt;Hierzu nutzt man die Konfigurationsoption &lt;code&gt;depth&lt;/code&gt;, mit dem die maximale Anzahl an Ebenen der abhängig installierten Libraries bestimmt wird Mit der Angabe &lt;code&gt;0&lt;/code&gt; werden keine Abhängigkeiten angezeigt:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$ npm ls --depth=0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Die Begrenzung der Anzeigetiefe ist ebenfalls interessant um sich übersichtlich anzeigen zu lassen, für welche Module neuere Versionen im NPM-Repository existieren:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$ npm outdated --depth=0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Will man die Anzeige auf veraltete Module beschränken, die im globalen Scope installiert sind, setzt man den entsprechenden Flag:

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$ npm outdated --global --depth=0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ref: &lt;a href=&quot;https://docs.npmjs.com/cli/ls&quot;&gt;NPM-Dokumentation (&lt;code&gt;ls&lt;/code&gt;)&lt;/a&gt;, &lt;a href=&quot;https://docs.npmjs.com/cli/outdated&quot;&gt;NPM-Dokumentation (&lt;code&gt;outdated&lt;/code&gt;)&lt;/a&gt;.&lt;/p&gt;
              </description>
      <pubDate>Mon, 23 Nov 2015 12:44:00 +0100</pubDate>
      <guid>http://olafgleba.de/notes/2015/11/23/augenfreundliche-npm-informationen/</guid>
    </item>
        <item>
      <title>Disabled ist nicht gleich Readonly</title>
      <link>http://olafgleba.de/notes/2015/11/11/disabled-ist-nicht-gleich-readonly/</link>
      <description>
                              &lt;p&gt;Möchte man in einem &lt;a href=&quot;http://processwire.com&quot;&gt;Processwire&lt;/a&gt;-API-Formular den Wert einen Feldes dynamisch vorbelegen, der zudem nicht vom Benutzer änderbar sein darf, sollte man auf ein kleines Detail acht geben.&lt;/p&gt;
                    &lt;p&gt;Folgendes Szenario:&lt;/p&gt;

&lt;p&gt;Ich hole mir einige Information aus der Datenbank, die ich anschließend im Formular nutzen möchte.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$meetings = $pages-&gt;get(&quot;parent=/tools/meetings/);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ein Wert im Array &lt;code&gt;$meetings&lt;/code&gt; ist ein einfacher Datums-String (&lt;code&gt;$meeting_date&lt;/code&gt;). Ein bestimmtes Feld des Formulars soll nun mit diesem Wert vorbelegt werden.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$field = $modules-&gt;get(&quot;InputfieldText&quot;);
$field-&gt;label = &quot;Datum&quot;;
$field-&gt;attr(&#039;value&#039;, $meetings-&gt;meeting_date);
$field-&gt;attr(&#039;id+name&#039;,&#039;meeting_date&#039;);
$form-&gt;append($field);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Damit der Benutzer den Wert des Feldes nicht anpassen kann, ergänze ich es durch ein entsprechende HTML5 Attribut, dass mir spontan sinnvoll erscheint:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$field-&gt;attr(&#039;disabled&#039;, &#039;disabled&#039;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Das Attribut &lt;code&gt;disabled&lt;/code&gt; wird von Processwire sehr wörtlich genommen, bzw. korrekt angewendet. Was dann dazu führt, dass das Formularfeld beim ersten Rendern mit den dynamischen Variablenwert befüllt wird, nach Verarbeiten des Formulars (nach einem Submit) allerdings leer ist.&lt;/p&gt;

&lt;p&gt;Was Sinn macht, habe ich das Feld ja auch mit dem Attribut &lt;code&gt;disabled&lt;/code&gt; versehen und das Formular somit angewiesen, dieses Feld in der Verarbeitung zu ignorieren. Hm...&lt;/p&gt;

&lt;p&gt;HTML5 bietet für nicht bearbeitbare Formularfelder zwei Attribute: &lt;code&gt;disabled&lt;/code&gt; und &lt;code&gt;readonly&lt;/code&gt;...&lt;/p&gt;

&lt;p&gt;... genau, &lt;code&gt;readonly&lt;/code&gt; repräsentiert exakt das, was ich erreichen will. So funktioniert es:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$field = $modules-&gt;get(&quot;InputfieldText&quot;);
$field-&gt;label = &quot;Datum&quot;;
$field-&gt;attr(&#039;value&#039;, $meetings-&gt;meeting_date);
$field-&gt;attr(&#039;id+name&#039;,&#039;meeting_date&#039;);
$field-&gt;attr(&#039;readonly&#039;, &#039;readonly&#039;);
$form-&gt;append($field);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Damit das Feld &lt;b&gt;nach&lt;/b&gt; Verarbeitung des Formulars (sei es durch einen erfolgreichen Submit oder das erneute Rendern im Falle eines aufgetretenen Fehlers) weiterhin dynamisch befüllt wird und trotzdem vom Benutzer nicht änderbar ist, ist das Attribut &lt;code&gt;readonly&lt;/code&gt; die richtige (und einzige) Wahl.&lt;/p&gt;
              </description>
      <pubDate>Wed, 11 Nov 2015 11:30:00 +0100</pubDate>
      <guid>http://olafgleba.de/notes/2015/11/11/disabled-ist-nicht-gleich-readonly/</guid>
    </item>
        <item>
      <title>Große Logs zeilenbasiert per &amp;#36; tail einlesen</title>
      <link>http://olafgleba.de/notes/2015/10/01/grosse-logs-zeilenbasiert-per-tail-einlesen/</link>
      <description>
                              &lt;p&gt;Es gibt ja lustige Provider, die die Logs (error oder/und access) nicht wenigstens monatlich aufräumen, zippen und als Archiv irgendwo hinschieben. So muss man gelegentlich mit Log-Dateien arbeiten, die mehrere Gigabyte groß sind. Um den Lieblings-Texteditor nicht zu verärgern, hilft hier ein Wechsel in die Bash und - für einfache Szenarien - der Textfilter &lt;code&gt;tail&lt;/code&gt;.&lt;/p&gt;
                    &lt;p&gt;Zumindest wenn es um Brot-und-Butter Probleme geht, wie eine Webseite die plötzlich nur noch als weiße Leinwand daher kommt, ist ein schneller Blick ins error.log des Servers von Nöten.&lt;/p&gt;

&lt;p&gt;Logs im Giga-Bereich in einem Texteditor zu öffnen ist zumeist eher ein holpriges Vergnügen (wenn es überhaupt geht). Der Umweg über die Bash bietet sich an. Mit Hilfe des Textfilter &lt;code&gt;tail&lt;/code&gt;, der auf allen unixbasierten Betriebssystemen zur Verfügung steht, ist dies eine Sache einer Zeile:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$ tail -n [X] /pfad/zur/Datei&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Das &lt;code class=&quot;emphase&quot;&gt;[X]&lt;/code&gt; steht hier für die Anzahl der Zeilen, die man anzeigen lassen möchte.  Wobei der Zeiger vom Ende Richtung Anfang der Datei zählt. Folgendes Beispiel also liest die letzten 100 Zeilen der Datei aus:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$ tail -n 100 /pfad/zur/Datei&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Die Beispiele eigenen sich natürlich nicht für ein gezieltes Durchsuchen der Logs. Bei aktuellen Problemen, für die zumeist nur die letzten Einträge relevant sind, kann die Methode aber durchaus hilfreich, bzw. ausreichend sein.&lt;/p&gt;
              </description>
      <pubDate>Thu, 01 Oct 2015 17:57:00 +0200</pubDate>
      <guid>http://olafgleba.de/notes/2015/10/01/grosse-logs-zeilenbasiert-per-tail-einlesen/</guid>
    </item>
        <item>
      <title>Let it flow, mate</title>
      <link>http://olafgleba.de/notes/2013/05/31/let-it-flow-mate/</link>
      <description>
                              	&lt;p&gt;Im Zuge einer als Hilfestellung gedachten E-Mail, die ich nach Ablauf meiner Mitarbeit an einem sog. &lt;i&gt;Responsive Projekt&lt;/i&gt;  an den verantwortlichen Mitarbeiter der Agentur schrieb, wurde mir wiederholt deutlich, wie grundlegend sich der Workflow in derartigen Projekten von dem &amp;#8211; immer noch sehr verbreiteten &amp;#8211; &lt;a href=&quot;https://de.wikipedia.org/wiki/Wasserfallmodel&quot;&gt;Wasserfallprinzip&lt;/a&gt; unterscheidet. Und zwingend muss.&lt;/p&gt;
                    	&lt;h2&gt;Responsive Web/Design im Abriss&lt;/h2&gt;

	&lt;p&gt;Das Web an sich ist &lt;i&gt;responsive&lt;/i&gt;. Eine ursprüngliche Intension der Hypertext  Markup Language war/ist die Anzeige von Inhalten unabhängig von bestimmten Viewports/Geräten.&lt;/p&gt;

	&lt;p&gt;Die Einführung von &lt;i&gt;fixen Layouts&lt;/i&gt; hat genau das pervertiert. Just war &lt;i&gt;Web&lt;/i&gt; == &lt;i&gt;Computer-Desktop&lt;/i&gt;, bzw. Computer-Monitor mit dezidierten Viewports. Und lange Zeit deckte sich die Annahme auch mit der Realität, respektive den technischen Möglichkeiten. Diese &lt;i&gt;Realität&lt;/i&gt; haben Entwickler sowie Kunden über all die Jahre erlernt und vollständig verinnerlicht.&lt;/p&gt;

	&lt;p&gt;Im Grunde geht es beim &lt;i&gt;Responsive Design&lt;/i&gt; um nichts anderes, als genau diese Denkweise zu durchbrechen und der ursprünglichen Intension von &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; wieder mehr Raum zu geben: Der  &lt;i&gt;Viewport- und geräteunabhängige Darstellung&lt;/i&gt; von Inhalten.&lt;/p&gt;

	&lt;h2&gt;Denkweisen (Device-Driven, Content-Driven)&lt;/h2&gt;

	&lt;p&gt;Erstaunlicherweise scheint es, dass auch in progressiven Entwicklerhirnen das Denken in fixen Viewports noch nicht ganz ausgestorben ist. &lt;i&gt;Responsive Design&lt;/i&gt; wird oft verstanden als die Optimierung einer Webseite auf bestimmte Viewports von Geräten, die gerade aktuell sind. So findet man überall die üblichen Verdächtigen an media queries (320px, 768px, 1024px etc.pp), die sich an den aktuellen Platzhirschen auf dem Gerätemarkt orientieren. Der Fokus liegt in erster Linie auf einen bestimmten Zustand der Darstellung (Viewport) eines jeweiligen Gerätes. &lt;/p&gt;

	&lt;p&gt;Wodurch wir uns dann im Grunde mit den gleichen Problemen rumschlagen müssen wie zuvor bei den fixen Pixel-Layouts&amp;#8230;&lt;/p&gt;

	&lt;p&gt;Nicht nur, das die unter dieser Prämisse erstellten Seiten heutzutage schneller veralten, als die Agentur/der Kunde &amp;#8220;&lt;i&gt;iphone/Galaxy&lt;/i&gt;&amp;#8221; sagen kann (Stichwort: Marktzyklen),- wir erheben es faktisch zum Prinzip, den Großteil der Besucher/Geräte da draußen mit einem Achselzucken einfach als &amp;#8220;unbekannt/nicht verifizierbar&amp;#8221; sich selbst und ihren Möglichkeiten der Darstellung zu überlassen.&lt;/p&gt;

	&lt;p&gt;Im Web geht es um eine adäquate Darstellung von Inhalten. Unabhängig vom Ausgabegerät. Salopp gesagt: Wir sollten die Viewports dezidierter, bekannter Geräte vergessen, an Design vorerst gar nicht auch nur denken, die Inhalte/Komponenten der geplanten Seite genau studieren, inhaltliche &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;-Protoypen bauen, uns anschauen, wie sich die Inhalte in verschiedenen Viewports verhalten und auf dieser Grundlage konzeptionelle Entscheidungen treffen, welche Breakpoints an welcher Stelle sinnvoll sind.&lt;/p&gt;

	&lt;p&gt;Soweit das Ideal. All das oben gesagte wirft natürlich &amp;#8211; gerade im Agenturalltag &amp;#8211; viele Fragen auf:  &lt;i&gt;In welcher Form ist das mit den derzeitigen Projekt- und Entwicklungsabläufen umsetzbar? Muss der Designer jetzt &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;/CSS können? Wie erkläre ich dem Kunden, warum er nicht eine gemalte, grafisch bis ins Detail ausformulierte Ansicht seiner fertigen Webseite vor Begin der Produktion bekommt? Wie binde ich ihn ein in den Entwicklungsprozess?&lt;/i&gt;&lt;/p&gt;

	&lt;p&gt;&lt;b&gt;Responsive Web ist nicht einfach&lt;/b&gt;. Im Gegenteil,- es ist komplex und kann zu Anfang ziemlich anstrengend sein. Man muss neue Wege gehen und immer wieder Entscheidungen in der laufenden Entwicklung treffen. Und &amp;#8211; das muss man klar so sehen &amp;#8211; es ist zumindest so lange zeit- und budgetaufwändiger, bis sich die veränderten Arbeitsweisen im Team etabliert haben. Zudem ist es schwer mit den gewohnten Konventionen zu brechen, die sich in der Vergangenheit vermeintlich bewährt haben (das gilt für Kunden ebenso).&lt;/p&gt;

	&lt;h2&gt;Aufgabenverteilung im Team&lt;/h2&gt;

	&lt;p&gt;Ein großer Unterschied zu konventionellen Projekten ist die Notwendigkeit die Rollen/Aufgabenteilung im Team neu zu definieren. Diese sind bislang in der Regel klar verteilt sind: Man hat einen Designer, der sich ausschließlich auf die Erstellung grafischer Mockups/Assets konzentriert und im Detail wenig/nichts über technische Beschränkungen oder Bedingungen der (responsive) &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;-Welt weiß. Und den Webentwickler, der die Designs in valides, voll zugängliches und effizientes &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;/CSS Markup verwandeln soll. Beide arbeiten im Kern mehr oder weniger unabhängig von einander (und i.d.R. auch nacheinander). &lt;/p&gt;

	&lt;p&gt;Dieses &lt;a href=&quot;https://de.wikipedia.org/wiki/Wasserfallmodel&quot;&gt;Wasserfallprinzip&lt;/a&gt; (Konzept -&amp;gt; Design -&amp;gt; Frontend -&amp;gt; Backend -&amp;gt; Release), funktioniert bei Responsive Projekten nicht, bzw. führt fast zwangsläufig in für alle schmerzhafte Sackgassen. In solchen Projekten ist es schon in der Konzeptionsphase zwingend erforderlich, technische Details zu berücksichtigen und inhaltliche Entscheidungen zu treffen. Mit einer konventionellen Arbeitsteilung, die einzelne Aufgaben der Reihe nach &lt;i&gt;abarbeitet&lt;/i&gt;, ist dies nicht erreichbar.&lt;/p&gt;

	&lt;p&gt;Zugespitzt gesagt: der Designer in einem solchen Projekt muss technische Kenntnisse haben, wie sich Markup im &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;-Flow verhält und wo es technische Fallstricke gibt etc.pp. Aber er kann nicht Experte für alles mögliche gleichzeitig sein: Typografie, &lt;a href=&quot;https://de.wikipedia.org/wiki/User_Experience&quot;&gt;UX&lt;/a&gt; &amp;#8211; und Interfacedesign, &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; etc.pp.&lt;/p&gt;

	&lt;p&gt;Der Workflow in &lt;i&gt;Responsive Projekten&lt;/i&gt; ist dem Prinzip der  &lt;a href=&quot;https://de.wikipedia.org/wiki/Agile_Softwareentwicklung&quot;&gt;agilen Webentwicklung&lt;/a&gt; sehr ähnlich. In beiden ist  das interdiziplinäre Teamwork von größter Bedeutung. Projektleitung, Kunde, Texter, Designer und Entwickler müssen eng zusammenarbeiten. Die Arbeitsabläufe laufen nicht linear &lt;i&gt;nacheinander&lt;/i&gt; ab, sondern bewegen sich in &lt;i&gt;kurzen Zyklen&lt;/i&gt;, an deren Ende immer wieder getestet, Lösungen evaluiert und eruiert und gemeinsam Entscheidungen getroffen werden.&lt;/p&gt;

	&lt;h2&gt;Grafische oder &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; Mockups?&lt;/h2&gt;

	&lt;p&gt;Das führt unweigerlich zur Frage: Wie soll ein Designer einen technisch umsetzbaren Layoutentwurf erstellen, der alle Eventualitäten und Besonderheiten von &lt;a href=&quot;http://bradfrost.github.io/this-is-responsive/index.html&quot;&gt;Responsive Design Techniken&lt;/a&gt; vorausschauend berücksichtigt? Die Antwort ist so schlicht wie wichtig: &lt;b&gt;Gar nicht!&lt;/b&gt;&lt;/p&gt;

	&lt;p&gt;Es ist unmöglich am Anfang eines Projektes (das ist i.d.R. ja der Zeitpunkt, an dem der Designer sein Grafikprogramm startet) die technischen sowie inhaltlichen Anforderungen zu berücksichtigen,- &lt;i&gt;sie sind zu dem Zeitpunkt noch gar nicht bekannt&lt;/i&gt;. Auch macht es keinen Sinn, Stunden, Tage an Arbeitszeit damit zu verschwenden, um etwas zu erstellen, dass trotz größter Sorgfalt und fantastischen Einfällen trotzdem immer nur eines bleibt: ein Bild. Etwas, das nichts mit dem Medium zu tun hat, in dem das Ergebnis unserer Arbeit &lt;i&gt;stattfinden&lt;/i&gt; wird.&lt;/p&gt;

	&lt;p&gt;Das ist auch des Pudel&amp;#8217;s Kern: Wir entwickeln Webseiten/Webanwendungen. Demzufolge ist es naheliegend und sinnvoll sobald als möglich direkt in dem Medium zu arbeiten, in dem unsere Arbeit konsumiert wird/funktionieren soll. Das, was häufig als &lt;i&gt;Design im Browser&lt;/i&gt; bezeichnet wird, bedeutet im Grunde nichts anderes, als dass wir zu dem frühstmöglichen Zeitpunkt der Entwicklung damit beginnen sollten, &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;-Prototypen zu bauen. Wir sollten keine Zeit (und somit Geld) dafür verschwenden, komplexe, statische Designs mühevoll in &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; nachzubauen. Um dann mitten in der Arbeit festzustellen, dass einzelne Designideen schlicht nicht funktionieren im &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;-Flow. Oder/und sich einfach als nicht benutzerfreundlich herstellen. Wie will man anhand einer statischen Grafik die &lt;i&gt;Usability/UX&lt;/i&gt; einer Webseite testen, bzw. bewerten?&lt;/p&gt;

	&lt;p&gt;All das heißt übrigens nicht, dass Photoshop (oder besser: &lt;a href=&quot;http://webkrauts.de/artikel/2012/plaedoyer-fuer-adobe-fireworks&quot; title=&quot;Externer Link zum Artikel auf webkrauts&quot;&gt;Fireworks&lt;/a&gt;) im Schrank und der Designer zu Hause bleiben kann ;-). Ich selber bspw. brauche grafische Scribbles um mir einen visuellen Eindruck machen zu können, ob ein Design in sich stimmig ist. Das möchte ich nicht erst im Prozess später entscheiden. Und es kann ebenfalls hilfreich sein, mit Hilfe von grafischen Wireframes an bestimmten Punkten der Entwicklung visuelle Ideen auszuprobieren. Auch initiale &lt;a href=&quot;http://bradfrost.github.io/this-is-responsive/resources.html&quot;&gt;Sketches&lt;/a&gt; werden ggf. benötigt. Ob diese in einem Grafikprogramm oder mit Zettel und Stift erstellt werden, ist allein abhängig, womit man sich wohl fühlt.&lt;br /&gt;
Aber der Designer malt nicht mehr die &lt;i&gt;Mastervorlage&lt;/i&gt;, an dem sich dann alle weiteren Entwicklungsschritte orientieren (müssen).&lt;/p&gt;

&lt;div class=&quot;accent&quot;&gt;
  &lt;blockquote&gt;&lt;p&gt;Alles schön und gut, aber der Kunde will sehen, wie seine Seite aussehen wird&lt;/p&gt;&lt;/blockquote&gt;
&lt;/div&gt;

	&lt;p&gt;Ein Knackpunkt, dem man bei richtiger Kommunikation (gerade bei größeren Auftraggebern) und Techniken oft beikommen kann.&lt;/p&gt;

	&lt;p&gt;Anstatt dem Kunden am Beginn des Projektes grafisch vollständig ausformulierte Layouts zu präsentieren, ist es sinnvoller mit sog. &lt;a href=&quot;http://www.styletil.es/&quot; title=&quot;Externer Link&quot;&gt;Style tiles&lt;/a&gt; zu arbeiten. &lt;i&gt;Style tiles&lt;/i&gt; konzentrieren sich auf die grundsätzliche visuelle Sprache, die im Gespräch mit dem Kunden in einem ersten Schritt entwickelt wird. Abgebildet werden bspw. Farben, Schriften, einzelne Interface-Elemente die Relevanz für die CI haben, Link-Auszeichnung etc.pp. Diese Datei bildet die gestalterische Blaupause im späteren Designprozess. &lt;/p&gt;

	&lt;p&gt;Das wichtigste hieran: &lt;b&gt;Das Design wird von der Entwicklung entkoppelt&lt;/b&gt;. Der Kunde erwartet in diesem Ansatz nicht eine &lt;b&gt;1:1&lt;/b&gt; Umsetzung eines ausformulierten, grafischen Designs, wenn er einen &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; Entwicklungsstand gezeigt bekommt. Präsentiere ich dem Kunden zu Anfangs ein  detailiertes, gemaltes Design, wird der Kunde &lt;i&gt;immer&lt;/i&gt; enttäuscht sein bei Ansicht eines beliebigen Entwicklungsstandes. Einfach aus dem Grund, dass er &amp;#8211; &lt;i&gt;bewusst oder unbewusst&lt;/i&gt; &amp;#8211; kontinuierlich vergleicht zwischen dem Bild, das ihm vorliegt und der aktuellen Ansicht des Prototypen. Er wird immer die Defizite sehen&amp;#8230;&lt;/p&gt;

	&lt;p&gt;Ein beispielhafter Workflow und die daraus entstehenden Vorteile für das Team und den Kunden folgt in einem folgenden Beitrag.&lt;/p&gt;
              </description>
      <pubDate>Fri, 31 May 2013 01:21:00 +0200</pubDate>
      <guid>http://olafgleba.de/notes/2013/05/31/let-it-flow-mate/</guid>
    </item>
        <item>
      <title>Terminal, Zeilenumbruch und &amp;#36; git diff</title>
      <link>http://olafgleba.de/notes/2013/04/02/terminal-zeilenumbruch-und-git-diff/</link>
      <description>
                              &lt;p&gt;Arbeitet man unter OS X im Terminal mit &lt;code&gt;Git&lt;/code&gt;, fällt auf, dass bei einem &lt;code&gt;$ git diff&lt;/code&gt; kein Zeilenumbruch entlang der Fenstergröße erfolgt. Eine Möglichkeit, dies zu erreichen, ist die Anwendung des  Kommandozeilen-Programm&#039;s &lt;a href=&quot;https://de.wikipedia.org/wiki/Less&quot;&gt;less&lt;/a&gt; als Pager.&lt;/p&gt;
                    &lt;p&gt;In der Standardinstallation von OS X ist das Kommandozeilen-Programm &lt;a href=&quot;https://de.wikipedia.org/wiki/Less&quot;&gt;less&lt;/a&gt;  bereits enthalten. Um die Nutzung des &lt;code&gt;less&lt;/code&gt; Pager permanent zu machen, erweitert man die Globalen Optionen von Git um einen weiteren Eintrag.&lt;/p&gt;

&lt;p&gt;Dieses kann man im Terminal mit der folgenden Zeile erreichen:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;$ git config --global core.pager &#039;less -+S&#039;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oder man trägt ihn händisch in der Git config Datei ein:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;[core]
  core.pager = less -+S
  ...&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Die Option &lt;code class=&quot;emphase&quot;&gt;-+S&lt;/code&gt; des &lt;code&gt;less&lt;/code&gt; Programm&#039;s macht in dem Fall nicht anderes als die Zeilen der &lt;code&gt;$ git diff&lt;/code&gt; Ausgabe auf die jeweilige Fensterbreite des Terminals zurecht zu stutzen.&lt;/p&gt;
              </description>
      <pubDate>Tue, 02 Apr 2013 19:23:00 +0200</pubDate>
      <guid>http://olafgleba.de/notes/2013/04/02/terminal-zeilenumbruch-und-git-diff/</guid>
    </item>
        <item>
      <title>&quot;It’s like in sex&quot;</title>
      <link>http://olafgleba.de/notes/2013/04/01/it-s-like-in-sex/</link>
      <description>
                              &lt;p&gt;Ab und zu hat man das Glück, den richtigen Spruch zur richtigen Zeit zu lesen,- und das Lächeln vom Morgen wieder ins Gesicht zu bekommen.&lt;/p&gt;
                    &lt;p&gt;Diesmal bin ich &lt;a href=&quot;http://johanbrook.com/development/html/flexible-markup/&quot;&gt;Johann Brook&lt;/a&gt; zu Dank verpflichtet.&lt;/p&gt;

&lt;div class=&quot;accent&quot;&gt;
  &lt;blockquote&gt;&lt;p&gt;Classes in your markup is fine. Just don’t abuse it, keep a sane balance. It’s like in sex: if it feels good, it’s probably totally okay to do.&lt;/p&gt;&lt;/blockquote&gt;
  &lt;footer&gt;
    &lt;cite&gt;&lt;a href=&quot;http://johanbrook.com/development/html/flexible-markup/&quot;&gt;Johann Brook&lt;/a&gt;&lt;/cite&gt;
  &lt;/footer&gt;
&lt;/div&gt;
              </description>
      <pubDate>Mon, 01 Apr 2013 19:07:00 +0200</pubDate>
      <guid>http://olafgleba.de/notes/2013/04/01/it-s-like-in-sex/</guid>
    </item>
      </channel>
</rss>