How to create image scrolling parallax effect with CSS? - javascript

I saw this cool scrolling effect online...
Where the image blends with the next image when scrolling through sections. I've been trying to reproduce it, but I can't seem to figure it out?
How can I create this effect on the web?
Here is the link to where I saw the effect... http://readingbuddysoftware.com/how-it-works/
I've tried using position: fixed on the screenshots with the z-index of the section higher then the image, but the last screenshot is always on the top.
Any ideas?
Update: For various reasons (including placement, using slants...), I can't use the background-image css solution. I need a solution for using the <img> element.

This can be done using background-attchement:fixed and two similar images.
Here is a simple example:
body {
min-height:200vh;
margin:0;
background:url(https://picsum.photos/id/1069/150/150?grayscale) 20px 20px no-repeat;
background-attachment:fixed;
}
.box {
margin-top:220px;
height:200px;
background:url(https://picsum.photos/id/1069/150/150) 20px 20px no-repeat,
grey;
background-attachment:fixed;
}
<div class="box">
</div>
That you can easily scale with many images:
body {
min-height:250vh;
margin:0;
background:url(https://picsum.photos/id/1069/150/150?grayscale) 50px 50px/auto no-repeat;
background-attachment:fixed;
}
.box {
height:200px;
background:url(https://picsum.photos/id/1069/150/150) 50px 50px/auto no-repeat,
grey;
background-attachment:fixed;
}
.box:first-child {
margin-top:200px;
}
<div class="box">
</div>
<div class="box" style="background-image:url(https://picsum.photos/id/11/150/150);background-color:yellow">
</div>
<div class="box" style="background-image:url(https://picsum.photos/id/106/150/150);background-color:pink">
</div>
You can also consider the use of img and position:fixed but you will need some trick to hide the overflow using clip-path
body {
min-height: 250vh;
margin: 0;
padding-top: 100px;
}
img {
position: fixed;
top: 50px;
left: 50px;
}
.box {
height: 200px;
background: grey;
clip-path: inset(0);
}
<div class="box">
<img src="https://picsum.photos/id/1074/200/120?grayscale">
</div>
<div class="box" style="background-color:red;">
<img src="https://picsum.photos/id/1074/200/120">
</div>
<div class="box" style="background-color:yellow;">
<img src="https://picsum.photos/id/1024/200/120?grayscale">
</div>
<div class="box" style="background-color:pink;">
<img src="https://picsum.photos/id/1024/200/120">
</div>
Or using mask
body {
min-height: 250vh;
margin: 0;
padding-top: 100px;
}
img {
position: fixed;
top: 50px;
left: 50px;
}
.box {
height: 200px;
background: grey;
-webkit-mask:linear-gradient(#fff,#fff);
mask:linear-gradient(#fff,#fff);
}
<div class="box">
<img src="https://picsum.photos/id/1074/200/120?grayscale">
</div>
<div class="box" style="background-color:red;">
<img src="https://picsum.photos/id/1074/200/120">
</div>
<div class="box" style="background-color:yellow;">
<img src="https://picsum.photos/id/1024/200/120?grayscale">
</div>
<div class="box" style="background-color:pink;">
<img src="https://picsum.photos/id/1024/200/120">
</div>
For better support, here is a similar idea with some JS to avoid the use of clip-path or mask
I will update the position of the image using a CSS variables but you can easily do without:
window.onscroll = function() {
var scroll = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
document.documentElement.style.setProperty('--scroll-var', scroll+"px");
}
:root {
--scroll-var: 0px;
}
body {
min-height: 150vh;
margin: 0;
}
img {
position: fixed;
top: 20px;
left: 20px;
}
.box {
margin-top: 220px;
height: 200px;
background: grey;
position: relative;
overflow: hidden;
}
.box img {
top: calc(-220px + 20px + var(--scroll-var));
/* margin of box + top of the other image + scroll*/
position: absolute;
}
<img src="https://picsum.photos/id/1069/150/150?grayscale">
<div class="box">
<img src="https://picsum.photos/id/1069/150/150">
</div>
With many images:
window.onscroll = function() {
var scroll = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
document.documentElement.style.setProperty('--scroll-var', scroll+"px");
}
:root {
--scroll-var: 0px;
}
body {
min-height: 250vh;
margin: 0;
padding-top:200px;
}
img {
position: fixed;
top: 50px;
left: 50px;
}
.box {
height: 200px;
background: grey;
position: relative;
overflow: hidden;
}
img.f1 {
top: calc(-200px + 50px + var(--scroll-var));
position: absolute;
}
img.f2 {
top: calc(-400px + 50px + var(--scroll-var));
position: absolute;
}
img.f3 {
top: calc(-600px + 50px + var(--scroll-var));
position: absolute;
}
<img src="https://picsum.photos/id/1069/100/100?grayscale">
<div class="box">
<img class="f1" src="https://picsum.photos/id/1069/100/100">
</div>
<div class="box" style="background-color:yellow;">
<img class="f2" src="https://picsum.photos/id/107/100/100">
</div>
<div class="box" style="background-color:pink;">
<img class="f3" src="https://picsum.photos/id/1072/100/100">
</div>

Related

Is it possible to make parent element (relative) fill the height of its absolute positioned content?

I'd like my parent div to expand the height of the content, as my content will be dynamic. However, the content must be (I think) positioned absolutely so they can overlap each other vertically.
I've concluded I'll have to use JS to find the offset from the top to the bottom of the last element in the container, then set the height to that.
I'm currently doing something like this:
var lastElement = document.getElementById('three');
var bounds = lastElement.getBoundingClientRect();
var bottomOffset = bounds.top + $("#three").height();
$("#container").height(bottomOffset);
However this is clunky within my application, and the application of the height is not instantaneous, leading to a sluggy site.
Is there a better way?
var lastElement = document.getElementById('three');
var bounds = lastElement.getBoundingClientRect();
var bottomOffset = bounds.top + $("#three").height();
$("#container").height(bottomOffset);
body,
html {
height: 100% padding: 0;
margin: 0;
}
.absolute {
display: inline-block;
position: absolute;
background-color: blue;
width: 100px;
height: 100px;
}
#two {
top: 80px;
left: 120px
}
#three {
top: 160px;
left: 240px;
}
#container {
position: relative;
width: 100%;
;
background-color: yellow;
;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="absolute" id="one"></div>
<div class="absolute" id="two"></div>
<div class="absolute" id="three"></div>
</div>
View on JSFiddle
You can accomplish your result without any JS, but instead use CSS margin around the boxes to get the same result.
For the horizontal margin you can also use percentages (by request of OP).
For the vertical margins this will give unexpected results, since the percentage will still reference the width of the container (under "Property Values"), not the height.
html,body {height:100%; padding:0; margin:0;}
.container {
background-color: yellow;
}
.box {
display: inline-block;
width: 100px;
height: 100px;
margin-right: 2%;
background-color: blue;
}
.box.one {margin-top:0; margin-bottom:160px;}
.box.two {margin-top:80px; margin-bottom:80px;}
.box.three {margin-top:160px; margin-bottom:0;}
<div class="container">
<div class="box one"></div>
<div class="box two"></div>
<div class="box three"></div>
</div>
pixel-margin: https://jsfiddle.net/xzq64tsh/
percent-margin: https://jsfiddle.net/xzq64tsh/3/
Perhaps taking out the getBoundingClientRect() function, using jQuery instead might speed it up and simplify it a bit.
var lastElement = $('#three');
var bottomOffset = lastElement.offset().top + lastElement.height();
$("#container").height(bottomOffset);
body,
html {
height: 100% padding: 0;
margin: 0;
}
.absolute {
display: inline-block;
position: absolute;
background-color: blue;
width: 100px;
height: 100px;
}
#two {
top: 80px;
left: 120px
}
#three {
top: 160px;
left: 240px;
}
#container {
position: relative;
width: 100%;
;
background-color: yellow;
;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="absolute" id="one"></div>
<div class="absolute" id="two"></div>
<div class="absolute" id="three"></div>
</div>

Vertical content slider - JQuery

I am trying to create vertical content slider using jQuery, I have tried creating but its not working. I am trying to change the slide on scroll, any navigation is not required, only the content have to changed on scroll.
Here is the JSfiddle of my code
function rotateImages(){
$(".slide-item").animate({top: "-100%"}, 1000).delay(4000);
$(".slide-item").animate({top: "200%"}, 1000).delay(4000);
}
$(".slider-wrapper").scroll(function() {
rotateImages();
});
.slider-wrapper {
float: left;
width: 100%;
height: 500px;
background: #dedede;
border: 1px solid #ccc;
overflow: hidden;
position: relative;
}
.slide-item {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.item-one {
top: 0;
}
.item-two {
top: 100%
}
.slide-item > .img-block {
float: left;
width: 30%;
}
.slide-item > .img-block > img {
width: 100%;
height: auto;
}
.slide-item > .content-block {
float: right;
width: 70%;
padding: 0 20px;
box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="slider-wrapper">
<div class="slide-item item-one">
<div class="img-block"><img src="https://camo.mybb.com/e01de90be6012adc1b1701dba899491a9348ae79/687474703a2f2f7777772e6a71756572797363726970742e6e65742f696d616765732f53696d706c6573742d526573706f6e736976652d6a51756572792d496d6167652d4c69676874626f782d506c7567696e2d73696d706c652d6c69676874626f782e6a7067"></div>
<div class="content-block">
<h1>Slider Heading 1</h1>
<p>This is content related to slider. This is content related to slider. This is content related to slider. This is content related to slider. </p>
</div>
</div>
<div class="slide-item item-two">
<div class="img-block"><img src="https://camo.mybb.com/e01de90be6012adc1b1701dba899491a9348ae79/687474703a2f2f7777772e6a71756572797363726970742e6e65742f696d616765732f53696d706c6573742d526573706f6e736976652d6a51756572792d496d6167652d4c69676874626f782d506c7567696e2d73696d706c652d6c69676874626f782e6a7067"></div>
<div class="content-block">
<h1>Slider Heading 1</h1>
<p>This is content related to slider. This is content related to slider. This is content related to slider. This is content related to slider. </p>
</div>
</div>
</div>
I would suggest using jquery-mousewheel because scroll event won't work until and unless there is scrollbar.
Fiddle demo
$('.slider-wrapper').on('mousewheel', function(event) {
console.log(event.deltaX, event.deltaY, event.deltaFactor);
rotateImages();
});

How to fix div position when it reaches middle of viewport?

I have reference image attach for description.As in figure it is having two section side by side.One is for image(mobile and tablet) and second is for is features.This whole section is below the fold.
Now when user scrolls to view it and when image reaches vertically middle of the viewport its position should remain fixed.While its position is fixed features should scroll as normally.As one feature goes out of viewport image should change. When all features are out of viewport, position of image should again become static.
I am using skrollr js plugin for this.Please help...
Here is the code
.featurenav {
margin: 0px;
padding: 0px;
list-style: none;
}
.featurenav li:before {
content: url('../images/point.png');
position: absolute;
left: 0px;
top: 5px
}
.featurenav li {
font-family: OpenSans-Light;
color: #838b80;
font-size: 30px;
margin-bottom: 90px;
padding-left: 83px;
position: relative;
}
.color {
float: left;
width: 74px;
height: 74px;
margin: 30px 25px 0px 0px;
border-radius: 5px;
}
.color1 {
background-color: #c9bda3;
}
.color2 {
background-color: #c99a32;
}
.color3 {
background-color: #838b80;
}
.color4 {
background-color: #fff;
}
.showcase img {
width: 100%;
}
.showcase img:not(:first-child) {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-xs-12 padding-zero">
<div class="col-sm-6">
<ul class="featurenav">
<li class="firstli">Graphical Layout</li>
<li class="secondli">Open sans Font Used</li>
<li class="thirdli">Colors Used
<br>
<div class="color color1"></div>
<div class="color color2"></div>
<div class="color color3"></div>
<div class="color color4"></div>
<div class="clearfix"></div>
</li>
<li class="fourthli">Parallax Smooth Scrolling</li>
<li class="fifthli">Adaptable</li>
</ul>
</div>
<div class="col-sm-6 showcase">
<img src="images/mobile_tablet.png" data-bottom-top="display:block" alt="showcase" data-anchor-target=".firstli" />
<img src="images/mobile_tablet_2.png" alt="showcase" />
<img src="images/mobile_tablet_3.png" alt="showcase" />
<img src="images/mobile_tablet_4.png" alt="showcase" />
<img src="images/mobile_tablet_5.png" alt="showcase" />
</div>
<div class="clearfix"></div>
</div>
Your images aren't working, so here's a generic solution. All you have to do is change the element to position: fixed; when you scroll to wherever the image is minus half the browser viewport height
$(window).on('load', function() {
$affix = $('#affix');
$affix.attr('data-affix', $affix.offset().top);
}).on('scroll', function() {
var scrolled = $(window).scrollTop(),
vh = $(window).height(),
halfView = (vh / 2),
scrollPoint = $affix.attr('data-affix') - halfView;
if (scrolled >= scrollPoint) {
$('img').addClass('fixed');
} else {
$('img').removeClass('fixed');
}
});
* {margin:0;}
section {
height: 500vh;
}
img {
max-width: 600px;
width: 100%;
}
.fixed {
position: fixed;
top: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section></section>
<section><img id="affix" src="http://plusquotes.com/images/quotes-img/cool_cat.jpg" data-affix></section>

Adjust a 100% width image to vertically center using jQuery or CSS?

Basically I have a fixed size div that contains an <img> tag. I cannot change the structure.
Often these images are much larger than the container due to keeping them 100% width and filling the box. Most times this results in too much of the image shown at top and not cropped to the center of the image.
So using jQuery (or pure CSS if possible) I want to adjust the position of the image to move it up so the top is cropped off instead of the bottom.
Also, this should remain responsive as the viewport changes width.
Here is a fiddle
.container {
height: 200px;
width: 100%;
overflow: hidden;
margin: 0 0 30px;
}
<div class="container">
<img src="http://placekitten.com/900/500/">
</div>
<div class="container">
<img src="http://placekitten.com/901/500/">
</div>
It's doable with known height container, like your demo. We can set the container to position:relative, and set the image to position:absolute, plus some extra set ups as follows.
.container {
height: 200px;
width: 100%;
overflow: hidden;
margin: 0 0 30px;
position: relative;
}
.container img {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
max-width: 100%;
height: auto;
}
<div class="container">
<img src="http://placekitten.com/900/500/">
</div>
<div class="container">
<img src="http://placekitten.com/901/500/">
</div>
jsfiddle
If you are OK with using the images as the div background, you can do the following:
Option1:
HTML:
<div class="container" id="first"></div>
<div class="container" id="second"></div>
CSS:
.container {
height: 200px;
width:100%;
overflow: hidden;
margin: 0 0 30px;
border: solid;
background-position: center center;
background-repeat: no-repeat;
}
#first {
background-image: url('http://placekitten.com/901/500/');
}
#second {
background-image: url('http://placekitten.com/900/500/');
}
Update- Option2:
without using the image as background.
HTML:
<div class="container">
<img class="centered" src="http://placekitten.com/900/500/" />
</div>
<div class="container">
<img class="centered" src="http://placekitten.com/901/500/" />
</div>
CSS:
.container {
height: 200px;
width:100%;
overflow: hidden;
margin: 0 0 30px;
border: solid;
}
.centered {
object-fit: none;
object-position: center;
width: 100%;
height: inherit;
}
Please check this option1, option2
For now I'm going to use:
$("img").each(function(){
var hHeight = $(this).height()/2;
$(this).css("top", - hHeight);
});
I would love to see other solutions, especially if they are better.

change image in a div with any effect like fadein when mouse hovered on another div

The below shown is the format of my html code. In the header div i have a image. Each box(box1, box2, box3) inside the contain div has link inside like(software development(box1), Graphic Designing(box2), and Technical Training(box3). These links when clicked will take me to separate pages which has their own header images. So i have 3 header image for each box and a default header image in the home page.In the home page when ever I hover my mouse in the box1 div the header image should change to the box1 header image with an effect like fadeIn and return my default image on mouse out. Same for box2 and box3. Please help me with doing this with CSS or JS or jQuery. Thank You
<body>
<div class="wrapper">
<div class="out">
<div class="in">
<div id="header"></div>
<div class="contain">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</div>
</div>
</div>
</div>
</body>
css:
.wrapper{
width: 100%
height: auto;
margin: 0px;
}
.out{
margin: auto;
width: 1000px;
height: 730px;
border-top: 5px solid #333333;
}
.in{
width: 900px;
height: 640px;
margin: auto;
margin-top: 25px;
}
#header{
background:url(../img/Untitled-1.jpg);
height: 175px;
width: 900px;
margin: 0px;
}
.contain{
margin: 0px;
width: 900px;
height: 428px;
}
.box1{
height: 360px;
width: 295px;
float: left;
margin: 67px 0px 0px 0px;
position: absolute;
background-color: #e6e7e9;
border-bottom: 4px solid #735d8c;
}
.box2{
height: 360px;
width: 295px;
float: left;
margin: 67px 0px 0px 302px;
position: absolute;
background-color: #e6e7e9;
border-bottom: 4px solid #735d8c;
}
.box3{
height: 360px;
width: 295px;
float: left;
margin: 67px 0px 0px 602px;
position: absolute;
background-color: #e6e7e9;
border-bottom: 4px solid #735d8c;
}
I have a made an BIN
I am placing same image for all the 3 divs like
$('#content,#content2,#content3').mouseover(function(){
$('#header').css('background','url(http://www.google.com/mobile/android/images/android.jpg)')
});
You change with your respective images like
$('#content').mouseover(function(){
$('#header').css('background','url(http://www.google.com/mobile/android/images/android.jpg)')
});
$('#content2').mouseover(function(){
$('#header').css('background','url(http://www.google.com/mobile/android/images/android.jpg)')
});....
jsBin demo
jQuery:
var currPage = 0; // PLAY HERE: set here current page (0 = home)
var $header = $('#header');
var $headerImg = $header.find('img');
$headerImg.eq( currPage ).show().addClass('currentImg');
// clone images to boxes:
var c = 0;
$('.box').each(function( i ){
$(this).prepend( $headerImg.eq(i==currPage? (i+1+c++) : c+i).clone() );
});
$('.box img[class^=headImg]').on('mouseenter mouseleave', function( e ){
var opacity = e.type=='mouseenter' ? 1 : 0 ;
var myClass = $(this).prop('class'); // get class
var $mainImg = $header.find('img.'+myClass);
$headerImg.hide();
$mainImg.stop().fadeTo(300, opacity);
$('.currentImg').stop().fadeTo(600, !opacity);
});
HTML:
<div class="wrapper">
<div class="out">
<div class="in">
<div id="header">
<img class="headImg1" src="home.jpg" alt="" />
<img class="headImg2" src="ONE.jpg" alt="" />
<img class="headImg3" src="TWO.jpg" alt="" />
<img class="headImg4" src="THREE.jpg" alt="" />
</div>
<div class="contain">
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
</div>
</div>
</div>
</div>
MODIFIED CSS PART:
/*ADDED*/
#header img{
position:absolute;
display:none;
}
.contain{
margin: 0px;
width: 900px;
height: 428px;
}
.box{ /* CHANGED */
height: 360px;
width: 294px;
float: left;
margin: 67px 3px 0px;
position: relative;
background-color: #e6e7e9;
border-bottom: 4px solid #735d8c;
}
/* ADDED */
.box img{
width:100%;
}
See this : http://jsfiddle.net/xTjQT/2/
$('a').mouseover(function() {
var src = $(this).attr('alt');
alert(src);
$('#header img').stop().fadeOut(100, function() {
$(this).attr('src', src);
$(this).fadeIn(100);
});
});
$('a').mouseout(function() {
$('#header img').stop().fadeOut(200, function() {
$(this).attr('src', 'http://jsfiddle.net/img/logo.png');
$(this).fadeIn(100);
});
});

Categories