Der Webschreiner

Willkommen beim WebSchreiner

Hier gibt es Wissenwertes und Informatives zum Thema Frontend-Development.

Der XmasSchreiner

...sagt euch wie lange es noch bis zur Bescherung dauert!

Da es ja jetzt auch schon Lebkuchen gibt, gibt es nun auch schon den XmasSchreiner ;-)

Nerdige Weihnachtstipps von Steffi

präsentiert vom WebSchreiner

Socken Windows

Windows Socken

In schönen Bluescreen Blau und minimalistisch eckig.

Socken Apple

Apple Socken

California White und mit runden Ecken.

Socken Linus

Linux Socken

Socken in den Tux Farben inklusive Anleitung zum Kompilieren.

Neues

HTML5

HTML5

Wissenswertes, Tipps & Tricks und vieles mehr zum Thema HTML.

HTML5 Responsive Mobile

Wichtige Meta-Tags für responsive Webseiten

Wenn eine Webseite für mobile Geräte optimiert werden soll ist es unerlässlich, das ein paar Meta-Tags gesetzt werden.

Meta-Tag Viewport

Ganz wichtig ist das Meta-Tag mit dem "viewport" Attribut. Hiermit kann gesteuert werden, wie sich die Seite auf mobilen Geräten verhält.

<meta name="viewport" content="initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,width=device-width,user-scalable=no" />

Wird dieses Meta-Tag nicht gesetzt so skaliert der Browser des mobilen Gerätes automatisch. Media Queries werden dann ignoriert!

Meta-Tag Internet Explorer Kompatibilität

Nicht unbedingt nötig aber schaden kann dieses Meta-Tag auch nicht. Es bewirkt, das der Internet Explorer nicht in einen Modus fällt, der nicht wirklich CSS3 kompatibel ist.

<meta http-equiv="X-UA-Compatible" content="IE=edge">
HTML5 Semantik

<article> oder <section>?

Bei diesen beiden HTML5 Tags scheiden sich oft die Geister - wann verwendet man <article> und wann <section>?

Semantik

Semantisch gesehen zeichnen beide Tags Bereiche in Seiten aus. Der Unterschied ist folgender:

<section>

In einer Section werden Bereiche einer Seite ausgezeichnet, die nicht ohne weiteres zu entfernen sind.

<article>

In einem Article werden Bereiche einer Seite ausgezeichnet, die entfernt werden können ohne den Sinn der Seite zu entstellen.

Als Beispiel nehme ich hier immer gerne die gute alte Zeitung. Sicher würde es auffallen, wenn in der Zeitung die Sportseiten fehlen (<section>). Es würde aber weniger auffallen, wenn der Spielbericht vom SV 1920 Gellershausen fehlt (<article>).

Oder als digitales Beispiel - nehmen wir eine Produktübersichtsseite eines Webshops. Wenn der Bereich für die Darstellung der Produkte (<section>) fehlt - na dann fällt das sich spätestens im Umsatz des Shops auf. Fehlt aber nur ein Produkt (<article>) dann geht davon die Welt nicht unter.

JavaScript / jQuery

JavaScript / jQuery

Wissenswertes, Tipps & Tricks und vieles mehr zum Thema JavaScript und jQuery.

node.js Desktop App Electron

Eine Desktop App mit node.js und Electron bauen

Mit JavaScript, HTML und CSS eine Desktop App mit Installer für Mac und Windows bauen - so geht's!

Einleitung

Ich habe vor kurzen ein kleines App Projekt begonnen und habe mich nach einiger Recherche für node.js und Electron entschieden.

Anfängliche Tuturials findet man leicht, doch wenn es dann an das bauen und gar an das erstellen einen Installers für mehrer Platformen geht - dann bekommt man im Internet recht unterschiedliche Aussagen dazu.

Hier möchte ich kurz erklären, wie ich zum Ziel gekommen bin und in welche Fallen ich hinein getappt bin.

Allgemeines

Als Vorraussetzung für die Umsetzung war schnell das richtige Tool gefunden - habe ich von einem ehemaligen Kollegen (Peter Meier) den Tipp bekommen, das mit node.js und Electron umzusetzen - er hatte schon gute Erfahrungen damit gemacht.

Erste Schritte & Fallen

Gleich zu Beginn des Projektes war es meine Anforderung, das das CSS auf jeden Fall durch einen Precompiler erstellt werden sollte. Eigentlich verwende ich für meine privaten Projekte immer SASS, da ich aber nun seit geraumer Zeit auf Arbeit LESS verwende, dachte ich, das ich das in diesem Projekt auch einsetzen könnte. Da ich mir aber GRUNT/GULP als Build System sparen wollte suchte ich nach einer "Eierlegenden Wollmilchsau" Lösung, die ich dann, wie ich dachte, mit "electron-compile" gefunden habe.

Electron-compile

Electron-compile verspricht, das man recht viele Precompiler in einem Electron Projekt verwenden kann. Das funktioniert auch soweit ganz gut. Bedenken sollte man aber, das das alles dann in der App gebaut wird!

Was diesem Tool dann den garaus gemacht hat, war die Tatsache, das es irgendwie nicht wirklich zu publizieren war. Dieses Tool hat so komische Abhängikeiten, das beim Publizieren immer irgendwas schief ging. Also nix mit der eierlegenden Wollmilchsau.

