• No results found

Creating a Drupal 8 theme from scratch

N/A
N/A
Protected

Academic year: 2021

Share "Creating a Drupal 8 theme from scratch"

Copied!
130
0
0

Loading.... (view fulltext now)

Full text

(1)

Creating a Drupal 8 theme

from scratch

Devsigner 2015

(2)

So you wanna build

a website…

(3)

And you want

(4)

Step 1:

(5)

Step 2:

(6)
(7)
(8)
(9)
(10)
(11)
(12)
(13)

You’re using a CMS?

Drupal, you say?

(14)
(15)
(16)

What is a theme?

Themes control appearance

Themes don’t provide functionality

Usually specific to a single site

Contains HTML (templates), CSS, Javascript, and a

(17)
(18)

Changes for Drupal 8

Drupal 8 loves abstractions

Drupal 8 loves themers and front end developers

Kinda

Documentation is still somewhat sparse

Drupal 8 is still changing

(19)

Setup for Drupal 8

Make sure you use newer versions of Drush, 8.x

minimum

Clear the cache, a lot

Disable page cache, and CSS/JS aggregation, these are

(20)
(21)

Themes now go in

themes directory

No more sites/all/

(22)

Add a

(23)
(24)

YAML…

YAML Ain’t Markup Language

Readable by machines

But also readable by humans, which is cool since

(25)

key:

value


strings:

"Quoted for special characters or spaces"

collection:

-

"Indented with spaces"

-

"Start with dash (-)"

collections:

can:

"specify key"

nested:

items:

"Work as well"

another:

"See?"

boolean:

true


or:

false

(26)

Make a directory for your theme with it’s name

Add a themename.info.yml file

(27)

demo.info.yml

name:

Demo


type:

theme


description:

'A demo theme.'

(28)
(29)
(30)
(31)

Wow, that looks like

the web in like 1996

(32)
(33)

Want to remove some of

Drupal’s default

(34)

demo.info.yml

name:

Demo


type:

theme


description:

'A demo theme.'

core:

8.x


libraries:

-

demo/global-styling


stylesheets-remove:

(35)
(36)

No more drupal_add_css()

or drupal_add_js()

(37)
(38)

Drupal 8 Libraries

Drupal 8 is all about abstraction and reuse, even with

front end code

Libraries represent external components

Libraries can have CSS, Javascript, and dependencies

Examples: normalize, html5shiv, jQuery, modernizer,

(39)

Libraries are defined in

themename.libraries.yml

(40)

demo.libraries.yml

global-styling:

version:

8.x-1.x


css:

theme:

css/styles.css:

{}

(41)

demo.info.yml

name:

Demo


type:

theme


description:

'A demo theme.'

core:

8.x


libraries:

(42)

Specify additional

(43)

demo.libraries.yml

global-styling:

version:

8.x-1.x


css:

theme:

css/styles.css:

{}


(44)

Let’s add some

Javascript

(45)

demo.libraries.yml

global-styling:

version:

8.x-1.x


css:

theme:

css/styles.css:

{}


css/print.css:

{

media:

print

}


js:

js/script.js:

{}


dependencies:

-

core/jquery


(46)

Note the dependencies,

jQuery is no longer included

on every page by default

(47)

What else can you

do with libraries?

(48)

demo.libraries.yml

global-styling:

version:

8.x-1.x


css:

theme:

css/styles.css:

{}


landing-pages:

version:

8.x-1.x


css:

theme:

css/landing-pages.css:

{}

(49)

How to include additional

libraries?

Specify globally in theme info.yml file

Add in preprocess function with #attached

Add via Twig function

(50)

demo.info.yml

name:

Demo


type:

theme


description:

'A demo theme.'

core:

8.x


libraries:

- demo/global-styling


(51)

Where do I put

(52)

Wait, Drupal 8 still has

preprocess functions????

(53)

Adding a

(54)

themes

└── demo

├── css

│   ├── print.css

│   └── styles.css

├── demo.info.yml

├── demo.libraries.yml

└── demo.theme

(55)

Think of .theme as a

replacement for

(56)

OH MY GOD ITS

FULL OF PHP

(57)

