Is it possible to apply scroll-snap to grand-children nested in children with overflow applied ? I can't seem to make it work.
What I aim to do is have a list of div with each a fixed height on which the viewport should snap vertically
html {
margin: 0;
scroll-snap-type: y mandatory;
overflow-x: hidden;
}
.horizontal-scroll {
max-width: 100vw;
}
.child {
width: 150vw;
scroll-snap-align: center;
height: 80vh;
background-color: rgb(143, 204, 241);
padding: 20px 15px;
}
.child:nth-child(even) {
background-color: rgb(133, 243, 155);
}
<!DOCTYPE html>
<html>
<head
</head>
<body>
<div class="horizontal-scroll">
<div class="child">
<h2>Section</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel laboriosam cupiditate vero, harum, ab facere ipsa mollitia exercitationem impedit alias nulla magnam aut tempore repudiandae
dolores. Sit maiores nemo ea.
</p>
</div> <div class="child">
<h2>Section</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel laboriosam cupiditate vero, harum, ab facere ipsa mollitia exercitationem impedit alias nulla magnam aut tempore repudiandae
dolores. Sit maiores nemo ea.
</p>
</div>
<div class="child">
<h2>Section</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel laboriosam cupiditate vero, harum, ab facere ipsa mollitia exercitationem impedit alias nulla magnam aut tempore repudiandae
dolores. Sit maiores nemo ea.
</p>
</div>
</div>
</body>
</html>
Homewer, I would also like the content to be horizontally-scrollable - as their content stretch beyond the viewport width.
They must also scroll together, so using overflow-x on each of them is not possible here.
To do so, I've wrapped the child in a scrollable-wrapper that is horizontally scrollable ( overflow-x : scroll ) and have a fixed width.
And this breaks the vertical scroll snap.
Could someone tell me if there's something I missed or if there's an alternative ?
Note : since each child have a fixed height, I would not mind using scroll-snap-points-y but it has been totally dropped on almost every browser. Is there a way to reproduce this behaviour ?
Edit : I might try this for the snap-point. It's jQuery based.
Vertical scrolling snap jQuery
Snippet
html {
margin: 0;
scroll-snap-type: y mandatory;
overflow-x: hidden;
}
.horizontal-scroll {
max-width: 100vw;
overflow-x: scroll;
}
.child {
width: 150vw;
scroll-snap-align: center;
height: 80vh;
background-color: rgb(143, 204, 241);
padding: 20px 15px;
}
.child:nth-child(even) {
background-color: rgb(133, 243, 155);
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="horizontal-scroll">
<div class="child">
<h2>Section</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel laboriosam cupiditate vero, harum, ab facere ipsa mollitia exercitationem impedit alias nulla magnam aut tempore repudiandae
dolores. Sit maiores nemo ea.
</p>
</div> <div class="child">
<h2>Section</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel laboriosam cupiditate vero, harum, ab facere ipsa mollitia exercitationem impedit alias nulla magnam aut tempore repudiandae
dolores. Sit maiores nemo ea.
</p>
</div>
<div class="child">
<h2>Section</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel laboriosam cupiditate vero, harum, ab facere ipsa mollitia exercitationem impedit alias nulla magnam aut tempore repudiandae
dolores. Sit maiores nemo ea.
</p>
</div>
</div>
</body>
</html>
Related
I spent the weekend trying to get my head around the Intersection Observer Animation for an animation that I'm trying to achieve. From my understanding of the intersection observer my code should work as I intended but the reality is it doesn't 🥲
My goal is that the scroll animation starts when the element reaches a certain point within the viewport. In my codepen, I've marked the point where the animation should start with a border. However, the animation starts as soon as the div enters the viewport.
Also, when the element gets below the border again, the animation should stop.
I would very much appreciate any help to achieve my goal.
Code example: https://codepen.io/aki-sol/pen/RwJPJrW?editors=1111
Also, if you have any feedback on my animation approach I'm very happy to receive criticism/ better way of approaching this.
<div class="text">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Expedita provident unde, sequi aliquid porro ipsa vitae nulla dolor neque aliquam quisquam nam magnam architecto, consequuntur est in beatae, nihil optio.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, architecto eveniet assumenda praesentium in laboriosam vitae atque, sunt minima aliquid quam distinctio voluptatum commodi veniam iure officia provident voluptas ea?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet quo commodi laborum perspiciatis nemo voluptates quod odio quis necessitatibus perferendis? Ipsum, quasi nesciunt. Debitis omnis consequuntur laboriosam veniam, non impedit!
</div>
<div class="box">
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
</div>
<div class="text">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Expedita provident unde, sequi aliquid porro ipsa vitae nulla dolor neque aliquam quisquam nam magnam architecto, consequuntur est in beatae, nihil optio.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, architecto eveniet assumenda praesentium in laboriosam vitae atque, sunt minima aliquid quam distinctio voluptatum commodi veniam iure officia provident voluptas ea?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet quo commodi laborum perspiciatis nemo voluptates quod odio quis necessitatibus perferendis? Ipsum, quasi nesciunt. Debitis omnis consequuntur laboriosam veniam, non impedit!
</div>
body {
position: relatvie;
heig;
}
body:after {
content: '';
position: fixed;
bottom: 40%;
height: 1px;
width: 100%;
border-bottom: 1px solid blue;
}
.text {
background-color: brown;
color: white;
height: 150vh;
}
.box {
display: flex;
position: relative;
}
.box-content {
width: 200px;
height: 200px;
background-color: greenyellow;
margin-right: 50px;
}
const boxElement = document.querySelector(".box");
//this function calls the aniamtion function and observes the window scroll position
function getWindowScrollPos() {
let windowPosition = window.scrollY;
window.addEventListener("scroll", () => {
windowPosition = window.scrollY;
animateBox(boxElement, windowPosition);
});
}
function animateBox(box, scrollPosition) {
let boxOffsetPosition = scrollPosition;
box.style.left = `${-boxOffsetPosition}px `;
}
function boxObserver(element) {
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
getWindowScrollPos();
}
});
},
{ rootMargin: "0% 0% 60% 0%" }
);
observer.observe(element);
}
boxObserver(boxElement);
Thanks a lot!
There are two things to note here, I guess.
First, the Intersection Observer (along with Resize Observer) is not the best thing to test in online sandboxes, because they run code in an iframe, which leads to such a behavior. You should try to run your code in a browser.
There are questions related to this problem. E.g.: In codepen, Intersection observer has different behavior from browser window
Second, you're probably misunderstanding rootMargin. You set it to 0% 0% 60% 0% which means “add 60% of the height of the root to the very root, and use it as a bottom border for intersection”.
What you actually want to is to decrease the bottom border, not to increase. So, just set it to 0% 0% -40% 0% and it will work.
The Intersection Observer tutorial that helped me a bit to understand the rootMargin weirdness. Maybe it will be useful for you too.
Demo
Here's your snippet that I changed a bit to make it work inside an iframe. I've added a container node and use it instead of window.
const boxElement = document.querySelector('.box');
const container = document.getElementById('container');
function setupListener() {
let scrollPosition = container.scrollTop;
animateBox(boxElement, scrollPosition);
container.addEventListener('scroll', () => {
scrollPosition = container.scrollTop;
animateBox(boxElement, scrollPosition);
});
}
function animateBox(box, scrollPosition) {
let boxOffsetPosition = scrollPosition;
box.style.left = `${-boxOffsetPosition}px`;
}
function boxObserver(element) {
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setupListener();
}
});
},
{
root: document.getElementById('container'),
rootMargin: `0px 0px -40% 0px`
}
);
observer.observe(element);
}
boxObserver(boxElement);
body {
margin: 0;
overflow: hidden;
}
body:after {
content: "";
position: fixed;
bottom: 40%;
height: 1px;
width: 100%;
border-bottom: 1px solid blue;
}
.container {
overflow: scroll;
max-height: 100vh;
}
.text {
background-color: brown;
color: white;
height: 150vh;
}
.box {
display: flex;
position: relative;
}
.box-content {
width: 200px;
height: 200px;
background-color: greenyellow;
margin-right: 50px;
}
<div class="container" id="container">
<div class="text">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Expedita provident unde, sequi aliquid porro ipsa vitae nulla dolor neque aliquam quisquam nam magnam architecto, consequuntur est in beatae, nihil optio.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, architecto eveniet assumenda praesentium in laboriosam vitae atque, sunt minima aliquid quam distinctio voluptatum commodi veniam iure officia provident voluptas ea?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet quo commodi laborum perspiciatis nemo voluptates quod odio quis necessitatibus perferendis? Ipsum, quasi nesciunt. Debitis omnis consequuntur laboriosam veniam, non impedit!
</div>
<div class="box">
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
<div class="box-content"></div>
</div>
<div class="text">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Expedita provident unde, sequi aliquid porro ipsa vitae nulla dolor neque aliquam quisquam nam magnam architecto, consequuntur est in beatae, nihil optio.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, architecto eveniet assumenda praesentium in laboriosam vitae atque, sunt minima aliquid quam distinctio voluptatum commodi veniam iure officia provident voluptas ea?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet quo commodi laborum perspiciatis nemo voluptates quod odio quis necessitatibus perferendis? Ipsum, quasi nesciunt. Debitis omnis consequuntur laboriosam veniam, non impedit!
</div>
</div>
What may be improved
Also, if you have any feedback on my animation approach I'm very happy to receive criticism/ better way of approaching this.
Well, you surely should think about the scroll listener you will have after the intersection started. If you don't remove it, it will hang. Or even worse, they will be increasing during each intersection. Not a good thing.
Also it's better to animate transform, not left. It's good for optimization. Otherwise you'll get junky animation which will freeze the whole site. Check this set of articles by Google: web.dev/animations/.
I am new to coding and I am trying to achieve the following using JQuery:
I have two Divs Where clicking on the first shows some content and clicking the second would hide the content of the first one and show its content instead (Toggling). What I want to do is that I want to keep the same functionality but I want the second Div to slide to the right when I click on the first Div and make a drawer shape and vice versa. I have attached images to it so it may explain more about my idea.
both of contents are hidden by default.
I can't seem to know how to join these two functionalities together
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test</title>
<script
src="https://code.jquery.com/jquery-3.5.1.js"
integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
crossorigin="anonymous"
></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div id="box-container">
<div id="div1">
<h1>Title one</h1>
<p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Inventore
quidem ex tenetur ipsum dolore repudiandae molestiae mollitia! Dolore
numquam.
</p>
</div>
<div id="div2">
<h1>Title two</h1>
<p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Inventore
quidem ex tenetur ipsum dolore repudiandae molestiae mollitia! Dolore
numquam.
</p>
</div>
</div>
<div id="contentDiv1">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla voluptatem
veritatis assumenda. Obcaecati veniam quo impedit tempora pariatur maiores
ipsa voluptates commodi esse eveniet! Nihil corrupti illum at accusantium
sit? Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut veritatis
et molestias? Reprehenderit distinctio sint provident ratione dolorem
veritatis sapiente, fuga amet obcaecati. Laboriosam rerum consectetur nemo
magnam saepe mollitia. Lorem ipsum dolor sit amet consectetur adipisicing
elit. Excepturi sit perferendis earum debitis corrupti dolore commodi
minima consectetur veniam itaque inventore et pariatur sapiente, maxime
quis, in nulla, eos molestias! Lorem ipsum dolor sit amet consectetur,
adipisicing elit. Quasi, incidunt repudiandae perferendis ea praesentium
blanditiis, voluptate accusantium, repellat molestiae quisquam eveniet
earum officia sed assumenda maxime officiis sequi laboriosam! Tempore.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias modi hic
officia iste optio in delectus veniam obcaecati reprehenderit, voluptate
ipsum! Incidunt ducimus animi, id quae blanditiis provident dignissimos
harum?
</div>
<div id="contentDiv2">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla voluptatem
veritatis assumenda. Obcaecati veniam quo impedit tempora pariatur maiores
ipsa voluptates commodi esse eveniet! Nihil corrupti illum at accusantium
sit? Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut veritatis
et molestias? Reprehenderit distinctio sint provident ratione dolorem
veritatis sapiente, fuga amet obcaecati. Laboriosam rerum consectetur nemo
magnam saepe mollitia. Lorem ipsum dolor sit amet consectetur adipisicing
elit. Excepturi sit perferendis earum debitis corrupti dolore commodi
minima consectetur veniam itaque inventore et pariatur sapiente, maxime
quis, in nulla, eos molestias! Lorem ipsum dolor sit amet consectetur,
adipisicing elit. Quasi, incidunt repudiandae perferendis ea praesentium
blanditiis, voluptate accusantium, repellat molestiae quisquam eveniet
earum officia sed assumenda maxime officiis sequi laboriosam! Tempore.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias modi hic
officia iste optio in delectus veniam obcaecati reprehenderit, voluptate
ipsum! Incidunt ducimus animi, id quae blanditiis provident dignissimos
harum?
</div>
</body>
</html>
CSS
body {
display: inline-block;
margin: 100px 100px 25px 100px;
text-align: center;
}
#box-container {
height: 300px;
display: flex;
}
#div1 {
background: linear-gradient(90deg, #f57350, #fa8282);
width: 50%;
height: 50%;
cursor: pointer;
}
#div2 {
background: linear-gradient(90deg, #a42e5a, #f57350);
width: 50%;
height: 50%;
cursor: pointer;
}
#contentDiv1,
#contetnDiv2 {
margin: 25px;
}
JQuery
jQuery(document).ready(function($){
$('#contentDiv1').hide();
$('#contentDiv2').hide();
$('#div1').on('click', function(){
$('#contentDiv1').slideToggle();
$('#contentDiv2').hide();
});
$('#div2').on('click', function(){
$('#contentDiv2').slideToggle();
$('#contentDiv1').hide();
});
});
attached image
It has more than one solution, and for me, this is my favorite method, I hope it helps you:
$('.tabs .tab').on('click', function () {
if ($(this).hasClass('active')) {
$(this).removeClass('active')
.closest('.tabs').removeClass('active1 active2');
$('.content').hide();
} else {
let i = $(this).index() + 1;
$(this)
.addClass('active')
.siblings('.tab').removeClass('active')
.closest('.tabs').removeClass('active1 active2')
.addClass('active' + i);
$('.content').hide();
$('.content' + i).fadeIn();
}
});
.tabs,
.tabs .tab,
.tabs .content {
border: 1px solid #000;
border-collapse: collapse;
box-sizing: border-box;
}
.tabs {
display: flex;
flex-wrap: wrap;
text-align: center;
position: relative;
}
.tabs.active1 {
padding-left: 0;
padding-right: 65px;
}
.tabs.active2 {
padding-left: 65px;
padding-right: 0;
}
.tabs .tab {
padding: 15px;
cursor: pointer;
min-width: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.tabs.active1 .tab,
.tabs.active2 .tab {
min-width: 100%;
width: 100%;
}
.tabs .content {
padding: 15px;
min-width: 100%;
display: none;
}
.tabs.active1 .tab1:not(.active),
.tabs.active2 .tab1:not(.active){
position: absolute;
left: 0;
top: 0;
bottom: 0;
min-width: 65px;
width: 65px;
}
.tabs.active1 .tab2:not(.active),
.tabs.active2 .tab2:not(.active) {
position: absolute;
right: 0;
top: 0;
bottom: 0;
min-width: 65px;
width: 65px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="tabs">
<div class="tab tab1">div1</div>
<div class="tab tab2">div2</div>
<div class="content content1">div content1</div>
<div class="content content2">div content2</div>
</div>
I am experimenting with a very basic layout that has 4 divs, the first and third divs have dark blue backgrounds and the second and fourth have white backgrounds. I have a div in fixed position to the right with a default white color. I need to write some code that if this fixed div is scrolled through the white background divs, it changes its color to black, if it scrolled in the blue, it remains white as it is.
I tinkered for a whole day with getClientBoundingRect() and the IntersectionObserver API and I didn't have any luck.
Here is the code of the basic layout:
const oddElems = document.querySelectorAll('.oddElem');
const evenElems = document.querySelectorAll('.evenElem');
const allElems = document.querySelectorAll('.elem');
function handleInteresection(entries) {
entries.forEach(entry => {
console.log(entry)
})
}
const observer = new IntersectionObserver(handleInteresection);
allElems.forEach(elem => {
observer.observe(elem);
})
* {
box-sizing: border-box;
}
body {
width: 70%;
margin: auto;
padding: 0;
}
.elem {
border: 2px solid;
}
#elem {
background: #007;
padding: 20rem;
color: white;
}
#elem2 {
padding: 20rem;
background: #fff;
}
#elem3 {
padding: 20rem;
background: #007;
}
#elem4 {
padding: 20rem;
background: #fff;
}
#flyingbox {
padding: 2rem;
width: 2rem;
left: 80%;
position: fixed;
top: 10px;
background: #fff;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Get Bounding</title>
</head>
<body>
<div id="flyingbox">
</div>
<div class="elem oddElem" id="elem">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa blanditiis reprehenderit odio, eos
recusandae ipsam nulla quas sed voluptatum ex neque natus fuga illum dolores. Quis quibusdam odit, unde
minus?
</p>
</div>
<div class="elem evenElem" id="elem2">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa blanditiis reprehenderit odio, eos
recusandae ipsam nulla quas sed voluptatum ex neque natus fuga illum dolores. Quis quibusdam odit, unde
minus?
</p>
</div>
<div class="elem oddElem" id="elem3">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa blanditiis reprehenderit odio, eos
recusandae ipsam nulla quas sed voluptatum ex neque natus fuga illum dolores. Quis quibusdam odit, unde
minus?
</p>
</div>
<div class="elem evenElem" id="elem4">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa blanditiis reprehenderit odio, eos
recusandae ipsam nulla quas sed voluptatum ex neque natus fuga illum dolores. Quis quibusdam odit, unde
minus?
</p>
</div>
</body>
</html>
It doesn't look like you have any event listener to track the current scroll position. Basically I created an array of each section's offsetTop (distance from parent top) in reverse order, and conditionally check whether window.scrollY (current scroll position) matches an even or odd index.
const allElems = document.querySelectorAll('.elem');
const offsetTops = Array.from(allElems).map(ele => ele.offsetTop).reverse();
const flyingBox = document.getElementById("flyingbox");
window.addEventListener("scroll", ()=> {
const isBlack = offsetTops.findIndex(offsetTop => window.scrollY + 45 > offsetTop)%2 === 0 ? true : false;
if(flyingBox.classList.contains("black") && !isBlack) flyingBox.classList.toggle("black");
if(!flyingBox.classList.contains("black") && isBlack) flyingBox.classList.toggle("black");
});
* {
box-sizing: border-box;
}
body {
width: 70%;
margin: auto;
padding: 0;
}
.elem {
border: 2px solid;
}
#elem {
background: #007;
padding: 20rem;
color: white;
}
#elem2 {
padding: 20rem;
background: #fff;
}
#elem3 {
padding: 20rem;
background: #007;
}
#elem4 {
padding: 20rem;
background: #fff;
}
#flyingbox {
padding: 2rem;
width: 2rem;
left: 80%;
position: fixed;
top: 10px;
background: #fff;
}
.black {
background-color: black !important;
}
It doesn't look like you have an event listener to retrieve the current scroll position:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Get Bounding</title>
</head>
<body>
<div id="flyingbox">
</div>
<div class="elem oddElem" id="elem">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa blanditiis reprehenderit odio, eos
recusandae ipsam nulla quas sed voluptatum ex neque natus fuga illum dolores. Quis quibusdam odit, unde
minus?
</p>
</div>
<div class="elem evenElem" id="elem2">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa blanditiis reprehenderit odio, eos
recusandae ipsam nulla quas sed voluptatum ex neque natus fuga illum dolores. Quis quibusdam odit, unde
minus?
</p>
</div>
<div class="elem oddElem" id="elem3">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa blanditiis reprehenderit odio, eos
recusandae ipsam nulla quas sed voluptatum ex neque natus fuga illum dolores. Quis quibusdam odit, unde
minus?
</p>
</div>
<div class="elem evenElem" id="elem4">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa blanditiis reprehenderit odio, eos
recusandae ipsam nulla quas sed voluptatum ex neque natus fuga illum dolores. Quis quibusdam odit, unde
minus?
</p>
</div>
</body>
</html>
I create an effect that is to constantly display the image while scrolling text. I have a question how to make it work the same way, instead of position: sticky, posititon: fixed, so that this effect works on ie.
var sticky = document.querySelector('.sticky-container');
var img = document.querySelector('.sticky-item');
window.addEventListener('scroll',setSticky);
function setSticky(){
var top = sticky.offsetTop - window.pageYOffset;
if(top <= 0){
sticky.classList.add('sticky');
}
if(top.toString().replace('-','') >= sticky.offsetHeight || top >= 0){
sticky.classList.remove('sticky');
}
};
* {
margin: 0;
}
body {
width: 100%;
padding: 120vh 0;
}
p {
font-size: 28px;
color: #fff;
text-align: center;
margin: 80px 0;
}
.sticky-item {
width: 100%;
height: 100vh;
background: url(https://www.apple.com/v/iphone-xs/a/images/overview/camera_hero_large.jpg) center / cover no-repeat;
}
.sticky-container.sticky .sticky-item{
position: sticky;
top: 0;
z-index: -1;
}
<div class="sticky-container">
<figure class="sticky-item"></figure>
<p class="anim">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint, magni suscipit modi enim assumenda optio tenetur recusandae sed nobis veritatis!</p>
<p class="anim">Lorem ipsum dolor sit amet consectetur adipisicing elit. A, at.</p>
<p class="anim">Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit laudantium, esse omnis neque, minima voluptatibus repellendus amet, quod odio architecto veniam fuga inventore adipisci! Delectus fugit quisquam ad, ab facilis at saepe? Soluta delectus consequuntur fuga ipsa quasi dolorem officiis?</p>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Cumque dolorum ipsum distinctio ut excepturi facilis laborum, nihil in aliquid assumenda necessitatibus quaerat recusandae. Nobis, dolore? Hic itaque ipsa inventore illo tempora similique perspiciatis architecto rem, nulla dicta error saepe earum ut atque aut aspernatur deserunt doloribus odit ea, a reprehenderit?</p>
</div>
EDIT:
<div class="sticky-container">
<p class="anim">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint, magni suscipit modi enim assumenda optio tenetur recusandae sed nobis veritatis!</p>
<p class="anim">Lorem ipsum dolor sit amet consectetur adipisicing elit. A, at.</p>
<p class="anim">Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit laudantium, esse omnis neque, minima voluptatibus repellendus amet, quod odio architecto veniam fuga inventore adipisci! Delectus fugit quisquam ad, ab facilis at saepe? Soluta delectus consequuntur fuga ipsa quasi dolorem officiis?</p>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Cumque dolorum ipsum distinctio ut excepturi facilis laborum, nihil in aliquid assumenda necessitatibus quaerat recusandae. Nobis, dolore? Hic itaque ipsa inventore illo tempora similique perspiciatis architecto rem, nulla dicta error saepe earum ut atque aut aspernatur deserunt doloribus odit ea, a reprehenderit?</p>
</div>
.sticky-item {
background-attachment: fixed;
background-size: 100%;
}
Dai is correct, you do not need to use a script to achieve this effect.
https://jsfiddle.net/tractionworks/h3r5uvqm/8/
Since you need to use the position:sticky feature I doubt this works on IE without a big effort and actually using JS. But with 1.4% global usage I doubt this is worth your time.
However if you are fine with the coverage of sticky, I would entirely skip using JS and solve it via CSS:
* {
margin: 0;
}
body {
width: 100%;
padding: 120vh 0;
}
p {
font-size: 28px;
color: #fff;
text-align: center;
margin: 80px 0;
}
.sticky-item {
position: sticky;
top: 0;
z-index: -1;
width: 100%;
height: 100vh;
background: url(https://www.apple.com/v/iphone-xs/a/images/overview/camera_hero_large.jpg) center / cover no-repeat;
}
<div class="sticky-item"></div>
<div class="sticky-container">
<p class="anim">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint, magni suscipit modi enim assumenda optio tenetur recusandae sed nobis veritatis!</p>
<p class="anim">Lorem ipsum dolor sit amet consectetur adipisicing elit. A, at.</p>
<p class="anim">Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit laudantium, esse omnis neque, minima voluptatibus repellendus amet, quod odio architecto veniam fuga inventore adipisci! Delectus fugit quisquam ad, ab facilis at saepe? Soluta delectus consequuntur fuga ipsa quasi dolorem officiis?</p>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Cumque dolorum ipsum distinctio ut excepturi facilis laborum, nihil in aliquid assumenda necessitatibus quaerat recusandae. Nobis, dolore? Hic itaque ipsa inventore illo tempora similique perspiciatis architecto rem, nulla dicta error saepe earum ut atque aut aspernatur deserunt doloribus odit ea, a reprehenderit?</p>
</div>
On the following website i have a navigation bar.
http://bit.do/bVXAs
I use this css code for the navigation:
z-index: 999;
position: relative;
background: #302f2f; /* Old browsers */
background: -moz-linear-gradient(top, #302f2f 0%, #000000 100%);
background: -webkit-linear-gradient(top, #302f2f 0%,#000000 100%);
background: linear-gradient(to bottom, #302f2f 0%,#000000 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#302f2f',
endColorstr='#000000',GradientType=0 ); /* IE6-9 */
box-shadow: 0px 7px 31px -5px #000;
border-bottom: 15px solid #ff9500;s
An i use a Javascript Code for the position fixed:
$(window).scroll(function () {
if ($(window).scrollTop() > 1) {
$('#navigationsleiste').css('top', $(window).scrollTop());
}
}
Now when i scroll the Navigation Bar have a space to the top of the browser window. But i dont want that space/gap. Know anyone why i have that gap/space?
The answer to 'Why the gap' has been answered in the comments I believe.
More generally, on how to fix the issue:
CSS has a position property that's very suited for your sticky menu: position: fixed. When the menu is scrolled outside of view, you change its position to fixed. Once it's back at its original location, you remove your fixed positioning.
You want to do as little as possible in a method that is executed on scroll, since it is triggered very often. Once there's too much code execution on a scroll, you loose your smooth 60fps framerate.
So what you could do is:
Make sure you always know how far the top of your sticky menu is away from the top of your window
On scroll, check if this point has been reached
Add or remove a class to your menu accordingly
Here's an example:
$(document).ready(function() {
var $doc = $(document);
var $menu = $("nav");
var menuTop = 0;
var setMenuTop = function() {
menuTop = $menu.offset().top;
}
$(window).resize(setMenuTop);
$doc.scroll(function() {
$menu.toggleClass("is-fixed", ($doc.scrollTop() > menuTop));
});
setMenuTop();
});
body {
width: 400px;
margin: 0 auto;
}
header {
height: 160px;
background: orange;
}
nav {
heigth: 40px;
background: yellow;
will-change: transform;
}
nav.is-fixed {
position: fixed;
width: 400px;
top: 0;
}
.is-fixed + article {
margin-top: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>header</header>
<nav>menu</nav>
<article>
<h1>content</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nulla enim placeat? Iure modi quasi facere provident, quidem ducimus impedit nulla harum sunt corrupti. Rem velit architecto omnis molestias, repellat.</p>
</article>
Instead $(window) set it better on $(document):
$('#navigationsleiste').css('top', $(document).scrollTop());