logo

Extra Block Types (EBT) - Neue Erfahrung im Layout Builder❗

Extra Block Types (EBT) - gestylte, anpassbare Blocktypen: Diashows, Registerkarten, Karten, Akkordeons und viele andere. Eingebaute Einstellungen für Hintergrund, DOM Box, Javascript Plugins. Erleben Sie die Zukunft der Layouterstellung schon heute.

Demo EBT-Module EBT-Module herunterladen

❗Extra Absatztypen (EPT) - Erfahrung mit neuen Absätzen

Extra Paragraph Types (EPT) - analoger, auf Absätzen basierender Satz von Modulen.

Demo EPT-Module EPT-Module herunterladen

Scroll

Hinzufügen von Stylesheets (CSS) und JavaScript (JS) zum Drupal 8 Theme

19/06/2025, by Ivan

Diese Dokumentation richtet sich an Themes. Informationen zu Modulen finden Sie im Abschnitt „Hinzufügen von Stylesheets (CSS) und JavaScript (JS) zu einem Drupal 8 Modul“.

In Drupal 8 werden Stylesheets (CSS) und JavaScript (JS) über dasselbe System für Module (Code) und Themes geladen: die Asset-Bibliotheken.

Zur Klarstellung sind diese Anweisungen nur für Themes gedacht und gelten nicht für Module.

Drupal folgt dem hohen Prinzip: Ressourcen (CSS oder JS) werden nur geladen, wenn Sie Drupal mitteilen, dass sie geladen werden sollen. Drupal lädt nicht alle Ressourcen auf jeder Seite, da dies die Performance beeinträchtigt.

Unterschiede zu Drupal 7

Es gibt sechs wichtige Unterschiede im Vergleich zu Drupal 7 für Enthusiasten:

  • Die Datei THEME.info.yml ersetzt die Datei THEME.info (mit denselben Daten).
  • Die Eigenschaft stylesheets (für CSS) in THEME.info wurde entfernt und durch *.libraries.yml ersetzt, wobei * der Name des Themes oder Moduls ist.
  • Die Eigenschaft scripts (für JS) in THEME.info wurde entfernt und ebenfalls durch *.libraries.yml ersetzt.
  • Nur das CSS und JS, das auf der Seite benötigt wird, wird geladen. Beispielsweise wird jQuery nicht mehr automatisch geladen, außer es wird explizit in *.libraries.yml angegeben. Wenn Ihr Theme jQuery oder andere Ressourcen auf allen Seiten benötigt, fügen Sie diese in *.libraries.yml hinzu und binden Sie die Bibliothek in THEME.info.yml ein.
  • In Drupal 7 mussten Bibliotheken mit hook_library_info() definiert werden. Das wurde durch die Datei *.libraries.yml ersetzt.
  • In Drupal 8 wurden drupal_add_css(), drupal_add_js() und drupal_add_library() zugunsten von #attached entfernt.

Vorgehensweise

So laden Sie CSS- oder JS-Ressourcen:

Bibliothek definieren

Definieren Sie alle Ihre Asset-Bibliotheken in der Datei *.libraries.yml im Verzeichnis Ihres Themes. Wenn Ihr Theme „fluffiness“ heißt, muss die Datei fluffiness.libraries.yml heißen. Jede „Bibliothek“ ist ein Eintrag, der CSS- und JS-Dateien (Assets) detailliert, zum Beispiel:

# fluffiness.libraries.yml
cuddly-slider:
  version: 1.x
  css:
    theme:
      css/cuddly-slider.css: {}
  js:
    js/cuddly-slider.js: {}

In diesem Beispiel befinden sich die JavaScript-Datei cuddly-slider.js und die CSS-Datei cuddly-slider.css in den Verzeichnissen js und css Ihres Themes.

Beachten Sie, dass dieses Beispiel nur eine CSS- und eine JS-Datei sowie jQuery zeigt. Es gibt jedoch viel mehr Optionen zur Definition von Bibliotheken, die Sie im Abschnitt „Bibliotheken definieren: Optionen und Details“ finden.

jQuery in Ihre Bibliothek einbinden

Drupal 8 lädt jQuery nicht mehr automatisch auf allen Seiten. Wenn beispielsweise cuddly-slider jQuery benötigt, müssen Sie die Abhängigkeit zur Basiskomponente, die jQuery enthält (bereitgestellt vom Drupal-Core, nicht vom Modul oder Theme), deklarieren. Die Abhängigkeit wird als core/jquery angegeben. Wenn eine andere Bibliothek cuddly-slider benötigt, deklariert sie fluffiness/cuddly-slider als Abhängigkeit. Sie können nicht einzelne Dateien als Abhängigkeit deklarieren, sondern nur ganze Bibliotheken.

