4 Sass Syntax und Funktionen

4.1 Variablen

Variablen sind das Fundament effizienter Sass-Entwicklung. Sie ermöglichen es, Werte zentral zu definieren und überall im Code wiederzuverwenden. Dies macht Änderungen einfach und reduziert Fehler erheblich.

4.1.1 Deklaration und Verwendung

Sass-Variablen beginnen immer mit einem Dollarzeichen (`# Sass Grundlagen

4.2 Einführung in Sass

Sass erweitert CSS um programmierähnliche Funktionen, die das Schreiben und Verwalten von Stylesheets erheblich vereinfachen. Sie schreiben Sass-Code, der dann zu normalem CSS kompiliert wird, das jeder Browser versteht.

4.2.1 Die zwei Sass-Syntaxformen im Vergleich

SCSS-Syntax (.scss) - Empfohlen für Anfänger und bestehende Projekte:

$primary-color: #3498db;
$margin: 16px;

.header {
  background-color: $primary-color;
  margin: $margin;
  
  h1 {
    color: white;
    font-size: 2rem;
  }
}

Sass-Syntax (.sass) - Kompakter, aber gewöhnungsbedürftig:

$primary-color: #3498db
$margin: 16px

.header
  background-color: $primary-color
  margin: $margin
  
  h1
    color: white
    font-size: 2rem

Beide Syntaxformen kompilieren zum identischen CSS-Output. Für Ihr Bootstrap-Flask-Projekt empfiehlt sich SCSS, da Bootstrap selbst in SCSS geschrieben ist.

4.2.2 Sass vs. normales CSS - Direkter Vergleich

Normales CSS (repetitiv und schwer wartbar):

.header {
  background-color: #3498db;
  margin: 16px;
}

.header h1 {
  color: white;
  font-size: 2rem;
}

.sidebar {
  background-color: #3498db;
  margin: 16px;
}

.footer {
  background-color: #3498db;
  margin: 16px;
}

Äquivalenter Sass-Code (DRY-Prinzip, wartbar):

$primary-color: #3498db;
$margin: 16px;

.header {
  background-color: $primary-color;
  margin: $margin;
  
  h1 {
    color: white;
    font-size: 2rem;
  }
}

.sidebar, .footer {
  background-color: $primary-color;
  margin: $margin;
}

4.3 Installation und Setup

4.3.1 Schritt 1: Sass installieren

Option A: Über npm (empfohlen für Webprojekte)

# Global installieren
npm install -g sass

# Oder lokal im Projekt (empfohlen)
npm install --save-dev sass

Option B: Standalone-Installation - Windows: Herunterladen von https://github.com/sass/dart-sass/releases - macOS: brew install sass/sass/sass - Linux: Download der Binary-Datei

4.3.2 Schritt 2: Installation testen

# Version prüfen
sass --version

# Sollte ausgeben: z.B. "1.69.5 compiled with dart2js 3.1.0"

4.3.3 Schritt 3: Erste Sass-Datei kompilieren

Erstellen Sie eine Testdatei test.scss:

$color: red;

.test {
  color: $color;
}

Kompilieren Sie diese:

sass test.scss test.css

Das Ergebnis in test.css:

.test {
  color: red;
}

4.3.4 Schritt 4: Automatisches Überwachen (Watch-Modus)

Für kontinuierliche Entwicklung verwenden Sie den Watch-Modus:

# Einzelne Datei überwachen
sass --watch input.scss:output.css

# Ganzes Verzeichnis überwachen
sass --watch sass/:css/

4.4 Integration in bestehende Projekte

4.4.1 Flask-Projekt-Integration: Schritt-für-Schritt

Schritt 1: Projektstruktur vorbereiten

Erstellen Sie folgende Verzeichnisstruktur in Ihrem Flask-Projekt:

your-flask-app/
├── app.py
├── static/
│   ├── css/           # Kompilierte CSS-Dateien (von Sass generiert)
│   └── scss/          # Ihre Sass-Quelldateien
│       ├── main.scss
│       ├── _variables.scss
│       └── components/
└── templates/

Schritt 2: Sass-Hauptdatei erstellen

Erstellen Sie static/scss/main.scss:

// Variablen importieren
@import 'variables';

// Bootstrap importieren (falls verwendet)
@import '../../node_modules/bootstrap/scss/bootstrap';

// Ihre eigenen Styles
.custom-header {
  background-color: $primary-color;
  padding: $base-padding;
}

Schritt 3: Variablen-Datei erstellen

Erstellen Sie static/scss/_variables.scss:

// Ihre Projekt-Farben
$primary-color: #2c3e50;
$secondary-color: #3498db;
$success-color: #27ae60;
$danger-color: #e74c3c;

// Abstände
$base-padding: 1rem;
$base-margin: 1rem;

// Breakpoints
$mobile: 768px;
$tablet: 1024px;
$desktop: 1200px;

Schritt 4: npm Scripts einrichten

Fügen Sie zu Ihrer package.json hinzu:

{
  "scripts": {
    "build-css": "sass static/scss/main.scss static/css/main.css",
    "watch-css": "sass --watch static/scss:static/css",
    "build-css-compressed": "sass --style compressed static/scss/main.scss static/css/main.min.css"
  },
  "devDependencies": {
    "sass": "^1.69.5"
  }
}

Schritt 5: HTML-Template anpassen

In Ihrem Flask-Template (templates/base.html):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Ihre App</title>
    <!-- Kompiliertes CSS einbinden -->
    <link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
</head>
<body>
    <!-- Ihr Content -->
</body>
</html>

4.4.2 Bootstrap-Integration mit Sass

Schritt 1: Bootstrap als Sass-Paket installieren

npm install bootstrap

Schritt 2: Bootstrap-Variablen überschreiben

Erstellen Sie static/scss/_bootstrap-overrides.scss:

// Bootstrap-Variablen vor dem Import überschreiben
$primary: #2c3e50;
$secondary: #3498db;
$font-family-base: 'Helvetica Neue', Arial, sans-serif;
$border-radius: 0.25rem;

// Nur benötigte Bootstrap-Komponenten importieren
@import '../../node_modules/bootstrap/scss/functions';
@import '../../node_modules/bootstrap/scss/variables';
@import '../../node_modules/bootstrap/scss/mixins';

// Basis-Styles
@import '../../node_modules/bootstrap/scss/root';
@import '../../node_modules/bootstrap/scss/reboot';
@import '../../node_modules/bootstrap/scss/type';

// Layout
@import '../../node_modules/bootstrap/scss/grid';
@import '../../node_modules/bootstrap/scss/containers';

// Komponenten (nur was Sie brauchen)
@import '../../node_modules/bootstrap/scss/buttons';
@import '../../node_modules/bootstrap/scss/forms';
@import '../../node_modules/bootstrap/scss/navbar';
@import '../../node_modules/bootstrap/scss/card';

4.4.3 Migration bestehender CSS-Dateien

Schritt 1: CSS zu SCSS umbenennen

Bestehende .css Dateien können direkt zu .scss umbenannt werden. Sass versteht normales CSS vollständig.

Schritt 2: Schrittweise Sass-Features hinzufügen

Beginnen Sie mit einfachen Verbesserungen:

Vorher (CSS):

.header {
  background-color: #2c3e50;
  padding: 20px;
}

.header h1 {
  color: white;
  margin: 0;
}

.header .nav {
  list-style: none;
  margin: 10px 0;
}

Nachher (SCSS):

$header-bg: #2c3e50;
$header-padding: 20px;

.header {
  background-color: $header-bg;
  padding: $header-padding;
  
  h1 {
    color: white;
    margin: 0;
  }
  
  .nav {
    list-style: none;
    margin: ($header-padding / 2) 0;
  }
}

4.4.4 Entwicklungsworkflow einrichten

Automatisierung für Entwicklung:

Erstellen Sie ein watch.js Script:

const { spawn } = require('child_process');

// Sass Watch-Prozess starten
const sassWatch = spawn('sass', ['--watch', 'static/scss:static/css'], {
  stdio: 'inherit'
});

console.log('Sass-Überwachung gestartet...');
console.log('Änderungen an .scss-Dateien werden automatisch kompiliert.');

VS Code Integration:

Installieren Sie die “Sass” Extension und fügen Sie zu .vscode/settings.json hinzu:

{
  "scss.validate": true,
  "scss.completion.completePropertyWithSemicolon": true,
  "files.associations": {
    "*.scss": "scss"
  }
}

4.4.5 Praktische Übung

Erstellen Sie jetzt eine einfache Sass-Datei für Ihr Flask-Projekt:

  1. Erstellen Sie die Verzeichnisstruktur wie oben beschrieben
  2. Schreiben Sie eine main.scss mit Variablen für Ihre Projektfarben
  3. Kompilieren Sie diese zu CSS
  4. Binden Sie das CSS in ein Flask-Template ein
  5. Testen Sie den Watch-Modus

) und werden wie CSS-Eigenschaften deklariert. Der große Vorteil liegt in der Wiederverwendbarkeit und zentralen Verwaltung von Designwerten.

Grundlegende Variablendeklaration:

// Farben definieren - einmal schreiben, überall verwenden
$primary-color: #3498db;
$secondary-color: #2ecc71;
$danger-color: #e74c3c;
$text-color: #2c3e50;
$background-color: #ecf0f1;

// Abstände und Größen
$base-padding: 1rem;
$base-margin: 1.5rem;
$border-radius: 4px;
$font-size-base: 16px;

// Diese Variablen verwenden
.header {
    background-color: $primary-color;
    color: white;
    padding: $base-padding;
    border-radius: $border-radius;
}

.button {
    background-color: $secondary-color;
    padding: ($base-padding / 2) ($base-padding * 1.5);
    border-radius: $border-radius;
    font-size: $font-size-base;
}

Warum das besser ist als normales CSS:

/* Ohne Variablen - schwer zu ändern */
.header { background-color: #3498db; padding: 1rem; }
.button { background-color: #3498db; padding: 0.5rem; }
.sidebar { background-color: #3498db; margin: 1rem; }
/* Wenn sich #3498db ändern soll, müssen Sie 3 Stellen bearbeiten */

4.4.6 Datentypen verstehen und nutzen

Sass unterstützt verschiedene Datentypen, die jeweils spezielle Anwendungsfälle haben. Das Verständnis dieser Typen hilft beim Schreiben robusteren Codes.

Zahlen - für Berechnungen und responsive Design:

// Verschiedene Zahlenformate
$width-percent: 85%;
$margin-pixels: 20px;
$line-height: 1.5;        // Ohne Einheit
$font-weight: 700;        // Ohne Einheit

// Berechnungen mit Zahlen
$container-width: 1200px;
$sidebar-width: $container-width * 0.25;  // 300px
$content-width: $container-width - $sidebar-width - (2 * $base-margin);

.container {
    max-width: $container-width;
    margin: 0 auto;
}

.sidebar {
    width: $sidebar-width;
    float: left;
}

.content {
    width: $content-width;
    float: right;
}

Strings - für Schriftarten und Content:

// Strings mit und ohne Anführungszeichen
$font-family-primary: "Helvetica Neue", Arial, sans-serif;
$font-family-code: 'Courier New', monospace;
$icon-prefix: fa-;

// String-Interpolation für dynamische Werte
$image-path: "/static/images/";

.hero-background {
    background-image: url("#{$image-path}hero.jpg");
}

// Dynamische Icon-Klassen generieren
@for $i from 1 through 5 {
    .#{$icon-prefix}star-#{$i}::before {
        content: "★" * $i;  // String-Multiplikation
    }
}

Listen - für mehrere verwandte Werte:

// Listen für Farbpaletten
$brand-colors: #3498db, #2ecc71, #e74c3c, #f39c12;
$font-sizes: 12px, 14px, 16px, 18px, 24px, 32px;
$breakpoints: 576px, 768px, 992px, 1200px;

// Listen verwenden mit nth() Funktion
.text-small  { font-size: nth($font-sizes, 1); }  // 12px
.text-normal { font-size: nth($font-sizes, 3); }  // 16px
.text-large  { font-size: nth($font-sizes, 5); }  // 24px

// Über Listen iterieren
@each $breakpoint in $breakpoints {
    @media (min-width: $breakpoint) {
        .container-#{$breakpoint} {
            max-width: $breakpoint - 60px;
        }
    }
}

Maps - für strukturierte Daten:

// Maps sind wie Dictionaries - perfekt für Designsysteme
$colors: (
    primary: #3498db,
    secondary: #2ecc71,
    danger: #e74c3c,
    warning: #f39c12,
    info: #17a2b8,
    light: #f8f9fa,
    dark: #343a40
);

$spacing: (
    xs: 0.25rem,
    sm: 0.5rem,
    md: 1rem,
    lg: 1.5rem,
    xl: 3rem
);

// Map-Werte abrufen mit map-get()
.alert-danger {
    background-color: map-get($colors, danger);
    padding: map-get($spacing, md);
}

// Über Maps iterieren für automatische Klassen-Generierung
@each $name, $color in $colors {
    .bg-#{$name} {
        background-color: $color;
    }
    
    .text-#{$name} {
        color: $color;
    }
}

4.4.7 Gültigkeitsbereiche (Scope) verstehen

Der Gültigkeitsbereich von Variablen bestimmt, wo sie verwendet werden können. Das Verständnis des Scopes verhindert unerwartete Fehler und macht Code vorhersagbarer.

Globale vs. lokale Variablen:

// Globale Variable - überall verfügbar
$global-color: #3498db;

.component {
    // Lokale Variable - nur innerhalb .component verfügbar
    $local-padding: 20px;
    
    padding: $local-padding;
    background-color: $global-color;  // Funktioniert
    
    .child {
        margin: $local-padding;        // Funktioniert - Child erbt Scope
        color: $global-color;          // Funktioniert
    }
}

.other-component {
    // margin: $local-padding;        // FEHLER! Variable nicht verfügbar
    color: $global-color;             // Funktioniert
}

!global Flag für Scope-Übersteuerung:

$theme-color: #333;  // Globale Variable

.dark-theme {
    $theme-color: #fff !global;  // Überschreibt globale Variable
    color: $theme-color;
}

.some-other-element {
    color: $theme-color;  // Jetzt #fff statt #333
}

!default für sichere Standardwerte:

// In einer Library oder Framework-Datei
$primary-color: #007bff !default;
$font-size-base: 1rem !default;

// Wird nur gesetzt, wenn die Variable noch nicht existiert
// Perfekt für anpassbare Bibliotheken wie Bootstrap

4.5 Verschachtelung

Verschachtelung macht CSS-Code strukturierter und spiegelt die HTML-Hierarchie wider. Richtig eingesetzt verbessert sie die Lesbarkeit erheblich, aber Übertreibung kann zu spezifischen und schwer wartbarem Code führen.

4.5.1 Regel-Verschachtelung verstehen

Die grundlegende Verschachtelung folgt der HTML-Struktur und macht Beziehungen zwischen Elementen deutlicher.

HTML-Struktur als Ausgangspunkt:

<nav class="main-navigation">
    <ul class="nav-list">
        <li class="nav-item">
            <a href="#" class="nav-link">Home</a>
        </li>
        <li class="nav-item">
            <a href="#" class="nav-link">About</a>
        </li>
    </ul>
</nav>

Verschachteltes Sass - spiegelt HTML-Struktur wider:

.main-navigation {
    background-color: $primary-color;
    padding: $base-padding;
    
    // Verschachtelte Regeln folgen der HTML-Hierarchie
    .nav-list {
        list-style: none;
        margin: 0;
        padding: 0;
        display: flex;
        
        .nav-item {
            margin-right: $base-margin;
            
            // Letztes Element ohne rechten Margin
            &:last-child {
                margin-right: 0;
            }
            
            .nav-link {
                color: white;
                text-decoration: none;
                padding: ($base-padding / 2);
                border-radius: $border-radius;
                transition: background-color 0.3s ease;
                
                // Hover-Zustand direkt beim Element definiert
                &:hover {
                    background-color: rgba(255, 255, 255, 0.1);
                }
                
                // Aktiver Zustand
                &.active {
                    background-color: rgba(255, 255, 255, 0.2);
                    font-weight: bold;
                }
            }
        }
    }
}

Das generierte CSS - flatten aber logisch:

.main-navigation {
    background-color: #3498db;
    padding: 1rem;
}

.main-navigation .nav-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
}

.main-navigation .nav-list .nav-item {
    margin-right: 1.5rem;
}

.main-navigation .nav-list .nav-item:last-child {
    margin-right: 0;
}

.main-navigation .nav-list .nav-item .nav-link {
    color: white;
    text-decoration: none;
    padding: 0.5rem;
    border-radius: 4px;
    transition: background-color 0.3s ease;
}

.main-navigation .nav-list .nav-item .nav-link:hover {
    background-color: rgba(255, 255, 255, 0.1);
}

.main-navigation .nav-list .nav-item .nav-link.active {
    background-color: rgba(255, 255, 255, 0.2);
    font-weight: bold;
}

4.5.2 Parent-Selektoren mit & meistern

Der Parent-Selektor (&) ist eines der mächtigsten Features von Sass. Er referenziert den übergeordneten Selektor und ermöglicht elegante Pseudo-Klassen, Modifikatoren und BEM-Syntax.

Grundlegende &-Verwendung:

.button {
    background-color: $primary-color;
    color: white;
    padding: $base-padding;
    border: none;
    border-radius: $border-radius;
    cursor: pointer;
    transition: all 0.3s ease;
    
    // & referenziert .button
    &:hover {
        background-color: darken($primary-color, 10%);
        transform: translateY(-2px);
    }
    
    &:active {
        transform: translateY(0);
    }
    
    &:focus {
        outline: 2px solid lighten($primary-color, 20%);
        outline-offset: 2px;
    }
}

BEM-Methodology mit &:

// Block
.card {
    background: white;
    border-radius: $border-radius;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    overflow: hidden;
    
    // Element (mit &__ )
    &__header {
        padding: $base-padding;
        background-color: $light-gray;
        border-bottom: 1px solid $border-color;
        
        // Nested element
        &__title {
            margin: 0;
            font-size: 1.25rem;
            color: $text-color;
        }
    }
    
    &__body {
        padding: $base-padding;
        
        &__content {
            line-height: 1.6;
            color: $text-color;
        }
    }
    
    &__footer {
        padding: $base-padding;
        background-color: $light-gray;
        border-top: 1px solid $border-color;
        text-align: right;
    }
    
    // Modifier (mit &-- )
    &--featured {
        border: 2px solid $primary-color;
        
        // Modifier für nested elements
        .card__header {
            background-color: $primary-color;
            color: white;
        }
    }
    
    &--large {
        .card__body {
            padding: ($base-padding * 1.5);
        }
    }
}

Erweiterte &-Techniken:

.notification {
    padding: $base-padding;
    border-radius: $border-radius;
    margin-bottom: $base-margin;
    
    // Prefix-Klassen generieren
    .theme-dark & {
        background-color: darken($background-color, 20%);
        color: $light-color;
    }
    
    // Suffix-Klassen
    &.is-visible {
        opacity: 1;
        transform: translateY(0);
    }
    
    &.is-hidden {
        opacity: 0;
        transform: translateY(-20px);
    }
    
    // Kombinierte Selektoren
    &:not(.is-dismissible) {
        padding-right: $base-padding;
    }
    
    // Geschwister-Selektoren
    & + & {
        margin-top: 0;
    }
}

4.5.3 Verschachtelungstiefe optimal nutzen

Die richtige Verschachtelungstiefe zu finden ist entscheidend für wartbaren Code. Zu tiefe Verschachtelung führt zu spezifischen Selektoren, die schwer zu überschreiben sind.

Goldene Regeln für Verschachtelungstiefe:

Regel 1: Maximum 3-4 Ebenen tief

// ✅ Gut - 3 Ebenen
.sidebar {
    .widget {
        .widget-title {
            color: $primary-color;
        }
    }
}

// ❌ Zu tief - 5 Ebenen
.page {
    .container {
        .sidebar {
            .widget {
                .widget-content {
                    .widget-text {  // Zu spezifisch!
                        color: red;
                    }
                }
            }
        }
    }
}

Regel 2: Häufig verwendete Komponenten flach halten

// ✅ Gut - Button als eigenständige Komponente
.btn {
    padding: $base-padding;
    border-radius: $border-radius;
    
    &--primary { background-color: $primary-color; }
    &--secondary { background-color: $secondary-color; }
}

// ❌ Schlecht - Button zu tief verschachtelt
.header {
    .navigation {
        .nav-item {
            .btn {  // Schwer wiederverwendbar
                padding: $base-padding;
            }
        }
    }
}

Regel 3: Verschachtelung für Kontext nutzen

// ✅ Gut - Kontext-spezifische Anpassungen
.form {
    .form-group {
        margin-bottom: $base-margin;
        
        // Nur innerhalb von Formularen anders
        .btn {
            margin-top: ($base-margin / 2);
        }
    }
    
    // Spezielle Form-Variante
    &--inline {
        .form-group {
            display: inline-block;
            margin-right: $base-margin;
            margin-bottom: 0;
        }
    }
}

4.6 Mixins

Mixins sind wiederverwendbare Code-Blöcke, die komplexe CSS-Muster abstrahieren und parametrisierbar machen. Sie sind besonders wertvoll für Cross-Browser-Kompatibilität und konsistente Design-Patterns.

4.6.1 Grundlagen und Syntax

Mixins werden mit @mixin definiert und mit @include aufgerufen. Sie können CSS-Eigenschaften, komplette Regelsätze und sogar andere Mixins enthalten.

Einfache Mixins für häufige Patterns:

// Mixin für Flexbox-Zentrierung definieren
@mixin flex-center {
    display: flex;
    justify-content: center;
    align-items: center;
}

// Mixin für Text-Overflow-Handling
@mixin text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

// Mixin für Box-Shadow-Varianten
@mixin shadow($level: 1) {
    @if $level == 1 {
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    } @else if $level == 2 {
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
    } @else if $level == 3 {
        box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
    }
}

// Mixins verwenden
.modal {
    @include flex-center;
    @include shadow(2);
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
}

.card-title {
    @include text-truncate;
    font-size: 1.25rem;
    margin-bottom: $base-margin;
}

4.6.2 Parameter und Standardwerte meistern

Parameter machen Mixins flexibel und wiederverwendbar. Standardwerte sorgen für einfache Nutzung bei gleichzeitiger Anpassbarkeit.

Mixins mit Parametern:

// Button-Mixin mit mehreren Parametern
@mixin button-style($bg-color, $text-color: white, $padding: $base-padding, $radius: $border-radius) {
    background-color: $bg-color;
    color: $text-color;
    padding: $padding;
    border: none;
    border-radius: $radius;
    cursor: pointer;
    transition: all 0.3s ease;
    
    &:hover {
        background-color: darken($bg-color, 10%);
        transform: translateY(-1px);
    }
    
    &:active {
        transform: translateY(0);
    }
}

// Responsive Font-Size Mixin
@mixin responsive-font($min-size, $max-size, $min-width: 320px, $max-width: 1200px) {
    font-size: $min-size;
    
    @media (min-width: $min-width) {
        font-size: calc(#{$min-size} + #{strip-unit($max-size - $min-size)} * ((100vw - #{$min-width}) / #{strip-unit($max-width - $min-width)}));
    }
    
    @media (min-width: $max-width) {
        font-size: $max-size;
    }
}

// Verwendung der Parameter-Mixins
.btn-primary {
    @include button-style($primary-color);
}

.btn-secondary {
    @include button-style($secondary-color, $text-color: $dark-color);
}

.btn-large {
    @include button-style($primary-color, $padding: ($base-padding * 1.5));
}

.hero-title {
    @include responsive-font(2rem, 4rem);
}

Erweiterte Parameter-Techniken:

// Variable Anzahl von Parametern mit ...
@mixin transition($properties...) {
    transition-property: $properties;
    transition-duration: 0.3s;
    transition-timing-function: ease;
}

// Map als Parameter für komplexe Konfiguration
@mixin component-theme($config) {
    background-color: map-get($config, bg-color);
    color: map-get($config, text-color);
    border: map-get($config, border-width) solid map-get($config, border-color);
    
    @if map-has-key($config, shadow) {
        box-shadow: map-get($config, shadow);
    }
}

// Verwendung
.card {
    @include transition(background-color, transform, box-shadow);
}

$card-theme: (
    bg-color: white,
    text-color: $text-color,
    border-width: 1px,
    border-color: $border-color,
    shadow: 0 2px 10px rgba(0, 0, 0, 0.1)
);

.themed-card {
    @include component-theme($card-theme);
}

4.6.3 Praxisbeispiele für Flask-Bootstrap-Projekte

Diese Mixins lösen häufige Probleme in modernen Webprojekten und können direkt in Ihrem Flask-Bootstrap-Projekt verwendet werden.

Responsive Grid-System erweitern:

// Erweiterte Bootstrap-Grid-Mixins
@mixin make-col-responsive($columns, $breakpoint: md) {
    .col-#{$breakpoint}-#{$columns} {
        flex: 0 0 percentage($columns / 12);
        max-width: percentage($columns / 12);
    }
}

// Custom Breakpoint-Mixin
@mixin respond-to($breakpoint) {
    @if $breakpoint == phone {
        @media (max-width: 767px) { @content; }
    }
    @if $breakpoint == tablet {
        @media (min-width: 768px) and (max-width: 991px) { @content; }
    }
    @if $breakpoint == desktop {
        @media (min-width: 992px) { @content; }
    }
}

// Flask-spezifische Form-Mixins
@mixin flask-form-group {
    margin-bottom: $base-margin;
    
    label {
        display: block;
        margin-bottom: ($base-margin / 2);
        font-weight: 600;
        color: $text-color;
    }
    
    input, select, textarea {
        width: 100%;
        padding: ($base-padding * 0.75);
        border: 1px solid $border-color;
        border-radius: $border-radius;
        font-size: $font-size-base;
        
        &:focus {
            border-color: $primary-color;
            outline: none;
            box-shadow: 0 0 0 3px rgba($primary-color, 0.1);
        }
    }
    
    .error {
        color: $danger-color;
        font-size: 0.875rem;
        margin-top: ($base-margin / 4);
    }
}

// Verwendung in Flask-Templates
.registration-form {
    .form-group {
        @include flask-form-group;
        
        @include respond-to(phone) {
            margin-bottom: ($base-margin * 0.75);
        }
    }
}

Animation und Interaction-Mixins:

// Hover-Effekt-Mixin für Cards
@mixin card-hover-effect($lift: 5px, $shadow-intensity: 0.15) {
    transition: transform 0.3s ease, box-shadow 0.3s ease;
    
    &:hover {
        transform: translateY(-$lift);
        box-shadow: 0 (($lift * 2)) (($lift * 4)) rgba(0, 0, 0, $shadow-intensity);
    }
}

// Loading-Spinner-Mixin
@mixin loading-spinner($size: 40px, $color: $primary-color) {
    width: $size;
    height: $size;
    border: 3px solid rgba($color, 0.3);
    border-radius: 50%;
    border-top-color: $color;
    animation: spin 1s ease-in-out infinite;
    
    @keyframes spin {
        to { transform: rotate(360deg); }
    }
}

// Flash-Message-Mixin für Flask
@mixin flask-flash-message($type: info) {
    padding: $base-padding;
    margin-bottom: $base-margin;
    border-radius: $border-radius;
    position: relative;
    
    @if $type == success {
        background-color: lighten($success-color, 40%);
        border-left: 4px solid $success-color;
        color: darken($success-color, 20%);
    } @else if $type == error {
        background-color: lighten($danger-color, 40%);
        border-left: 4px solid $danger-color;
        color: darken($danger-color, 20%);
    } @else if $type == warning {
        background-color: lighten($warning-color, 40%);
        border-left: 4px solid $warning-color;
        color: darken($warning-color, 30%);
    } @else {
        background-color: lighten($info-color, 40%);
        border-left: 4px solid $info-color;
        color: darken($info-color, 20%);
    }
}

// Praktische Anwendung
.product-card {
    @include card-hover-effect;
    background: white;
    border-radius: $border-radius;
    overflow: hidden;
}

.loading-indicator {
    @include loading-spinner(30px, $secondary-color);
    margin: 20px auto;
}

.flash-messages {
    .flash-success { @include flask-flash-message(success); }
    .flash-error { @include flask-flash-message(error); }
    .flash-warning { @include flask-flash-message(warning); }
    .flash-info { @include flask-flash-message(info); }
}

4.6.4 Praktische Übung

Erstellen Sie jetzt ein praktisches Mixin-System für Ihr Flask-Projekt:

  1. Erstellen Sie eine _mixins.scss Datei mit den Button-, Form- und Card-Mixins von oben
  2. Importieren Sie diese in Ihre main.scss
  3. Wenden Sie die Mixins auf echte HTML-Elemente an
  4. Testen Sie die Parameter-Variationen
  5. Erstellen Sie ein eigenes Mixin für ein wiederkehrendes Design-Pattern in Ihrem Projekt

Diese Sass-Funktionen bilden das Rückgrat effizienter Stylesheet-Entwicklung und bereiten Sie optimal auf komplexere Sass-Features vor.