Nachdem ich generell an der Anleitung zum Publizieren gezweifelt habe - alle Packages neu installiert habe und dann immer noch nix ging - habe ich ein leeres Projekt aufgesetzt, um zu sehen, ob die Anleitung funktioniert. Und das tat Sie - also noch mal die ganze Application in ein neues Projekt ohne diese tolle Wollmilchsau ;-(.

Somit - Back to the Roots und einen File Watcher in PHP Storm eingerichtet - da ich ja eh nur LESS kompilieren wollte, reichte das ja aus.

Der CSS Precompiler

Also schnell in PHP Storm den File Watcher für Less eingerichtet. Da ich mir mit electron-compile nicht sicher war, ob es einen modularen Aufbau der Less Files unterstützt habe ich alles in eine Less geschrieben. Das ist aber nicht wirklich optimal - also ging es an das Refactorn und das Auslagern der einzelnen Module.

Doch da sollte die nächste Falle kommen in die ich ohne mit der Wimper zu zucken rein gerannt bin. Von SASS kannte ich die Partials. Hier werden alle Dateien, die mit einem Underscore beginnen nicht mit kompiliert. Das dachte ich, mache ich in LESS auch - aber weit gefehlt - so einfach ist das nicht wie in SASS. Der File Watcher von PHPStorm hat mir einfach alle Daten kompiliert - inklusive der Partials. Gut - das ist ja nicht so schlimm. Also weiter - alles in Module auslagern und in die "main.less" per Import importieren.

Und da kam dann auch schon der nächste Nachteil von LESS. In SASS bin ich es gewohnt, das Variablen in Partials in anderen Partials verfübar sind, wenn diese vor dem zu verwendeten Partial in der "main.scss" importiert wurden. Hierzu, zur Veranschaulichung, ein kleines Beispiel:

_commons.scss
$test: 'test';
_foo.scss
.foo { content: $test; }
main.scss
@import 'commons'; @import 'foo';

Dadurch, das in der "main.scss" das Partial "commons" vor dem Partial "foo" importiert wurde, ist die Variable "$test" auch in "_foo.scss" verfügbar.

Das ist aber in LESS nicht so. Hier muss man die "_commons.less" immer wieder in das File importieren, in dem man die Variable verwenden will. Das ist schon umständlicher, wäre aber immer noch nicht so schlimm gewesen.

Den Todestoß für LESS gab es dann mit der Tatsache, das der File Watcher zwar Änderungen in den Partials erkannt hat und dies auch gleich kompiliert hat - aber eben diese Änderunegn nicht in die "main.less" integriert wurden. Hier hätte ich jedes mal, wenn ich in einem Partial was ändere, auch in der "main.less" etwas ändern und speichern müssen. Das war mir dann zu blöd.

Also wieder Back to the Roots und SASS verwendet.

Kurzes Fazit

Das hat mich schon ein wenig Nerven und auch viel Umbau und Zeit gekostet. Aber als Mitglied der "Sons of Refactor" ist man sowas ja gewohnt.

Es sollte aber noch mehr Spaß auf mich zukommen - aber erst mal zum generellen Herangehen an das Bauen einer App mit node.js und Electron.

Die Basics

Um eine App mit Electron zu bauen muss matürlich erst einmal node.js installiert sein. Dies kann auf der Node.js Webseite herunter geladen werden.

Als kleine Beispiel App werden wir eine App bauen, die eine eindeutige ID eines Computers erechnet und diese ausgibt.

Erstellen wir uns dazu einen Projekt-Ordner - nennen wir ihn "Machine_ID_App". Dann öffnen wir ein Terminal und navigieren zu diesem Ordner.

Init

Als erstes initialisieren wir unser Projekt. Dafür benutzen wir den Befehl:

npm init

Hier werden wir nun nach ein paar Werten gefragt, die wir eigentlich alle so bestätigen können, wie sie vorgeschlagen werden. Zum Schluss wird mit der Eingabe von "yes" eine "package.json" Datei in unserem Projekt-Ordner erstellt. In dieser Datei werden unsere Projekteinstellungen, Abhängigkeiten und Skripte definiert.

Electron

Nun können wir gleich damit fortfahren Electron zu installieren. In die Konsole geben wir folgenden Befehl ein:

npm install electron --save-dev

Nach kurzer Zeit sollte das nun fertig sein und durch den Parameter "--save-dev" wurde das Package auch zu unseren Abhängigkeiten in der "package.json" hinzugefügt.

index.js

In unserer "package.json" gibt es einen Wert "main" der mit "index.js" befüllt ist. Diese Datei wird beim Starten aufgerufen. Da es diese Datei noch nicht gibt, erstellen wir diese nun auf der selben Ebene wie unsere "package.json".

In diese Datei implementieren wir unsere Steuerung für Electron.

index.js
const electron = require('electron'); // Module to control application life. const app = electron.app; const path = require('path'); const url = require('url'); // Module to create native browser window. const BrowserWindow = electron.BrowserWindow; let mainWindow; let windowParams = { width: 1000, height: 700 };

Über "require('electron')" holen wir uns die Klasse und speichern sie in der Konstanten "electron". Zusätzlich erstellen wir die Konstanten "app, path, url und BrowserWindow".

Ebenfalls erstellen wir die Variable "mainWindow", welche dann das Hauptfenster unsere App hält, und die Variable "windowParams", über die wir die Fenster Parameter steuern. In diese Parameter kann man auch einen "icon" Wert definieren, dem man den Pfad zu einem png Icon vergeben kann. Wie ich aber feststellen musste scheint das unter MacOS nicht zu funktionieren - also sparen wir uns das. Eine ausfühliche Doku zu den Optionen von BrowserWindow kann man hier nachlesen.

Als nächstes erstellen wir eine Funktion, die das Hauptfenster erstellt und unser HTML lädt.

index.js
function createWindow(){ mainWindow = new BrowserWindow(windowParams); // and load the index.html of the app. mainWindow.loadURL(url.format({ pathname: path.join(__dirname, 'app/index.html'), protocol: 'file:', slashes: true })); }

Zu guter Letzt fügen wir noch ein paar Event Listener hinzu.

index.js
app.on('ready', ()=>{ createWindow(); }); // Quit when all windows are closed. app.on('window-all-closed', function() { // On OS X it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', function() { // On OS X it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (mainWindow === null) { createWindow(); } });

Damit das ganze dann auch was zum Anzeigen hat, müssen wir noch eine HTML Datei erstellen.

index.html

Die "index.html" ist, wie bei den meisten Webseiten, unsere Startseite der App.

Damit das alles ein wenig aufgräumter ist, erstellen wir diese in einem Ordner "app".

app/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Machine ID App</title> </head> <body> <h1>Unsere Machine ID lautet: <span id="machineId"></span></h1> </body> </html>

Erstes starten unserer App

Um unsere App immer komfortabel starten zu können, fügen wir der "package.json" im Bereich "scripts" noch ein Startskript hinzu:

package.json
"scripts": { "start": "electron .", "test": "echo \"Error: no test specified\" && exit 1" },

Nun können wir einfach in der Konsole durch Eingabe von "npm start" unsere App starten.

Soweit - so gut - schließen wir die App mal wieder.

Machine ID berechnen und anzeigen

Um nun die Funktion zu implementieren müssen wir das Package "node-machine-id" installieren und eine JavaScript Datei "main.js" in unserem App Ordner erstellen.

Da wir dieses Package nicht nur zum Entwickeln, sondern auch dann in der App benötigen müssen, wir es als normale Dependency installieren. Dies geschieht über folgenden Befehl:

npm install node-machine-id -P

In unserer "package.json" müsste das nun unter "Dependencies" und nicht unter "devDependencies" auftauchen.

Als nächstes erstellen wir unsere "main.js" Datei. Damit das wieder aufgräumt ist, erstellen wir diese in einem js Ordner im app Ordner.

Damit diese auch verwendet wird, müssen wir sie noch in unserer HTML Datei refenzieren:

app/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Machine ID App</title> </head> <body> <h1>Unsere Machine ID lautet: <span id="machineId"></span></h1> <script type='text/javascript'> require('./js/main.js'); </script> </body> </html>

In unserer "main.js" requiren wir das Package "node-machine-id", generieren eine Machine ID und gebe diese in dem Feld mit der ID "machineId" aus:

app/js/main.js
const MachineId = require('node-machine-id'); const generatedMachineID = MachineId.machineIdSync(); const machineIdObject = document.getElementById('machineId'); machineIdObject.innerHTML = generatedMachineID;

Nun können wir unsere App noch einmal mit "npm start" öffen und wir sehen unsere eindeutige Machine ID.

Bauen und den Installer für Mac und Windows erstellen

Nun zu dem Teil, der mich viel Zeit und Nerven gekostet hat. Will man das Projekt nur bauen und dann so weiter verteilen reicht es, wenn man das Package "electron-package" verwendet. Soll dann aber noch ein schönes DMG für den Mac und ein Installer für Windows dabei raus springen - dann fängt der Spaß an.

Im Internet gibt es dazu ein paar Anleitungen - viele sind nicht mehr auf dem aktuellen Stand und funktionieren auch so nicht mehr. Einige verwenden eine Kompniation aus "electron-packager" und "electron-builder" - aber das ist mit der aktuellen Version des Builder gar nicht nötig. Anbei nun meine Methode, wie ich zum Ergebnis kam. Hierfür verwendete ich nun das Package "electron-builder". Dieses Package baut unsere App und baut dann auch gleich noch einen geeigneten Installer dafür.

Installieren wir das Package als Dev Dependency:

npm install electron-builder --save-dev

Icon

Damit unsere App auch ein schönes Icon hat, müssen wir eines erstellen. Hierfür legen wir ein png mit einer Größe von 1024x1024 Pixel an. Dieses PNG können wir dann über die Webseite iconverticons.com in die benötigten Formate für den Mac(icns) und Windows(ico) umwandeln. Ich habe mal ein kleines Icon erstellt und auch schon in die richtigen Formate umgewandelt (icons.zip)

Diese beiden Icons legt man nun im Ordner "build" ab, welcher im root Folder angelegt wird. Auf diesen Ordner greift dann "electron-builder" zu.

Für das Mac DMG benötigen wir noch ein Hintergrundbild welches auch im "build" Ordner abgelegt wird und "background.png" heißen sollte.

Bauen

Haben wir das erledigt können wir die Vorbereitungen für das Bauen treffen. In der "package.json" müssen wir ein paar Werte hinzufügen. Wir müssen ein paar Skripte erstellen und die Build Parameter erstellen.

package.json
{ "name": "machine_id_app", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "electron .", "build": "npm run build:mac && npm run build:win", "build:mac": "electron-builder --mac --x64", "build:win": "electron-builder --win --ia32" }, "author": "", "license": "ISC", "build": { "appId": "de.machineId.app", "files": [ "package.json", "index.js", "**/app/**/*" ], "asar": true, "directories": { "output": "packed" }, "dmg" : { "title": "Machine ID App", "background": "build/background.png", "icon": "build/icon.icns", "iconSize": 128, "contents": [ { "x": 355, "y": 125, "type": "link", "path": "/Applications" }, { "x": 155, "y": 125, "type": "file" } ] }, "win" : { "icon": "build/icon.ico" } }, "devDependencies": { "electron": "^1.7.5", "electron-builder": "^19.27.3" }, "dependencies": { "node-machine-id": "^1.1.9" } }

Nun können wir in der Konsole den Befehl "npm run build" ausführen.

Sollte das mit dem Fehler "Error: Cannot spawn Machine_ID_App/node_modules/7zip-bin-mac/7za: Error: spawn EACCES " abrechen, dann muss diese genannte Datei noch ausführbar gemacht werden. Das machen wir mit dem Befehl:

sudo chmod +x ./node_modules/7zip-bin-mac/7za

Sollte beim Bauen der Hinweis kommen, das für den Windows Build Wine benötigt wird, so kann man sehr gut dieser Anleitung folgen.

Abschluss

Ja - nicht ganz einfach sowas zu bauen - aber schon äußerst cool, wenn man nur mit Frontend Skills eine App bauen kann.

Ich hoffe das war manchen eine Hilfe - bei Fragen benutzt das Kontaktformular.

Kleines Update

In Electron funktioniert HTML5 Datalist nicht ;-(

jQuery Addon

jQuery Addon erstellen

Hier wird erklärt, was es beim Erstellen eines jQuery Addons zu beachten gilt.

Allgemeines

jQuery hat den tollen Vorteil, das es durch Addons sehr einfach zu erweitern ist. Hierbei gilt es ein paar Dinge zu beachten. So sollte das übergebene jQuery Object immer wieder mit zurück gegeben werden, damit ein weiterer jQuery Aufruf mit dem selben Objekt möglich ist (Chaining). Ebenfalls ist es immer von Vorteil das Addon möglichst gut durch den User steuerbar zu machen.

Erstellen eines Addons - "myAddon"

Um ein jQuery Addon zu erstellen erweitert man einfach das jQuery "fn" Object um eine eigene Funktion. Als Beispiel nennen wir unser Addon einfach "myAddon". Dies wird dann natürlich durch den Namen eures Addons ersetzt.

jQuery.fn.myAddon = function(){ };

Mehr ist gar nicht nötig. Nun kann unser Addon schon aufgerufen werden:

$('#foo').myAddon();

Damit auch das Chaining - also das Aneinanderketten von jQuery Funktionen an einem jQuery Selektor - funktioniert muss das übergebene Object wieder zurück gegeben werden.

jQuery.fn.myAddon = function(){ return this; };

Das war einfach - nun ist auch Chaining möglich:

$('#foo').myAddon().css('foo','bar');

Damit eine Konfiguration unseres Addons beim Aufruf möglich ist muss es die Möglichkeit geben Optionen zu übergeben. Dies wird meist über ein Konfigurations-Object gelöst. Damit der User nicht immer die Parameter mitgeben muss ist es sinnvoll, das im Addon schon Default-Werte vergeben werden.

jQuery.fn.myAddon = function(options){ var defaults = { foo: 1, bar: 2 } return this; }; $('#foo').myAddon().css('foo','bar');

Wird das Addon nun ohne Angabe von Optionen aufgerufen so werden die Default-Werte in der Variable "defaults" verwendet. Diese Default-Werte müssen aber durch eventuelle benutzerdefinierte Werte verändert werden können. Hierfür wird die jQuery "extend" Methode verwendet.

jQuery.fn.myAddon = function(options){ var defaults = { foo: 1, bar: 2 } var settings = $.extend({},defaults,options); return this; }; $('#foo').myAddon({foo:3}).css('foo','bar');

Nun kann das Addon mit Optionen aufgerufen werden, welche die Default-Werte überschreiben. Hierbei werden nur die Werte überschrieben, die auch übergeben werden. Alle anderen Werte bleiben bei den Default-Werten. In unserem Beispiel wäre der Inhalt von "settings" nun:

{ foo: 3, bar: 2 }

Das wäre es auch schon fast. Nun kann die Funktion implementiert werden. Da bei einem jQuery Selector nicht immer nur ein Object zurück gegeben wird sondern das auch mehrere sein können empfiehlt es sich hier gleich am Anfang mit der "each" Funktion zu arbeiten.

jQuery.fn.myAddon = function(options){ var defaults = { foo: 1, bar: 2 } var settings = $.extend({},defaults,options); $(this).each(function(){ var self = $(this); }); return this; }; $('#foo').myAddon({foo:3}).css('foo','bar');

Die Variable "self" steht nun immer für ein jQuery Object das bearbeitet werden muss.

Nun viel Spaß beim jQuery Addon erstellen ;-)

Erweiterte Techniken

Es kommt vor, das beim Aufruf eines Addon nur ein Parameter benutzdefiniert übergeben werden muss. Damit das nicht über ein Object geschehen muss kann das Addon so erweitert werden, das auch eine Kombination aus 2 Werten möglich ist.

Hierfür muss geprüft werden, ob die Parameter ein String sind.

jQuery.fn.myAddon = function(options){ var defaults = { foo: 1, bar: 2 } var opt = {}; if(typeof options == 'string'){ opt[arguments[0]] = arguments[1]; } else { opt = options; } var settings = $.extend({},defaults,opt); $(this).each(function(){ var self = $(this); }); return this; }; $('#foo').myAddon('foo',3).css('foo','bar');

Nun funktioniert unser Addon auch mit einer String Übergabe ;-)