Um jQuery für cuddly-slider verfügbar zu machen, erweitern wir das obige Beispiel:

# fluffiness.libraries.yml
cuddly-slider:
  version: 1.x
  css:
    theme:
      css/cuddly-slider.css: {}
  js:
    js/cuddly-slider.js: {}
  dependencies:
    - core/jquery

Abhängigkeiten deklarieren

Um eine Abhängigkeit zu deklarieren, geben Sie die benötigte Bibliothek in der Form resource/library an. Für Core-Bibliotheken ist „resource“ „core“, für andere der Name des Moduls oder Themes. Wenn z. B. new_library von jQuery aus dem Core sowie von my_library aus dem Theme my_theme und my_library aus dem Modul my_module abhängt, deklarieren Sie die Abhängigkeiten so:

# fluffiness.libraries.yml
new_library:
  js:
    js/new_library.js: {}
  dependencies:
    - core/jquery
    - my_module/my_library
    - my_theme/my_library

Modul- und Themennamen sorgen für Namensräume, sodass Bibliotheken mit gleichem Namen unterschieden werden können.

Bibliothek auf allen Seiten einbinden

In den meisten Themes wird die Asset-Bibliothek global-styling für CSS-Dateien verwendet, die auf jeder Seite, auf der das Theme aktiv ist, geladen werden sollen. Ebenso kann man JS über die Bibliothek global-scripts laden:

# fluffiness.libraries.yml
global-styling:
  version: 1.x
  css:
    theme:
      css/layout.css: {}
      css/style.css: {}
      css/colors.css: {}
global-scripts:
  version: 1.x
  js:
    js/navmenu.js: {}

Um diese Bibliotheken überall im Theme verfügbar zu machen, müssen global-styling und global-scripts in der info.yml Ihres Themes (z. B. fluffiness.info.yml) eingebunden werden:

# fluffiness.info.yml
name: Fluffiness
type: theme
description: 'Ein kuscheliges Theme, das extra Flauschigkeit bietet.'
core: 8.x
libraries:
  - fluffiness/global-styling
  - fluffiness/global-scripts
base theme: classy
regions:
  header: Header
  content: Inhalt
  sidebar_first: 'Sidebar first'
  footer: Footer

Bibliothek im Twig-Template einbinden

Sie können eine Asset-Bibliothek im Twig-Template mit der Funktion attach_library() einbinden, zum Beispiel in jeder *.html.twig-Datei so:

{{ attach_library('fluffiness/cuddly-slider') }}
Ein wenig flauschige Markup {{ message }}

Bibliothek nur auf bestimmten Seiten einbinden

Manchmal wollen Sie, dass Ihre Bibliothek nur auf bestimmten Seiten aktiv ist, z. B. nur bei der Anzeige eines bestimmten Blocks oder eines bestimmten Knotentyps.

Das Theme kann dies über eine Funktion THEME_preprocess_HOOK() in der .theme-Datei umsetzen, wobei THEME durch den Maschinen-Namen Ihres Themes und HOOK durch den thematischen Hook-Namen ersetzt wird.

Beispiel: Wenn Sie JavaScript auf der Wartungsseite einbinden wollen, ist der Hook „maintenance_page“, und Ihre Funktion sieht so aus:

function fluffiness_preprocess_maintenance_page(&$variables) {
  $variables['#attached']['library'][] = 'fluffiness/cuddly-slider';
}

Sie können ähnliche Funktionen für andere Theme-Hooks schreiben und natürlich Logik hinzufügen, z. B. prüfen, welcher Block im Block-Hook vorverarbeitet wird oder welcher Knotentyp im Node-Hook usw.

Wichtiger Hinweis! In solchen Fällen müssen Sie passende Cache-Metadaten angeben! Das obige Beispiel ist ohne Bedingungen, daher braucht es keine Cache-Metadaten. Ein häufiges Szenario ist, eine Bibliothek abhängig von der aktuellen Route einzubinden:

function fluffiness_preprocess_page(&$variables) {
  $variables['page']['#cache']['contexts'][] = 'route';
  $route = "entity.node.preview";
  if (\Drupal::routeMatch()->getRouteName() === $route) {
    $variables['#attached']['library'][] = 'fluffiness/node-preview';
  }
}

Bibliotheken definieren: Optionen und Details

Eigenschaften zu eingebundenem CSS/JS hinzufügen

Eigenschaften werden in geschweifte Klammern nach jeder Datei in THEMENAME.libraries.yml geschrieben.

CSS-Eigenschaften

