logo

Dodatni tipovi blokova (EBT) - Novo iskustvo rada sa Layout Builder-om❗

Dodatni tipovi blokova (EBT) – stilizovani, prilagodljivi tipovi blokova: slajdšouvi, kartice sa tabovima, kartice, akordeoni i mnogi drugi. Ugrađena podešavanja za pozadinu, DOM Box, javascript dodatke. Iskusite budućnost kreiranja rasporeda već danas.

Demo EBT moduli Preuzmite EBT module

❗Dodatni tipovi pasusa (EPT) – Novo iskustvo rada sa pasusima

Dodatni tipovi pasusa (EPT) – analogni skup modula zasnovan na pasusima.

Demo EPT moduli Preuzmite EPT module

Scroll

Dodavanje stilskih tablica (CSS) i JavaScript (JS) u Drupal 8 temu

19/06/2025, by Ivan

Ova dokumentacija je za teme. Informacije o modulima pogledajte u odeljku Dodavanje stilskih tablica (CSS) i JavaScript (JS) u Drupal 8 modul.

U Drupalu 8, stilovi (CSS) i JavaScript (JS) se učitavaju kroz isti sistem za module (kod) i teme za sve: biblioteke resursa.

Za jasnoću, ove instrukcije su namenjene SAMO radu u temama i ne odnose se na module.

Drupal koristi princip visokog nivoa: resursi (CSS ili JS) se učitavaju samo ako vi kažete Drupalu da ih treba učitati. Drupal ne učitava sve resurse na svakoj stranici jer bi to umanjilo performanse interfejsa.

Razlike u odnosu na Drupal 7

Postoji šest važnih razlika u odnosu na Drupal 7 za entuzijaste:

  • Fajl THEME.info.yml je zamenio THEME.info fajl (sa istim podacima).
  • Properti stylesheets (za dodavanje CSS-a) u THEME.info je uklonjen i zamenjen fajlom *.libraries.yml, gde je `*` ime teme ili modula.
  • Properti scripts (za dodavanje JS) u THEME.info je uklonjen i takođe zamenjen *.libraries.yml fajlom.
  • Učitavaće se samo CSS i JS koji su potrebni na stranici. Na primer, jQuery više nije automatski učitan osim ako nije eksplicitno naveden u *.libraries.yml. Ako vašoj temi treba jQuery ili drugi resursi koji treba da se učitaju na svim stranicama, dodajte ih u *.libraries.yml, a zatim uključite biblioteku u THEME.info.yml.
  • U Drupalu 7 biblioteke su se definisale preko hook_library_info(). To je zamenjeno fajlom *.libraries.yml.
  • U Drupalu 8 drupal_add_css(), drupal_add_js() i drupal_add_library() su uklonjeni u korist #attached

Proces

Da biste učitali CSS ili JS resurse:

Definisanje biblioteke

Sve biblioteke resursa definišite u fajlu *.libraries.yml u folderu vaše teme. Ako se vaša tema zove fluffiness, fajl mora biti fluffiness.libraries.yml. Svaka "biblioteka" u fajlu detaljno navodi CSS i JS fajlove (resurse), na primer:

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

U ovom primeru, JavaScript fajl cuddly-slider.js i CSS cuddly-slider.css se nalaze u odgovarajućim direktorijumima js i css unutar vaše teme.

Napomena: iako primer pokazuje jedan css i jedan js fajl + jquery, dostupno je mnogo više opcija za definisanje biblioteka. Više informacija potražite u sekciji "Definisanje biblioteka: opcije i detalji".

Uključivanje jQuery u vašu biblioteku

Zapamtite, Drupal 8 više ne učitava jQuery na sve stranice po defaultu, zato ako cuddly-slider zahteva jQuery, morate navesti zavisnost od osnovne biblioteke koja sadrži jQuery (drupal core pruža jQuery, a ne modul ili tema). Zavisnost se navodi kao naziv prostora imena, pa kosa crta, zatim ime biblioteke, ovde je to core/jquery. Ako neka druga biblioteka zavisi od cuddly-slider biblioteke, ona navodi fluffiness/cuddly-slider, ime teme plus ime biblioteke. Ne možete navesti pojedinačni fajl kao zavisnost, samo celu biblioteku.