CSS3 / SASS

CSS3 / SASS

Wissenswertes, Tipps & Tricks und vieles mehr zum Thema CSS3 & SASS.

SASS Special for Steffi

CSS Hamburger mit Hover Animation

Ein kleines Tuturial, wie man ein Hamburger Icon mit CSS baut und das mit Animation beim Hover.

Allgemeines

Steffi wollte gerne ein Tutorial, wie man ein Hamburger Menu mit Hilfe von CSS erstellt und animiert. Und was Steffi sich wünscht, bekommt Steffi auch \m/

Anbei nun das HTML

HTML
<div class="hamburger_wrapper"> <span class="top"></span> <span class="middle"></span> <span class="bottom"></span> </div>

Das SASS für den Hamburger

SASS
.hamburger_wrapper { $HamburgerSize: 20px; $width: $HamburgerSize * 1.4; $h: $HamburgerSize / 5; display: inline-block; width: $width; height: $HamburgerSize; cursor: pointer; span { display: block; width: 100%; height: $h; border-radius: $h; margin-bottom: $h; position: relative; background-color: black; transition: all 400ms ease-in-out; &.top { top: 0; } &.bottom { margin-bottom: 0; bottom: 0; } } }

Und nun noch den Hover integrieren. Der Hamburger soll zu einem Pfeil animiert werden. Der mittlere Strich soll sich nach rechts verkleinern. Der obere und untere Strich soll sich zu einem Pfeil formen.

