Case studies
Scroll to reveal more
Native Communities
Talk to us4,466
viewings booked through PPC
175%
increase in organic conversions
6,121
website enquiries
@import "../../resources/scss/util/variables";
@import "../../resources/scss/util/mixins";
@import "../../resources/scss/vendor/bootstrap/vendor/rfs";
.block-homepage-hero {
--text-color: var(--white);
--hero-mask-size: 75%;
--mask-y-offset: 90%;
--mask-overlay-opacity: 0;
@include bp($md) {
--hero-mask-size: 50%;
--mask-y-offset: 75%;
}
@include bp(1100px) {
--hero-mask-size: 40%;
// --mask-y-offset: 75%;
}
@include bp(1270px) {
--hero-mask-size: 30%;
// --mask-y-offset: 75%;
}
@include bp(1560px) {
--hero-mask-size: 25%;
// --mask-y-offset: 75%;
}
@include bp(1900px) {
--hero-mask-size: 20%;
// --mask-y-offset: 75%;
}
@include padding-top(rem-calc(120));
@include padding-bottom(rem-calc(120));
margin-bottom: 0.5rem;
background-color: var(--primary);
height: calc(100vh - #{rem-calc(20)});
min-height: rem-calc(400);
@include bp($lg) {
min-height: rem-calc(930);
}
position: relative;
.hero-social-links {
position: absolute;
z-index: 10;
display: flex;
flex-direction: row;
gap: rem-calc(20);
top: unset;
bottom: rem-calc(20);
left: 50%;
transform: translateX(-50%);
@include bp($lg) {
gap: rem-calc(16);
bottom: unset;
top: rem-calc(20);
left: rem-calc(20);
transform: unset;
}
.social-icon {
width: rem-calc(24);
height: rem-calc(24);
display: block;
background-repeat: no-repeat;
background-position: center;
background-size: contain;
transition: opacity 0.3s ease;
@include bp($md) {
width: rem-calc(32);
height: rem-calc(32);
}
&:hover {
opacity: 0.7;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
&-tiktok {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' stroke-linejoin='round' stroke-miterlimit='2' clip-rule='evenodd' viewBox='0 0 64 64' id='tiktok'%3E%3Cpath d='M33 7a1 1 0 0 0-1 1v34c0 2.76-2.24 5-5 5s-5-2.24-5-5 2.24-5 5-5a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1c-8.28 0-15 6.721-15 15 0 8.28 6.72 15 15 15 8.279 0 15-6.72 15-15V25.494A16.927 16.927 0 0 0 49 27h2a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-2c-3.863 0-7-3.137-7-7V8a1 1 0 0 0-1-1zm1 2h6v1c0 4.967 4.033 9 9 9h1v6h-1c-2.731 0-5.292-.73-7.499-2.009a1 1 0 0 0-1.501.866V42c0 7.175-5.825 13-13 13s-13-5.825-13-13c0-6.838 5.292-12.45 12-12.962v6.033c-3.39.486-6 3.405-6 6.93 0 3.862 3.137 7 7 7s7-3.138 7-7z' fill='white' stroke='white' stroke-width='3'/%3E%3C/svg%3E%0A");
}
&-linkedin {
background-image: url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M16.2109 8.54297C17.8022 8.54297 19.3284 9.17511 20.4536 10.3003C21.5788 11.4255 22.2109 12.9517 22.2109 14.543V21.543H18.2109V14.543C18.2109 14.0125 18.0002 13.5038 17.6252 13.1288C17.2501 12.7537 16.7414 12.543 16.2109 12.543C15.6805 12.543 15.1718 12.7537 14.7967 13.1288C14.4217 13.5038 14.2109 14.0125 14.2109 14.543V21.543H10.2109V14.543C10.2109 12.9517 10.8431 11.4255 11.9683 10.3003C13.0935 9.17511 14.6196 8.54297 16.2109 8.54297Z' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M6.21094 9.54297H2.21094V21.543H6.21094V9.54297Z' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M4.21094 6.54297C5.31551 6.54297 6.21094 5.64754 6.21094 4.54297C6.21094 3.4384 5.31551 2.54297 4.21094 2.54297C3.10637 2.54297 2.21094 3.4384 2.21094 4.54297C2.21094 5.64754 3.10637 6.54297 4.21094 6.54297Z' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
}
&-instagram {
background-image: url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M17.2109 2.54297H7.21094C4.44951 2.54297 2.21094 4.78154 2.21094 7.54297V17.543C2.21094 20.3044 4.44951 22.543 7.21094 22.543H17.2109C19.9724 22.543 22.2109 20.3044 22.2109 17.543V7.54297C22.2109 4.78154 19.9724 2.54297 17.2109 2.54297Z' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M16.2106 11.9133C16.3341 12.7455 16.1919 13.5955 15.8044 14.3423C15.4169 15.0891 14.8038 15.6947 14.0523 16.0729C13.3008 16.4512 12.4491 16.5829 11.6184 16.4492C10.7878 16.3155 10.0204 15.9234 9.42548 15.3284C8.83056 14.7335 8.43838 13.9661 8.30471 13.1355C8.17105 12.3048 8.30271 11.4532 8.68097 10.7016C9.05923 9.95012 9.66483 9.33701 10.4116 8.94951C11.1584 8.56201 12.0084 8.41986 12.8406 8.54327C13.6896 8.66915 14.4755 9.06473 15.0823 9.67158C15.6892 10.2784 16.0848 11.0643 16.2106 11.9133Z' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M17.7109 7.04297H17.7209' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
}
}
}
.initial-content {
padding-top: 4rem;
.col-12 {
text-align: center;
.btn {
@include fluid-type(16, 26);
padding: rem-calc(17 30);
}
}
}
.container {
position: relative;
z-index: 5;
&.mask-container {
&.inactive {
pointer-events: none;
}
}
}
> picture {
border-radius: rem-calc(24);
overflow: hidden;
}
.pill {
width: rem-calc(416);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: absolute;
top: var(--mask-y-offset);
left: 50%;
z-index: 10;
transform: translate3d(-50%, calc(-1.25 * var(--mask-y-offset)), 0);
&-title {
//
}
&-subtitle {
margin-bottom: 0;
}
}
.alt-container {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
border-radius: rem-calc(24);
mask: url("data:image/svg+xml,%3Csvg width='416' height='196' viewBox='0 0 416 196' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 98C0 43.8761 43.8761 0 98 0H318C372.124 0 416 43.8761 416 98C416 152.124 372.124 196 318 196H98C43.8761 196 0 152.124 0 98Z' fill='white'/%3E%3C/svg%3E%0A");
mask-repeat: no-repeat;
mask-position: center var(--mask-y-offset);
mask-size: 10%;
mask-size: var(--hero-mask-size);
.alt-hero {
height: 100%;
position: relative;
.container,
.row {
height: 100%;
}
}
.container {
position: relative;
z-index: 2;
}
.alt-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.content-col {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: rem-calc(24);
padding-bottom: rem-calc(40);
}
.content-inner {
margin-top: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: rem-calc(24);
}
}
.stats {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: rem-calc(24);
margin-top: auto;
margin-bottom: 2rem;
@include bp($lg) {
margin-bottom: 0;
}
.stat {
max-width: rem-calc(140);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 0;
p {
margin-bottom: 0;
&.stat-number {
line-height: 1;
}
&.stat-description {
font-weight: 400;
}
}
}
}
picture {
z-index: 1;
&:before {
width: 100%;
height: 100%;
content: '';
background-color: black;
position: absolute;
inset: 0;
z-index: 1;
opacity: var(--mask-overlay-opacity);
}
}
}
.alt-content {
opacity: 0;
}
.initial-content {
height: 100%;
}
.partner-logos {
position: absolute;
width: 100%;
padding: 0 1.5rem;
}
@media (min-height: 820px) {
.partner-logos {
top: 50%;
}
}
@media (min-width: 1200px) {
.partner-logos {
top: 72%;
}
}
@media (min-width: 768px) {
.block-homepage-hero {
--mask-y-offset: 85%
}
}
@media (min-width: 1024px) {
.block-homepage-hero {
--mask-y-offset: 77%
}
}
@media (min-width: 1200px) {
.block-homepage-hero {
--mask-y-offset: 75%
}
}
.partner-logos .logo {
padding: 0.5rem 0;
}
.partner-logos .logo img {
max-height: 35px;
width: auto;
margin-top: 1rem;
@media (min-width: 1024px) {
margin-top: 0;
max-height: 50px;
}
}
.alt-container .alt-content .content-inner {
margin-top: 5%;
}
.alt-container .stats {
margin-top: 3rem;
}
.alt-container .stats {
align-items: flex-start;
}
}
class HomepageHero {
/**
* Create and initialise objects of this class
* @param {object} block
*/
constructor(block) {
this.block = block;
this.scrollTriggers = [];
this.animation = null;
this.baseMaskPx = 416; // base mask size in pixels used to derive start percentage
const debounce = (func, wait) => {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
};
const debouncedInit = debounce(() => {
this.init();
}, 250);
window.addEventListener('resize', debouncedInit);
this.init();
}
/**
* Clean up all ScrollTrigger instances and animations
*/
cleanup() {
// Kill all ScrollTrigger instances
this.scrollTriggers.forEach(trigger => {
trigger.kill();
});
this.scrollTriggers = [];
// Kill the animation timeline if it exists
if (this.animation) {
this.animation.kill();
this.animation = null;
}
// Remove inline CSS variable so it can be recalculated cleanly
if (this.block && this.block.style) {
this.block.style.removeProperty('--hero-mask-size');
}
// Refresh ScrollTrigger to recalculate positions
ScrollTrigger.refresh();
}
init() {
// Clean up any existing ScrollTriggers and animations before reinitializing
this.cleanup();
const pill = this.block.querySelector('.pill');
const initialContent = this.block.querySelector('.initial-content');
const altContent = this.block.querySelector('.alt-content');
const maskContainer = this.block.querySelector('.mask-container');
// Reset styles that might have been modified
if (altContent) {
altContent.style.opacity = '';
}
if (maskContainer) {
maskContainer.classList.remove('inactive');
}
// Compute and set initial mask size based on viewport width
const startMaskPercent = Math.max(0, Math.min(75, (this.baseMaskPx / window.innerWidth) * 100));
this.block.style.setProperty('--hero-mask-size', `${startMaskPercent}%`);
const firstScrollTrigger = ScrollTrigger.create({
trigger: initialContent,
start: 'top top',
end: 'bottom top',
onEnter: () => {
if (altContent) {
altContent.style.opacity = 1;
}
}
});
this.scrollTriggers.push(firstScrollTrigger);
// scrolltrigger, pin the block, on scroll, animate the --mask-size to 160%
this.animation = gsap.timeline({
paused: true,
});
this.animation.to(initialContent, {
autoAlpha: 0,
duration: 0.5,
ease: 'power1.inOut',
}, 0);
this.animation.to(pill, {
autoAlpha: 0,
duration: 0.5,
ease: 'power1.inOut',
}, 0);
this.animation.add(() => {
if (maskContainer) {
maskContainer.classList.toggle('inactive');
}
});
let maxMaskSize = 400;
if(window.innerWidth >= 768) {
maxMaskSize = 300;
}
if(window.innerWidth >= 992) {
maxMaskSize = 220;
}
// Animate from current --hero-mask-size value to the computed end size
this.animation.to(this.block, {
'--hero-mask-size': `${maxMaskSize}%`,
duration: 0.5,
ease: 'power1.inOut',
}, '-=50%');
this.animation.to(this.block, {
'--mask-overlay-opacity': 0.7,
duration: 0.5,
ease: 'power1.inOut',
}, '<50%');
this.animation.fromTo(altContent, {
autoAlpha: 0,
}, {
autoAlpha: 1,
duration: 0.5,
ease: 'power1.inOut',
}, '<50%');
const secondScrollTrigger = ScrollTrigger.create({
trigger: this.block,
start: 'top 10px',
end: 'bottom top',
pin: true,
pinSpacing: true,
animation: this.animation,
scrub: 0.5,
refreshPriority: 1,
});
this.scrollTriggers.push(secondScrollTrigger);
requestAnimationFrame(() => {
ScrollTrigger.refresh();
});
}
}
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.block-homepage-hero').forEach( block => new HomepageHero(block) );
});
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "strategiq/homepage-hero",
"title": "Homepage hero",
"description": "Block to be used as a template",
"category": "strategiq",
"icon": "strategiq",
"acf": {
"mode": "preview",
"renderTemplate": "block-homepage-hero.php"
},
"supports": {
"anchor": true,
"align": false,
"color": {
"background": false,
"text": false,
"gradients": false
},
"spacing": {
"padding": [],
"margin": []
}
},
"example": {
"attributes": {
"mode": "preview",
"data": {
"heading_type": "h2",
"heading_text": "Example - Example",
"content": "This is some example content to represent what the content will look like"
}
}
},
"style": "file:../../assets/css/homepage-hero/block-homepage-hero.css"
}

