I chose ScrollMagic because it seems to be more active than many of the other solutions out there. Also you can do all kinds of animations, pins and scrolling effects, not just parallax effects.

Fluid Container

Note: I’m using Bootstrap subtheme in this tutorial. Here’s how to install it: http://www.wdtutorials.com/drupal/8/theming/bootstrap-1/

Change the main container class to .container-fluid in your theme settings (admin/appearance/settings/yourtheme):

This will make our layout fluid so the parallax sections stretch from edge to edge.

Custom Blocks

Go to admin/structure/block/block-content/types and create a new block type called Parallax.

Go to block/add and create two Parallax blocks:

Go to admin/structure/block and place the blocks in the content region:

Place also some Basic blocks around the Parallax blocks:

Organize the blocks like this:

Now you should see something like this in the frontpage:

Template For a Custom Block Type

Turn on debug mode. Easiest way to disable caching and turn on debugging is to use Drupal Console:

1
drupal site:mode dev

Or you can do it manually: http://www.wdtutorials.com/drupal/theming/how-to-disable-page-cache-drupal-8-tutorial-37

Add this in themes/YOURTHEME/YOURTHEME.theme:

1
2
3
4
5
6
7
8
9
10
11
/**
 * Implements hook_theme_suggestions_HOOK_alter() for form templates.
 * @param array $suggestions
 * @param array $variables
 */
function YOURTHEME_theme_suggestions_block_alter(array &$suggestions, array $variables) {
    // Block suggestions for custom block bundles.
   if (isset($variables['elements']['content']['#block_content'])) {
        array_splice($suggestions, 1, 0, 'block__bundle__' . $variables['elements']['content']	['#block_content']->bundle());
    }
}

Source: https://www.drupal.org/node/2724333#comment-11184655

This adds a theme suggestion for the Parallax block type that can be seen in the source code if you have enabled debugging:

Create themes/YOURTHEME/templates/block–bundle–parallax.html.twig file and add this in it:

1
2
3
4
5
6
7
<div class="parallax parallax--{{ elements['#id'] }}">
    <div class="parallax__bg"></div>
    <div class="parallax__content">
        <h2{{ title_attributes }}>{{ label }}</h2>
        {{ content['body']['0']['#text'] | raw}}
    </div>
</div>
parallax--{{ elements['#id'] }} Adds a unique identifier so we can add background images later.
parallax__bg} Will be used for the background image.
parallax__content Contains the block label and body.

You can use kint() for debugging:

1
drush -y en devel kint search_kint

Install Devel module and enable kint submodule: https://www.drupal.org/project/devel

Search kint adds additional features like copy path button: https://www.drupal.org/project/search_kint

1
2
{{  kint() }}
<div class="parallax parallax--{{ elements['#id'] }}">

CSS (less)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// general

.main-container {
  padding: 0px;
}
.page-header {
  padding-bottom: 0px;
}

// normal sections

.block-block-content1a31ff52-7962-454d-8df9-e5a203d1e4ca {
  text-align: center;
  padding: 10em;
  font-size: 20px;
  background-color: #204d74;
  color: #fff;
}

// parallax sections

.parallax {
  text-align: center;
  // so we can absolute position the background
  position: relative;
  overflow: hidden;
  height: 600px;
}

.parallax__bg {
  position: absolute;
  width: 100%;
  height: 140%;
}

.parallax--parallax01 .parallax__bg {
  background: url('../images/1-darker.png');
}
.parallax--parallax02 .parallax__bg  {
  background: url('../images/2-darker.png');
}

.parallax__content {
  // center content vertically
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  transform: translateY(-50%);
  color: #fff;
  h2 {
    margin: 0px;
    font-size: 30px;
  }
  p {
    font-size: 20px;
  }
}

Javascript

ScrollMagic library: https://github.com/janpaepke/ScrollMagic/

Create a js folder in the themes/YOURTHEME folder.

Download the scripts and put them in themes/YOURTHEME/js folder:

