I tried a lot of code snippets to do this, but nothing worked.
In CSS I used this to make the menu floating on mobile:
#media screen and (max-width: 900px){
header#s5_header_area1 {
position: sticky;
top: 0;
z-index: 2;
}
}
It's working, but I want to give the menu a little transparency after I start to scroll down. How can I do this?
When the user has scrolled it will apply a class .menu--alt to the menu otherwise it will just have the class .menu.
Updating the CSS should do what you want. Looing back at your question you will want to edit the styles for header#s5_header_area1 using javascript - a simple refactor of the example below will do it.
const menu = document.querySelector(".menu");
document.addEventListener("scroll", () => {
// use document.documentElement for chrome, firefox, ie or opera
// and document.body for safari since that's where overflow is set in those browsers
if (document.documentElement.scrollTop > 0)
menu.classList.add("menu--alt");
else
menu.classList.remove("menu--alt");
});
.content {
height: 2000px;
background: pink;
}
.menu {
background-color: #000;
color: #fff;
position: fixed;
top: 0;
left: 0;
padding: 20px;
box-sizing: border-box;
}
.menu--alt {
opacity: 0.5;
}
<div class="menu">
menu (not clickable) - scroll to see opacity change
</div>
<div class="content">
hi there
</div>
Related
I have a website header which appears full-size and is positioned absolutely such that it allows the underlying content to be partially visible 'behind' it. It should scroll off screen as the user scrolls down the page.
When the user hits a certain scroll point, 400px down the page, the header should re-appear in a fixed position at the top of the viewport and should be a smaller/minimal version. To facilitate this in a performant way (i.e not using window scroll events) I'm using an invisible marker and setting an IntersectionObserver on it to set a class on the body when the marker has been hit.
This works nicely, although please run this in a full-size viewer as the small inline version doesn't work so well (something I will address, but not part of the question):
let waypoint = new IntersectionObserver(entries => {
document.body.classList.toggle('waypoint-passed', !entries[0].isIntersecting);
});
waypoint.observe(document.querySelector('.waypoint'));
* {
margin: 0;
padding: 0;
}
.header {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 10;
background-color: rgba(0,0,255,0.5);
color: #fff;
}
.header__full {
padding: 100px 0;
}
.header__min {
padding: 20px 0;
display: none;
}
body.waypoint-passed .header {
position: fixed;
}
body.waypoint-passed .header__full {
display: none;
}
body.waypoint-passed .header__min {
display: block;
}
.section {
aspect-ratio: 4 / 3;
background-color: #ddd;
color: #333;
display: grid;
place-items: center;
}
.section + .section {
margin-top: 10px;
}
.trigger-indicator {
border-top: 1px dashed red;
color: red;
position: absolute;
top: 400px;
right: 0;
left: 0;
}
.waypoint {
position: absolute;
top: 400px;
width: 0;
height: 0;
}
<header class="header">
<div class="header__full">Full Header</div>
<div class="header__min">Minimal Header</div>
</header>
<section class="section">Section 1</section>
<section class="section">Section 2</section>
<section class="section">Section 3</section>
<section class="section">Section 4</section>
<div class="trigger-indicator">Trigger Point</div>
<div class="waypoint"></div>
However, the last requirement is proving tricky! I need the minimal version of the header to slide down into position when the trigger point has been passed as the user scrolls down the page and then slide back up when the trigger point has been passed when the visitor scrolls back up.
The most performant way to do the animation is via CSS transform: translateY() so I'd like to implement it like that, but I just cannot figure out a nice way to trigger the slide down/up transitions.
I'm creating a page where the navigation bar should only appear after scrolling a few thousand pixels. But when I refresh the browser, the navigation bar appears first and disappears as soon as I start scrolling. After that everything works as intended.
How can I make the bar hidden when the page is refreshed?
Here the JS code I have used:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){$(window).scroll(function(){
if( $(this).scrollTop() > 4000){
$('#navigation').fadeIn( "slow", "linear" )
} else {
$('#navigation').fadeOut( "slow", "linear" )
}
})
})
</script>
Here the CSS code I have used:
nav ul {
position:fixed;
list-style: none;
width: 1100px;
height: 40px;
margin: 30px 222px auto;
padding: 20px 20px 20px 20px;
background-color: #798c39;
text-align: center;
}
Maybe try another way. Instead of doing everything with jquery I recommend using pure javascript and css. This method is more efficient and works better.
const nav = document.querySelector('#navigation');
function showNav(){
nav.classList.add('show');
}
function hidewNav(){
nav.classList.remove('show');
}
var currPos = window.scrollY;
document.addEventListener('scroll', () => {
if (window.scrollY < currPos) {
//scroll up
hidewNav();
} else {
//scroll down
showNav();
}
currPos = window.scrollY;
});
body {
margin: 0;
height: 2000px;
margin-top: 100px;
}
nav {
position: fixed;
list-style: none;
width: 100%;
height: 70px;
top: 0;
margin: 0;
background-color: #798c39;
text-align: center;
transform: translateY(-100px);
transition: 0.3s;
}
.show {
transform: translateY(0);
}
<html>
<head>
</head>
<body>
<header>
<nav id="navigation">
<ul>
</ul>
</nav>
</header>
<main>
</main>
</body>
</html>
It depends on whether the navbar's space is to be reserved for it or not on load.
I suspect it is given the JS you have shown, in which case you need to ensure it has opacity: 0 on load.
The only alteration to your code would be in the stylesheet add:
nav {
opacity: 0;
}
This is assuming that the fadeIn/fadeOut keyframes just alter opacity. It they alter some dimension as well, for example, that would also need catering for. Perhaps you could show us those keyframes so we can check?
For a small project, I experience a behaviour in Firefox (both mobile and desktop) that I believe is a bug : using chromium I don't have the bug and inspecting the html triggers a repaint and solves the problem.
In an attempt for a responsive design I have a side panel that is absolutely positionned and slides in and out. In this side panel, I am willing to have a fixed element. The fixed position is only specified for bottom, and the fixed element should therefore translate sideways with the containing panel. In firefox the position is however not updated properly, and the fixed element does not translate lateraly. Searching, I came up with a hacky workaround, but this fix is not perfect, and introduces tiny bugs where other browsers didn't have any. I therefore also desigend a test to check whether the browser experiences the bug, so that I only use the hack when necessary. Here is a minimal example derived from my code.
/* Fix to programatically force fixed element repositionning */
var trigger = document.getElementById('trigger');
var container = document.getElementById('container');
var child = document.getElementById('child');
function from_and_back(evt) {
if (container.children.length) {
container.removeChild(child);
setTimeout(function() {
container.appendChild(child);
}, 300);
}
}
trigger.addEventListener('mouseenter', from_and_back);
trigger.addEventListener('mouseleave', from_and_back);
/* Simulate the bug to check whether the browser experiences it */
var bug_status = document.getElementById('bug-status');
bug_status.innerText = (function() {
//create an absolutely positionned element
var abs = document.createElement('div');
abs.style.position = 'relative';
abs.style.left = '0px';
//create a fixed element to put inside
var fix = document.createElement('div');
fix.style.position = 'fixed';
//insert it into the document
abs.appendChild(fix);
document.body.appendChild(abs);
//test
fix.getBoundingClientRect(); /************ this line *************/
abs.style.left = '20px';
var fix_left = fix.getBoundingClientRect().left;
var abs_left = abs.getBoundingClientRect().left;
//remove test elements from the document
document.body.removeChild(abs);
//send the result
return abs_left !== fix_left;
})();
/* Wrapper class to trigger the effect */
.trigger {
width: 220px;
border: 1px solid #000;
display: inline-block;
}
.trigger:hover .container {
left: 200px;
}
/* Absolutely positionned element */
.container {
position: relative;
width: 20px;
height: 20px;
left: 0px;
background: #aaa;
transition: all .25s ease-out;
}
/* Fixed element inside the absolute one */
.child {
position: fixed;
width: 20px;
height: 20px;
background: #aaa;
top: 100px;
}
<!-- Display the bug test result -->
Your browser has the bug : <span id='bug-status'></span>
<br/>
<br/>
<div class="trigger">
<!-- Demonstrate the error without any fix -->
<span>Reference</span>
<br/>
<div class="container">
<div class="child"></div>
</div>
</div>
</div>
<!-- Apply the fix fix -->
<div class="trigger" id="trigger">
<span>Fixed</span>
<br/>
<div class="container" id="container">
<div class="child" id="child"></div>
</div>
</div>
Now the questions :
Obviously my workaround is not fully satisfactory : the smooth transition is lost, and in the example, if the mouse moves fastly in and out of the trigger, the fixed element remains dangling in the middle. Do you have ideas for a better workaround, or design with the same behaviour without the bug ?
In the javascript test, I marked a line. Removing the line makes the test pass on Firefox. I don't get why, but perhaps this could be used to workaround the bug less roughly ?
A workaround which might give the same result you want is to move the .child outside the moving container, and apply the same transformation on trigger:hover, just using margin-left or even transform: translateX(200px) to not mess with the fixed positioning.
(Using transform instead of positioning on the container actually would solve the rendering issue, but sadly it also makes the position:fixed relative to the transformed element instead of the viewport.)
/* Wrapper class to trigger the effect */
.trigger {
width: 220px;
border: 1px solid #000;
display: inline-block;
}
.trigger:hover .container {
left: 200px;
}
.trigger:hover .child {
margin-left: 200px;
}
.container {
position: relative;
width: 20px;
height: 20px;
left: 0px;
background: #aaa;
transition: all .25s ease-out;
}
.child {
position: fixed;
width: 20px;
height: 20px;
background: #aaa;
top: 100px;
margin-left: 0;
transition: all .25s ease-out;
}
<div class="trigger">
<div class="container">
</div>
<div class="child"></div>
</div>
I'm facing right now weird problem that so far occurs just in Safari (8.0.7) under OS X (Yosemite 10.10.4). What is the problem? I ahve two menu bars. Both are relative and positioning works fine. The point is that when I scroll, 50 px from top I add class that makes second bar position fixed + top 0. This also works perfectly but... when this class is added I see that font-weight of the target bar is changed to something smaller.
(I'm taking about bar that has items: "Australia", "New Zealand" etc.)
I've recorded my screen: https://www.youtube.com/watch?v=H9_VmXDqqBE. Please watch in HD. Top right. Second bar contains names of some categories. If you will look closer you will see that font weight is changed and names are much more thinner than they should be.
I'm pretty much confident about my code and:
I don't manipulate font-weight explicitly.
This happens just in Safari (OS X)
Chrome and FF work good.
It's a minor issue but I want to learn something new and face it.
Below are some code snippets to give you general preview of the situation.
$(window).scroll(function()
{
var top = $(window).scrollTop();
if (top > 50) {
$('#blog_categories_container').addClass('sticky_top');
} else {
$('#blog_categories_container').removeClass('sticky_top');
}
});
CSS for the "blog_categories_container" bar and "sticky_top" class:
nav#blog_categories_container.container_white {
background-color: rgba(0,0,0,0.66);
}
nav#blog_categories_container {
left: 0;
list-style: none outside none;
margin: 0;
padding: 0;
position: absolute;
top: 50px;
width: 100%;
z-index: 1030;
}
nav#blog_categories_container ul {
float: right;
margin: 0;
overflow: auto;
padding: 0;
}
nav#blog_categories_container ul li {
float: left;
overflow: hidden;
padding: 5px 30px 5px 5px;
white-space: nowrap;
position: relative;
color: #cccccc;
}
nav#blog_categories_container ul li:last-of-type {
padding-right: 0;
}
nav#blog_categories_container.sticky_top {
position: fixed;
top: 0;
}
Can someone give me any hints? Thank you.
This generally happens when something causes the font smoothing to change (probably when you add/ remove the sticky_top class).
Try adding
-webkit-font-smoothing: antialiased;
to the nav#blog_categories_container section of your css file.
If that doesn't work try -webkit-font-smoothing: subpixel-antialiased;
EDIT: Here's a Youtube video that illustrates my problem:
http://youtu.be/OguwjZR_GdU
On my website Black Star Opal I've been trying to implement a sticky menu, much like this one Dansk Kids. I looked at the Dansk Kids website javascript and CSS: there seems to be no javascript involved in their menu (other than the removal of the logo underneath their sticky menu when they scroll). I want my sticky menu to be as smooth as theirs if possible (ie staying flush with the url bar as it pops in and out).
Here's my css for #carttrans, the menu div:
position: fixed;
-webkit-backface-visibility: hidden;
height: 49px;
top: 0px;
left: 0px;
background-color: rgb(255, 255, 255);
width: 100% !important;
z-index: 10000;
text-align: center;
margin-left: 0px;
padding-left: 7px;
border: 1px solid rgb(221, 221, 221);
border-left: none;
border-right: none;
border-bottom-style: solid !important;
border-bottom-width: 1px !important;
border-bottom-color: rgb(221,221,221) !important;
-webkit-transform: translateZ(0);
I also use this js code (only because the menu wouldn't display on iOS Safari without it, although I'm unsure why):
$(function() {
// grab the initial top offset of the navigation
var sticky_navigation_offset_top = $('#carttrans').offset().top;
// our function that decides weather the navigation bar should have "fixed" css position or not.
var sticky_navigation = function(){
var scroll_top = $(window).scrollTop(); // our current vertical position from the top
if ($(window).width() < 500)
{
// if we've scrolled more than the navigation, change its position to fixed to stick to top, otherwise change it back to relative
if (scroll_top > sticky_navigation_offset_top) {
$('#carttrans').css({ 'position': 'fixed', 'top':0, 'left':0 });
} else {
$('#carttrans').css({ 'position': 'fixed' });
}
}
};
// run our function on load
sticky_navigation();
// and run it again every time you scroll
$(window).scroll(function() {
sticky_navigation();
});
});
I even removed all the elements in the menu and just left the blank white bar there to see if it would do the same thing. It popped in and out awkardly just like before.
Any help with this would be amazing.
EDIT: As I said below, it's the URL bar popping in and out that seems to be disturbing my sticky menus. It could possibly be a repaint issue or slow down, because on other sites the disappearance of the url bar and the subsequent movement of the menu (for example, on sticky menu demos) is quite smooth and I'm doing/have tested them with the same url bar popping.
Cheers,
Rob
HTML
<header><h1>Sticky Header</h1></header>
<img src="large-image.jpg" width="782" height="2000" alt="Big Image" />
jQuery (remember to include the jquery library)
$(window).scroll(function() {
if ($(this).scrollTop() > 1){
$('header').addClass("sticky");
}
else{
$('header').removeClass("sticky");
}
});
CSS:
header{
position: fixed;
width: 100%;
text-align: center;
font-size: 72px;
line-height: 108px;
height: 108px;
background: #335C7D;
color: #fff;
font-family: 'PT Sans', sans-serif;
}
header.sticky {
font-size: 24px;
line-height: 48px;
height: 48px;
background: #efc47D;
text-align: left;
padding-left: 20px;
transition: all 0.4s ease;
}
REFERENCES:
http://www.webdesignerdepot.com/2014/05/how-to-create-an-animated-sticky-header-with-css3-and-jquery/
PREVIOUS SAME QUESTION ON STACK OVERFLOW:
CSS Sticky header
I used firebug for firefox and just added the following to your #carttrans ID i am assuming you only want this to stick? If so check the css below replace your #carttrans with the below and lemme know if that is what you want?
#carttrans {
background: none repeat scroll 0 0 white;
position: fixed;
text-align: right;
top: 40px;
z-index: 999;
}
Hi i looked at your youtube clip and i see that it could be that the jquery you are using is affecting your main div for the top section #carttrans make sure on this div that your css is marked as important for the top 0px !important so that the jquery won't be able to change it have a try and see if this works?