Dakle, da bismo omogućili jQuery za cuddly-slider, ažuriraćemo primer gore:

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

Definisanje zavisnosti

Da biste naveli zavisnosti, potrebne biblioteke se navode kao resurs/biblioteka. Za osnovne biblioteke resurs je core, dok za druge zavisi od imena modula ili teme. Na primer, ako new_library zavisi od jQuery iz core, my_library definisane u my_theme i my_library definisane u my_module, onda ćete zavisnosti navesti ovako:

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

Imena modula i tema služe kao imenski prostori za biblioteke istih naziva.

Prikačivanje biblioteke na sve stranice

U većini tema koristi se global-styling biblioteka resursa za CSS fajlove koje treba učitati na svakoj stranici gde je tema aktivna. Takođe je moguće isto uraditi za JS koristeći global-scripts biblioteku.

# fluffiness.libraries.yml (više biblioteka može biti definisano u istom fajlu, ovo bi se nalazilo ispod cuddly-slider biblioteke)
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: {}   

Da bi ove biblioteke bile dostupne na svim stranama teme, global-styling/global-scripts moraju biti dodate u info.yml vaše teme (npr. fluffiness.info.yml)

#fluffiness.info.yml
name: Fluffiness
type: theme
description: 'A cuddly theme that offers extra fluffiness.'
core: 8.x
libraries:
  - fluffiness/global-styling
  - fluffiness/global-scripts
base theme: classy
regions:
  header: Header
  content: Content
  sidebar_first: 'Sidebar first'
  footer: Footer

Prikačivanje biblioteke preko Twig šablona

Biblioteku resursa možete prikačiti Twig šablonu koristeći funkciju attach_library() u bilo kojem *.html.twig fajlu, na primer:

{{ attach_library('fluffiness/cuddly-slider') }}
<div>Neki fluffy markup {{ message }}</div>

Prikačivanje biblioteke na podskup stranica

U nekim slučajevima ne želite da vaša biblioteka bude aktivna na svim stranicama, već samo na podskupu. Na primer, možda želite da se vaša biblioteka učitava samo kada se prikaže određeni blok ili određeni tip čvora.

Tema to može uraditi implementacijom funkcije THEME_preprocess_HOOK() u .theme fajlu, zamenjujući "THEME" mašinskim imenom vaše teme, a "HOOK" mašinskim imenom tematskog hook-a.

Na primer, ako želite da dodate JavaScript na stranicu za održavanje, deo "HOOK" je "maintenance_page", pa funkcija izgleda ovako:

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

Slično možete napraviti i za druge hookove, a funkcija može sadržati i logiku — npr. da proveri koji se blok procesira u hooku "block", koji je tip čvora u hooku "node", itd.

Važna napomena! U ovom slučaju morate navesti metapodatke za keširanje koji odgovaraju vašem stanju! Gornji primer radi bez dodatnih metapodataka za keširanje. Najčešći slučaj je kada dodajete biblioteku resursa na osnovu trenutne rute:

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';
  }
}

Definisanje biblioteka: opcije i detalji

Dodavanje atributa u prikačene css/js

Atributi se dodaju unutar vitičastih zagrada iza svakog fajla u THEMENAME.libraries.yml fajlu vaše teme.

CSS atributi

Sledeći atributi su opciono i primenjuju se za svaki CSS resurs.