Das ist ein wenig Rechnerei. Die beiden Striche müssen rotiert werden und damit diese sich auch an der Spitze treffen muss die "transform-orientation" nach rechts verschoben werden. Zusätzlich muss man dann die neue Positionierung berechnen. Das speichern wir in die Variable "$pos".

SASS
.hamburger_wrapper { $HamburgerSize: 20px; $width: $HamburgerSize * 1.4; $h: $HamburgerSize / 5; display: inline-block; width: $width; height: $HamburgerSize; cursor: pointer; span { display: block; width: 100%; height: $h; border-radius: $h; margin-bottom: $h; position: relative; background-color: black; transition: all 400ms ease-in-out; &.top { top: 0; } &.bottom { margin-bottom: 0; bottom: 0; } } &:hover { $pos: $HamburgerSize / 2 - $h / 2; .top { top: $pos; transform: rotate(30deg); transform-origin: 100% 100%; } .middle { transform: scaleX(0); transform-origin: 100% 50%; } .bottom { bottom: $pos; transform: rotate((30deg) * -1); transform-origin: 100% 0; } } }

Will man anstatt des Pfeils ein "X" machen erfolgt das über folgenden Code.

SASS
.hamburger_wrapper { &.close { .top { top: $h * 2; transform: rotate(45deg + 90); } .middle { transform: scaleX(0); } .bottom { bottom: $h * 2; transform: rotate((45deg + 90) * -1); } } }

So Steffi - viel Spaß beim Nachmachen.

SASS Flex Special for Steffen

Vertikales Zentrieren von Inhalt...

...mit Flexbox kein Problem

Allgemeines

Vorbei sind nun die Zeiten, als man zum vertikalen Zentrieren von Inhalten diesen absolut positionieren musste oder mit display:table arbeiten musste. Mit Flexbox ist das einfach und spart viel Code.

Anbei nun das HTML

