CSS Contract

ID 2
UUID 4134c9b2-ee2f-4a2e-a466-8ceb5df87ade
Version 1.0
Status active
Scope
Erstellt 2025-12-20 10:59:58 von migration
Aktualisiert 2025-12-20 10:59:58

YAML-Inhalt

contract:
  name: "CSS Contract"
  version: "1.0"
  status: active
  scope:
    - "/src/View/**/*.php"
    - "/public/css/**/*.css"
    - "inline styles"
  principles:
    - WCAG    # Web Content Accessibility Guidelines 2.1 AA
    - DRY     # Don't Repeat Yourself
    - KISS    # Keep It Simple, Stupid

rules:
  accessibility:
    - id: A11Y-001
      severity: critical
      rule: "Farbkontrast min. 4.5:1 für normalen Text"
      wcag: "1.4.3 Contrast (Minimum)"
      forbidden:
        - "color: white; background: #f5f5f5"  # 1.3:1
        - "color: #999; background: #fff"       # 2.8:1
        - "color: #777; background: #eee"       # 2.5:1
      valid:
        - "color: #333; background: #f5f5f5"    # 9.7:1
        - "color: #000; background: #fff"       # 21:1
        - "color: #555; background: #fff"       # 7.5:1
      tools:
        - "https://webaim.org/resources/contrastchecker/"

    - id: A11Y-002
      severity: critical
      rule: "Farbkontrast min. 3:1 für großen Text (>= 18pt)"
      wcag: "1.4.3 Contrast (Minimum)"

    - id: A11Y-003
      severity: major
      rule: "Keine Farbe als einziges Unterscheidungsmerkmal"
      wcag: "1.4.1 Use of Color"
      example:
        wrong: |
          .error { color: red; }
          .success { color: green; }
        correct: |
          .error { color: #c00; border-left: 3px solid #c00; }
          .success { color: #060; border-left: 3px solid #060; }

    - id: A11Y-004
      severity: major
      rule: "Focus-Styles niemals entfernen"
      wcag: "2.4.7 Focus Visible"
      forbidden:
        - "outline: none"
        - "outline: 0"
      exception: "Nur wenn alternativer Focus-Style definiert"
      example:
        wrong: |
          a:focus { outline: none; }
        correct: |
          a:focus { outline: 2px solid #007bff; outline-offset: 2px; }

  typography:
    - id: TYP-001
      severity: major
      rule: "Mindestschriftgröße 16px für Fließtext"
      reason: "Lesbarkeit auf allen Geräten"
      forbidden:
        - "font-size: 12px"
        - "font-size: 0.75rem"
      valid:
        - "font-size: 16px"
        - "font-size: 1rem"

    - id: TYP-002
      severity: major
      rule: "Zeilenhöhe min. 1.5 für Fließtext"
      wcag: "1.4.12 Text Spacing"
      example:
        correct: "line-height: 1.5"

    - id: TYP-003
      severity: minor
      rule: "Maximale Zeilenlänge 80 Zeichen"
      reason: "Lesbarkeit"
      example:
        correct: "max-width: 70ch"

  colors:
    - id: COL-001
      severity: critical
      rule: "Vordergrundfarbe immer mit Hintergrundfarbe definieren"
      reason: "User-Stylesheets können Farben überschreiben"
      example:
        wrong: |
          .box { color: #333; }
        correct: |
          .box { color: #333; background-color: #fff; }

    - id: COL-002
      severity: major
      rule: "CSS-Variablen für Farben verwenden"
      example:
        correct: |
          :root {
            --color-text: #333;
            --color-bg: #fff;
            --color-primary: #007bff;
            --color-success: #28a745;
            --color-error: #dc3545;
            --color-warning: #ffc107;
          }
          .element { color: var(--color-text); }

    - id: COL-003
      severity: major
      rule: "Status-Farben konsistent verwenden"
      palette:
        pending: "#856404 on #fff3cd"      # Gelb/Warnung
        in_progress: "#004085 on #cce5ff"  # Blau/Info
        completed: "#155724 on #d4edda"    # Grün/Erfolg
        failed: "#721c24 on #f8d7da"       # Rot/Fehler
        cancelled: "#383d41 on #e2e3e5"    # Grau/Neutral

  layout:
    - id: LAY-001
      severity: minor
      rule: "Box-sizing border-box global setzen"
      example:
        correct: |
          *, *::before, *::after {
            box-sizing: border-box;
          }

    - id: LAY-002
      severity: minor
      rule: "Spacing-System mit konsistenten Werten"
      example:
        correct: |
          :root {
            --space-xs: 0.25rem;
            --space-sm: 0.5rem;
            --space-md: 1rem;
            --space-lg: 1.5rem;
            --space-xl: 2rem;
          }

  code_blocks:
    - id: CODE-001
      severity: critical
      rule: "Pre/Code-Blöcke: dunkler Text auf hellem Hintergrund"
      example:
        correct: |
          pre, code {
            background: #f5f5f5;
            color: #333;
          }

    - id: CODE-002
      severity: major
      rule: "Monospace-Font für Code"
      example:
        correct: |
          pre, code {
            font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
          }

  responsive:
    - id: RES-001
      severity: major
      rule: "Mobile-First Breakpoints"
      breakpoints:
        sm: "576px"
        md: "768px"
        lg: "992px"
        xl: "1200px"

    - id: RES-002
      severity: major
      rule: "Viewport Meta-Tag erforderlich"
      example:
        correct: |
          <meta name="viewport" content="width=device-width, initial-scale=1">

  forbidden:
    - id: FRB-001
      severity: critical
      rule: "Kein !important außer für Utility-Klassen"
      exception: "Nur für .hidden, .sr-only etc."

    - id: FRB-002
      severity: major
      rule: "Keine inline-styles für wiederholte Muster"
      fix: "CSS-Klassen definieren"

    - id: FRB-003
      severity: minor
      rule: "Keine vendor-prefixes ohne Fallback"

validation:
  pass_threshold:
    critical: 0
    major: 2
    minor: 5

  checklist:
    - "Alle Texte haben Kontrast >= 4.5:1"
    - "Focus-States sind sichtbar"
    - "Farben haben immer Vorder- UND Hintergrund"
    - "Pre/Code-Blöcke sind lesbar"
    - "Responsive auf 320px getestet"

fixes:
  task_show_pre:
    file: "/src/View/tasks/show.php"
    issue: "Weiße Schrift auf hellgrauem Hintergrund"
    fix: |
      pre {
        background: #f5f5f5;
        color: #333;  /* NICHT #fff oder inherit von parent */
      }

Aktionen

Bearbeiten

Letzte Validierungen

Datum Ergebnis Critical Major Minor Dauer
2025-12-20 14:38:20 passed 0 0 0 6ms

← Zurück zur Übersicht