<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    
    <title>Netz - Rettung - Recht (Artikel mit Tag bootstrap)</title>
    <link>https://netz-rettung-recht.de/</link>
    <description>Aus dem Leben eines Szlauszafs</description>
    <dc:language>de</dc:language>
    <generator>Serendipity 2.5.0 - http://www.s9y.org/</generator>
    <pubDate>Wed, 25 Aug 2021 20:09:46 GMT</pubDate>

    <image>
    <url>https://netz-rettung-recht.de/templates/2k11/img/s9y_banner_small.png</url>
    <title>RSS: Netz - Rettung - Recht - Aus dem Leben eines Szlauszafs</title>
    <link>https://netz-rettung-recht.de/</link>
    <width>100</width>
    <height>21</height>
</image>

<item>
    <title>Naives MVC</title>
    <link>https://netz-rettung-recht.de/archives/2304-Naives-MVC.html</link>
            <category>Bits'n'Bytes</category>
    
    <comments>https://netz-rettung-recht.de/archives/2304-Naives-MVC.html#comments</comments>
    <wfw:comment>https://netz-rettung-recht.de/wfwcomment.php?cid=2304</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://netz-rettung-recht.de/rss.php?version=2.0&amp;type=comments&amp;cid=2304</wfw:commentRss>
    

    <author>nospam@example.com (Thomas Hochstein)</author>
    <content:encoded>
    &lt;p&gt;Seit 2014 setze ich sowohl bei neuen Websites als auch bei der &amp;#8220;Renovierung&amp;#8221; alter auf &lt;em&gt;static site generators&lt;/em&gt;, also &lt;a href=&quot;https://netz-rettung-recht.de/archives/1755-Generatoren-fuer-statische-Websites.html&quot; title=&quot;&quot;&gt;Generatoren für statische Webseiten&lt;/a&gt;, die aus Templates und Inhalten in verschiedenen Markups, aus Helper-Klassen und ggf. auch Datenbankinhalten HTML-Seiten generieren, die dann auf den Server hochgeladen werden. Das hat verschiedene Vorteile ggü. CMS oder selbstgeschriebenem Code: weil nur statisches HTML ausgeliefert wird, muss auf dem Server keine Scriptsprache wie PHP laufen, was die Last vermindert und vor allem auch aus Sicherheitsgründen angenehm ist, denn wo kein Code läuft, gibt es auch keine Sicherheitslücken. Außerdem bringen Generatoren wie &lt;em&gt;Nanoc&lt;/em&gt;, mein bevorzugtes Werkzeug, ein ganzes Toolset wie Helper-Klassen für häufige Aufgaben und Filter für die verschiedensten Markup-Formate mit. So habe ich mich daran gewöhnt, dass ich das Grundgerüst einer Website in Form von Templates, meistens in &lt;em&gt;HAML&lt;/em&gt;, erstelle, für die optische Gestaltung CSS-Frameworks wie &lt;em&gt;Bootstrap&lt;/em&gt; nutzen kann, wobei ein LESS-Compiler automatisch mitkommt, und dass ich die eigentlichen Inhalte in &lt;em&gt;Markdown&lt;/em&gt; (oder in einer Kombination aus &lt;em&gt;HAML&lt;/em&gt; und &lt;em&gt;Markdown&lt;/em&gt;) erstellen kann. Auf diese Weise habe ich mir einen gut funktionierenden &lt;a href=&quot;https://netz-rettung-recht.de/archives/1994-Workflow-fuer-die-Erstellung-und-Pflege-von-Webseiten.html&quot; title=&quot;&quot;&gt;Workflow&lt;/a&gt; geschaffen.&lt;/p&gt;