HTML
<body> <div class="verticalMetaler"> <div class="content"> Inhalt zum Zentrieren </div> </div> </body>

Das CSS

Mit FlexBox und generated Content schaffen wir es einfach den Inhalt zu zentrieren. Dafür sorgt folgender Code:

CSS
html, body { height: 100%; } .verticalMetaler { display: flex; align-items: center; justify-content: center; height: 100%; } .verticalMetaler:before, .verticalMetaler:after { content: ''; width: 0; height: 100%; } .verticalMetaler .content { max-height: 100%; }

Oder als SASS:

SASS
%h100 { height: 100%; } html { @extend %h100; } body { @extend %h100; } .verticalMetaler { @extend %h100; display: flex; align-items: center; justify-content: center; &:before, &:after { @extend %h100; content: ''; width: 0; } .content { max-height: 100%; } }

Fazit

Das war es auch schon - mehr benötigt man heutzutage nicht.

Update - das geht noch viel einfacher!!!!

SASS
%h100 { height: 100%; } html { @extend %h100; } body { @extend %h100; } .verticalMetaler { @extend %h100; display: flex; align-items: stretch; justify-content: center; .content { display: flex; align-items: center; } }
SASS Grid Special for Josh

Ein kleines Grid selber bauen...

...das ist gar nicht schwer. Mit SASS ist das ein ganz einfaches Unterfangen.

Allgemeines

Dieses kleine Grid basiert auf Flexbox und CSS Calc. Also das ist nichts für alte Browser.

Das Grid basiert darauf, das es einen Gridwrapper gibt und alle direkten Child Notes dann ein Grid Element sind.

Anbei nun das HTML

HTML
<div class="gridWrapper"> <div class="col_6">Col 6</div> <div class="col_6">Col 6</div> <div class="col_4">Col 4</div> <div class="col_4">Col 4</div> <div class="col_4">Col 4</div> <div class="col_12 gridWrapper"> <div class="col_6">Col 6</div> <div class="col_6">Col 6</div> </div> </div>

Die Sass Datei

Ich selber habe das Grid immer in einem Partial mit dem Namen "_grid.scss". Da meine Projekte sehr Modular aufgebaut sind, sind meine Settings für das Grid auf mehrere Partials verteilt (_vars.scss, _functions.scss, _placeholder.scss). Damit das hier nicht so durcheinander geht, mache ich alle Settings in einer Datei.

Die Variablen

Als erstes Definiere ich in Variablen die Spaltenanzahl, das CSS Klassen Prefix und das Grid-Padding. Somit kann dann später das Grid leicht angepasst werden.

_grid.scss
// Variables $grid_items: 12; $grid_cssClass_prefix: col_; $grid_pad: 1em;

Der GridWrapper

Als nächstes werden die Einstellungen für den Gridwrapper gemacht. In meinen Projekten verwende ich dafür Placeholder - hier schreibe ich die Setting direkt in das Partial.

Achtet auf das Margin des Wrappers - dies wird mal -1 multipliziert um somit ein negatives Margin zu generieren. Dies sort dafür, das die Grid Elemente auch korrekt links anfangen und rechts enden ohne das etwas am Abstand geändert werden muss.

_grid.scss
// Variables $grid_items: 12; $grid_cssClass_prefix: col_; $grid_pad: 1em; // GridWrapper Settings .gridWrapper { display: -ms-flex; display: -webkit-flex; display: flex; -ms-justify-content: space-between; -webkit-justify-content: space-between; justify-content: space-between; -ms-align-items: center; -webkit-align-items: center; align-items: center; margin: $grid_pad * -1; }

Die Grid Klassen

Das Erstellen der Grid Klassen überlasse ich SASS. Hier nutze ich eine @for Schleife.

Den Klassen-Namen baue ich dynamisch aud dem definierten Prefix und der aktuellen Zahl in der Schleife ($i) zusammen. Das Verwenden des Hash mit den Mustaches bewikt, das SASS zuerst den Namen parsed und diesen dann als String als Klassenname zusammenbaut.

Die Breite des Grids wird über eine Methode berechnet.

Sollte ein Grid Element wieder ein Wrapper sein, sorgt die Einstellung der Breite wieder dafür, das die Positionierung inklusive der Margins wieder passt.

_grid.scss
// Variables $grid_items: 12; $grid_cssClass_prefix: col_; $grid_pad: 1em; // GridWrapper Settings .gridWrapper { display: -ms-flex; display: -webkit-flex; display: flex; -ms-justify-content: space-between; -webkit-justify-content: space-between; justify-content: space-between; -ms-align-items: center; -webkit-align-items: center; align-items: center; margin: $grid_pad * -1; } // create grid classes @for $i from 1 through $grid_items { .#{$grid_cssClass_prefix}#{$i} { width: getGridWidth($i); margin: $grid_pad; box-sizing: border-box; &.gridWrapper { width: getGridWidth($i,true); margin: 0; } } }

Die Breiten-Berechnung

Die Breiten-Berechnung erfolgt über eine Funktion. Dies ist eigentlich in dem "_functions.scss" Partial, damit diese global verwendet werden kann.

Die Methode erwartet mindestens einen Parameter - die gewünschte Grid Breite. Optional kann der Methode noch mit übergeben werden, ob die Breite ohne Margin berechnet werden soll. Dies wird für das Reset des GridWrappers innerhalb eines GridWrappers benötigt.

_grid.scss
// Variables $grid_items: 12; $grid_cssClass_prefix: col_; $grid_pad: 1em; // GridWrapper Settings .gridWrapper { display: -ms-flex; display: -webkit-flex; display: flex; -ms-justify-content: space-between; -webkit-justify-content: space-between; justify-content: space-between; -ms-align-items: center; -webkit-align-items: center; align-items: center; margin: $grid_pad * -1; } // calculate grid width @function getGridWidth($value, $withoutMargin: false){ @if $withoutMargin == true { @return calc(#{100% * $value / $grid_items}); } @else { @return calc(#{100% * $value / $grid_items} - #{$grid_pad * 2}); } } // create grid classes @for $i from 1 through $grid_items { .#{$grid_cssClass_prefix}#{$i} { width: getGridWidth($i); margin: $grid_pad; box-sizing: border-box; &.gridWrapper { width: getGridWidth($i,true); margin: 0; } } }

Fazit