1
2
3
4
5
6
cd themes/YOURTHEME
wget https://github.com/janpaepke/ScrollMagic/zipball/master
unzip master
cp janpaepke-ScrollMagic-ae215ee/scrollmagic/minified/ScrollMagic.min.js .
cp janpaepke-ScrollMagic-ae215ee/scrollmagic/minified/plugins/animation.gsap.min.js .
cp janpaepke-ScrollMagic-ae215ee/js/lib/greensock/TweenMax.min.js .

Add this in YOURTHEME.info.yml:

1
2
libraries:
  - 'YOURTHEME/global-styling'

Add this in themes/YOURTHEME/YOURTHEME.libraries.yml:

1
2
3
4
5
6
7
8
9
10
11
12
global-styling:
  css:
    theme:
      css/style.css: {}
  js:
    js/ScrollMagic.min.js: {}
    js/animation.gsap.min.js: {}
    js/TweenMax.min.js: {}
    js/main.js: {}
  dependencies:
    - core/drupal
    - core/jquery

Add this in themes/YOURTHEME/js/main.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function ($) {
    'use strict';
    Drupal.behaviors.myBehavior = {
        attach: function (context, settings) {

            var controller = new ScrollMagic.Controller();
            var scene1 = new ScrollMagic.Scene({
                triggerElement: '.parallax--parallax01',
                triggerHook: 1,
                duration: "100%"
             })
            .setTween(TweenMax.from('.parallax--parallax01 .parallax__bg', 1, {y: '-40%', ease:Power0.easeNone}))
            .addTo(controller);
        }
    };
}(jQuery));

Clear caches and you should see the effect.

It is important to set the .parallax__bg height according to the tween y value. So in this line I have y as -40%:

1
setTween(TweenMax.from('.parallax--parallax01 .parallax__bg', 1, {y: '-40%', ease:Power0.easeNone}))

Thus I have to set:

1
2
3
4
.parallax__bg {
     
  height: 140%;
}

Note (2016.11.29) : Quick-edit module broke the effect for admin user. Quickfix: disable it.

We need a scene for each block, so you can either add another scene (just change the class name):

1
2
3
4
5
6
7
	var scene2 = new ScrollMagic.Scene({
		triggerElement: '.parallax--parallax02',
		triggerHook: 1,
		duration: "100%"
		 })
	.setTween(TweenMax.from('.parallax--parallax02 .parallax__bg', 1, {y: '-40%', ease:Power0.easeNone}))
	.addTo(controller);

Or you can make a loop:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
	(function ($) {
	    'use strict';
	    Drupal.behaviors.myBehavior = {
	        attach: function (context, settings) {

	            var controller = new ScrollMagic.Controller();

	            var blocks = [".parallax--parallax01", ".parallax--parallax02"];

	            blocks.forEach(function (block, index) {

	                var $bg = $(block).find('.parallax__bg');
	                var $content = $(block).find('.parallax__content');

	                var tl = new TimelineMax();
	                tl
	                    .from($bg, 2, {y: '-40%', ease: Power0.easeNone}, 0)
	                    .from($content, 1, {autoAlpha: 0, ease: Power0.easeNone}, 0.4)
	                ;

	                var scene = new ScrollMagic.Scene({
	                    triggerElement: block,
	                    triggerHook: 1,
	                    duration: "100%"
	                })
	                .setTween(tl)
	                .addTo(controller);
	            });
	        }
	    }
	}(jQuery));

TimelineMax allows you to define multiple tweens (transitions). In this case I also added a second tween for the content to fade it in:

1
.from($content, 1, {autoAlpha: 0, ease: Power0.easeNone}, 0.4)

Improvement ideas

Other solutions

http://keithclark.co.uk/articles/pure-css-parallax-websites/

https://www.drupal.org/project/entity_background

https://www.drupal.org/project/parallax_bg

Scrollmagic and Screensock

https://greensock.com/docs/#/HTML5/GSAP

https://github.com/janpaepke/ScrollMagic