demo.theme

<?php

/**

* @file

* Contains preprocess functions for Demo theme.

*/

/**

* Preprocess for node pages.

*/

function

demo_preprocess_node(&

$variables

) {


$variables

[

'#attached'

][

'library'

][] =

'demo/landing-pages'

;


}


(58)

Don’t forget to rebuild

caches when changing

(59)
(60)

Templates, what are

they good for?

(61)
(62)

What’s so great about Twig

Flexible

Easy to use

Similar to other template systems (jinja2, swig, etc)

SECURE

(63)
(64)

{# All twig tags use braces #}

{# Comment use the hash/pound #}

{{ this_tag_prints_output }}


{# Tags with percent signs, are control blocks #}

{%

if

variable %}


{{ variable }}


{%

endif

%}


(65)

{%

set

variable =

'Special value.'

%}


{{ variable|clean_class }}


(66)

Example filters

Part of Twig — capitalize, date, escape, first, length,

lower, number_format, trim, etc

Drupal provided — t, trans, passthrough,

placeholder, drupal_escape, safe_join, without,

clean_class, clean_id, render

(67)

{{

'This text will be translated'

|t }}


<title>{{ head_title|safe_join(

' | '

) }}</title>


(68)

region.html.twig

{%


set

classes = [


'region'

,


'region-'

~ region|clean_class,


]


%}


{%

if

content %}


<

div

{{ attributes.addClass(classes) }}>


{{ content }}


</

div

>


{%

endif

%}

(69)

Working with

Drupal regions

(70)

page.html.twig

{%

if

page.sidebar_first %}


<

aside

class=

"layout-sidebar-first"

role=

"complementary"

>


{{ page.sidebar_first }}


</

aside

>


(71)
(72)

Templates are

cached!

(73)

Fast websites are good,

but caching sucks when

(74)

Disable render caching in

sites/default/settings.php

(75)

sites/default/settings.php

/**

* Disable CSS and JS aggregation.

*/

$config

[

'system.performance'

][

'css'

][

'preprocess'

] =

FALSE

;


$config

[

'system.performance'

][

'js'

][

'preprocess'

] =

FALSE

;


/**

* Disable the render cache (this includes the page cache).

*

* This setting disables the render cache by using the Null cache back-end

* defined by the development.services.yml file above.

*

* Do not use this setting until after the site is installed.

*/

(76)

Disable caching in

(77)

sites/default/services.yml

parameters:

twig.config:

# Twig auto-reload:

#

# Automatically recompile Twig templates whenever the source code changes.

# If you don't provide a value for auto_reload, it will be determined

# based on the value of debug.

#

# Not recommended in production environments

# @default null

auto_reload:

null


# Twig cache:

#

# By default, Twig templates will be compiled and stored in the filesystem

# to increase performance. Disabling the Twig cache will recompile the

# templates from source each time they are used. In most cases the

# auto_reload setting above should be enabled rather than disabling the

# Twig cache.

#

# Not recommended in production environments

# @default true

(78)
(79)

sites/default/services.yml

parameters:


twig.config:


# Twig debugging:

#

# When debugging is enabled:

# - The markup of each Twig template is surrounded by HTML comments that

# contain theming information, such as template file name suggestions.

# - Note that this debugging markup will cause automated tests that directly

# check rendered HTML to fail. When running automated tests, 'debug'

# should be set to FALSE.

# - The dump() function can be used in Twig templates to output information

# about template variables.

# - Twig templates are automatically recompiled whenever the source code

# changes (see auto_reload below).

#

# For more information about debugging Twig templates, see

# http://drupal.org/node/1906392.

#

# Not recommended in production environments

# @default false

(80)
(81)

(after clearing the

cache, of course)

(82)

<!-- THEME DEBUG -->

<!-- THEME HOOK: 'menu__main' -->

<!-- FILE NAME SUGGESTIONS:

* menu--main.html.twig

x menu.html.twig

-->

<!-- BEGIN OUTPUT from 'core/modules/system/templates/menu.html.twig' -->

<

ul

class=

"menu"

>


<

li

class=

"menu-item"

>


<

a

href=

"/"

data-drupal-link-system-path=

"

&lt;

front

&gt;

"

>Home</

a

>


</

li

>


</

ul

>


(83)
(84)

Debug features

We can see template suggestions

We can see what the default or current used

template is

We can also use the dump() function to inspect

(85)

themes

└── demo

├── css

│   └── styles.css

├── demo.info.yml

├── demo.libraries.yml

├── demo.theme

└── templates

└── region.html.twig

(86)

templates/region.html.twig

{%


set

classes = [


'region'

,


'region-'

~ region|clean_class,


]


%}


{{ dump(attributes) }}


{%

if

content %}


<

div

{{ attributes.addClass(classes) }}>


{{ content }}


</

div

>


{%

endif

%}

(87)
(88)

The existence of a

template file is still cached,

even with debug enabled :(

(89)
(90)
(91)

templates/node.html.twig

<

article

{{ attributes }}>


{{ title_prefix }}


{%

if not

page %}


<

h2

{{ title_attributes }}>


<

a

href=

"

{{ url }}

"

rel=

"bookmark"

>{{ label }}</

a

>


</

h2

>


{%

endif

%}


{{ title_suffix }}


{%

if

display_submitted %}


<

footer

>


{{ author_picture }}


<

div

{{ author_attributes }}>


{%

trans

%}Submitted by {{ author_name }} on {{ date }}{%

endtrans

%}


{{ metadata }}


</

div

>


</

footer

>


{%

endif

%}


<

div

{{ content_attributes }}>


{{ dump(content) }}


{{ content }}


</

div

>


</

article

>

(92)

array (size=5)

'field_image'

=>

array (size=2)

'#cache'

=>

array (size=3)

'contexts'

=>

array (size=0)

...

'tags'

=>

array (size=0)

...

'max-age'

=>

int

-1

'#weight'

=>

int

-1

'body'

=>

array (size=16)

'#theme'

=>

string

'field'

(length=5)

'#title'

=>

string

'Body'

(length=4)

'#label_display'

=>

string

'hidden'

(length=6)

'#view_mode'

=>

string

'full'

(length=4)

'#language'

=>

string

'en'

(length=2)

'#field_name'

=>

string

'body'

(length=4)

'#field_type'

=>

string

'text_with_summary'

(length=17)

'#field_translatable'

=>

boolean

true

'#entity_type'

=>

string

'node'

(length=4)

'#bundle'

=>

string

'article'

(length=7)

(93)

<

div

{{ content_attributes }}>


<

div

class="for-the-tags"

>


{{ content.field_tags }}


</

div

>


{{ content|without(

'field_tags'

) }}


</

div

>

(94)

But what variables

are defined?

(95)
(96)

Other fun stuff to

do with templates

(97)
(98)

{%

import _self as

menus %}


{#

We call a macro which calls itself to render the full tree.

@see http://twig.sensiolabs.org/doc/tags/macro.html

#}

{{ menus.menu_links(items, attributes,

0

) }}


{%

macro

menu_links(items, attributes, menu_level) %}


{%

import _self as

menus %}


{%

if

items %}


{%

if

menu_level ==

0

%}


<

ul

{{ attributes.addClass(

'menu'

) }}>


{%

else

%}


<

ul

class=

"menu"

>


{%

endif

%}


{%

for

item

in

items %}


<

li

{{ item.attributes }}>


{{ link(item.title, item.url) }}


{%

if

item.below %}


{{ menus.menu_links(item.below, attributes, menu_level +

1

) }}


{%

endif

%}


</

li

>


{%

endfor

%}


</

ul

>


{%

endif

%}


{%

endmacro

%}


(99)

So you’ve got a

(100)

You know how to find

template names,

(101)
(102)
(103)

Not included by

(104)
(105)

But what if you

liked those?

(106)

Enter the Classy

theme

(107)

Classy theme

Provides a base theme that just adds classes for

other themes to build on

Literally only has about 40 lines of CSS

No PHP at all

But over a hundred templates!

(108)

What’s with the

(109)

@import url("/core/modules/tour/css/tour.module.css?nqlozl");
 </style>


<style media="all">


@import url("/core/modules/contextual/css/contextual.toolbar.css?nqlozl");


@import url("/core/modules/editor/css/editor.css?nqlozl");


@import url("/core/modules/filter/css/filter.caption.css?nqlozl");


@import url("/core/modules/ckeditor/css/plugins/drupalimagecaption/ckeditor.drupalimagecaption.css?nqlozl");


@import url("/core/modules/toolbar/css/toolbar.menu.css?nqlozl");


@import url("/core/modules/ckeditor/css/ckeditor.css?nqlozl");


@import url("/core/modules/contextual/css/contextual.theme.css?nqlozl");


@import url("/core/modules/contextual/css/contextual.icons.theme.css?nqlozl");


@import url("/core/assets/vendor/jquery.ui/themes/base/theme.css?nqlozl");


@import url("/core/misc/dialog.theme.css?nqlozl");


@import url("/core/modules/quickedit/css/quickedit.theme.css?nqlozl");


@import url("/core/modules/quickedit/css/quickedit.icons.theme.css?nqlozl");


@import url("/core/themes/seven/css/components/quickedit.css?nqlozl");


@import url("/core/modules/toolbar/css/toolbar.theme.css?nqlozl");


@import url("/core/modules/toolbar/css/toolbar.icons.theme.css?nqlozl");


@import url("/core/modules/user/css/user.icons.theme.css?nqlozl");


@import url("/core/modules/shortcut/css/shortcut.theme.css?nqlozl");


@import url("/core/modules/shortcut/css/shortcut.icons.theme.css?nqlozl");


@import url("/core/modules/filter/css/filter.admin.css?nqlozl");
 </style>


<style media="all">


@import url("/core/themes/bartik/css/base/elements.css?nqlozl");


@import url("/core/themes/bartik/css/layout.css?nqlozl");


@import url("/core/themes/bartik/css/components/admin.css?nqlozl");


@import url("/core/themes/bartik/css/components/block.css?nqlozl");


@import url("/core/themes/bartik/css/components/book.css?nqlozl");


@import url("/core/themes/bartik/css/components/breadcrumb.css?nqlozl");


@import url("/core/themes/bartik/css/components/captions.css?nqlozl");


@import url("/core/themes/bartik/css/components/comments.css?nqlozl");


@import url("/core/themes/bartik/css/components/content.css?nqlozl");


@import url("/core/themes/bartik/css/components/contextual.css?nqlozl");


@import url("/core/themes/bartik/css/components/dropbutton.component.css?nqlozl");


@import url("/core/themes/bartik/css/components/featured-top.css?nqlozl");


@import url("/core/themes/bartik/css/components/feed-icon.css?nqlozl");


@import url("/core/themes/bartik/css/components/form.css?nqlozl");


@import url("/core/themes/bartik/css/components/forum.css?nqlozl");


@import url("/core/themes/bartik/css/components/header.css?nqlozl");


@import url("/core/themes/bartik/css/components/region-help.css?nqlozl");


@import url("/core/themes/bartik/css/components/item-list.css?nqlozl");


@import url("/core/themes/bartik/css/components/list-group.css?nqlozl");


@import url("/core/themes/bartik/css/components/node-preview.css?nqlozl");


@import url("/core/themes/bartik/css/components/pager.css?nqlozl");


@import url("/core/themes/bartik/css/components/panel.css?nqlozl");


@import url("/core/themes/bartik/css/components/primary-menu.css?nqlozl");


@import url("/core/themes/bartik/css/components/search.css?nqlozl");


@import url("/core/themes/bartik/css/components/search-results.css?nqlozl");


@import url("/core/themes/bartik/css/components/secondary-menu.css?nqlozl");


@import url("/core/themes/bartik/css/components/shortcut.css?nqlozl");


@import url("/core/themes/bartik/css/components/skip-link.css?nqlozl");


@import url("/core/themes/bartik/css/components/sidebar.css?nqlozl");


@import url("/core/themes/bartik/css/components/site-footer.css?nqlozl");


@import url("/core/themes/bartik/css/components/table.css?nqlozl");
 </style>


(110)
(111)

Drupal 8 uses

SMACSS

(112)

Scalable and Modular CSS

It’s a book! By Jonathan Snook!

It’s also a workshop!

(113)

SMACSS in Drupal 8

Base — CSS reset/normalize plus HTML element styling.

Layout — macro arrangement of a web page, including

any grid systems.

Component — discrete, reusable UI elements.

State — styles that deal with client-side changes to

components.

Theme — purely visual styling (“look-and-feel”) for a

(114)

But it’s really up to

you in your theme

(115)

What are you likely to use in

your theme?

Base

Layouts

Component overrides

Theme styles

(116)

css

├── base

│   └── elements.css

├── components

│   ├── admin.css

│   ├── book.css

│   ├── breadcrumb.css

│   ├── buttons.css

│   ├── comments.css

│   ├── content.css

│   ├── contextual.css

│   ├── form.css

│   ├── forum.css

│   ├── sidebar.css

│   ├── skip-link.css

│   ├── tabs.css

│   └── views.css

├── layout.css

├── maintenance-page.css

└── print.css

(117)

Standards for organizing CSS

(118)

Best practices for CSS architecture in Drupal

8

(119)

Thank you!

Please evaluate this session

(120)

Extras

(121)
(122)

Allows you to expose your

CSS breakpoints to the

(123)

demo.breakpoint.yml

demo.mobile:

label:

mobile


mediaQuery:

''

weight:

2


multipliers:

-

2x


demo.narrow:

label:

narrow


mediaQuery:

'all and (min-width: 560px) and (max-width: 850px)'

weight:

1


multipliers:

-

2x


demo.wide:

label:

wide


mediaQuery:

'all and (min-width: 851px)'

weight:

0


multipliers:

(124)
(125)

<

picture

>


<!--[if IE 9]><video style="display: none;"><![endif]-->

<

source

srcset=

"styles/large/Billy_Mays.jpg 1x, styles/

large_960x_960_/Billy_Mays.jpg 2x"

media=

"all and (min-width: 851px)"

type=

"image/jpeg"

>


<

source

srcset=

"styles/medium/Billy_Mays.jpg 1x, styles/

medium_440x440_/Billy_Mays.jpg 2x"

media=

"all and (min-width: 560px) and

(max-width: 850px)"

type=

"image/jpeg"

>


<

source

srcset=

"styles/thumbnail/Billy_Mays.jpg 1x"

type=

"image/jpeg"

>


<!--[if IE 9]></video><![endif]-->

<

img

property=

"schema:image"

srcset=

""

alt=

"Billy Mays here"

typeof=

"foaf:Image"

data-pfsrcset=

"styles/large_960x_960_/

Billy_Mays.jpg"

src=

"styles/large_960x_960_/Billy_Mays.jpg"

style=

""

width=

"350"

>


(126)
(127)
(128)

Add a screenshot

Make a PNG

Make it 588 x 438

Call it screenshot.png

(129)

But really, there are directions

(130)

Thank you!

Please evaluate this session

References

Related documents

The Site URL (“URL”) must be specified at the moment of the purchase. The license will not be valid for sub-domains of the specified URL. This license includes 5 Developer

In a nutshell, low-powered contracts emerge in equilibrium because a buyer, when designing a procurement contract to an activity provider, does not fully internalize that

 Exception to market value rule on the transfer by executor to beneficiaries of tax base property, providing the only beneficiaries are close relatives or a charity. Note only

This chapter locates the contemporary wedding in a particular tradition of theology and Christian practice, which includes a particular history of involvement with the

Against this backdrop, in an attempt to consider the differential washback effects of task based language assessment procedure and traditional assessment modes on the follow up

• JQuery HTML o JQuery Get o JQuery Set o JQuery Add o JQuery Remove o JQuery CSS Classes o JQuery css() o JQuery Dimensions • JQuery Traversing o JQuery Traversing o

Skills used: PHP, Symfony 2.3 MVC framework, Object oriented programming, MySQL, JQuery, doctrine, javascript, CSS, HTML, Cross browser compatibility, Twitter

Bootstrap example of Sliding Sidebar Contact Form using HTML Javascript jQuery and CSS Snippet by akshayptdr4.. Automatically request if you get an deed of form blogger page,