Site logo

Archived topic

Zoom effect on Header Element

27 replies · Started by Samuel on October 26, 2021

Viewing posts 16–28 of 28

Not sure what the issue is... but if you want a different 'style' for mobile and desktop then i would probably use this for the script:

var pagehero = document.querySelector('.page-hero');
setTimeout(function() {
    pagehero.classList.add('animate-hero');
}, 2000 );

This will add the animate-hero class to the page-hero after a 2000 ms delay.

Then you can add the styles using CSS instead of writing them in the JS.

.page-hero.animate-hero {
    // your desktop  styles here
}

@media(max-width: 768px) {
    .page-hero.animate-hero {
        // your mobile  styles here
    } 
}

Sorry but I'm lost !

To resume : I'm trying to add a zoom effect on hero header.

Elvin proposed me to add this script:

<script>
var pagehero = document.querySelector('.page-hero');

function hero_animation(){
		pagehero.style.backgroundSize = 100+'%';
		pagehero.style.opacity = '1';
}
	
	document.onload = hero_animation();
</script>

And then add this CSS:

.page-hero{
	 transition: background-size 1s cubic-bezier(0.785, 0.135, 0.15, 0.86), opacity 1s ease-out 0.2s !important;
	opacity: 0;
	background-size: 150%;
}

It's working on desktop but not on mobile : header image on mobile does not fill the entire header container (see in private info)

And now sorry but I'm lost and I don't know what to do exactly. Do I have to delete Elvin's solution and replace it by yours ?

To add something, I tried to play with JS and CSS and it's possible to have a good result on mobile changing % like this :

JS
pagehero.style.backgroundSize = 200+'%';

CSS
background-size: 250%;

This is why I'm trying to find a way to have 2 different setting on JS depending on devices and I don't know how to do it.

David's suggestion was to delay the execution of the code so the effect is noticable.

I believe this was suggested because the script runs too fast that we fail to perceive the animation actually happening.

This suggestion works in tandem w/ my suggestion w/ a bit of editing.

<script>
var pagehero = document.querySelector('.page-hero');

function hero_animation(){
	setTimeout(function() {
    pagehero.classList.add('animate-hero');
}, 2000 );
}
	
	document.onload = hero_animation();
</script>

And then you apply the effects on the CSS instead of adding it on JS:


/* keeping the transition effect and default sizing */
.page-hero{
	 transition: background-size 1s cubic-bezier(0.785, 0.135, 0.15, 0.86), opacity 1s ease-out 0.2s !important;
	opacity: 0;
	background-size: 100%;
	background-position: center center;
}

/* size change on desktop */
.page-hero.animate-hero {
    background-size: 200%;
}

/* size change on mobile */
@media(max-width: 768px) {
    .page-hero.animate-hero {
        background-size: 250%;
    } 
}

But then again, background-size animation is limiting because the starting position can't be controlled unlike when you do it like how your reference site does it with scale.

Another alternative is by trying to completely replicate how your reference site did its animation:

To do that, we'll have to insert the dynamic featured image itself first.

We can do that with a shortcode.

Here's a php snippet to create the shortcode:

add_shortcode( 'featured_image', function( ) {
ob_start();
	global $post;
	$featured_img_url = get_the_post_thumbnail_url($post->id);

	echo '<img class="page-hero-featured-image" src="'.$featured_img_url.'" alt="'.get_the_title($post->id).'"/>';

return ob_get_clean();
});

with this, you can use [featured_image] shortcode on the Header element to add the image.

Now we add the script.

Here's the script to for adding animation selector to the page hero.

<script>
/*!
 * Determine if an element is in the viewport
 * (c) 2017 Chris Ferdinandi, MIT License, https://gomakethings.com
 * @param  {Node}    elem The element
 * @return {Boolean}      Returns true if element is in the viewport
 */
var isInViewport = function (elem) {
	var distance = elem.getBoundingClientRect();
	return (
		distance.top >= 0 &&
		distance.left >= 0 &&
		distance.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
		distance.right <= (window.innerWidth || document.documentElement.clientWidth)
	);
};

var pagehero = document.getElementsByClassName('page-hero')[0];

function hero_animation(){
	if( isInViewport(pagehero) ){
		if(pagehero.classList.contains('animate-hero')){
			return;
		} else {
					setTimeout(function() {
						pagehero.classList.add('animate-hero');
					}, 500 );
		} 
	} else {
			console.log('not in view port');
			pagehero.classList.remove('animate-hero');
	}
}
	