attributes Nepotrebni atributi. Poznat slučaj korišćenja Bootstrap CDN.
{ attributes: { crossorigin: anonymous } }
browsers Učitaj resurs uslovno prema pretraživaču. Napomena: ovaj metod koristi uslovne komentare koji nisu podržani u IE10 i novijim verzijama.
{ browsers: { IE: 'lte IE 9', '!IE': false } }
group Aktivi se agregiraju po grupama. Podrazumevano: SMACSS grupa kojoj pripada aktiv. Retko se koristi
media Tip medijuma.
{ media: print }
minified Da li je aktiv već minimiziran. Podrazumevano: false
{ type: external, minified: true }
preprocess Da li treba da se agregira. Podrazumevano: true
{ preprocess: false }
type Izvor aktivacije. Podrazumevano: file
{ type: external, minified: true }
weight Podešava redosled u odnosu na druge aktive u istoj SMACSS grupi. Podrazumevano: 0. Koristite vrednost od -50 do +50.
{ weight: 1 }

JS atributi

Sledeći atributi su opciono i primenjuju se za svaki JS resurs.

attributes Dodatni atributi skripti.
{ type: external, attributes: { async: true } }
browsers Učitaj resurs uslovno prema pretraživaču. Napomena: ovaj metod koristi uslovne komentare koji nisu podržani u IE10 i novijim verzijama.
{ browsers: { IE: 'lte IE 9', '!IE': false } }
preprocess Da li treba da se agregira. Podrazumevano: true
{ preprocess: false }
type Izvor aktivacije. Podrazumevano: file
{ type: external, minified: true }
weight Ne preporučuje se, umesto toga koristite zavisnosti. Podešava redosled u odnosu na druge aktive. Treba da bude negativan.
{ weight: -1 }

Perepisivanje i proširivanje biblioteka

Da biste promenili biblioteke definisane u *.libraries.yml, morate ići u *.info.yml. One se mogu zameniti ili proširiti pomoću libraries-override ili libraries-extend. Override definisan u *.info.yml će se naslediti u podtemama.

Properti stylesheets-remove koji se koristi u *.info.yml je zastareo i biće uklonjen u Drupal 9.0.x. stylesheets-override je već uklonjen.

libraries-override

Logika koju treba koristiti prilikom kreiranja override-a:

  • Koristite originalni namespace modula (ili core) za ime biblioteke.
  • Koristite putanju najnovijeg override-a kao ključ.
  • Ta putanja treba da bude puna putanja do fajla.

Na primer:

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

Ovde contextual/drupal.contextual-links je namespace osnovne biblioteke, a /core/themes/stable/css/contextual/contextual.module.css je puna putanja poslednjeg override-a. U ovom slučaju fajl je uklonjen (false).

Važno je napomenuti da je samo poslednji deo puna putanja, dok ostali predstavljaju namespace. Linije css: i component: odražavaju strukturu override-ovane biblioteke.

Ovo imajte na umu jer zavisnost od fajl sistema može da pukne ako se promeni struktura fajlova sajta. Zbog toga postoji problem uklanjanja zavisnosti od pune putanje korišćenjem stream wrapper-a.

Evo još nekoliko primera korišćenja libraries-override za uklanjanje ili zamenu CSS ili JS fajlova ili cele biblioteke koju nasleđuje vaša tema iz modula ili druge teme.

libraries-override:
  # Zamena cele biblioteke.
  core/drupal.collapse: mytheme/collapse
  
  # Zamena fajla drugim.
  subtheme/library:
    css:
      theme:
        css/layout.css: css/my-layout.css

  # Zamena fajla override-ovanog iz stable teme.
  contextual/drupal.contextual-toolbar:
    css:
      component:
        core/themes/stable/css/contextual/contextual.toolbar.css: css/contextual.toolbar.css

  # Zamena JS fajla iz core modula.
  toolbar/toolbar:
    js:
      js/views/BodyVisualView.js: js/views/BodyVisualView.js

  # Uklanjanje fajla.
  drupal/dialog:
    css:
      theme:
        dialog.theme.css: false
  
  # Uklanjanje cele biblioteke.
  core/modernizr: false
  
  # Zamena specifičnih fajlova iz biblioteke kontribut modula.
  # Napomena: Biblioteke koje modul može override-ovati su u njegovom *.libraries.yml fajlu. U ovom primeru, libraries.yml je u: /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 omogućava temama da menjaju biblioteke dodavanjem dodatnih zavisnosti biblioteci pri svakom učitavanju biblioteke.
