π Create snippets
Our hero is up and running, nice! But we should create snippets in order to improve readability and avoid repeating ourselves later.
Creating the logo snippetβ
The first candidate is the logo, it's also present in the footer according to the designs, instead of copy/pasting the SVG, let's create a snippet for it and call it inside our hero:
{# All of this allows to pass `classes` and `modifiers` parameters to our snippet #}
{% set _classes = classes | default(null) %}
{% set _modifiers = modifiers | default(null) %}
{% set _attr = attr | default(null) %}
{% if _classes != null %}
{% set _classes = ' ' ~ _classes %}
{% endif %}
{% if _modifiers != null %}
{% set _classes = ' ' ~ _modifiers ~ ' ' ~ _classes %}
{% endif %}
<svg
class="{{ _classes }}"
{{ _attr }}
x="0px" y="0px" viewBox="0 0 1400 515" style="enable-background:new 0 0 1400 515;" xml:space="preserve">
<!-- S -->
<path d="M226.5,514H67.9c-37.5,0-67.4-29.9-67.4-67.4v-121c0-12.3,10-22.2,22.2-22.2h91.9c12.3,0,22.2,10,22.2,22.2v111.1h21.4 V313.3c0-16.9-14.6-31.4-32.2-31.4H61.8c-33.7,0-61.3-29.9-61.3-67.4V81.3c0-51.3,29.9-81.2,67.4-81.2h158.6 c37.5,0,67.4,29.9,67.4,67.4v94.2c0,12.3-10,22.2-22.2,22.2h-91.2c-12.3,0-22.2-10-22.2-22.2v-85h-21.4v96.5 c0,17.6,13.8,31.4,31.4,31.4h65.1c33.7,0,60.5,30.6,60.5,68.2v173.9C293.9,483.4,264,514,226.5,514z"/>
<!-- W -->
<path d="M385.1,514c-37.5,0-67.4-30.6-67.4-67.4V22.3c0-12.3,10-22.2,22.2-22.2h91.9C444,0.1,454,10,454,22.3v351.6h21.4V22.3 c0-12.3,10-22.2,22.2-22.2H585c12.3,0,22.2,10,22.2,22.2v351.6h21.4V22.3c0-12.3,10-22.2,22.2-22.2h91.9C755,0.1,765,10,765,22.3 v424.3c0,36.8-30.6,67.4-67.4,67.4h-78.1c-37.5,0-67.4-30.6-67.4-67.4v-37.5h-21.4v37.5c0,36.8-29.9,67.4-67.4,67.4H385.1z"/>
<!-- A -->
<path d="M788.2,491.8V67.5c0-37.5,30.6-67.4,67.4-67.4h159.3c36.8,0,67.4,29.9,67.4,67.4v424.3c0,12.3-10.7,22.2-23,22.2h-91.1 c-12.3,0-22.2-10-22.2-22.2V295.7h-21.4v196.1c0,12.3-10,22.2-22.2,22.2h-91.2C798.1,514,788.2,504.1,788.2,491.8z M946,218.4V76.7 h-21.4v141.7H946z"/>
<!-- G -->
<path d="M1285.3,416c-12.2,0-22.2-10-22.2-23v-87.3c0-12.3,10-22.2,22.2-22.2h91.2c12.3,0,23,10,23,22.2v140.9 c0,36.8-30.6,67.4-67.4,67.4h-159.3c-36.8,0-67.4-30.6-67.4-67.4V67.5c0-37.5,30.6-67.4,67.4-67.4h159.3c36.8,0,67.4,29.9,67.4,67.4 v172.3c0,12.3-10.7,22.2-23,22.2h-91.2c-12.2,0-22.2-10-22.2-22.2V76.7h-21.4v328.6c0,17.6,13.8,31.4,31.4,31.4h49V416H1285.3z"/>
</svg>
{% include "@snippets/logo.twig" with {
classes: 'c-hero_logo'
} only %}
When using include and embed twig tags, it's always a good idea to pass local parameters followed with the only suffix.
This prevents nested snippets to inherit parameters and cause a nightmare, especially with classes and modifiers
Analyzing the image snippetβ
This file is already added in the chapter's snapshot!
The next snippet will be used extensively accross the site, that will save us a lot of time but it requires quite a lot of parameters for all our use cases.
{# Image settings #}
{% set _src = src | default(null) %}
{% set _width = width | default(null) %}
{% set _height = height | default(null) %}
{% set _alt = alt | default(null) %}
{% set _is_figure = is_figure ?? false %}
{% set _is_lazy = is_lazy ?? true %}
{% set _tag = _is_figure ? 'figure' : 'div' %}
{# BASICS #}
{% set _classes = classes | default(null) %}
{% set _modifiers = modifiers | default(null) %}
{% set _attr = attr | default(null) %}
{% if _classes != null %}
{% set _classes = ' ' ~ _classes %}
{% endif %}
{% if _is_lazy %}
{% set _modifiers = _modifiers ~ ' -lazy-load' %}
{% endif %}
{% if _modifiers != null %}
{% set _classes = ' ' ~ _modifiers ~ ' ' ~ _classes %}
{% endif %}
{% if _src %}
<{{ _tag }} class="c-image{{ _classes }}" {{ _attr }}>
<img
class="c-image_img"
alt="{{ _alt }}"
width="{{ _width }}"
height="{{ _height }}"
src="{{ _src }}"
{% if _is_lazy %}
loading="lazy"
onload="this.classList.add('is-loaded'); this.parentNode.classList.add('is-loaded');"
{% endif %}
>
</{{ _tag }}>
{% endif %}
Oof, lots of things to decypher! The first highlighted part contains the local variables we create relatively to the passed parameters. We also use the default filter in case the data is not given! Then we find the same classes / modifiers bit of code than in the logo snippet: you'll see that in almost all our snippets.
Finally, the last highlighted section shows the markup with the variables in use.
Lazy-loadingβ
We'll have a lot of images on our page and performance wise it would be smart not to load them all at once. That's why added a lazy-loading feature to our snippet:
{# Image settings #}
{% set _src = src | default(null) %}
{% set _width = width | default(null) %}
{% set _height = height | default(null) %}
{% set _alt = alt | default(null) %}
{% set _is_figure = is_figure ?? false %}
{% set _is_lazy = is_lazy ?? true %}
{% set _tag = _is_figure ? 'figure' : 'div' %}
{# BASICS #}
{# ... #}
{% if _src %}
<{{ _tag }} class="c-image{{ _classes }}" {{ _attr }}>
<img
class="c-image_img"
alt="{{ _alt }}"
width="{{ _width }}"
height="{{ _height }}"
src="{{ _src }}"
{% if _is_lazy %}
loading="lazy"
onload="this.classList.add('is-loaded'); this.parentNode.classList.add('is-loaded');"
{% endif %}
>
</{{ _tag }}>
{% endif %}
For more informations about the loading attribute and lazy loading images: check this article out
That is-loaded class added to our element and it's parent allows us to have a small fade-in animation detailed in this snippet:
This SCSS snippet is already added in the chapter's snapshot!
.c-image {
background-color: rgba(lighten($color-darkest, 10%), 0.5); // Add a background to our container
}
.c-image_img {
width: 100%; // Always fill the width
// Handle lazy-loading fade-in
.c-image.-lazy-load & {
opacity: 0;
transition: opacity $speed $easing;
&.is-loaded {
opacity: 1;
}
}
}
Let's use our snippet in the hero now:
<header>
<h1 class="u-screen-reader-text">{{ site.title }}</h1>
<figure class="c-hero" aria-label="{{ site.hero.label }}" data-scroll data-scroll-css-progress>
<div class="c-hero_image-wrapper">
<div class="c-hero_image">
{% include "@snippets/image.twig" with {
src: site.hero.img.src,
width: site.hero.img.width,
height: site.hero.img.height,
is_lazy: false,
attr: 'data-scroll data-scroll-speed="-0.1"'
} only %}
</div>
</div>
{% include "@snippets/logo.twig" with {
classes: 'c-hero_logo'
} only %}
</figure>
</header>
This particular image being above the fold, we don't want it lazy-loaded, hence the is_lazy: false