window.addEventListener('load',(event) => {
  hero_animation();
})
	
window.addEventListener('scroll',(event) => {
  hero_animation();
})

</script>

And then we add the CSS for the actual animation:

.page-hero {
    position: relative;
    overflow: hidden;
	transition: opacity 1s ease-out 0.2s !important;
	opacity: 0;
}

.page-hero img.page-hero-featured-image {
	transition: all 1s cubic-bezier(0.785, 0.135, 0.15, 0.86);
    position: absolute;
height:auto;
	width: 100%;
    top:50%;
    left:50%;
	z-index: -1;
	transform: translate(-50%,-50%) scale(1);
}

@media (max-width:768px){
	.page-hero img.page-hero-featured-image{
		height: 100%;
		width: auto;
		object-fit: cover;
	}
}

.page-hero.animate-hero{
	opacity: 1;
}

.page-hero.animate-hero img.page-hero-featured-image{
	opacity: 1;
	transform: translate(-50%,-50%) scale(1.3);
}

Here's a demo page - https://dev-generate-press.pantheonsite.io/illo-quia-ut-voluptate-eum-ratione-omnis/

Hi Elvin, thanks for your explanation.

So, I tried David's solution but it's breaking the header (no image displaying). Maybe I miss something.

Then I tried your solution and it's half working, there is no zoom effect, only fade in fade out effect.

Then I tried your solution and it’s half working, there is no zoom effect, only fade in fade out effect.

You'll have to remove the background image on the Header element and use the shortcode I've provided to add the image to replace the background.

You’ll have to remove the background image on the Header element and use the shortcode I’ve provided to add the image to replace the background.

How do I have to use the [featured_image] shortcode ?

I tried using it in a Hook set to generate_header but it's breaking everything.

Thanks Elvin, it's working ! :)
Is it possible to display the image without the first blank part ? When scrolling the image disappears is it normal ?

I've coded it to restart its animation when the page-hero re-enters the viewport similar to the reference site. (the animation restarts when you scroll back up to it.)

Do you have any particular animation behavior in mind? ( in context of page-hero re-entry to viewport when you scroll back up.)

Would it be possible, like on reference site, to have both image staying in place and zoom animation restarting when you scroll back up ? There is no fade out in reference site animation.

I see.

Let's modify the JS a bit.

Try this instead:

<script>
/*!
 * Determine if an element is in the viewport
 * (c) 2017 Chris Ferdinandi, MIT License, https://gomakethings.com
 * @param  {Node}    elem The element
 * @return {Boolean}      Returns true if element is in the viewport
 */
var isInViewport = function (elem) {
	var distance = elem.getBoundingClientRect();
	return (
		distance.top >= 0 &&
		distance.left >= 0 &&
		distance.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
		distance.right <= (window.innerWidth || document.documentElement.clientWidth)
	);
};

var pagehero = document.getElementsByClassName('page-hero')[0];

function hero_animation(){
	if( isInViewport(pagehero) ){
		if(pagehero.classList.contains('animate-hero')){
			return;
		} else {
					setTimeout(function() {
						pagehero.classList.add('animate-hero');
                        pagehero.classList.add('full-opaque');
					}, 500 );
		} 
	} else {
			console.log('not in view port');
			pagehero.classList.remove('animate-hero');
	}
}
	
window.addEventListener('load',(event) => {
  hero_animation();
})
	
window.addEventListener('scroll',(event) => {
  hero_animation();
})

</script>

And modify the CSS as well to this:

.page-hero {
    position: relative;
    overflow: hidden;
	transition: opacity 1s ease-out 0.2s !important;
	opacity: 0;
}

.page-hero img.page-hero-featured-image {
	transition: all 1s cubic-bezier(0.785, 0.135, 0.15, 0.86);
    position: absolute;
    height:auto;
	width: 100%;
    top:50%;
    left:50%;
	z-index: -1;
	transform: translate(-50%,-50%) scale(1);
}

@media (max-width:768px){
	.page-hero img.page-hero-featured-image{
		height: 100%;
		width: auto;
		object-fit: cover;
	}
}

.page-hero.full-opaque{
	opacity: 1;
}

.page-hero.animate-hero img.page-hero-featured-image{
	transform: translate(-50%,-50%) scale(1.3);
}

Thanks a lot Elvin ! It's working great, but first it's displaying blank image and then effect is starting, would you have a trick to remove the blank part ?

This archived topic is closed to new replies.