Yesterday I managed to realize a shrink (/resizing) effect on header on scrolling, in may main website.
But this morning I noticed that the used code is not enough responsive: with some resolution it is very ugly. Moreover in small screens, at some point of scrolling, the header is no more fixed/sticky.
Could you help me to get a responsive code?
I just adjusted it (not yet perfect, but somehow better): any feedback would be welcomed.
When you click the menu on small screen all the dark gray list items overflow the lighter gray ul wrapper. You need to change the width of the ul to auto and not 100%.
e.g.
In here:
@media screen and (max-width: 600px) {
#menu {
/* width: 100%;*/
width:auto;
}
}
The text on that mobile menu is rather small and difficult to touch one item without selecting something else.
Done! Thank you very much!
It remains a further problem: a flickering effect when the scrolling is in a given point.
I have found on internet many cases of flickering on scrolling shrinking header, in particular when header is sticky
and not fixed
.
I don’t remember exactly why I choose sticky
instead of fixed
, but there is a quite strong reason…
With Falkon flickering is very big, in Firefox less, but I’d like, if possible, to fix this.
This is a known problem with the intersection observer and position:sticky. The top pixel seems to get rounded up and down and triggers a continuous loop that flickers.
The best way to avoid this is not to shrink the size of the sticky element itself but shrink the size of the contents.
This is just proof of concept but requires a lot of over-rides.
The reason position:sticky is used is because if you used position:fixed then the content would slide under it initially. Also if you add the position:fixed dynamically then the whole page jumps up by the height of the header and looks really bad.
Thank you very much. In your code th shrink effect is not applied to the logo…
So I have simplified your code (I had read something similar on the web), in this way:
css
#intestazione {
margin: 0;
background: url(multimedia/img/logo/cezanne.jpg) top left no-repeat;
background-size: cover; /* Changed to cover for better responsiveness */
height: auto; /* Set to auto for better responsiveness */
max-height: 25vh;
box-shadow: 0 8px 6px -6px black;
position: sticky;
top: 0;
z-index: 4;
/* transition: height 0.8s ease-in-out; */
display: grid;
align-items: center;
padding: 10px; /* Add padding for spacing */
}
#inner-header {/* to avoid flickering on scroll */
transition: height 0.8s ease-in-out;
/* height: 100%; */
}
/*#intestazione.scrolled*/ #inner-header.scrolled{
height: auto; /* Allow height to adjust */
min-height: 3vh;
}
html
<header id="intestazione" role="banner">
<div id="inner-header"><!-- inner-header BEGIN -->
...
</div>
</header>
js
This is the modified js
document.addEventListener('DOMContentLoaded', () => {
window.addEventListener('scroll', () => {
console.log('Scroll event detected');
const header = document.querySelector('#inner-header');
if (header) {
console.log('Scroll position:', window.scrollY);
if (window.scrollY > 50) {
header.classList.add('scrolled');
console.log('Added scrolled class');
} else {
header.classList.remove('scrolled');
console.log('Removed scrolled class');
}
} else {
console.error('Element with ID "inner-header" not found');
}
});
});
But in this way I shrink the text (logo) but not the whole header…
Better modifying also this:
@media screen and (min-width: 1024px) {
#inner-header {min-height: 140px;}
I modified my code in this way:
html
as above:
<header id="intestazione" role="banner">
<div id="inner-header"><!-- inner-header BEGIN -->
...
</div>
</header>
css
#intestazione {
margin: 0;
background: url(multimedia/img/logo/cezanne.jpg) top left no-repeat;
background-size: cover; /* Changed to cover for better responsiveness */
height: auto; /* Set to auto for better responsiveness */
max-height: 25vh;
box-shadow: 0 8px 6px -6px black;
position: sticky;
top: 0;
z-index: 4;
/* transition: height 0.8s ease-in-out; */
display: grid;
align-items: center;
padding: 10px; /* Add padding for spacing */
}
#inner-header {/* to avoid flickering on scroll */
transition: height 1.2s ease-in-out;
/* height: 100%; */
}
/*#intestazione.scrolled*/ #inner-header.scrolled{
height: auto; /* Allow height to adjust */
min-height: 3vh;
}
.logo {
transition: font-size 1.2s ease;
}
js
document.addEventListener('DOMContentLoaded', () => {
let timeout;
window.addEventListener('scroll', () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
const header = document.querySelector('#inner-header');
if (header) {
if (window.scrollY > 50) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
} else {
console.error('Element with ID "inner-header" not found');
}
}, 100); // Adjust debounce time as needed
});
});
Flickering in this way is avoided. But The text (in .logo) change has a delay (header is resizing faster).
That behaves awfully on my mobile and very jumpy. It’s not as smooth as the demo version I gave above.
I’ll have a look later when I get back to my desktop
Indeed. But at least no flickering…
Its flickering very badly for me and continually jumping.
I haven’t got a video but here’s the same screen jumping up and down continuously.
Un fortunately your css and html changes break my original demo so I’ll have to debug again from scratch. It might take me a while
I’m not having much luck with this concerning the jumping as that is a known problem with position:sticky and shrinking the header. It triggers a continuous loop at a certain height causing the flicker.
You can stop it using overflow:anchor:none
which stops the jumping but may have other drawbacks.
body {
overflow-anchor: none;
}
Try it and see if it helps.
Your other issues are probably just timing issues in your transitions although you do seem to be using some animation library classes on that text.
For chrome you can do something similar without JS but probably is not as flexible as you can’t use the class to change everything.
Thank you. I will try to follow your suggestion.
As a minimum example I have put up a demo here:
From research it seems impossible to shrink a sticky header without the endless jumping at the sticky point unless you either:
a) fix the height of the sticky header and shrink the inner content instead. This of course defeats all responsiveness in one go and creates a magic number nightmare.
or
b) use the overflow-anchor:none as in my demo. This has drawbacks in the behaviour of content that loads later on but is probably not an issue for most people.
As an aside there is no jumping if the element is made position:fixed instead of position:sticky but then of course it sits over the initial content and you are back to magic number or js fixes to overcome this.
In light of the above my css only demo would be my preferred solution although it only works for modern browsers but will eventually work for all.
You could use the @supports rule for modern browsers and let all others just get a non resizing header.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.