It's unusual, but I have a client who would like to change the primary logo on scroll. One logo at the top, a second logo on scroll.
I have managed to implement the visible change of logo through css by using an image and then on scroll hiding the image and using a ::before pseudo class (the second logo is text based).
The problem however is I need to change the url in the menu php file based on the class as the two logos need to go to seperate URLS.
Unfortunately I do not know how to write php.
I have found the relevant php file and have tried editing it to:
$logoDiv = '<a href="https://www.link1.com" target="_blank" class="navbar-brand"' . $data_padding_shrink . ' data-minheight="'.(($LOGO->logo_min == "") ? "20" : esc_attr($LOGO->logo_min)).'">';
$logoDiv = '<a href="https://www.www.link2.com" target="_blank" class=".window-scrolled"' . $data_padding_shrink . ' data-minheight="'.(($LOGO->logo_min == "") ? "20" : esc_attr($LOGO->logo_min)).'">';
This does not work and I think it may be more of an 'if/else' statement but I do not now how to complete it.
Edit: So to clarify, I am trying to work out how to change an href destination for an image on scroll. For clarity, I guess you could think of it as the same image, as one is a psuedo on the other.
Any help would be great.
Edit #2 The php from the theme files that outputs the logo is this
$logoDiv = '<a href="'.esc_url( home_url( get_current_blog_id(), '/' ) ).'" class="navbar-brand"' . $data_padding_shrink . ' data-minheight="'.(($LOGO->logo_min == "") ? "20" : esc_attr($LOGO->logo_min)).'">';
$logoDiv = '<a href="https:url-1.com" target="_blank" class="navbar-brand"' . $data_padding_shrink . ' data-minheight="'.(($LOGO->logo_min == "") ? "20" : esc_attr($LOGO->logo_min)).'">';
I am hiding the image on scroll but showing a pseudo class with text content (the second logo I need to show is actually just text) - so it behaves like one element. I either need to change the url on scroll OR, find a way to add php to add 2 logos, and then hide each one at the appropriate scroll points.
Currently this is how I change the logo from an image to text:
.logo-image.logo-skinnable img {
opacity: 1;
transition: opacity 900ms;
}
.window-scrolled .logo-image.logo-skinnable img {
opacity: 0;
transition: opacity 900ms;
}
.logo-image.logo-skinnable::before {
font-size: 29px !important;
font-family: "Poppins";
content: 'word logo';
opacity: 0;
transition: opacity 700ms;
position: absolute;
top: 38px;
}
You can use the following code in the page to change the image.
$(document).ready(function(){
$( window ).scroll(function() {
//change image css in here when scrolling
if ($(window).scrollTop()==0) {
//here you can set the initial logo when the screen comes back to the top
}
});
});
The answer demonstrates how to accomplish the desired end-result from the OPs requirements:
I either need to change the url on scroll OR, find a way to add php to add 2 logos, and then hide each one at the appropriate scroll points.
URL is perceived to be the anchor link (<a href=""/>
), as the OP has proclaimed that the logo image url is not desired to be changed.
As per my comment, I suggest rendering both simultaneously on the page and use a css rule to hide the second logo using display:none
. This will make it not visible on initial load. Then you can use jQuery to track scroll position and swap the css rules between the two logo elements, hiding the first and subsequently displaying the second. Alternatively you may also use absolute positioning, z-index and opacity, as desired to achieve a fading effect of the logos transitioning during scroll.
Method A: find a way to add php to add 2 logos, and then hide each one at the appropriate scroll points
You should be able to render both of the logos in the template, by combining the elements in your PHP $logoDiv
variable.
$logoDiv = '<a href="https:url-1.com" target="_blank" class="navbar-brand"' . $data_padding_shrink . ' data-minheight="'.(($LOGO->logo_min == "") ? "20" : esc_attr($LOGO->logo_min)).'">Logo Text</a>
<a href="'.esc_url( home_url( get_current_blog_id(), '/' ) ).'" class="navbar-brand"' . $data_padding_shrink . ' data-minheight="'.(($LOGO->logo_min == "") ? "20" : esc_attr($LOGO->logo_min)).'">';
This approach has the added benefit of being pre-rendered by the browser, preventing a delay for slower systems, when the logo element transitions occur.
jQuery(function($) { //same as $(document).ready()
var logos = $('.scroll-logo');
$(window).on('scroll', function(e) {
if ($(this).scrollTop() === 0) {
$(logos[0]).addClass('hidden');
$(logos[1]).removeClass('hidden');
} else {
$(logos[1]).addClass('hidden');
$(logos[0]).removeClass('hidden');
}
});
});
.scroll-logo.hidden {
display: none;
}
/* below rules are for demo purposes only */
div {
position: fixed;
}
body{
height: 8000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div>
<!-- <?php echo $logoDiv; ?> -->
<a href="https:url-1.com" class="scroll-logo hidden">
Logo Text
</a>
<a href="//chrome.google.com" class="scroll-logo">
<img src="//www.google.com/chrome/static/images/chrome-logo.svg" alt="Google Chrome"/>
</a>
</div>
Since as you say, you want to change the href attribute of an element, a similar scroll technique can be used to alter element attributes as well. Allowing you to use a data
attribute in order to specify the URL to change to.
Method B: change the url on scroll (using the data-url
attribute)
$logoDiv = '<a href="'.esc_url( home_url( get_current_blog_id(), '/' ) ).'" class="navbar-brand"' . $data_padding_shrink . ' data-minheight="'.(($LOGO->logo_min == "") ? "20" : esc_attr($LOGO->logo_min)).'" data-url="https:url-1.com">';
jQuery(function($) { //same as $(document).ready()
var logo = $('[data-url]');
var newHref = logo.data('url');
var originalHref = logo.attr('href');
$(window).on('scroll', function(e) {
if ($(this).scrollTop() === 0) {
logo.attr('href', originalHref)
.removeClass('hide_logo');
} else {
logo.attr('href', newHref)
.addClass('hide_logo');
}
});
});
a.hide_logo img {
display: none;
}
a.hide_logo:before {
content: "Logo Text";
}
/* below is for demo purposes only */
div {
position: fixed;
}
body {
height: 8000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div>
<!-- <?php echo $logoDiv; ?> -->
<a href="//chrome.google.com" data-url="https:url-1.com">
<img src="//www.google.com/chrome/static/images/chrome-logo.svg" alt="Google Chrome"/>
</a>
</div>
Method B + Scroll-Spy class
To run as a scroll-spy, listening for the class window-scrolled
instead, you simply need to use hasClass
instead of checking the position of scrollTop
. Change the logo.hasClass
to the appropriate element that has the class added to it.
jQuery(function($) { //same as $(document).ready()
var logo = $('[data-url]');
var newHref = logo.data('url');
var originalHref = logo.attr('href');
var scrollSpy = null;
$(window).on('scroll', function(e) {
if (null !== scrollSpy) {
//cancel previous delay
window.clearTimeout(scrollSpy);
}
//delay scrollSpy to ensure class is not added after checking
scrollSpy = window.setTimeout(function() {
if (!logo.hasClass('window-scrolled')) {
logo.attr('href', originalHref);
} else {
logo.attr('href', newHref);
}
}, 250); //adjust timeout as desired
});
//--- demo purposes only (DO NOT USE BELOW) ---
$(window).on('scroll', function(e) {
if ($(this).scrollTop() === 0) {
logo.removeClass('window-scrolled');
} else {
logo.addClass('window-scrolled');
}
});
});
a.window-scrolled img {
display: none;
}
a.window-scrolled:before {
content: "Logo Text";
}
/* below is for demo purposes only */
div {
position: fixed;
}
body {
height: 8000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div>
<!-- <?php echo $logoDiv; ?> -->
<a href="//chrome.google.com" data-url="https:url-1.com">
<img src="//www.google.com/chrome/static/images/chrome-logo.svg" alt="Google Chrome"/>
</a>
</div>
Alternatively you can also use $('.window-scrolled').length === 0
to determine if any element has the class, or specify a desired element parent of window-scrolled
like so $('[selector] .window-scrolled')
(replace [selector] with the desired parent element selector ie. div.wrapper
).
</div>