Das war es auch schon - mehr benötigt man in SASS nicht für ein kleines Grid.

CSS3 Responsive Mobile Navigation

Off Canvas Navigation für Mobile Geräte

Erklärung und Stolpersteine einer Off Canvas Navigation

Allgemeines

Hier soll es darum gehen, wie eine Off Canvas Navigation gebaut werden kann, die auch auf Mobilen Geräten gut funktioniert. Hierbei gilt es ein wenig zu beachten und es gibt ein paar Stolpersteine.

Falls jemand nicht weiß was eine Off Canvas Navigation ist - hier eine kurze Erklärung. Bei einer solchen Naviagtion wird beim Klick auf den Hamburger - oder eines ähnlichen Triggers - die Naviagtion von der Seite her eingeblendet. Jedoch geht diese nicht über den Inhalt sonder verdrängt den Inhalt zur Seite.

Umsetzung

Gegeben sei folgendes HTML:

HTML
... <body> <div id="wrapper"> <div id="content"> <div id="hamburger"> Hier kommt der Hamburger hin </div> Hier kommt der Content rein </div> <div id="offCanvasNavigation"> <div class="btn_close"> Hier kommt der Schließen Button hin </div> Hier kommt die Navigation rein </div> </div> </body> ...

Den Schließen Button braucht man nur, wenn der Hamburger nicht auch gleichzeitig schließen soll. Das Triggern der Anzeige erfolgt über jQuery.

Anbei nun das Grundlegende CSS:

CSS
// body body { width: 100%; } // wrapper #wrapper { overflow: hidden; } // content #content { transition: all 400ms ease-in-out; transform: translateX(0); } // offCanvasNavigation #offCanvasNavigation { width: 40vw; transition: all 400ms ease-in-out; transform: translateX(-40vw); }

Das wäre erst mal die Ausgangssituation. Der Body wird mit der Angabe der "width" von 100% auf die Breite des Viewports gebracht. Alternativ könnte auch 100vw verwendet werden. Der Wrapper bekommt ein "overflow:hidden" damit sich die Seite nicht verbreitert, wenn der Inhalt zur Seite geschoben wird. Der Inhaltsbereich bekommt eine transition und eine Grundformatierung von "translateX". Die "offCanvasNavigation" bekommt eine Breite, eine transition und wird dann gleich mit "transform: translateX(-40vw)" wieder um den selben Wert aus dem Viewport geschoben.

Mit SASS kann das ein wenig gynamsicher gemacht werden:

SASS
$offCanvasWidth: 40vw; $transition: all 400ms ease-in-out; // body body { width: 100%; } // wrapper #wrapper { overflow: hidden; } // content #content { transition: $transition; transform: translateX(0); } // offCanvasNavigation #offCanvasNavigation { width: $offCanvasWidth; transition: $transition; transform: translateX($offCanvasWidth * -1); }

Nun kann mit Hilfe von jQuery das Einblenden der Navigation gesteuert werden:

jQuery
$('#hamburger, #offCanvasNavigation btn_close').on('click',function(){ $('#wrapper').toggleClass('showNavigation'); })

Dieses Script sorgt dafür, dass der Wrapper die CSS Klasse "showNavigation" bekommt, wenn auf den Hamburger geklickt wird und wieder entfernt wird, wenn auf den Hamburger oder den "Schließen Button" geklickt wird.

Die eigentliche Animation wird im SASS gemacht:

SASS
$offCanvasWidth: 40vw; $transition: all 400ms ease-in-out; // body body { width: 100%; } // wrapper #wrapper { overflow: hidden; } // content #content { transition: $transition; transform: translateX(0); } // offCanvasNavigation #offCanvasNavigation { width: $offCanvasWidth; transition: $transition; transform: translateX($offCanvasWidth * -1); } // Animation .showNavigation { #content { transform: translateX($offCanvasWidth); } #offCanvasNavigation { transform: translateX(0); } }

Mehr braucht man nicht - schon geht es.

Erweiterung für Mobile Geräte

Die hier im Beispiel angegebene Breite von 40vw (40% des Viewport) kann auf Mobilen Geräten recht schmal werden. Mit Hilfe von SASS kann das leicht angepasst werden:

SASS
$offCanvasWidth: 40vw; $transition: all 400ms ease-in-out; @mixin break_mobile(){ @media all and (max-width: 450px){ @content; } } // body body { width: 100%; } // wrapper #wrapper { overflow: hidden; } // content #content { transition: $transition; transform: translateX(0); } // offCanvasNavigation #offCanvasNavigation { width: $offCanvasWidth; transition: $transition; transform: translateX($offCanvasWidth * -1); } // Animation .showNavigation { #content { transform: translateX($offCanvasWidth); } #offCanvasNavigation { transform: translateX(0); } } @include break_mobile(){ $offCanvasWidth: 80vw; #offCanvasNavigation { width: $offCanvasWidth; transform: translateX($offCanvasWidth * -1); } .showNavigation { #content { transform: translateX($offCanvasWidth); } } }

Stolpersteine

Blöd wird es, wenn die eigene Seite eine sticky Navigation hat. Dies wird eigentlich über "position: fixed" gemacht. Das funktioniert aber laut CSS3 Spezifikation nicht so wie erwartet. Durch das Nutzen von "transform" funktioniert "position: fixed" nicht mehr, da nicht mehr der Context des Viewports, sondern der des Containers mit der Transform Eigenschaft gilt - der Browser verhält sich also so, als ob die Navigation "position: absolute" hätte.

Mit der neuen CSS3 Eigenschft "position:sticky" könnte das umgangen werden. Hier gibt es aber das Problem, das die Browserunterstützung noch mager ist - Chrome kann es gar nicht - und diese Eigenschaft nicht funktioniert, wenn Eltern-Objekte "overflow: hidden" haben. Aber genau das brauchen wir für die Off-Canvas Navigation.

Es bliebe noch die Option die Naviagtion mit "position: absolute" zu positionieren und dann per jQuery "sticky" zu machen - das sieht aber auf iOS Geräten eher suboptimal aus - hier gibt es ein starkes Ruckeln der Navigation.

Mein Fazit ist - wenn das Layout eine "Sticky Navigation" haben soll sollte man, wenn Mobile eine Rolle spielt, auf Off-Canvas verzichten. Das habe ich hier auf DerWebschreiner dann auch gemacht.