attributes Optionale Attribute. Bekannter Anwendungsfall: Bootstrap CDN.
{ attributes: { crossorigin: anonymous } }
browsers Ressource bedingt nach Browser laden. Nutzt Conditional Comments, die ab IE10 nicht mehr unterstützt werden.
{ browsers: { IE: 'lte IE 9', '!IE': false } }
group Assets werden in Gruppen zusammengefasst.
Standard: SMACSS-Gruppe, zu der das Asset gehört.
Wird selten verwendet
media Medientyp.
{ media: print }
minified Ist das Asset bereits minifiziert.
Standard: false
{ type: external, minified: true }
preprocess Sollen Assets aggregiert werden.
Standard: true
{ preprocess: false }
type Quelle des Assets.
Standard: Datei
{ type: external, minified: true }
weight Ordnet die Reihenfolge relativ zu anderen Assets in derselben SMACSS-Gruppe.
Standard: 0. Werte von -50 bis +50.
{ weight: 1 }

JS-Eigenschaften

attributes Zusätzliche Skript-Attribute.
{ type: external, attributes: { async: true } }
browsers Ressource bedingt nach Browser laden. Nutzt Conditional Comments, die ab IE10 nicht mehr unterstützt werden.
{ browsers: { IE: 'lte IE 9', '!IE': false } }
preprocess Sollen Assets aggregiert werden.
Standard: true
{ preprocess: false }
type Quelle des Assets.
Standard: Datei
{ type: external, minified: true }
weight Besser Abhängigkeiten verwenden.
Regelt die Reihenfolge relativ zu anderen Assets. Sollte negativ sein.
{ weight: -1 }

Bibliotheken überschreiben und erweitern

Um Bibliotheken, die in *.libraries.yml definiert sind, zu überschreiben, bearbeiten Sie die *.info.yml Datei. Sie können Bibliotheken überschreiben oder erweitern. Überschreibungen, die Sie in *.info.yml hinzufügen, werden von Unterthemes geerbt.

Die Eigenschaft stylesheets-remove, die in *.info.yml verwendet wird, ist veraltet und wird in Drupal 9.0.x entfernt. Die Eigenschaft stylesheets-override wurde bereits entfernt.

libraries-override

Logik für das Erstellen von Überschreibungen:

  • Verwenden Sie den Original-Namespace des Moduls (oder Core) für den Bibliotheksnamen.
  • Verwenden Sie den Pfad des letzten Überschreibungsdatei als Schlüssel.
  • Dieser Pfad muss der vollständige Dateipfad sein.

Beispiel:

libraries-override:
  contextual/drupal.contextual-links:
    css:
      component:
        /core/themes/stable/css/contextual/contextual.module.css: false

Hier ist contextual/drupal.contextual-links der Namespace der Originalbibliothek und /core/themes/stable/css/contextual/contextual.module.css ist der vollständige Pfad der Datei, die überschrieben oder deaktiviert wird (false).

Beachten Sie, dass nur der letzte Teil der Pfad zum Dateisystem ist, der Rest sind Namespace-Ebenen. Die Schlüssel css: und component: spiegeln die Struktur der Bibliothek wider.

Beachten Sie, dass Abhängigkeiten, die vom Dateisystempfad abhängen, bei Änderungen der Dateistruktur brechen können. Deshalb gibt es die Problematik, Abhängigkeiten vom kompletten Pfad durch Bundler zu entfernen siehe hier.

Weitere Beispiele zum Entfernen oder Ersetzen von CSS/JS oder ganzen Bibliotheken, die Ihr Theme von Modulen oder anderen Themes erbt:

libraries-override:
  # Ganze Bibliothek ersetzen.
  core/drupal.collapse: mytheme/collapse
  
  # Einzelnes Asset ersetzen.
  subtheme/library:
    css:
      theme:
        css/layout.css: css/my-layout.css

  # Override Asset aus stable ersetzen.
  contextual/drupal.contextual-toolbar:
    css:
      component:
        core/themes/stable/css/contextual/contextual.toolbar.css: css/contextual.toolbar.css

  # JS Asset eines Core-Moduls ersetzen.
  toolbar/toolbar:
    js:
      js/views/BodyVisualView.js: js/views/BodyVisualView.js

  # Asset entfernen.
  drupal/dialog:
    css:
      theme:
        dialog.theme.css: false
  
  # Ganze Bibliothek entfernen.
  core/modernizr: false
  
  # Sehr spezifische Assets einer Bibliothek eines Contrib-Moduls ersetzen.
  # Hinweis: Die Bibliotheken des Moduls, die überschrieben werden können, finden Sie in der *.libraries.yml Datei des Moduls, z. B. /modules/contrib/webform/webform.libraries.yml 

  webform/webform.element.location.places:
    css:
      component:
        css/webform.element.location.places.css: css/my-themes-replacement-file.css
    js:
      js/webform.element.location.places.js: js/my-themes-replacement-file.js