libraries-extend definiše proširenje biblioteke sa bilo kojim brojem drugih biblioteka.

Ovo je idealno za različito stilizovanje komponenti u temi, a da ne uključujete CSS globalno. Tako da prilagodite izgled komponente samo gde treba.

# Proširenje drupal.user: dodavanje asseta iz classy teme.
libraries-extend:
  core/drupal.user: 
    - classy/user1
    - classy/user2

Dodatna podešavanja JavaScripta

Redosled učitavanja asseta

Redosled u kom su fajlovi navedeni je redosled u kom se učitavaju. Po defaultu, svi JS resursi se učitavaju u podnožju (footer). JS za kritične UI elemente, koje nije moguće prikazati bez pripadajućeg JS-a, može se učitati u zaglavlju, ako je potrebno, na sledeći način:

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

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

Postavite header na true da označite da se JS iz ove biblioteke nalazi na "kritičnom putu" i mora biti učitan iz zaglavlja. Sve direktne ili indirektne zavisnosti biblioteke će se automatski učitati iz zaglavlja, nije potrebno posebno ih navoditi. To znači da je resurs "kritičan" i treba ga učitati prvi.

Dodavanje prilagođenog JavaScripta

Ponekad želite dodati JavaScript na stranicu koji zavisi od nekih PHP vrednosti.

U tom slučaju, kreirajte JS fajl, definišite i prikačite biblioteku kao i do sada, ali takođe prikačite JS podešavanja i dozvolite JS fajlu da čita te podatke preko drupalSettings (naslednik Drupal 7 Drupal.settings). Da bi drupalSettings bio dostupan JS fajlu, morate navesti zavisnost od njega, kao što je slučaj sa jQuery.

Tako postaje:

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

i

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

Gde je 'bar' neka izračunata vrednost. (Napomena: potrebno je navesti i keš metapodatke!)

Zatim cuddly-slider.js može pristupiti settings.fluffiness.cuddlySlider.foo (što će biti 'bar'):

(function ($, Drupal, drupalSettings) {

  'use strict';

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

})(jQuery, Drupal, drupalSettings);

Dodavanje atributa elementima skripte

Ako želite dodati atribute u script tag, dodajte key attributes u JSON nakon URL-a skripte. Unutar objekta iza key attributes, navedite ime atributa kao novi key. Vrednost tog key-a je vrednost atributa. Ako je vrednost true, atribut će biti prikazan sam, bez vrednosti.

Na primer:

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

Ovo će proizvesti sledeću markup:

<script src="https://maps.googleapis.com/maps/api/js?key=myownapikey&signed_in=true&libraries=drawing&callback=initMap" async defer data-test="map-link"></script>

Inline JavaScript

Inline JavaScript se snažno ne preporučuje. Preporučuje se da se JavaScript stavi u fajl koji se učitava, jer to omogućava keširanje na strani klijenta. Takođe omogućava lakše pregledanje i uređivanje JavaScript koda.

Inline JavaScript koji generiše markup
To se ne preporučuje i obično nije potrebno. Stavite JavaScript u fajl. Primeri su reklame, dugmad za deljenje na društvenim mrežama, vidžeti društvenih mreža. Oni koriste inline JavaScript, ali su specifičan tip sadržaja/markupa, jer nisu namenjeni da ukrase sadržaj sajta ili interaktivnost, već da izvuku spoljašnji sadržaj preko JavaScripta.

Možete ih staviti u prilagođeni blok ili čak direktno u Twig šablon.

Na primer:

<script type="text/javascript"><!--
ad_client_id = "some identifier"
ad_width = 160;
ad_height = 90;
//--></script>
<script type="text/javascript" src="http://adserver.com/ad.js"></script>
<a class="twitter-timeline" href="https://twitter.com/wimleers" data-widget-id="307116909013368833">Tweets by @wimleers</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

Inline JavaScript koji utiče na celu stranicu

Korišćenje bilo kakvog inline JavaScripta se snažno ne preporučuje. Primeri inline JS koji utiču na celu stranicu su analitika (npr. Google Analytics) i servisi za hostovanje fontova. Inline JS koji utiče na celu stranicu može biti ili frontend/stilizacija ili logika.

Za frontend/stilizaciju (npr. hostovani fontovi) JS pripada temi. Stavite JS direktno u vaš html.html.twig fajl. Za fontove, ovo omogućava da se ispravno pozicionira za najbolji i najbrži prikaz krajnjem korisniku, jer sprečava FOUT (Flash Of Unstyled Text), dok se font učitava (fontovi preko JS treba da se nalaze u HTML <HEAD> pre CSS-a)!
(Više o tome pročitajte u odličnoj analizi "Async Typekit & Micro-FOUT".)

U drugom slučaju, JS pripada modulu; u tom slučaju pogledajte "Dodavanje CSS i JS u Drupal 8 modul".

Inline JavaScript u integracionom modulu

Korišćenje bilo kakvog inline JavaScripta se snažno ne preporučuje. Ako možete, koristite gore navedene primere pre nego što pokušate inline JS.

Dve stvari koje treba uzeti u obzir prilikom pružanja polja koje prihvata inline JS koje postavlja korisnik sajta:

1. Polje, forma ili stranica koja prihvata inline JS mora imati prikačeno odgovarajuće dozvole.
Primer: MODULE.routing.yml

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

2. Vrednost, ako je uskladištena u konfiguracionom objektu, mora obavestiti sistem renderovanja o svojoj CacheableMetadata, tako da se keš renderovanja očisti/istekne kada se promeni.
Primer: MODULES.module

<?php

/**
 * @file
 * Integracija MODULE u Drupal sajt.
 */

use Drupal\Core\Render\Markup;

/**
 * Implementira hook_page_bottom().
 */
function MODULE_page_bottom(array &$page_bottom) {
  $settings = \Drupal::config('MODULE.settings');
  $user = \Drupal::currentUser();
  $page_bottom['MODULE'] = [
    '#markup' => Markup::create($settings->get('js_code')),
    '#cache' => [
      'contexts' => ['user'],
      'tags' => ['user:' . $user->id()],
    ],
  ];
  // Dodaj metapodatke keširanja konfiguracije.
  /** @var Drupal\Core\Render\Renderer $renderer */
  $renderer = \Drupal::service('renderer');
  $renderer->addCacheableDependency($page_bottom['MODULE'], $settings);
}

CDN / Spoljašnje biblioteke

Možda želite da koristite JavaScript sa CDN-a (Content Delivery Network) — na primer, web fontovi su uglavnom dostupni samo preko eksternih URL-ova. To možete uraditi deklarisanjem biblioteke kao eksternu (type: external). Takođe je korisno uključiti neke informacije o spoljnim bibliotekama u definiciju.

(Napomena: Ovo uopšte nije dobra praksa za biblioteke sa CDN-a; izbegavajte ako je moguće jer uvodi dodatne tačke kvara i utiče na performanse i sigurnost, zahteva više TCP/IP konekcija i uglavnom nije keširano u browseru. Međutim, spoljne biblioteke ne treba da se hostuju na Drupal.org kao deo vašeg repozitorijuma — pogledajte Politiku o spoljnim bibliotekama na Drupal.org za detalje.)

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 }

Ako želite da vaš eksterni fajl bude zatražen istim protokolom kao i stranica, koristite URL bez protokola:

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

Za dodavanje CSS-a, evo primera integracije 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 }

Primer Bootstrap CDN CSS sa prilagođenim atributima.

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"

Više informacija

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.