&lt;p&gt;Das alles erfüllt seinen Zweck im Grundsatz sehr gut, auch für in begrenztem Umfang dynamische Elemtente: es genügt ja, die Webseitengenerierung in regelmäßigen Abständen neu anzustoßen, bspw. nachts, oder wenn man will auch stündlich. &lt;em&gt;Nanoc&lt;/em&gt; kann man zudem aus Datenbanken speisen, und auch beim bloßen Umgang mit Textdateien lassen sich deren Metadaten auswerten, um bspw. die letzten Änderungen zu verlinken, Termine anzukündigen (aber nur, solange sie noch bevorstehen), Zeitangaben automatisch zu ersetzen (&amp;#8220;Diese Seiten stehen schon seit x Jahren online&amp;#8221;) und anderes mehr. Man kann auch mal ein PHP-Script dazwischenmixen, beispielsweise für ein Kontaktformular. Ihre Grenzen erreicht die Technik erst, wenn es um tatsächlich dynamische Seiten geht, also bspw. die Suche in Datenbanken (bei der man die Einträge nicht schlicht insgesamt vorab als statische Seiten erzeugen kann) - oder wenn ein Passwortschutz (jenseits von &lt;em&gt;Basic Auth&lt;/em&gt;) oder ein Session-Management implementiert werden soll. Dann braucht es etwas anderes. Nur was?&lt;/p&gt;

&lt;p&gt;Bestimmt fünf Jahre lang habe ich die Überarbeitung verschiedener Webseiten vor mir hergeschoben, deren Anforderungen über die Möglichkeit von &lt;em&gt;static site generators&lt;/em&gt; hinausgehen. Der ursprüngliche Ansatz aus meinen ersten (und zweiten) Schritten mit PHP - jede Seite ein Mix von HTML und PHP, letzteres vor allem Funktionen zum Generieren der Seitenstruktur (Header, Footer) und Navigation als &amp;#8220;Templating für Arme&amp;#8221; - kam natürlich nicht mehr in Betracht; natürlich machen allein &lt;a href=&quot;https://netz-rettung-recht.de/archives/1821-Templates-und-Template-Engines.html&quot; title=&quot;&quot;&gt;Templates&lt;/a&gt; in diesem Zusammenhang Sinn. Aber ich wollte die Inhalte auch nicht mehr in HTML verfassen, sondern zumindest in &lt;em&gt;Markdown&lt;/em&gt;; und ein CSS-Baukasten wie &lt;em&gt;Bootstrap&lt;/em&gt; sollte sich auch einbinden lassen, was einen Preprocessor wie LESS oder SASS zumindest wünschenswert macht. Über die Jahre habe ich mit vielen Gedanken gespielt, bspw. an &lt;a href=&quot;https://netz-rettung-recht.de/archives/1822-Webseiten-und-Webapplikationen-erstellen-und-pflegen.html&quot; title=&quot;&quot;&gt;Frameworks&lt;/a&gt; wie &lt;em&gt;Laravel&lt;/em&gt; oder &lt;em&gt;Symfony&lt;/em&gt;; früher hatte ich über viele Jahre die &lt;em&gt;CakePHP&lt;/em&gt;-Mailingliste abonniert. Das erschien mir dann aber doch vergleichsweise aufwendig, um letztlich einen Passwortschutz und ein paar Formulare bzw. Datenbankausgaben zu implementieren.&lt;/p&gt;

&lt;p&gt;Nach langer Pause und Stagnation wollte ich das Thema dieses Jahr über die Osterzeit aber noch einmal angehen. Dazu gehörten mehrere Schritte: Zunächst waren einige eng verbundene Webseiten zu entkoppeln, die gemeinsame Ressourcen nutzten, also bspw. alle dieselbe CSS-Datei eingebunden hatten. Danach brauchte es ein Design, das optisch den bisherigen Webseiten ähnlich sein sollte, nur schicker und möglichst unter Verwendung von &lt;em&gt;Bootstrap&lt;/em&gt; - und dafür wiederum musste ich mich mit &lt;em&gt;Bootstrap 5&lt;/em&gt; auseinandersetzen (meine bisherigen Webseiten setzen alle noch auf die Version 3 auf), und dafür wiederum von &lt;em&gt;LESS&lt;/em&gt; auf &lt;em&gt;SASS&lt;/em&gt; wechseln. Der wiederum nächste Schritt wäre dann ein PHP-basiertes Templating-System, und dann musste all das zusammengesetzt und um die notwendige Funktionalität erweitert werden.&lt;/p&gt;

&lt;h3 id=&quot;-bootstrap-5-und-sass-&quot;&gt;&lt;em&gt;Bootstrap 5&lt;/em&gt; und &lt;em&gt;SASS&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Bootstrap 5&lt;/em&gt; erwies sich als gar nicht so anders; klar, das Grid ist neu und setzt auf Flexbox, es gibt einen Haufen Utility-Klassen für Abstände und bei den Komponenten hat das neue &amp;#8220;Card&amp;#8221;-Element einige bisherige Elemente ersetzt, aber die einzige Neuerung mit Umstellungs- und Änderungsbedarf war der Wechsel von &lt;em&gt;LESS&lt;/em&gt; als CSS-Preporzessor zu &lt;em&gt;SASS&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Ich habe also zunächst die &lt;a href=&quot;https://getbootstrap.com/docs/5.0/getting-started/download/#source-files&quot; title=&quot;Download · Bootstrap v5.0&quot;&gt;Quell-Dateien&lt;/a&gt; heruntergeladen und mich damit vertraut gemacht und mir dann eines der &lt;a href=&quot;https://getbootstrap.com/docs/5.0/examples/&quot; title=&quot;Examples · Bootstrap v5.0&quot;&gt;Beispiele&lt;/a&gt; ausgesucht, um davon ausgehend einen groben Design-Entwurf zu puzzeln. Das war dann auch der Zeitpunkt, wo ich einen &lt;em&gt;SASS&lt;/em&gt;-Compiler brauchte. Das erwies sich als überraschend einfach: &lt;a href=&quot;https://sass-lang.com/dart-sass&quot; title=&quot;Document moved&quot;&gt;Dart Sass&lt;/a&gt; bietet Pakete für Windows an. Herunterladen, &lt;code&gt;dart.exe&lt;/code&gt; und &lt;code&gt;sass.snapshot&lt;/code&gt; in ein &lt;code&gt;bin/&lt;/code&gt;-Verzeichnis packen, eine Batch-Datei mit &lt;code&gt;bin/dart.exe bin/sass.snapshot mein.scss mein.css&lt;/code&gt; ins Hauptverzeichnis des Projekts, und schon kann ich aus &lt;code&gt;mein.scss&lt;/code&gt; eine CSS-Datei zaubern. In der &lt;code&gt;.scss&lt;/code&gt;-Datei importiere ich dann die notwendigen &lt;em&gt;Bootstrap&lt;/em&gt;-Komponenten (oder auch einfach alles), ggf. weitere Elemente (wie &lt;em&gt;Font Awesome&lt;/em&gt;), passe Variablen an (insbesondere das Farbschema), ergänze eigenes CSS - et voilá. Und all das kann ich dann direkt lokal auf meinem unter Windows laufenden Entwicklungsrechner testen: Änderungen vornehmen, Build-Script starten, HTML-Datei im Browser neu laden - und ggf. von vorne.&lt;/p&gt;

&lt;p&gt;Eine solche &lt;code&gt;.scss&lt;/code&gt;-Datei kann dann beispielsweise so anfangen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/* --------------------------------------------------------
 *  SCSS styles and Bootstrap import
 */

// custom variables
$primary:   #314e8c;
$secondary: #bad1e1;
$info:      #ced4da; /* gray-400 */
$body-bg:   $secondary;

// import from Bootstrap
@import &quot;bootstrap/scss/bootstrap.scss&quot;;

// import from FontAwesome (Solid)
@import &quot;fontawesome/scss/fontawesome.scss&quot;;
@import &quot;fontawesome/scss/solid.scss&quot;;

// custom SCSS
/* --------------------------------------------------------
 * Text elements
 */

h1, h2, h3, h4, h5, h6 {
  color: $primary;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Damit werden die gewünschten Primär- und Sekundärfarben gesetzt, die ich aus dem bisherigen Design übernommen habe, die Farbe für &amp;#8220;Info&amp;#8221;-Boxen auf einen Grauton umgestellt und der Hintergrund in der Sekundärfarbe eingefärbt. Dann ziehe ich das komplette &lt;em&gt;Bootstrap&lt;/em&gt;-Framework und &lt;em&gt;Font Awesome&lt;/em&gt; als Webfont ein (hier kann man sich natürlich auf die Elemente beschränken, die man nutzt; das macht alles schlanker), und danach folgen die Anpassungen und eigenen Elemente. So färbe ich bspw. die Überschriften gerne in der Primärfarbe der jeweiligen Website ein.&lt;/p&gt;

&lt;p&gt;Das war, ehrlich gesagt, im Ergebnis dann sehr viel einfacher als ich befürchtet habe, und es gelang mir überraschend schnell, ein brauchbares Mockup zu erstellen. Feinheiten folgen dann, wie immer, sobald sie für bestimmte Elemente oder Situationen benötigt werden.&lt;/p&gt;

&lt;p&gt;Den ganzen Kram - &lt;em&gt;Bootstrap&lt;/em&gt;-Quellcode, &lt;em&gt;Font-Awesome&lt;/em&gt;-Quellcode, die ausführbaren Dateien von &lt;em&gt;Dart Sass&lt;/em&gt; und meine &lt;code&gt;.scss&lt;/code&gt;-Datei - habe ich natürlich in ein Git-Repository gepackt. Dabei haben sowohl &lt;em&gt;Bootstrap&lt;/em&gt; als auch &lt;em&gt;Font Awesome&lt;/em&gt; als auch &lt;em&gt;Dart Sass&lt;/em&gt; jeweils nach dem initialen Einkopieren der Dateien einen eigenen Branch erhalten. Wenn ich nun bspw. eine neue &lt;em&gt;Bootstrap&lt;/em&gt;-Version einspielen will, genügt es, den Bootstrap-Branch auszuchecken, die neuen Dateien einzukopieren und ihn in den Master-Branch zu mergen. So sehe ich sofort alle Änderungen und kann ggf. Anpassungen vornehmen.&lt;/p&gt;

&lt;p&gt;Die am Ende dieser Operationen erzeugte &lt;code&gt;mein.css&lt;/code&gt;-Datei kann ich dann jeweils in das Repository (oder die Repositories) für den Quellcode der einzelnen Webseiten einkopieren.&lt;/p&gt;

&lt;h3 id=&quot;templates&quot;&gt;Templates&lt;/h3&gt;

&lt;p&gt;So weit, so gut. Im nächsten Schritt sollte ich dann aus dem Mockup ein Template machen, in das sich Inhalte einbinden lassen. Davor bedarf es aber eines Template-Systems, das diesen Schritt (Template laden, mit Inhalten füllen) technisch umsetzt.&lt;/p&gt;

&lt;p&gt;Für eine simple interne Seite - Erzeugen von Mailboxen und Mailadressen über ein Webinterface - hatte ich 2017 bei der Renovierung des ursprünglich aus dem Jahr 2009 stammenden &lt;a href=&quot;https://netz-rettung-recht.de/archives/1475-Personalisierte-Mailadressen.html&quot; title=&quot;&quot;&gt;Codes&lt;/a&gt; auf &lt;a href=&quot;http://platesphp.com/&quot; title=&quot;Plates - Native PHP Templates&quot;&gt;&lt;em&gt;Plates&lt;/em&gt;&lt;/a&gt;, ein einfaches PHP-Templating-System, gesetzt. Zusammen mit &lt;em&gt;Bootstrap&lt;/em&gt; sah das hübsch aus und war funktional, wenn auch vielleicht von der Funktionalität her eher überschaubar. So richtig wollte das aber nichts werden; schon das Einbinden machte mir Schwierigkeiten, und mit dem Templating-System wurde ich ebenfalls nicht warm.&lt;/p&gt;

&lt;p&gt;Also dachte ich mir, warum nicht etwas verwenden, von dem ich weiß, dass es sich anderswo bereits bewährt hat? So habe ich mich dann für &lt;a href=&quot;https://www.smarty.net/&quot; title=&quot;PHP Template Engine | Smarty&quot;&gt;&lt;em&gt;Smarty&lt;/em&gt;&lt;/a&gt; entschieden, denn was für &lt;em&gt;Serendipity&lt;/em&gt; gut ist, kann für ein simples Projekt nicht schlecht sein. Außerdem kann ich dann das, was ich lerne, direkt noch anderswo zum Einsatz bringen. Das funktionierte dann auch direkt sehr schön, zumal &lt;em&gt;Smarty&lt;/em&gt; das Einbinden von Teil-Templates (Partials) in Templates unterstützt; man kann sich also das endgültige Template aus wiederverwertbaren Bausteinen zusammenstückeln. Einen Wermutstropfen gibt es freilich: die Templates sind kein &lt;em&gt;HAML&lt;/em&gt;, sondern HTML und &lt;em&gt;Smarty&lt;/em&gt;, aber das passt - so viele Templates braucht man ja in der Regel nicht.&lt;/p&gt;

&lt;p&gt;Wichtiger war mir, die Inhalte nicht komplett als HTML verfassen zu müssen; &lt;em&gt;Markdown&lt;/em&gt; ist da meine Standardlösung. Und wenn ich mich schon an &lt;em&gt;Serendipity&lt;/em&gt; bediene, warum dann nicht auch hier? Das &lt;em&gt;Markdown&lt;/em&gt;-Plugin dort nutzt &lt;a href=&quot;https://michelf.ca/projects/php-markdown/&quot; title=&quot;PHP Markdown&quot;&gt;PHP Markdown&lt;/a&gt;, und das lässt sich natürlich auch sehr schön in meinem Projekt verwenden.&lt;/p&gt;

&lt;h3 id=&quot;model-view-controller&quot;&gt;Model-View-Controller&lt;/h3&gt;

&lt;p&gt;Jetzt mussten alle diese Einzelteile &amp;#8220;nur noch&amp;#8221; sinnvoll zusammengeführt werden. In meinem schon angesprochenen &lt;em&gt;Plates&lt;/em&gt;-Projekt hatte ich für jede Webseite weiterhin jeweils eine gesonderte PHP-Datei, die im Prinzip aber nichts anderes machte, als das Template aufzurufen und mit Inhalten zu füllen. Außerdem gab es für jede Seite dann ein gesondertes Template, dass auf ein Standard-Template aufsetzte. Das kann aber natürlich nicht die Lösung sein. Nicht nur &lt;em&gt;Serendipity&lt;/em&gt; macht das anders: im Prinzip gibt es primär eine PHP-Datei, nämlich eine &lt;code&gt;index.php&lt;/code&gt; im Webroot, die als Parameter die jeweils anzuzeigende Webseite übergeben bekommt und sich dann um den Rest kümmert.&lt;/p&gt;

&lt;p&gt;Im Grundsatz ist das ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Model_View_Controller&quot; title=&quot;&quot;&gt;&lt;em&gt;Model-View-Controller&lt;/em&gt;&lt;/a&gt;-Pattern, kurz &lt;em&gt;MVC&lt;/em&gt;. Das &lt;em&gt;Model&lt;/em&gt; liefert die Daten, sorgt also in einer Applikation üblicherweise für die Abbildung in einer Datenbank. &lt;em&gt;Views&lt;/em&gt; sind die Präsentation, die Templates, die mit Inhalten gefüllt werden. Und der &lt;em&gt;Controller&lt;/em&gt; führt beides zusammen. Natürlich kann man das mehr oder weniger ausgefeilt betreiben; mir genügte eine weniger ausgefeilte Lösung, die bspw. einzelne Aktionen im &lt;em&gt;Controller&lt;/em&gt; nicht in Funktionen auslagert, sondern im Kern auf ein langes &lt;code&gt;switch&lt;/code&gt;-Statement setzt. Immerhin enthält der Großteil der Webseiten primär einmal Text, der angezeigt werden muss; ich will ja keine Webapp schreiben.&lt;/p&gt;

&lt;p&gt;Am Anfang steht die Frage, wie man die anzuzeigende Webseite als Parameter übergeben möchte. Eine URL wie &lt;code&gt;https://meine-website.example/index.php?page=about/contact&lt;/code&gt; sieht ja wirklich hässlich aus und ist auch unter SEO-Gesichtspunkten keine gute Idee. Stattdessen möchte ich gerne URLS wie &lt;code&gt;https://meine-website.example/about/contact/&lt;/code&gt; haben. Hier kommt &lt;em&gt;mod_rewrite&lt;/em&gt; zu Hilfe:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;RewriteEngine On
# rewrite URLs to controller
RewriteCond %{REQUEST_URI} !^/.well-known
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?page=$1 [QSA,L]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Die erste der beiden Bedingungen sorgt dafür, dass alle Aufrufe in das Verzeichnis &lt;code&gt;/.well-known/&lt;/code&gt; nicht umgesetzt werden; das ist bspw. erforderlich, damit &lt;code&gt;certbot&lt;/code&gt; von &lt;em&gt;Let&amp;#8217;s encrypt&lt;/em&gt; seine Aufgaben erfüllen kann. Die zweite sorgt dafür, dass tatsächlich physisch vorhandene Dateien angezeigt werden. So lassen sich bspw. Textdateien oder Downloads unterbringen, die &amp;#8220;as is&amp;#8221; ausgeliefert werden sollen. Die darauffolgende Regel schnappt sich den Pfad - im Beispiel also &lt;code&gt;about/contact/&lt;/code&gt; - und ruft die &lt;code&gt;index.php&lt;/code&gt; mit diesem Pfad als Parameter auf. Damit lässt sich arbeiten.&lt;/p&gt;

&lt;p&gt;Im zentralen PHP-Script wird dieser Pfad dann zunächst normalisiert (damit er mit oder ohne abschließenden Slash &amp;#8220;/&amp;#8221; zur selben Seite führt) und auf unerwünschte Zeichen geprüft, damit nicht böse Menschen versuchen, unerwünschte Pfade (&lt;code&gt;../../../../etc/passwd&lt;/code&gt;) zu übergeben. Der Rest des Scripts arbeitet dann mit diesem Pfad weiter. Dazu wird eine weitgehend aus &lt;em&gt;Smarty&lt;/em&gt; abgeleitete Controller-Klasse benutzt, die ein Template-Objekt erzeugt und mit Variablen befüllt; wo erforderlich, steht eine spezialisierte Datenbank-Klasse bereit, die spezifische Funktionen für alle erforderlichen Lese- und Schreib-Operationen bereithält. Für das Session-Management konnte ich auf eine bestehende PHP-Klasse aus dem Jahre 2011 zurückgreifen, die ich damals für ein anderes Projekt geschrieben und bewusst modular aufgebaut hatte; tatsächlich war sie 10 Jahre später mit kleinen Anpassungen - vor allem in bisher nicht oder kaum genutzten Codepfaden - sofort verwendbar. Auth- und Controller-Klasse lassen sich modular wiederverwenden, die Datenbank-Klasse ist weitgehend projektspezifisch.&lt;/p&gt;

&lt;p&gt;Den Hauptteil der &lt;code&gt;index.php&lt;/code&gt; bildet dann tatsächlich ein langes &lt;code&gt;switch&lt;/code&gt;-Statement, das für bestimmte Seiten spezifischen (Datenbank-)Code enthält, in den meisten Fällen aber auf &lt;code&gt;default&lt;/code&gt; zurückfallen und schlicht eine &lt;em&gt;Markdown&lt;/em&gt;-Datei in HTML konvertieren, in ein Template einsetzen und dann anzeigen kann.&lt;/p&gt;

&lt;h3 id=&quot;verzeichnisstruktur&quot;&gt;Verzeichnisstruktur&lt;/h3&gt;

&lt;p&gt;Die Verzeichnisstruktur des Projekts sieht im Grundsatz so aus:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;\___ source/
 \
  \__ data/
   \
    \__ web/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Das &lt;code&gt;web&lt;/code&gt;-Verzeichnis ist das Webroot; dort finden sich die &lt;code&gt;index.php&lt;/code&gt;, die Unterverzeichniss mit CSS, Javascript, Webfonts, Bildern und Icons und die Downloadverzeichnisse, also alles, was &amp;#8220;as is&amp;#8221; ausgeliefert werden soll.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;source&lt;/code&gt; liegen die Module und externen Elemente: &lt;em&gt;Smarty&lt;/em&gt;, &lt;em&gt;PHP Markdown Extra&lt;/em&gt;, meine eigenen Module und eine Konfigurationsdatei, die etliche Variablen setzt (bspw. für die Datenbankanbindung) und zugleich alle notwendigen Elemente einbindet.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;data&lt;/code&gt; schließlich enthält zum einen die Templates (also die typischen &lt;em&gt;Smarty&lt;/em&gt;-Verzeichnisse wie &lt;code&gt;templates&lt;/code&gt;, &lt;code&gt;templates_c&lt;/code&gt;, &lt;code&gt;cache&lt;/code&gt; und Co.) und zum anderen im Verzeichnis &lt;code&gt;content&lt;/code&gt; die eigentlichen Inhalte in Form von &lt;em&gt;Markdown&lt;/em&gt;-Dateien in einer Verzeichnisstruktur, die der der Webseite entspricht. Der Inhalt, der nach Aufruf von &lt;code&gt;https://meine-website.example/about/contact/&lt;/code&gt; angezeigt werden soll, liegt also in &lt;code&gt;data/content/about/contact.md&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;umsetzungsbeispiele&quot;&gt;Umsetzungsbeispiele&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;$controller = new Controller($config);
$controller-&amp;gt;assign(&#039;page&#039;,$page);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Auf diese Weise wird ein neues Controller-Element erzeugt, dass den Inhalt des Arrays &lt;code&gt;$config&lt;/code&gt; (aus der zentralen Konfigurationsdatei) und die anzuzeigende Seite (&lt;code&gt;$page&lt;/code&gt;) in &lt;em&gt;Smarty&lt;/em&gt; verfügbar macht. Die &lt;code&gt;assign&lt;/code&gt;-Methode akzeptiert entweder ein Array oder - wie im Beispiel - ein Tupel aus Schlüssel und Wert.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# create pages from Markdown/YAML
$yaml = $controller-&amp;gt;create_from_md($page);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Diese Funktion liest eine Datei ein, konvertiert das enthaltene &lt;em&gt;Markdown&lt;/em&gt; in HTML und kann &lt;em&gt;YAML front matter&lt;/em&gt; verarbeiten, also &lt;a href=&quot;https://yaml.org/&quot; title=&quot;  - YAML Ain&#039;t Markup Language&quot;&gt;&lt;em&gt;YAML&lt;/em&gt;&lt;/a&gt;, das als Vorspann (eingefasst in &lt;code&gt;---&lt;/code&gt;) in einer anderen Datei enthalten ist. Diese Inhalt werden in &lt;em&gt;Smarty&lt;/em&gt; als Variablen bereitgestellt.&lt;/p&gt;

&lt;p&gt;Die technische Umsetzung der Funktion &lt;code&gt;create_from_md()&lt;/code&gt; ist im Kern wirklich einfach:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# parse YAML and copy to Smarty
$yaml = yaml_parse_file($content_file);
$this-&amp;gt;template-&amp;gt;assign($yaml);

# parse Markdown, ignoring YAML front matter, and assign to content
$this-&amp;gt;template-&amp;gt;assign(&#039;content&#039;,Michelf\MarkdownExtra::defaultTransform($this-&amp;gt;read_ignore_frontmatter($content_file)));

# return YAML metadate
return $yaml;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Die PHP-Funktion &lt;code&gt;yaml_parse_file()&lt;/code&gt; kann &lt;em&gt;YAML front matter&lt;/em&gt; verarbeiten und ignoriert den Rest. Die selbstgeschriebene Funktion &lt;code&gt;read_ignore_frontmatter()&lt;/code&gt; ist das Gegenstück dazu; sie sorgt dafür, dass beim erneuten Einlesen der Datei diesmal das &lt;em&gt;YAML front matter&lt;/em&gt; übersprungen und nur der &lt;em&gt;Markdown&lt;/em&gt;-Teil verarbeitet wird. Danach werden die eingelesenen &lt;em&gt;YAML&lt;/em&gt;-Daten zurückgegeben und stehen daher nicht nur im &lt;em&gt;Smarty&lt;/em&gt;-Template, sondern auch für den PHP-Code zur Verfügung.&lt;/p&gt;

&lt;p&gt;Auf diese Weise können beispielsweise Titel und Beschreibung der Seite, der Autor usw. übergeben werden. Für die (wenigen) Seiten, die nicht nur aus &lt;em&gt;Markdown&lt;/em&gt; bestehen, sondern weitergehende Funktionalität enthalten, werden diese Daten als Array in der &lt;code&gt;index.php&lt;/code&gt; definiert. Jede Webseite besteht also entweder aus einem speziellen &lt;em&gt;Smarty&lt;/em&gt;-Template mit zusätzlichem Code in der &lt;code&gt;index.php&lt;/code&gt; oder aus dem Inhalt einer &lt;em&gt;Markdown&lt;/em&gt;-Datei, die in das Default-Template eingesetzt wird.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# check for protected pages
if(isset($yaml[&#039;login&#039;])) $auth-&amp;gt;check_session();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wenn im &lt;em&gt;YAML&lt;/em&gt;-Vorspann &lt;code&gt;login&lt;/code&gt; gesetzt ist, wird geprüft, ob ein berechtigter Benutzer eingeloggt ist; ansonsten erfolgt die Umleitung zur Anmeldeseite.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# display template
$controller-&amp;gt;display(&#039;index.tpl&#039;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Am Schluss wird das mit Inhalt gefüllte Template angezeigt.&lt;/p&gt;

&lt;h3 id=&quot;ein-paar-worte-zum-schluss&quot;&gt;Ein paar Worte zum Schluss&lt;/h3&gt;

&lt;p&gt;Das Konzept stand natürlich nicht von Anfang an in der hier präsentierten Form, sondern ist dynamisch gewachsen - so gab es zunächst nur &lt;em&gt;Smarty&lt;/em&gt;-Templates, dann kam die Möglichkeit von &lt;em&gt;Markdown&lt;/em&gt;-Dateien hinzu, und noch später das Parsing von &lt;em&gt;YAML front matter&lt;/em&gt;. Und natürlich waren viele Tests und etliche Iterationen über einige Abende und ein langes Wochenende notwendig - aber am Ende war ich überrascht, erfreut und beeindruckt, mit wie vergleichsweise geringem Aufwand sich ein solches doch (für meine Verhältnisse) einigermaßen komplexes Projekt umsetzen lässt. Frei verfügbare externe Projekte und Frameworks - &lt;em&gt;Smarty&lt;/em&gt;, &lt;em&gt;PHP Markdown&lt;/em&gt;, &lt;em&gt;Bootstrap&lt;/em&gt;, &lt;em&gt;SASS&lt;/em&gt; und natürlich am Ende auch &lt;em&gt;PHP&lt;/em&gt; selbst -, eigene kleine Module und ein bißchen Klebstoff, um das alles miteinander zu verbinden, dazu ein altes Design zum Aufhübschen und die bestehenden Inhalte, die ergänzt und übernommen werden, sind eine ebenso mächtige wie vielseitige Kombination.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[Nachträglich veröffentlicht im August 2021.]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Titelbild © pripir - stock.adobe.com&lt;/em&gt;&lt;/p&gt;
&lt;img src=&quot;https://ssl-vg03.met.vgwort.de/na/1f21a4874f62403e99eb8b517e2fa29e&quot; width=&quot;1&quot; height=&quot;1&quot; alt=&quot;&quot;&gt; 
    </content:encoded>

    <pubDate>Thu, 25 Mar 2021 21:20:00 +0000</pubDate>
    <guid isPermaLink="false">https://netz-rettung-recht.de/archives/2304-guid.html</guid>
    <category>bootstrap</category>
<category>php</category>
<category>webdesign</category>

</item>
<item>
    <title>Bootstrap mit nanoc</title>
    <link>https://netz-rettung-recht.de/archives/1991-Bootstrap-mit-nanoc.html</link>
            <category>Bits'n'Bytes</category>
    
    <comments>https://netz-rettung-recht.de/archives/1991-Bootstrap-mit-nanoc.html#comments</comments>
    <wfw:comment>https://netz-rettung-recht.de/wfwcomment.php?cid=1991</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://netz-rettung-recht.de/rss.php?version=2.0&amp;type=comments&amp;cid=1991</wfw:commentRss>
    

    <author>nospam@example.com (Thomas Hochstein)</author>
    <content:encoded>
    &lt;p&gt;Unter anderem für den Relaunch meiner Homepage habe ich mich damit beschäftigt, wie ich das CSS-Framework &lt;a href=&quot;https://getbootstrap.com/&quot; title=&quot;&quot;&gt;&lt;i&gt;Bootstrap&lt;/i&gt;&lt;/a&gt; am besten mit &lt;a href=&quot;https://nanoc.ws/&quot; title=&quot;&quot;&gt;&lt;i&gt;nanoc&lt;/i&gt;&lt;/a&gt;, meinem bevorzugten &lt;em&gt;static site generator&lt;/em&gt;, zur Anwendung bringen kann.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Bootstrap&lt;/i&gt; bringt einen ganzen Haufen CSS, etwas Javascript und &lt;i&gt;Glyphicon Halflings&lt;/i&gt; als Webfont mit. Webfont und Javascript können unverändert bleiben, das CSS hingegen sollte aus den LESS-Dateien kompiliert werden, um so mit wenigen Anpassungen in &lt;code&gt;variables.less&lt;/code&gt; das Aussehen der Website zu personalisieren.&lt;/p&gt;

&lt;p&gt;Meine &lt;i&gt;nanoc&lt;/i&gt;-Quelldateien habe ich dementsprechend folgendermaßen strukturiert:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;content/
 :
 :--bootstrap/
 :   :
 :   :--js/
 :   :
 :   :--fonts/
 :   :
 :   :--less/
 :    
 :--res/
     :
     :--css/
     :
     :--fonts/
     :
     :--js/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In &lt;code&gt;content/bootstrap/js/&lt;/code&gt; landet das Javascript aus &lt;i&gt;Bootstraps&lt;/i&gt; &lt;code&gt;dist/js/&lt;/code&gt;, in &lt;code&gt;content/bootstrap/fonts/&lt;/code&gt; die Schriften aus &lt;code&gt;dist/fonts/&lt;/code&gt;, und die Dateien aus &lt;code&gt;less/&lt;/code&gt; kommen nach &lt;code&gt;content/bootstrap/less/&lt;/code&gt;. Dabei müssen jedenfalls in meiner alten Version 3 von &lt;i&gt;nanoc&lt;/i&gt; noch einige Dateien umbenannt werden, weil sich nur in der Endung unterscheiende Dateien unzulässig sind: aus &lt;code&gt;bootstrap.min.js&lt;/code&gt; wird so &lt;code&gt;bootstrap-min.js&lt;/code&gt;, bei den Schriftdateien wird die Endung auch in den Dateinamen übernomme, so dass aus &lt;code&gt;glyphicons-halflings-regular.ttf&lt;/code&gt; dann &lt;code&gt;glyphicons-halflings-regular-ttf.ttf&lt;/code&gt; wird.&lt;/p&gt;

&lt;p&gt;Der Inhalt von &lt;code&gt;content/bootstrap/js/&lt;/code&gt; landet dann beim Kompilieren in &lt;code&gt;content/res/js/&lt;/code&gt;, derjenige von &lt;code&gt;content/bootstrap/fonts/&lt;/code&gt; unter Entfernung der &amp;#8220;doppelten&amp;#8221; Endungen in &lt;code&gt;content/res/fonts/&lt;/code&gt;, und aus &lt;code&gt;content/bootstrap/less/bootstrap.less&lt;/code&gt; wird (unter Einbindung aller anderen LESS-Dateien) &lt;code&gt;content/res/css/bootstrap.css&lt;/code&gt; kompiliert.&lt;/p&gt;

&lt;p&gt;Fertig.&lt;/p&gt;

&lt;p&gt;In den &lt;code&gt;Rules&lt;/code&gt; sieht das dann ungefähr so aus:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env ruby

#########################
### compilation rules ###
#########################

# compile Bootstrap CSS (only) from bootstrap.less
compile &#039;/bootstrap/less/bootstrap&#039; do
  filter :less
end
compile &#039;/bootstrap/*&#039; do
  nil
end

# main rule
compile &#039;*&#039; do
  [...]
end

#####################
### routing rules ###
#####################

# copy font files and move last -XXX to extension
route &#039;/res/fonts/*/&#039; do
  # /bootstrap/fonts/foo-eot/ -&amp;gt; /res/fonts/foo.eot
  item.identifier.sub(&#039;/bootstrap/less/&#039;,&#039;/res/css/&#039;).sub(/-[^-]+\/$/, &#039;&#039;) + &#039;.&#039; + item[:extension]
end

# copy bootstrap files
route &#039;/bootstrap/less/bootstrap&#039; do
  item.identifier.sub(&#039;/bootstrap/less/&#039;,&#039;/res/css/&#039;).chop + &#039;.css&#039;
end
route &#039;/bootstrap/less/*&#039; do
  nil
end
route &#039;/bootstrap/*/&#039; do
  item.identifier.sub(&#039;/bootstrap/&#039;,&#039;/res/&#039;).chop + &#039;.&#039; + item[:extension]
end

# main rule
route &#039;*&#039; do
  [...]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Es geht sicherlich einfacher und weniger komplex, aber so geht es jedenfalls auch. &lt;img src=&quot;https://netz-rettung-recht.de/plugins/serendipity_event_emoticate/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wenn man in seinem &lt;i&gt;Git&lt;/I&gt;-Repository auch direkt einen &lt;code&gt;bootstrap&lt;/code&gt;-Branch anlegt, kann man &lt;i&gt;Bootstrap&lt;/i&gt;-Updates dort einspielen und in der Regel durch ein einfaches &lt;code&gt;git checkout master; git merge bootstrap&lt;/code&gt; für die eigenen Seiten übernehmen.&lt;/p&gt;
&lt;img src=&quot;https://ssl-vg03.met.vgwort.de/na/8916b18ed9d6465cbe3b6addf4f87938&quot; width=&quot;1&quot; height=&quot;1&quot; alt=&quot;&quot;&gt; 
    </content:encoded>

    <pubDate>Fri, 05 May 2017 15:15:00 +0000</pubDate>
    <guid isPermaLink="false">https://netz-rettung-recht.de/archives/1991-guid.html</guid>
    <category>bootstrap</category>
<category>nanoc</category>
<category>webdesign</category>

</item>
<item>
    <title>Frameworks für HTML, CSS und Javascript</title>
    <link>https://netz-rettung-recht.de/archives/1817-Frameworks-fuer-HTML,-CSS-und-Javascript.html</link>
            <category>Bits'n'Bytes</category>
    
    <comments>https://netz-rettung-recht.de/archives/1817-Frameworks-fuer-HTML,-CSS-und-Javascript.html#comments</comments>
    <wfw:comment>https://netz-rettung-recht.de/wfwcomment.php?cid=1817</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://netz-rettung-recht.de/rss.php?version=2.0&amp;type=comments&amp;cid=1817</wfw:commentRss>
    

    <author>nospam@example.com (Thomas Hochstein)</author>
    <content:encoded>
    &lt;p&gt;Vergangene Woche hatte ich einen &lt;a href=&quot;https://netz-rettung-recht.de/archives/1816-HTML-5-und-CSS-3.0.html&quot; title=&quot;&quot;&gt;Überblick&lt;/a&gt; über die vielfältigen Möglichkeiten gegeben, die in &lt;i&gt;HTML 5&lt;/i&gt; und &lt;i&gt;CSS 3.0&lt;/i&gt; enthalten sind - ohne dabei &lt;i&gt;Javascript&lt;/i&gt; überhaupt anzusprechen. Heute möchte ich zeigen, wie man sich diese neuen Möglichkeiten zunutze machen kann, ohne zuvor monatelang Bücher zu studieren und auszuprobieren. &lt;img src=&quot;https://netz-rettung-recht.de/plugins/serendipity_event_emoticate/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; class=&quot;emoticon&quot; /&gt; Kluge Leute haben nämlich bereits &lt;em&gt;Frameworks&lt;/em&gt; zusammengestellt, eine Art Baukasten, aus dem man sich bedienen kann.&lt;/p&gt;

&lt;p&gt;Im einfachsten Fall enthält dieser Baukasten &lt;em&gt;CSS&lt;/em&gt; und &lt;em&gt;Javascript&lt;/em&gt;, um Webseiten einigermaßen elegant und &lt;em&gt;responsive&lt;/em&gt; zu gestalten, einschließlich der notwendigen Tricks für die Kompatibilität zu älteren Browsern. Meistens gehört dazu dann auch irgendeine Art von &lt;em&gt;Grid&lt;/em&gt;, also einer Aufteilung, um mehrspaltige Seiten zu gestalten, deren Aufbau sich auf kleineren Bildschirmen anpasst - bspw. indem Spalten nicht nebeneinander, sondern übereinander dargestellt werden.&lt;/p&gt;

&lt;p&gt;Umfangreichere &lt;em&gt;Frameworks&lt;/em&gt; enthalten zusätzlich &lt;em&gt;CSS&lt;/em&gt;-Formatierungen für Standard-Elemente wie eine Navigationsleiste, Tabellen mit wechselndem Hintergrund pro Zeile oder auch andere Gestaltungselemente.&lt;/p&gt;

&lt;p&gt;Dazu kommen dann noch &lt;em&gt;Templates&lt;/em&gt; oder &lt;em&gt;Themes&lt;/em&gt;, die im einfachsten Fall Beispiele oder besser Vorlagen dafür darstellen, wie der Baukasten, das &lt;em&gt;Framework&lt;/em&gt;, zur Anwendung gebracht werden kann. Oft enthalten sie auch weitere &lt;em&gt;CSS&lt;/em&gt;-Definitionen über den Grundbestand des &lt;em&gt;Frameworks&lt;/em&gt; hinaus.&lt;/p&gt;

&lt;h3 id=&quot;-boilerplates-und-css-frameworks-&quot;&gt;&lt;em&gt;Boilerplates&lt;/em&gt; und &lt;em&gt;CSS-Frameworks&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;Ein &amp;#8220;einfaches&amp;#8221; &lt;em&gt;Framework&lt;/em&gt; - hinter dem dennoch viel Arbeit und Erfahrung steht - ist bspw. &lt;a href=&quot;https://html5boilerplate.com/&quot; title=&quot;HTML5 Boilerplate: The web&amp;#8217;s most popular front-end template&quot;&gt;&lt;strong&gt;HTML 5 Boilerplate&lt;/strong&gt;&lt;/a&gt;. Es enthält - wie üblich - ein &lt;code&gt;normalize.css&lt;/code&gt;, um die in Browsern enthaltenen Standard-&lt;em&gt;CSS&lt;/em&gt;-Definitionen zu vereinheitlichen, Basis-Formatierungen und eine schlanke &lt;em&gt;HTML&lt;/em&gt;-Beispielseite, dazu &lt;em&gt;Modernizr&lt;/em&gt;, eine Javascript-Bibliothek, die austestet, welche Funktionalität der Browser unterstützt, und &lt;em&gt;jQuery&lt;/em&gt;, quasi &lt;strong&gt;die&lt;/strong&gt; Javascript-Standard-Bibliothek. &lt;a href=&quot;http://www.initializr.com/&quot; title=&quot;Initializr - Start an HTML5 Boilerplate project in 15 seconds!&quot;&gt;&lt;strong&gt;Initializr&lt;/strong&gt;&lt;/a&gt; ergänzt &lt;strong&gt;HTML 5 Boilerplate&lt;/strong&gt; um einen Template-Generator, der eine Vorlage für ein neues Web-Projekt in drei verschiedenen Varianten erzeugen kann.&lt;/p&gt;

&lt;p&gt;Bereits etwas umfangreicher (und aus deutschen Landen) kommt dann das &amp;#8220;altehrwürdige&amp;#8221; - 2005 begonnene - &lt;a href=&quot;http://www.yaml.de/&quot; title=&quot;YAML CSS Framework &amp;mdash; for truly flexible, accessible and responsive websites&quot;&gt;&lt;strong&gt;YAML&lt;/strong&gt;&lt;/a&gt;-&lt;em&gt;CSS&lt;/em&gt;-Framework in Version 4 daher. Sein Schwerpunkt liegt auf der Gestaltung flexibler Layouts (Stichwort &lt;em&gt;responsive design&lt;/em&gt;), die es umfangreich unterstützt; dazu kommen - natürlich neben einer abgestimmten Typographie - Formular-Elemente und Buttons sowie Navigationselemente. Die &lt;em&gt;CSS&lt;/em&gt;-Stylesheets werden dabei dynamisch via &lt;em&gt;SASS&lt;/em&gt; erzeugt; &lt;em&gt;YAML&lt;/em&gt; enthält aber auch eine fertig kompilierte, &amp;#8220;statische&amp;#8221; Version, die unmittelbar eingesetzt werden kann, ohne dass &lt;em&gt;SASS&lt;/em&gt; als &lt;em&gt;CSS&lt;/em&gt;-Präprozessor zum Einsatz gebracht werden müsste.&lt;/p&gt;

&lt;p&gt;Ein anderer Ansatz, ein weiteres Framework ist &lt;a href=&quot;http://sass.fffunction.co/&quot; title=&quot;&quot;&gt;&lt;strong&gt;Sassaparilla&lt;/strong&gt;&lt;/a&gt;, ein massiv auf &lt;em&gt;SASS&lt;/em&gt; und &lt;em&gt;Compass&lt;/em&gt; aufsetzendes System, das allerdings an Dokumentation - soweit ich sehe - eher sparsam ist.&lt;/p&gt;

&lt;h3 id=&quot;gro-e-frontend-frameworks-&quot;&gt;Große &lt;em&gt;Frontend-Frameworks&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;Vertreter der Gattung sehr umfangreicher Baukästen sind bspw. (Twitter) &lt;a href=&quot;http://getbootstrap.com/&quot; title=&quot;&quot;&gt;&lt;strong&gt;Bootstrap&lt;/strong&gt;&lt;/a&gt;, das mit Version 3 in sein fünftes Jahr geht, und das nur ein Jahr jüngere ZURB &lt;a href=&quot;http://foundation.zurb.com/&quot; title=&quot;&quot;&gt;&lt;strong&gt;Foundation&lt;/strong&gt;&lt;/a&gt; (aktuell in Version 5). Beide bieten eine weit über die &amp;#8220;Grundzutaten&amp;#8221; hinausgehende Auswahl an fertigen Bausteinen für Navigationselemente, Menüs mit verschiedenen Buttons und Dropdowns, farbige Hinweise und Einblendungen (sog. &lt;em&gt;Modals&lt;/em&gt;), Fortschrittsbalken und so weiter, und so fort.&lt;/p&gt;

&lt;p&gt;Ausgangspunkt ist natürlich auch hier ein flexibles &lt;em&gt;Grid&lt;/em&gt;, mit dem die Webseiten &lt;em&gt;responsive&lt;/em&gt; gestaltet werden können. Zudem ist aber auch eine reiche Auswahl an &lt;em&gt;CSS&lt;/em&gt;-Formatierungen und &lt;em&gt;Javascript&lt;/em&gt; enthalten, um eine Vielzahl von Gestaltungselementen einbauen zu können, die in der umfangreichen Dokumentation anhand von Beispielen dargestellt werden. Alle diese Beispiele können sofort per &lt;em&gt;copy &amp;amp; paste&lt;/em&gt; in das eigene Webprojekt übernommen und angepasst werden-&lt;/p&gt;

&lt;p&gt;Die Verwendung von &lt;em&gt;CSS&lt;/em&gt;-Compilern wie &lt;em&gt;LESS&lt;/em&gt; oder &lt;em&gt;SASS&lt;/em&gt; ist nicht zwingend, weil auch &lt;em&gt;Bootstrap&lt;/em&gt; eine fertig kompilierte &lt;em&gt;CSS&lt;/em&gt;-Datei enthält; sie bietet aber noch umfangreichere Möglichkeiten, durch Änderungen an zentralen Variablen das ganze &amp;#8220;look and feel&amp;#8221; einheitlich für die gesamte Website anzupassen. Für den, der diese Compiler nicht verwenden kann oder will, bietet &lt;strong&gt;Bootstrap&lt;/strong&gt; überdies einen Mittelweg: mittels &lt;a href=&quot;http://getbootstrap.com/customize/&quot; title=&quot;&quot;&gt;&lt;em&gt;Customizing&lt;/em&gt;&lt;/a&gt; kann mit allen vorhandenen Variablen experimentiert und dann eine entsprechend angepasste, statische &lt;em&gt;CSS&lt;/em&gt;-Version erzeugt und heruntergeladen werden.&lt;/p&gt;

&lt;h3 id=&quot;eigene-anpassungen&quot;&gt;Eigene Anpassungen&lt;/h3&gt;

&lt;p&gt;Natürlich bedeutet die Verwendung eines solchen &lt;em&gt;Frameworks&lt;/em&gt; nicht, dass individuelle Anpassungen nicht möglich wären; alle Vorgaben können problemlos in einer eigenen &lt;em&gt;CSS&lt;/em&gt;-Datei übersteuert und auch ergänzt werden. &lt;em&gt;Frameworks&lt;/em&gt; bieten eine professionelle Ausgangsbasis, auf der man seine eigenen Anpassungen aufsetzen kann.&lt;/p&gt;

&lt;p&gt;Natürlich besteht - je umfangreicher das verwendete &lt;em&gt;Framework&lt;/em&gt; ist und je weniger man seine Vorgaben anpasst - die Gefahr, dass man den mit Hilfe des &lt;em&gt;Frameworks&lt;/em&gt; erzeugten Webseiten ihre Herkunft ansieht oder sie gar - zumindest in ihrer Grundstruktur - alle einigermaßen ähnlich aussehen. Auch das ist aber nicht neu; das Web kannte immer schon bestimmte Moden, und eine ähnliche Grundstruktur oder wiedererkennbare Basis-Elemente müssen nicht per se schlecht sein.&lt;/p&gt;

&lt;p&gt;Der Rest ist der Kreativität jedes einzelnen überlassen.&lt;/p&gt;

&lt;h3 id=&quot;-templates-bzw-themes-&quot;&gt;&lt;em&gt;Templates&lt;/em&gt; bzw. &lt;em&gt;Themes&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;Wer sich immer noch nicht ausreichend von der Muse geküsst fühlt, kann sich weitere Inspirationen durch &lt;em&gt;Templates&lt;/em&gt; (oder &lt;em&gt;Themes&lt;/em&gt;), also Vorlagen, holen, die auf einem &lt;em&gt;Framework&lt;/em&gt; aufbauen. Für &lt;em&gt;Bootstrap&lt;/em&gt; bietet &lt;a href=&quot;http://startbootstrap.com/&quot; title=&quot;&quot;&gt;&lt;strong&gt;StartBootstrap&lt;/strong&gt;&lt;/a&gt; rund drei Dutzend (kosten)freie Varianten, von simplen Rastern über Beispiele für Blogs und Portfolio-Seiten bis hin zu Vorlagen für ein Administrations-Interface einer Webapplikation. &lt;a href=&quot;https://wrapbootstrap.com/&quot; title=&quot;Just a moment...&quot;&gt;&lt;strong&gt;WrapBootstrap&lt;/strong&gt;&lt;/a&gt; legt noch ein paar hundert - meist kommerzielle - Beispiele nach.&lt;/p&gt;

&lt;p&gt;Ähnliche Sammlungen gibt es auch an anderen Orten und für andere &lt;em&gt;Frameworks&lt;/em&gt; - und grundsätzlich können &lt;em&gt;Frameworks&lt;/em&gt; und &lt;em&gt;Templates&lt;/em&gt; natürlich auch mit Blogsystemen wie &lt;em&gt;Wordpress&lt;/em&gt; und &lt;em&gt;Serendipity&lt;/em&gt;, mit &lt;em&gt;Content Management Systemen (CMS)&lt;/em&gt; und &lt;em&gt;Web Application Frameworks&lt;/em&gt; kombiniert werden.&lt;/p&gt;

&lt;p&gt;Doch auch schon ohne eine weitere &amp;#8220;Automatisierung&amp;#8221; bieten sie eine reichhaltige Basis für die Gestaltung der eigenen Website, ohne dass der Anwender zwingend über fortgeschrittene Kenntnisse von &lt;em&gt;HTML&lt;/em&gt;, &lt;em&gt;CSS&lt;/em&gt; und &lt;em&gt;Javascript&lt;/em&gt; verfügen müsste.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dieser Beitrag gehört zur Reihe &amp;#8220;&lt;a href=&quot;https://netz-rettung-recht.de/archives/1810-Webdesign-anno-2015.html&quot; title=&quot;&quot;&gt;Webdesign anno 2015&lt;/a&gt;&amp;#8221;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[Dieser Eintrag wurde nachträglich im Februar 2015 veröffentlicht.]&lt;/em&gt;&lt;/p&gt;
&lt;img src=&quot;https://ssl-vg03.met.vgwort.de/na/a942bd0db2fd4af4875ea0c445fde089&quot; width=&quot;1&quot; height=&quot;1&quot; alt=&quot;&quot;&gt; 
    </content:encoded>

    <pubDate>Fri, 16 Jan 2015 08:00:00 +0000</pubDate>
    <guid isPermaLink="false">https://netz-rettung-recht.de/archives/1817-guid.html</guid>
    <category>bootstrap</category>
<category>webdesign</category>

</item>

</channel>
</rss>