libraries-extend

libraries-extend erlaubt es Themes, Bibliotheken zu verändern, indem zusätzliche abhängige Ressourcen hinzugefügt werden, wenn die Bibliothek geladen wird. Es definiert Erweiterungen durch eine oder mehrere andere Bibliotheken.

Dies ist ideal, um bestimmte Komponenten im Theme unterschiedlich zu stylen, ohne globales CSS zu laden. So können Sie das Aussehen eines Components anpassen, ohne CSS auf jeder Seite zu laden.

# Erweitere drupal.user: füge Assets von Classys User-Bibliotheken hinzu.
libraries-extend:
  core/drupal.user: 
    - classy/user1
    - classy/user2

Weitere Javascript-Einstellungen

Lade-Reihenfolge der Assets

Wie erwartet entspricht die Reihenfolge der Dateien der Reihenfolge ihres Ladens. Standardmäßig werden alle JS-Ressourcen im Footer geladen. JS für kritische UI-Elemente, die nicht angezeigt werden können, ohne dass ihr JS ausgeführt wird, kann bei Bedarf im Header geladen werden, z. B. so:

js-header:
  header: true
  js:
    header.js: {}

js-footer:
  js:
    footer.js: {}

Das Property header: true kennzeichnet die JS-Ressourcen dieser Bibliothek als Teil des „kritischen Pfades“ und zwingt sie, im Header geladen zu werden. Direkt oder indirekt deklarierte Abhängigkeiten werden automatisch ebenfalls im Header geladen. So sorgt man dafür, dass diese Ressourcen und ihre Abhängigkeiten zuerst geladen werden.

Custom JavaScript anhängen

Manchmal wollen Sie JavaScript auf der Seite einfügen, das von PHP-Werten abhängt.

Erstellen Sie in dem Fall eine JS-Datei, definieren und binden Sie eine Bibliothek wie gehabt ein, fügen Sie aber auch JS-Einstellungen hinzu, die Ihre JS-Datei mit drupalSettings auslesen kann (Nachfolger von Drupal 7s Drupal.settings). Um drupalSettings verfügbar zu machen, müssen Sie die Abhängigkeit darauf ebenfalls deklarieren.

Das sieht dann so aus:

cuddly-slider:
  version: 1.x
  js:
    js/cuddly-slider.js: {}
  dependencies:
    - core/jquery
    - core/drupalSettings

Und im Preprocess-Hook:

function fluffiness_page_attachments_alter(&$page) {
  $page['#attached']['library'][] = 'fluffiness/cuddly-slider';
  $page['#attached']['drupalSettings']['fluffiness']['cuddlySlider']['foo'] = 'bar';
}

Dabei ist 'bar' ein berechneter Wert. (Cache-Metadaten sind hier ebenfalls erforderlich!)

Dann kann cuddly-slider.js auf settings.fluffiness.cuddlySlider.foo zugreifen, was 'bar' sein wird:

(function ($, Drupal, drupalSettings) {

  'use strict';

  Drupal.behaviors.mybehavior = {
    attach: function (context, settings) {
      
      console.log(settings.fluffiness.cuddlySlider.foo);
      
    }
  };

})(jQuery, Drupal, drupalSettings);

Attribute zu Script-Tags hinzufügen

Um Attribute zu einem Script-Tag hinzuzufügen, fügen Sie im JSON nach der Script-URL den Schlüssel attributes hinzu. Innerhalb des attributes-Objekts geben Sie als Schlüssel den Attributnamen an, als Wert den Attributwert. Ist der Wert true, wird das Attribut ohne Wert ausgegeben.

Beispiel:

https://maps.googleapis.com/maps/api/js?key=myownapikey&signed_in=true&libraries=drawing&callback=initMap:
  type: external
  attributes:
    defer: true
    async: true
    data-test: map-link

Dies erzeugt folgendes Markup:


Inline JavaScript

Inline JavaScript wird stark nicht empfohlen. Es ist besser, das JavaScript in Dateien auszulagern, damit es clientseitig gecached werden kann und der Code leichter sichtbar und editierbar ist.

Inline JavaScript, das Markup generiert
Das wird generell nicht empfohlen und ist meist nicht nötig. Typische Beispiele sind Werbung, Social-Sharing-Buttons, Social-Widget-Listen. Diese verwenden Inline-JavaScript, da sie externen Content einbinden und nicht das Layout oder die Interaktivität der Seite direkt steuern.