SASS Responsive Mobile Breakpoints

Mixins für Breakpoints

Um Breakpoints für eine mobile Seite zu definieren bieten sich Mixins ideal an.

Allgemeines

Ohne Media Queries funktioniert kein Responsive. Mit Hilfe dieser definiert man in modernen Webprojekten die Breakpoints bei denen sich das Layout anpassen soll.

Um sich diese nicht immer merken zu müssen benutze ich in meinen Projekten eine Kombination aus Variablen und Mixins.

Umsetzung

Als erstes definiere ich mir meine benötigten Breakpoints als Variable in der Datei "_vars.scss".

Code in "_vars.scss"
$content_maxWidth: 1200px; $breakpoint_tablet: 900px; $breakpoint_maobile: 600px

Dann verwende ich diese Werte in Media Query Mixins in der Datei "_mixins.scss".

Code in "_mixins.scss"
// media Queries @mixin breakPoint_maxWidth(){ @media (min-width: $content_maxWidth) { @content; } } @mixin breakPoint_mobile(){ @media all and (max-width: $breakPoint_mobile) { @content; } } @mixin breakPoint_tablet(){ @media (max-width: $breakPoint_tablet) { @content; } } @mixin breakPoint_mobile_land(){ @media (max-width: $breakPoint_tablet) and (orientation: landscape) { @content; } }

Mit "@content" wird nun das CSS eingebunden, welches an das Mixin übergeben wird. So könnte das aussehen:

Code in "_nav.scss"
nav{ ul { li { float: left; @include breakpoint_mobile(){ float: none; } } } }
SASS

Allgemeiner Aufbau meiner SASS Projekte

Hier stelle ich kurz dar, wie ich meine SASS Projekt aufbaue.

Allgemeines

Sass hat den Vorteil, das man ungemein modulares CSS schreiben kann. Wenn man einige Dinge beachtet kann man sich das Leben sehr leicht machen und viel CSS sparen.

Hierbei impfiehlt es sich sehr viel mit Partials zu arbeiten. Partials sind SASS Module, die in andere SASS Dateien inkludiert werden können. Sie werden aber nicht als eigene CSS Datei vom Processor ausgegeben. Um dies zu bewirken, wird dem Datei-Namen einfach ein Underscore vorangestellt. Wie in meinem Beispiel ebene die "_vars.scss".

Ich Strukturiere meine Dateien immer in "common", "helper", "modules" und "sites". Im Root liegt dann immer die "main.scss". Diese ist meist die einzige Datei, die ich kompilieren lasse. Müsste ich noch Browser wie alte Internet Explorer (<10) unterstützen würde ich dann da für jede Version eine Bugfix Datei erstellen. Das lasse ich aber hier weg - wer will schon den Mist unterstüzen. So sieht bei mir also die Ordner-Struktur aus:

  • common
  • helper
    • _vars.scss
    • _mixins.scss
    • _placeholder.scss
  • modules
  • sites
  • main.scss

Helper

Im Ordner "Helper" sind meine allgemeinen Helfer Partials. Dies sind immer die "_vars.scss", "_mixins.scss" und die "_placeholder.scss". In manchen Projekten kommt noch die "_functions.scss" dazu.

_vars.scss

In diesem Partial speichere ich alle notwendigen globalen Variablen. Das können Maße, Breakpoints, Farben, etc. sein. Als Beispiel mal hier ein kleiner Ausschnitt aus der Date vom WebSchreiner:

_vars.scss
$content_maxWidth: 1200px; $content_minWidth: 400px; $site_sideSpace: 4vw; // Colors $color_bg: rgba(225,210,190,1); $color_default: rgba(38,20,0,1); $link: rgba(39,91,155,1); $link_hover: lighten($link,10); $link_active: darken($link,10); // Typo $copy: 'Cairo', sans-serif; $head: 'Teko', sans-serif; // Navigation $nav_li_pad_side: 0.5em; // grid $grid_items: 12; $grid_cssClass_prefix: col_; $grid_pad: 1em; // Breakpoints $breakPoint_mobile: 600px; $breakPoint_tablet: 900px;

_mixins.scss

Wie der Name schon beschreibt, werden hier alle SASS Mixins deklariert, die global verfügbar sein sollen. Hier mal ein Auszug aus der des WebSchreiners:

_mixins.scss
@mixin link($color: false){ $col: $link; $hov: $link_hover; $act: $link_active; @if($color != false){ $col: $color; $hov: lighten($color,10); $act: darken($color,10); } display: inline-block; color: $col; text-decoration: none; transition: color 400ms ease-in-out; &:focus, &:hover { color: $hov; } &:active, &.active { color: $act; } }

_placeholder.scss

Und in als letzte Datei diese, in der alle SASS Placeholder deklariert werden, die global verfügbar sein sollen. Hier mal ein Auszug aus der des WebSchreiners:

_placeholder.scss
%reset { padding: 0; margin: 0; }

main.scss

Diese Helper Partial werden dann als erstes in die "main.scss" importiert. Hier spielt die richtige Reiehnfolge eine Rolle. SASS parsed immer von Oben nach unten. Wird als weiter oben im Code auf eine Variable zuggegriffen, die weiter unten erst deklariert wird so wird es einen Kompilier-Fehler geben. Deshalb habe ich mir angewöhnt, das ich immer erst die "_vars.scss", dann die "_mixins.scss" und dann die "_placeholder.scss" importiere.

Ich habe mir angewöhnt in die "main.scss" KEIN CSS zu schreiben. In diese Datei kommen bei mir nur Importe!

main.scss
@import "helper/vars"; @import "helper/mixins"; @import "helper/placeholder";

Common

Im Ordner "Common" sind die Partials, die sich um die Grundformatierung kümmern. So habe ich dort immer eine "_defaults.scss", in der alle Resets gemacht werden. Typischerweiße auch eine "_forms.scss" und viele andere.

  • common
    • _defaults.scss
    • _forms.scss
    • _grid.scss
    • _typo.scss
  • main.scss

Ein kurzer Ausszug der "_defaults.scss" vom WebSchreiner:

_defaults.scss
h1 { @extend %reset; @extend %headline; margin-bottom: 0.6em; font-size: 3em; } h2 { @extend %reset; @extend %headline; font-size: 2.5em; } h3 { @extend %reset; @extend %headline; font-size: 2em; }

