@moRtenDk #dRupaLTWIg #srijAnwW
tHemIngSRIjAN wEDNeSDAy WEbINArS
DRUpAL
@moRtenDk #dRupaLTWIg #srijAnwW
DRUpAl 8 BEtA 14
(DRuPAL.ORG/DRUpAl-8.0.0-BEtA1)
WEBiNAR D8 THeMe
GIThUB.cOM/mORTeNDK/WEBiNAR-SRIjANWw
dOwnLoad
@moRtenDk #dRupaLTWIg #srijAnwW
@MorTenDk
CLAsSy
MAInTAInER
GEEk
RÖYALe
THE ANGrY
THEmER
TaG1
CONsULTiNG
@moRtenDk #dRupaLTWIg #srijAnwW
sTocKhoLm
sYndRome
@moRtenDk #dRupaLTWIg #srijAnwW
ACTuAL dRUPaL7
MARkUP
@moRtenDk #dRupaLTWIg #srijAnwW
“IT’S A FEAtUrE”
dIviTis
<DIV><DIV><DIV><DIV><DIV><DIV><DIV><DI
V><DIV><DIV><DIV><DIV><DIV><DIV><DIV><
DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV
><DIV><DIV><DIV><DIV><DIV><DIV><DIV>
</DIV></DIV></DIV></DIV></DIV></DIV></
DIV></DIV></DIV></DIV></DIV></DIV>
@moRtenDk #dRupaLTWIg #srijAnwW
5000LINeS Of PHpTEMpLATe.PHp
TotAllY oK
@moRtenDk #dRupaLTWIg #srijAnwW
<div
class=“foo bar baz foo-more-more bar-
more-yet another one”>
fEatUre
THE CLAsS SoUP IS AnOTHeR
@moRtenDk #dRupaLTWIg #srijAnwW
nO mOre
aAaaRgh!
@moRtenDk #dRupaLTWIg #srijAnwW
nEw
tHemE eNgiNe
GOOd-BYe
PHPtEMPlAtEHELlO TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
tHemE
fUncTioNs
dEad!
@moRtenDk #dRupaLTWIg #srijAnwW
tWig
tEmpLatEs
EVErYTHiNG iS
BLOcK.HtML.tWiG
MARk.HTmL.TwIG
TABlE.HtML.tWiG
PAGe.HTmL.TwIGNODe.HTmL.TwIG
VIEw.HTmL.TwIG
FIElD.HtML.tWiG IMAgE-WiDGEt.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
tHemE iS
iN cOntRol
ThE
OF mARKuP & CSs
@moRtenDk #dRupaLTWIg #srijAnwW
uNleArn
pHptEmpLa
te
<? pHP dIe(‘PHPtEMPlAtE’) ?>
@moRtenDk #dRupaLTWIg #srijAnwW
REAdY?
@moRtenDk #dRupaLTWIg #srijAnwW
tWig
DRUpAl 8
@moRtenDk #dRupaLTWIg #srijAnwW
IS a “MODeRN” TEmPLAtE LaNGUaGe
-> sYMPhONY
USEd BY OTHeR SySTEmS
+ ItS EaSY tO LeARN :)
tWig
@moRtenDk #dRupaLTWIg #srijAnwW
{{ var }}
{# comment #}
oUtpUt
@moRtenDk #dRupaLTWIg #srijAnwW
{{ data.is.here }}
{{ also.this[#hashtags] }}
vAr DriLliNg
$yo[‘drupal_where ’]->is[‘und’][0]->my_data7
@moRtenDk #dRupaLTWIg #srijAnwW
{{ var|makemepretty(‘now’) }}
fUncTion
PIBe
TWIg FUnCTIoNVaR
@moRtenDk #dRupaLTWIg #srijAnwW
{{ username|uppercase }}
MORTENDK
fUncTion
(mortendk)
@moRtenDk #dRupaLTWIg #srijAnwW
{{ ‘Copenhagen’|t }}
København
{% trans %}
Copenhagen {{ var }}
{% endtrans %}
tRanSlaTe
@moRtenDk #dRupaLTWIg #srijAnwW
{% if person=“mortendk” %}
<h1>Loves Drupal8</h1>
{% endif %}
cOntRol
@moRtenDk #dRupaLTWIg #srijAnwW
{{ sushi|raw}}
aUtoEscApe
SECuRITy IS SOMeTHInG
DEVeLOPeRS LIKe
@moRtenDk #dRupaLTWIg #srijAnwW
{% set foo = “bar” %}
{{ foo }}
bar
cReaTe Var
@moRtenDk #dRupaLTWIg #srijAnwW
TWIg.SEnSIOlABS.ORG/DOCuMENtATIoN
tWig
@moRtenDk #dRupaLTWIg #srijAnwW
cLasSy
THE DRUpAl 8 BAsE ThEmE
@moRtenDk #dRupaLTWIg #srijAnwW
7
corE
claSsy
<HTmL>
.CSs
CLAsS=“FoO”
<HTmL>
.CSs
CLAsS=“FoO”
@moRtenDk #dRupaLTWIg #srijAnwW
bAseTheMe
corE claSsy
my ThemE
? barTik
sevEn
$VArS
@moRtenDk #dRupaLTWIg #srijAnwW
bAseTheMe
<div>
{{ foo }}
</div>
corE claSsy“MY tHEMe”
NOT DEFiNeD
@moRtenDk #dRupaLTWIg #srijAnwW
bAseTheMe
<div class=“node node—article”>
{{ foo }}
</div>
corE claSsy“MY tHEMe”
BASe THeME: CLAsSY
@moRtenDk #dRupaLTWIg #srijAnwW
gRouPing
@moRtenDk #dRupaLTWIg #srijAnwW
tEmpLatE gRouPs
LAYoUT
FIElD
DATaSeT
VIEwS
BLOcK CONtENT-EDIt
CONtEnT
MISc
USEr
NAViGATiON
FORm
@moRtenDk #dRupaLTWIg #srijAnwW
dEfiNe BasEthEme
base theme: classy
THEmENAmE.InFO.yML
@moRtenDk #dRupaLTWIg #srijAnwW
sEtup
SETtING UP a THeME
@moRtenDk #dRupaLTWIg #srijAnwW
[ROOt]/ThEMEs/[THEmENAmE]
I LiVE wHERe NOw ?
@moRtenDk #dRupaLTWIg #srijAnwW
tHemE cOnfIg FilEs
*.InFO.yMl
*.LiBRArIES.YML
*.BrEAKpOINtS.YmL
*.ThEmE
@moRtenDk #dRupaLTWIg #srijAnwW
*.inFo.Yml
THEmE CoNFIgURAtION, CSs & jS
@moRtenDk #dRupaLTWIg #srijAnwW
BASiC
INFo
REGiOnS
LIBrARIeS
REMoVE cSS
@moRtenDk #dRupaLTWIg #srijAnwW
@moRtenDk #dRupaLTWIg #srijAnwW
*.liBraRieS.yMl
ADD Js & CSs FIlES
@moRtenDk #dRupaLTWIg #srijAnwW
.INfO.YmL
.LIbRARiES.yML
@moRtenDk #dRupaLTWIg #srijAnwW
NAMe
DEPeNDEnCIEs
CSS FILeS
*.liBraRieS.yMl
JS fILEs
@moRtenDk #dRupaLTWIg #srijAnwW
global:
version: VERSION
css:
component:
css/user/user.theme.css: {}
theme:
css/layout.css: {}
cSs Lib
BASe
LAYoUt
COMpONEnT
STAtE
THEmE
@moRtenDk #dRupaLTWIg #srijAnwW
{{ attach_library('classy/book-navigation') }}
cSs FilEs In TemPlaTe
@moRtenDk #dRupaLTWIg #srijAnwW
[*].BreAkpOinTs.Yml
RESpONSiVE iMAGeS
@moRtenDk #dRupaLTWIg #srijAnwW
*.BrEAKpOINtS.YmL
@moRtenDk #dRupaLTWIg #srijAnwW
*.BrEAKpOINtS.YmL
@moRtenDk #dRupaLTWIg #srijAnwW
[*].TheMe
WAS
PHPtEMPlATE.PhP
@moRtenDk #dRupaLTWIg #srijAnwW
.TheMe
.LIbRARiES.yML
.THeME
@moRtenDk #dRupaLTWIg #srijAnwW
tOols
HOW TO fIND STUfF & DEbUg
@moRtenDk #dRupaLTWIg #srijAnwW
sEttIngS.pHp
if (file_exists(__DIR__ . '/settings.local.php')) {
include __DIR__ . '/settings.local.php';
}
COPy: SiTES/EXAmPLE.SETtINGs.LOcAL.pHP
TO: SITeS/DeFAUlT/SeTTInGS.lOCAl.PHp
UNCoMMEnT In SEtTINgS.PhP
@moRtenDk #dRupaLTWIg #srijAnwW
DOWnLOAd DEvEL mODUlE
INStALL DEVeL + KINt
INStALL DRUsH
DRUsH En KInT
DOCs.DRuSH.oRG/eN/MaSTEr/INsTALl/
dEveL mOduLe
@moRtenDk #dRupaLTWIg #srijAnwW
dIsaBle csS cAche
@moRtenDk #dRupaLTWIg #srijAnwW
dEbuG fTw
LETs LOoK At THe THeME nOw
(LIvE CoDE dEMO)
@moRtenDk #dRupaLTWIg #srijAnwW
FILe NAmE SuGGEsTIOnS
@moRtenDk #dRupaLTWIg #srijAnwW
kInt
{{ kint( foo ) }}
KRUmO FoR DrUPAl 8
{{ content.field_image }}
@moRtenDk #dRupaLTWIg #srijAnwW
TWIg DEbUg:

SITeS/AlL/DeFAUlT/SeRVIcES.yMl
DRUsH Cr

{{ KInT(FoO) }}
dEbuG:
@moRtenDk #dRupaLTWIg #srijAnwW
tEmpLatE
sTruCtuRe
HOW IS iT StRUCtUREd IN D8
@moRtenDk #dRupaLTWIg #srijAnwW
hTml
HTMl.HTmL.TwIG
CSS + Js
HEAdER
@moRtenDk #dRupaLTWIg #srijAnwW
HTMl.HTmL.TwIG
pAge
PAGe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
HTMl.HTmL.TwIGREGiON.hTML.TWIg
REGiON.hTML.TWIg
REGiON.hTML.TWIg
rEgiOn's
PAGe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
HTMl.HTmL.TwIG
cOntEnt
BLOcK.HtML.tWiG NODe.HTmL.TwIG VIEw.HTmL.TwIG
REGiON.hTML.TWIg
@moRtenDk #dRupaLTWIg #srijAnwW
nOde
FIElD.HtML.tWiG
NODe.HTmL.TwIG
FIElD.HtML.tWiGFIElD.HtML.tWiG
FIElD-—IMAgE.HtML.tWiGFIElD.HtML.tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
aLl The fiElds
FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG
FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG
FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG
FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
lAyoUt
THE MAGiC Of WItHOUt
@moRtenDk #dRupaLTWIg #srijAnwWNODe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
@moRtenDk #dRupaLTWIg #srijAnwW
{{ content|without(‘field’) }}
wIthOut fuNctIon
PIBe
NAMe
TWIg FUnCTIoN
VaR
@moRtenDk #dRupaLTWIg #srijAnwW
conTeNt
imaGe
tagS
lAyoUt
@moRtenDk #dRupaLTWIg #srijAnwW
{{ coNtenT }}
{{ imAge }}
{{ content }}
{{ teXt }} {{ taGs }}
@moRtenDk #dRupaLTWIg #srijAnwW
{{ coNtenT | WithOut(*) }}
{{ imAge }}
{{ content|without(‘image’) }}
{{ content.image }}
{{ teXt }} {{ taGs }}
@moRtenDk #dRupaLTWIg #srijAnwW
{{ coNtenT | WithOut(**) }}
{{ imAge }}
{{ content|without(‘image’,‘tags’) }}
{{ content.image }}
{{ teXt }}
{{ taGs }}
{{ content.tags }}
@moRtenDk #dRupaLTWIg #srijAnwW
{{ coNtenT | WithOut(**) }}
{{ imAge }}
{{ content|without(‘image’,‘tags’) }}
{{ content.image }}
{{ teXt }}
{{ taGs }}
{{ content.tags }}
{{ neW }}
NEW FIElD
@moRtenDk #dRupaLTWIg #srijAnwW
CONtEnT
nOde.htMl.Twig
@moRtenDk #dRupaLTWIg #srijAnwW
CONtENT.FIElD_ImAgE
@moRtenDk #dRupaLTWIg #srijAnwW
CONtENT.FIElD_TaGS
@moRtenDk #dRupaLTWIg #srijAnwW
mArkUp
OVErWRItE FiELDs
@moRtenDk #dRupaLTWIg #srijAnwW
nOde.htMl.Twig
@moRtenDk #dRupaLTWIg #srijAnwW
fIle naMe SugGesTioNs
@moRtenDk #dRupaLTWIg #srijAnwW
fIelD-[Foo].hTml.twIg
FIElD--nODE--FIeLD-tAGS--ARtICLe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
@moRtenDk #dRupaLTWIg #srijAnwW
<div {{ attributes }}>
class=“foo”
data-drupal-foo
aria-hidden=“true”
aTtrIbuTes
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSY
<DIv CLaSs=“FOO FOO-BAR FOO-BAR-BaZ”>
*.TpL.PhP
THEmE FuNCTiOnS
PREpROCeSS
$VArS
DRUpAL7
7
@moRtenDk #dRupaLTWIg #srijAnwW
NODe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
{%
set classes = [
'tags',
'field-' ~ field_name|clean_class ~ '
]
%}
<div {{ attributes.addClass(classes) }}>…</div>


<div class=“tags field-tags”>…
aDdcLass
@moRtenDk #dRupaLTWIg #srijAnwW
<i {{ attributes.removeClass(red) }}> … </i>


<i class=“blue”>…</i>
<div class=“red blue”> … </div>
BAD MODuLE oUTPuT
rEmoVe ClaSs
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“CORe”>
ESSeNTIaL ClASSeS Ex:
“IS-vISIbLE”
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“CORe MOdUlE”>
$vaR[‘attRibuTes’]->AddCLass(‘modUle’)
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“CORe MOdULE THEmE”>
{{ ATtRIBuTES.ADDcLASs(‘THEmE’) }}
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“CORe THeME”>
{{ ATtRIBuTES.REMoVe(‘MODuLE’) }}
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“THEmE”>
{{ ATtRIBuTES.REMoVe(‘MODuLE’,’CORe’) }}
@moRtenDk #dRupaLTWIg #srijAnwW
jS- PreFix
<DIv CLaSs=“JS-fOO fOO”>…
$(.jS-FoO) .FOo{…}
@moRtenDk #dRupaLTWIg #srijAnwW
<div class="blablabla">
{{
attributes
.removeClass(‘blablabla’)
.addClass(‘hero-main’)
.setAttribute('id', 'top')
}}
<div id="top" class="hero-main">
aTtrIbuTes
@moRtenDk #dRupaLTWIg #srijAnwW
tWigBloCk
MORe COoLNEsS FrOM tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
datA (pAge.Html.twiG)
PAGe.HTmL.TwIGD8
datA (pAge.Html.twiG)
@moRtenDk #dRupaLTWIg #srijAnwW
datA (pAge.Html.twiG)
{% block foo %}
{% endblock %}
PAGe.HTmL.TwIGD8
datA (pAge.Html.twiG)
@moRtenDk #dRupaLTWIg #srijAnwW
datA (pAge.Html.twiG)
(paGe-—froNt.hTml.Twig)
{% extends "page.html.twig" %}
PAGe.HTmL.TwIGD8
datA (pAge.Html.twiG)
@moRtenDk #dRupaLTWIg #srijAnwW
PAGe.HTmL.TwIG
PAGe—FROnT.HtML.tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
PAGe.HTmL.TwIG
PAGe—FROnT.HtML.tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
CAUsE WhAT cOULd GO WROnG…
lIve deMo
@moRtenDk #dRupaLTWIg #srijAnwW
TINyURL.COM/DIViTiS
dIviTis…
@moRtenDk #dRupaLTWIg #srijAnwW
DRUpAL.oRG/tHEMe-GUiDe/8
DRUpAL.oRG/cODInG-StANDaRDS/CSS
SMAcSS.cOM

TWIg.SEnSIOlABS.ORG/DOCuMENtATIoN
lInks
@moRtenDk #dRupaLTWIg #srijAnwW
dOwnLoaD d8
BETa 14! - ONlY 11 BLoCKErS LeFT
DRUpAL.oRG/dRUPaL8
@moRtenDk #dRupaLTWIg #srijAnwW
WEEkLY mEETiNG’S
THUrSDAy 1700 CEt
#DruPalTwig
@moRtenDk #dRupaLTWIg #srijAnwW
USE TWItTER
#SRiJANwW
QUEsTIOnS, cOMMeNTS & FEeDBAcK
@MOrTENdK
qUesTioNs

[Srijan Wednesday Webinars] Drupal 8: Goodbye to 10 Years of Theming Headaches