Solche Scripte können in benutzerdefinierte Blöcke oder direkt in Twig-Templates eingefügt werden.

Beispiel:





Inline JavaScript, das die ganze Seite beeinflusst

Der Einsatz von Inline-JavaScript wird stark nicht empfohlen. Beispiele sind Analytics (z. B. Google Analytics) und Web-Font-Services. Solches Inline-JavaScript kann zwei Kategorien angehören: Frontend/Styling oder Logik.

Im Fall von Frontend/Styling (z. B. Webfonts) gehört das JS zum Theme. Platzieren Sie das JS direkt in der Datei html.html.twig. So können Sie das Laden optimieren und z. B. FOUT (Flash Of Unstyled Text) verhindern, indem Fonts im HTML-<head> vor CSS geladen werden. (Siehe Artikel „Async Typekit & Micro-FOUT“.)

In anderen Fällen gehört das JavaScript zum Modul. Siehe dazu „Hinzufügen von Stylesheets (CSS) und JavaScript (JS) zu einem Drupal 8 Modul“.

Inline JavaScript in Integration-Modulen

Inline-JavaScript sollte vermieden werden. Prüfen Sie die obigen Beispiele, bevor Sie Inline-JS verwenden.

Zwei wichtige Punkte bei Feldern, die vom Nutzer eingebettetes Inline-JS akzeptieren:

1. Das Feld, Formular oder Seite, das dieses Inline-JS annimmt, muss die richtige Berechtigung haben.
Beispiel: MODULE.routing.yml

MODULE.settings:
  path: /admin/config/services/MODULE
  defaults:
    _title: 'MODULE Einstellungen'
    _form: \Drupal\MODULE\Form\MODULESettings
  requirements:
    _permission: 'administer site configuration'

2. Der Wert, falls er in einer Konfigurations-Objekt gespeichert ist, muss dem Render-System die CacheableMetadata mitteilen, damit bei Änderungen der Cache geleert wird.
Beispiel: MODULES.module

 Markup::create($settings->get('js_code')),
    '#cache' => [
      'contexts' => ['user'],
      'tags' => ['user:' . $user->id()],
    ],
  ];
  // Cache-Metadaten für Konfiguration hinzufügen.
  /** @var Drupal\Core\Render\Renderer $renderer */
  $renderer = \Drupal::service('renderer');
  $renderer->addCacheableDependency($page_bottom['MODULE'], $settings);
}

CDN / externe Bibliotheken

Sie möchten eventuell JavaScript von einem CDN (Content Delivery Network) laden, z. B. Webfonts, die meist nur über externe URLs verfügbar sind. Dies kann durch Deklaration einer externen Bibliothek (mit type: external) erreicht werden. Es ist hilfreich, weitere Informationen zur externen Bibliothek anzugeben.

(Hinweis: Es ist im Allgemeinen keine gute Idee, Bibliotheken über CDN zu laden, da dies zusätzliche Fehlerquellen und Performance- sowie Sicherheitsprobleme verursachen kann. Außerdem erhöht es die Anzahl der TCP/IP-Verbindungen und verhindert Browser-Caching. Drittanbieter-Bibliotheken sollten nicht als Teil Ihres Repos auf Drupal.org liegen – siehe Richtlinien für Drittanbieter-Bibliotheken auf Drupal.org.)

angular.angularjs:
  remote: https://github.com/angular
  version: 1.4.4
  license:
    name: MIT
    url: https://github.com/angular/angular.js/blob/master/LICENSE
    gpl-compatible: true
  js:
    https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js: { type: external, minified: true }

Wenn Sie möchten, dass die externe Datei mit demselben Protokoll wie die Webseite geladen wird, verwenden Sie eine protokoll-relative URL:

js:
  //ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js: { type: external, minified: true }

Oder für CSS, z. B. Font Awesome:

font-awesome:
  remote: https://fortawesome.github.io/Font-Awesome/
  version: 4.5.0
  license:
    name: MIT
    url: https://fortawesome.github.io/Font-Awesome/license/
    gpl-compatible: true
  css:
    theme:
      https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css: { type: external, minified: true }

Beispiel für Bootstrap CDN CSS mit benutzerdefinierten Attributen

bootstrap-cdn:
  remote: getbootstrap.com
  version: 4.0
  license:
    name: MIT
    url: https://github.com/twbs/bootstrap/blob/master/LICENSE
  css:
    theme:
      'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css':
        type: external
        minified: true
        attributes:
          crossorigin: anonymous
          integrity: "sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"

Weitere Informationen

?>

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.