Durch das verwenden von Placeholdern und das extenden von "%reset" erspare ich mir die leidige Konkatinierung der Tags beim reseten - das macht SASS für mich ;-)

Diese Partials werden dann in die "main.scss" importiert - wichtig hierbei - immer nach dem Import der Helper Partials.

main.scss
@import "helper/vars"; @import "helper/mixins"; @import "helper/placeholder"; @import "common/defaults"; @import "common/form"; @import "common/grid"; @import "common/typo";

Modules

Im Ordner "modules" landen bei mir alle Module der Seite. Als Module sehe ich beim WebSchreiner die Parts Impressum, News, der Opener und andere Teile.

Site

Und im Ordner "sites" landen bei mir alle Partials für einzelne Unterseiten. Da der WebSchreiner ein One-Pager ist (und auch erst mal bleiben wird - sorry Max) habe ich hier keine Partials.

In anderen Projekten würde ich hier die Ausnahmen einer ganzen Seite deklarieren z.B. Kontakt-Formular-Seite, etc.

Fazit

So das soll es erst mal gewesen sein. Viel Spaß beim umsetzen.

Ueber Mich

Der Webschreiner

Der Webschreiner

was es damit auf sich hat, gibt es hier zu erfahren.

TBC

Kontakt

Impressum
Angaben gemäß § 5 TMG:

Jan Koch
Dorfstrasse 97a
98663 Bad Colberg-Heldburg

Kontakt:
Telefon: «0152•387•204•38»
E-Mail: «info@derwebschreiner.de»

 

Quelle: https://www.e-recht24.de

Haftungsausschluss (Disclaimer)

Haftung für Inhalte

Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.

Haftung für Links

Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.

Urheberrecht

Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.

Datenschutzerklärung:

Datenschutz

Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung.

Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben.

Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich.

Datenschutzerklärung für die Nutzung von Google +1

Unsere Seiten nutzen Funktionen von Google +1. Anbieter ist die Google Inc. 1600 Amphitheatre Parkway Mountain View, CA 94043,  USA.

Erfassung und Weitergabe von Informationen: Mithilfe der Google +1-Schaltfläche können Sie Informationen weltweit veröffentlichen. über die Google +1-Schaltfläche erhalten Sie und andere Nutzer personalisierte Inhalte von Google und unseren Partnern. Google speichert sowohl die Information, dass Sie für einen Inhalt +1 gegeben haben, als auch Informationen über die Seite, die Sie beim Klicken auf +1 angesehen haben. Ihre +1 können als Hinweise zusammen mit Ihrem Profilnamen und Ihrem Foto in Google-Diensten, wie etwa in Suchergebnissen oder in Ihrem Google-Profil, oder an anderen Stellen auf Websites und Anzeigen im Internet eingeblendet werden. Google zeichnet Informationen über Ihre +1-Aktivitäten auf, um die Google-Dienste für Sie und andere zu verbessern. Um die Google +1-Schaltfläche verwenden zu können, benötigen Sie ein weltweit sichtbares, öffentliches Google-Profil, das zumindest den für das Profil gewählten Namen enthalten muss. Dieser Name wird in allen Google-Diensten verwendet. In manchen Fällen kann dieser Name auch einen anderen Namen ersetzen, den Sie beim Teilen von Inhalten über Ihr Google-Konto verwendet haben. Die Identität Ihres Google- Profils kann Nutzern angezeigt werden, die Ihre E-Mail-Adresse kennen oder über andere identifizierende Informationen von Ihnen verfügen.

Verwendung der erfassten Informationen: Neben den oben erläuterten Verwendungszwecken werden die von Ihnen bereitgestellten Informationen gemäß den geltenden Google-Datenschutzbestimmungen genutzt. Google veröffentlicht möglicherweise zusammengefasste Statistiken über die +1-Aktivitäten der Nutzer bzw. gibt diese an Nutzer und Partner weiter, wie etwa Publisher, Inserenten oder verbundene Websites.

Datenschutzerklärung für die Nutzung von Twitter

Auf unseren Seiten sind Funktionen des Dienstes Twitter eingebunden. Diese Funktionen werden angeboten durch die Twitter Inc., 1355 Market Street, Suite 900, San Francisco, CA 94103, USA. Durch das Benutzen von Twitter und der Funktion "Re-Tweet" werden die von Ihnen besuchten Webseiten mit Ihrem Twitter-Account verknüpft und anderen Nutzern bekannt gegeben. Dabei werden auch Daten an Twitter übertragen. Wir weisen darauf hin, dass wir als Anbieter der Seiten keine Kenntnis vom Inhalt der übermittelten Daten sowie deren Nutzung durch Twitter erhalten. Weitere Informationen hierzu finden Sie in der Datenschutzerklärung von Twitter unter http://twitter.com/privacy.

Ihre Datenschutzeinstellungen bei Twitter können Sie in den Konto-Einstellungen unter http://twitter.com/account/settings ändern.

Datenschutzerklärung für die Nutzung von YouTube

Unsere Webseite nutzt Plugins der von Google betriebenen Seite YouTube. Betreiber der Seiten ist die YouTube, LLC, 901 Cherry Ave., San Bruno, CA 94066, USA. Wenn Sie eine unserer mit einem YouTube-Plugin ausgestatteten Seiten besuchen, wird eine Verbindung zu den Servern von YouTube hergestellt. Dabei wird dem Youtube-Server mitgeteilt, welche unserer Seiten Sie besucht haben.
Wenn Sie in Ihrem YouTube-Account eingeloggt sind ermöglichen Sie YouTube, Ihr Surfverhalten direkt Ihrem persönlichen Profil zuzuordnen. Dies können Sie verhindern, indem Sie sich aus Ihrem YouTube-Account ausloggen.

Weitere Informationen zum Umgang von Nutzerdaten finden Sie in der Datenschutzerklärung von YouTube unter https://www.google.de/intl/de/policies/privacy

Cookies

Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert.

Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen.

Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein.

Kontaktformular

Wenn Sie uns per Kontaktformular Anfragen zukommen lassen, werden Ihre Angaben aus dem Anfrageformular inklusive der von Ihnen dort angegebenen Kontaktdaten zwecks Bearbeitung der Anfrage und für den Fall von Anschlussfragen bei uns gespeichert. Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.