I have a landing page, consisting of three frames, this frames always take 100% of viewport height and width.
I need to make transitions between frames, like "powerpoint presentation" etc. User scroll's, frame-1 slides up above viewport and frame-2 becomes in his place from bottom of viewport. I have almost zero experience in javascript/jquery. Have some ideas, that you can see in the code, but this ideas not works.
HTML:
<div class="wrapper" id="wrapper">
<div class="frame frame-1">
<!-- Content here -->
</div>
<div class="frame frame-2">
<!-- Content here -->
</div>
<div class="frame frame-3">
<!-- Content here -->
</div>
</div>
CSS:
.wrapper {
height: 300vh;
}
.frame {
position: fixed;
height: 100vh;
transition: all 1s ease;
}
.frame-1 {
top: 0vh;
}
.frame-2 {
top: 100vh;
}
.frame-3 {
top: 200vh;
}
JS:
var $document = $(document),
$element1 = $('.frame-1'),
$element2 = $('.frame-2'),
$element3 = $('.frame-3');
$(window).scroll(function () {
if ($(this).scrollTop() >= 50) {
$element1.css("top", "-100vh");
$element2.css("top", "0vh");
$element3.css("top", "100vh");
} else if ($(this).scrollTop() >= 100) {
$element1.css("top", "-200vh");
$element2.css("top", "-100vh");
$element3.css("top", "0vh");
} else {
$element1.css("top", "0vh");
$element2.css("top", "100vh");
$element3.css("top", "200vh");
}
});
If you have a set number of frames, I would suggest placing them all in a single div, and changing the top value of that. that way, only one value need be modified.
Like this: http://jsfiddle.net/xkh4D/10/
(Note that, though px are used, vh or whichever other unit should work just as well... haven't tried %, though...)
HTML
<div id='yo' class='view'>
<div>
<div class='frame red'></div>
<div class='frame green'></div>
<div class='frame blue'></div>
</div>
</div>
<input type='button' value='Scroll' onclick='scrollFrame()'/>
CSS
.view {
position:relative;
width:300px;
height:250px;
border:1px solid black;
overflow:hidden;
}
.view > div {
position:absolute;
width:inherit;
height:inherit;
top:0px;
}
.frame {
width:inherit;
height:inherit;
}
.red { background-color:#faa }
.green { background-color:#afa }
.blue { background-color:#aaf }
JavaScript
scrollFrame = function()
{
var h = $('#yo').height();
var y = parseFloat($('.view > div').css('top'));
var hsum = $('.view .frame').length * h;
console.log('h,y,hsum',h,y,hsum);
if (hsum-h == -1*y)
$('.view > div').animate({'top':0});
else
$('.view > div').animate({top:y-h},500);
}
This js could be your solution
http://alvarotrigo.com/fullPage/
Related
I am expecting the images to shift to the right. Runner increments and prints 1px, 2px, 3px etc. to console, but new margin wont be set. What's the problem?
Together with the code below, what I have written above should be sufficient to understand my problem. But I am, at this point, simply writing to get rid of the prompt to write more text.
<body>
<div class="normal">
<img id="normal" src="whiteboard.jpeg">
</div>
<div class="scaled">
<img id="scaled" src="whiteboard.jpeg">
</div>
</body>
<style>
.normal{
background-image: url('whiteboard.jpeg');
position:absolute;
z-index:-1;
}
.scaled{
transform:scale(120%);
z-index:2;
clip-path: circle(5% at 33% 42%);
}
.normal, .scaled{
width:100vw;
}
div img{
width:100%;
height:auto;
}
</style>
<script>
window.onload=function(){
const normal = document.getElementById('normal');
const scaled = document.getElementById('scaled');
let runner =0;
setInterval(function(){
normal.style.marginRight="-"+runner+"px";
scaled.style.marginRight="-"+runner+"px";
runner++;
console.log("respons - "+runner+"px")
},50);
}
</script>
The marginRight style describes the distance of the div element to its parent's right side. A negative marginRight will not work here - instead try marginLeft. Depending your desired direction of the animation use a positive or negative value.
window.onload = function() {
const normal = document.getElementById('normal');
const scaled = document.getElementById('scaled');
let runner = 0;
setInterval(function() {
normal.style.marginLeft = "-" +runner + "px";
scaled.style.marginLeft = "-" +runner + "px";
runner++;
console.log("respons - "+runner+"px")
}, 50);
}
<body>
<div class="normal">
<img id="normal" src="whiteboard.jpeg">
</div>
<div class="scaled">
<img id="scaled" src="whiteboard.jpeg">
</div>
</body>
<style>
.normal {
background-image: url('whiteboard.jpeg');
position: absolute;
z-index: -1;
background-color: blue;
}
.scaled{
transform: scale(120%);
z-index:2;
clip-path: circle(5% at 33% 42%);
background-color: red;
}
.normal, .scaled{
width: 100vw;
}
div img {
width: 100%;
height: auto;
}
</style>
I am making a project where I have images animating on a screen as I am scrolling down.I have tried animate but it doesnt seem like it is going with the scroll if i constantly keep going up&down.Hope what i provided helps.
$(window).scroll(function() {
var rep = $(window).scrollTop();
if (rep > 860) {
$('.teaimg').fadeIn();
}
if (rep < 860) {
$('.teaimg').fadeOut();
}
});
.teaimg {
background-image: url("leaf.jpg");
width: 779px;
height: 439px;
position: absolute;
top: 0;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<main>
<div class="laptopbox1">
<img id="laptop" src="laptop.jpg">
<div id="screen">
<p id="text"></p>
<div class="teaimg"></div>
</div>
</div>
</main>
Try to use opacity concept here by adding and removing a class...Using fadeIn() and fadeOut() will give you abrupt effect as its show and hide the element which will also affect the document height and gives fluctuating effect on scroll...
Also use else for the else part of the condition...
I have created a example here...
$(window).scroll(function() {
var rep = $(window).scrollTop();
if (rep > 150) {
$('.teaimg').addClass("show");
} else {
$('.teaimg').removeClass("show");
}
});
.laptopbox1 {
margin: 200px 0;
}
.teaimg {
background-image: url("http://via.placeholder.com/350x150");
width: 350px;
height: 150px;
opacity: 0;
transition: all .3s ease;
}
.teaimg.show {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<main>Scroll
<div class="laptopbox1">
<div id="screen">
<p id="text"></p>
<div class="teaimg"></div>
</div>
</div>
</main>
I have 5 div containers. I want to render the first div to be the entire height of the viewport. And on scroll, next div takes over entire height of viewport. How would I do this?
HTML Code:
<div class="wrapper">
<div id="first-container" >
<p> hello </p>
</div>
<div id="second-container">
<p> hello </p>
</div>
<div id="third-container">
<p> hello </p>
</div>
<div id="four-container">
<p> hello </p>
</div>
<div id="five-container">
<p> hello </p>
</div>
</div>
I found this simple CSS code. It works on the first div but then doesn't allow me to scroll to the next div.
#first-container{
position: fixed !important;
position: absolute;
top:0;
right:0;
bottom:0;
left:0;
}
#second-container{
background-image: url("blue-gradient.png");
}
#third-container{
background-color: #A8CEFF;
}
#four-container{
background-image: url("green-gradient.png");
}
#five-container{
background-color: #394457;
}
UPDATE:
I've created a working fiddle of this: https://jsfiddle.net/zrgLahbx/1/ for demonstration
How to set to 100% height of the viewport
You can set the CSS height property of the and div containers (#first-container, #second-container etc.) to 100vh.
This 100vh essentially means "set the height to 100% of the viewport height (vh).
Like so:
#first-container {
height: 100vh;
}
#second-container {
height: 100vh;
}
... and so on ...
Personally, I would create a class for this:
.full-viewport-height {
height: 100vh;
}
Then apply this to each container:
<div class="full-viewport-height" >
<p> hello </p>
</div>
<div class="full-viewport-height">
<p> hello </p>
</div>
... and so on ...
Furthermore
I would also advise to set a fallback value (just above the 100vh). Just in case the browser does not support vh - trust me I've seen this happen.
Like this:
.full-viewport-height {
height: 800px;
height: 100vh;
}
CSS goes top-down. So, in case the browser does not support vh, it will use the first value.
If the browser does support vh, the vh value will override the first px value, anyway.
I would advise using ems if you can, instead of pixels.
Why what you've tried didn't work
Setting the position: fixed property like you have done, along with the top, bottom... etc. will make that div appear fixed to 100% of the screen, and not move whatsoever.
Confusingly, you then set the position to absolute.
Hope this helps! :)
Set your html, and body to height: 100% and apply height: 100% to your sections. Like this:
HTML
<div class="wrapper">
<section>
Content 1
</section>
<section>
Content 2
</section>
<section>
Content 3
</section>
<section>
Content 4
</section>
<section>
Content 5
</section>
</div>
CSS
body, html {
height: 100%;
width: 100%;
}
section {
height: 100%;
width: 100%
}
Your position code will make any DIV take up the whole screen and ignore scrolling. You need to pull that code out into a class:
.active {
position: fixed !important;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
Then you can use the vh unit to specify that all child DIVs take up 100% of the viewport. Only the active one will ever be visible, but you need this to block off the space in the document and to calculate where they change.
.wrapper>div {
height: 100vh;
}
Next you need to tap into the scroll event and set the active class based on current positioning.
(function() {
'use strict';
var containers = [...document.querySelectorAll('.wrapper > div')],
heights = containers.map(c => $(c).height()),
scrollTops = [],
currentIdx = 0,
nextUp = null,
nextDown = null;
heights.forEach( (h,i) => scrollTops.push(h + scrollTops[i-1] || 0) );
setCurrentIdx(0);
function setCurrentIdx(idx){
if (containers[currentIdx])
containers[currentIdx].classList.remove('active');
currentIdx = idx;
containers[currentIdx].classList.add('active');
nextUp = ( idx === 0 ? null : scrollTops[currentIdx] );
nextDown = ( idx === scrollTops.length - 1 ? null : scrollTops[currentIdx + 1] );
}
function move(direction){
var newIdx = currentIdx + (direction === 'up' ? -1 : 1);
if (newIdx < 0 || newIdx >= containers.length)
return;
setCurrentIdx(newIdx);
}
$(window).scroll(function() {
var currentScroll = $(this).scrollTop();
console.log(nextUp, '<--', currentScroll, '-->', nextDown);
if (nextDown && currentScroll > nextDown)
move('down');
if (nextUp && currentScroll <= nextUp)
move('up');
});
}());
.wrapper>div {
height: 100vh;
}
.wrapper{
margin-bottom:100vh;
}
#first-container {
background-color: gray;
}
#second-container {
background-color: blue;
;
}
#third-container {
background-color: #A8CEFF;
}
#four-container {
background-color: green;
}
#five-container {
background-color: #394457;
}
.active {
position: fixed !important;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div id="first-container" class="active">
<p>hello 1</p>
</div>
<div id="second-container">
<p>hello 2</p>
</div>
<div id="third-container">
<p>hello 3</p>
</div>
<div id="four-container">
<p>hello 4</p>
</div>
<div id="five-container">
<p>hello 5</p>
</div>
</div>
I would like to have some help about the transition of a div in CSS or JavaScript.
I have a <div> with dispay:none;.
With some JS, i change the display option on display:block.
All is working correctly.
But i would like to know how to make a transition when the <div> appear on the screen.
Like the player Spotify when you want to search something.
Thanks for you help.
And really sorry for my BAD english !
You can do it with a JQuery like this:
$(function() {
var open=false;
$('.menubar span').click(function(){
if(open==false){
$('.search').css('left','50px');
open=true;
}
else{
$('.search').css('left','-100px');
open=false;
}
});
});
.menu{
position:fixed;
left:0;
top:0;
width:50px;
height:100%;
background:#222021;
z-index:4;
}
.menubar{
width:50px;
height:100%;
color:white;
font-family:arial;
}
.search{
position:absolute;
left:-100px;
top:0;
width:100px;
background:lightgrey;
height:100%;
-o-transition:.3s;
-ms-transition:.3s;
-moz-transition:.3s ;
-webkit-transition:.3s;
transition:.3s ;
}
.search input{
margin:0;
width:75px;
border:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="menu">
<div class="menubar">
<span>Home</span>
</div>
</div> <div class="search"><input type="search"></div>
Click "Menu" in the menu bar, and the search bar slides out, click again to hide it.
To use JQuery, you have to include the jquery library:
include this in <head>:
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
Or download it from:http://jquery.com/download/
Then, just use the script like normal JS, in a <script> tag.
EDIT:
With your problem in the comments below, #navbar had a static position, which means z-index will not work for it:
#nav-bar {
background-color: #23232C;
bottom: 0px;
left: 0px;
top: 0px;
width: 220px;
height: 100%;
margin-top: -17px;
z-index: 99;
position: absolute;
}
The following answers uses CSS Style Declarations to accomplish the transition effect.
if you declare the transition: all 1s style on an element. If the style property changes on that element your browser's (user-agent's) graphic device will calculate and update the frames (or visual changes) that occur between the two states (initial state, and end state). However, the property that is being changed must be scalar; that is, both the initial value and new value are scalar (like 0% being set to 100%). Additionally, if you're changing a property that is not scalar, but affects the rendering of other properties.. they will skip the transition effect (aka display:none being set to display:block).
Note: Instead of changing the inline style on the elements using Javascript, we're going to instead change the class of those elements; meaning, the following styles represent visual states, which we'll toggle between..
Again, the transition style declaration (or rather, the graphic device) will handle the incremental rendering of the frames between these two states.
Code Sample of changing 4 style properties (explicitly)
var str = 'hide';
var btn = document.querySelector("button#toggler").addEventListener('click', function(ev)
{
var elms = document.querySelectorAll('div.block');
for (var i = 0, lng = elms.length; i < lng; i++)
{
elms[i].className = elms[i].className.replace("hide", "").replace("show", "").replace(" ", "");
elms[i].className = elms[i].className + ' ' + str;
}
str = (str === 'show') ? str = 'hide' : 'show';
});
.block {
display:block; position:absolute;
top:0;
left:0;right:80%;
bottom:0;
background-color: rgba(0,0,0);
border:0.1em solid black;
min-width:5em;
transition: left 2s, opacity 2s, right 2s, background-color 1s;
}
.wrapper
{
display:block;position:relative;background-color:whitesmoke;
min-height:10em;
width:auto;
}
.show {opacity:1;left:0%;right:80%;background-color:rgb(255,0,0);}
.hide {opacity:0;left:80%;right:0%;background-color:rgb(0,0,255);}
<button id="toggler">Toggle Block</button>
<div class="wrapper">
<div class="block"></div>
</div>
The following is a fairly more complex slider, which ulitmately uses the same principal for rendering the transitions.
$("div.slide > button.show" ).on('click', function (ev)
{
var slide = $(ev.target).closest(".slide");
slide.toggleClass("hide").toggleClass("show");
var slidePrev = slide.prev();
slidePrev.toggleClass("hide").toggleClass("show");
slidePrev = slidePrev.prev();
slidePrev.toggleClass("hide").toggleClass("show");
slidePrev = slidePrev.prev();
slidePrev.toggleClass("hide").toggleClass("show");
slidePrev = slidePrev.prev();
slidePrev.toggleClass("hide").toggleClass("show");
})
$("div.slide > button.hide" ).on('click', function (ev)
{
var slide = $(ev.target).closest(".slide");
slide.toggleClass("hide").toggleClass("show");
var slideNext = slide.next();
slideNext.toggleClass("hide").toggleClass("show");
slideNext = slideNext.next();
slideNext.toggleClass("hide").toggleClass("show");
slideNext = slideNext.next();
slideNext.toggleClass("hide").toggleClass("show");
slideNext = slideNext.next();
slidePrev.toggleClass("hide").toggleClass("show");
})
html, body {display:block;position:relative;margin:0 auto;padding:0;height:100%}
div.wrapper {position:relative;
left:0;right:0;top:0;bottom:0;
width:auto;
background-color:whitesmoke;
display:block;
overflow:hidden; height:100%;
}
button {line-height:2em;padding:0.2em;display:block;}
div.slide {
display:block;
position:absolute;
border:0.2em solid black;
background-color:white;
top:0;
bottom:0;
right:0;
left:0;
opacity:1;
transition: left 1s, opacity 0.5s;
}
div.slide:nth-child(1) {
left: 1em;
z-index: 1;
}
div.slide:nth-child(2) {
left: 3.5em;
z-index: 2;
}
div.slide:nth-child(3) {
left: 6em;
z-index: 3;
}
div.slide:nth-child(4){
left: 8.5em;
z-index: 4;
}
div.slide.hide {
opacity:0.3;
left: 59%;
}
div.slide.show {
opacity:1;
}
div.show > button.show {display:none;}
div.hide > button.hide {display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="slide show">
<button class="show">show</button>
<button class="hide">hide</button>
</div>
<div class="slide show">
<button class="show">show</button>
<button class="hide">hide</button>
</div>
<div class="slide show">
<button class="show">show</button>
<button class="hide">hide</button>
</div>
<div class="slide show">
<button class="show">show</button>
<button class="hide">hide</button>
</div>
</div>
I want to divide my website into two parts: a header containing a large image, and a main part, containing other images, text, etc.
When I scroll the page, the large image on the header should scroll together with the main part. In a certain point, the image should become fixed, and the main part scroll behind it.
I have tried some different approaches, but I can't get the right combination of position, display, top, etc to work.
That's the closest I've got so far: https://jsfiddle.net/aor0abhf/
HTML
<body onscroll='scroll(event)'>
<div class='top' id='top'><img src='http://www.vejanomapa.net.br/wp-content/uploads/2013/03/Maria-Fuma%C3%A7a-em-Tiradentes-MG.jpg'></div>
<div class='bottom'>
<div class='menu'>Menu</div>
<div class='main'><img src='http://tvulavras.com.br/wp-content/uploads/2017/04/maria-fuma%C3%A7a.jpg'></div>
</div>
</body>
Javascript
function scroll(e) {
var T = document.getElementById('top');
var imgH = T.clientHeight; // header image height
var hH = 200; // fixed header height
if (imgH-e.pageY > hH) { // image is scrolling
T.style.top = '-'+e.pageY+'px';
T.style.position = 'sticky';
} else { // image should remain fixed
T.style.top = '-'+(imgH-hH)+'px';
T.style.position = 'fixed';
}
}
CSS
html, body {
margin:0;
}
body {
overflow-y:scroll;
overflow-x:hidden;
}
img {
display:block;
}
.top {
background:#FCC;
display:block;
top:0;
}
.bottom {
display:flex;
min-height:1500px;
background:#CFC;
}
.menu {
width:100px;
background:#CCF;
}
But still there's a glitch in the transition between scroll/fixed positions. And if the left menu (in light blue) could stick together, that would be great! (Maybe subject to another question?)
I updated your fiddle to the following:
No Change to HTML
<body onscroll='scroll(event)'>
<div class='top' id='top'><img src='http://www.vejanomapa.net.br/wp-content/uploads/2013/03/Maria-Fuma%C3%A7a-em-Tiradentes-MG.jpg'></div>
<div class='bottom' id='bottom'>
<div class='menu'>Menu</div>
<div class='main'><img src='http://tvulavras.com.br/wp-content/uploads/2017/04/maria-fuma%C3%A7a.jpg'></div>
</div>
</body>
CSS
html, body {
margin:0;
}
body {
overflow-y:scroll;
overflow-x:hidden;
}
img {
display:block;
}
.top {
background:#FCC;
display:block;
top:0;
}
/* start new rules */
.active{
position: fixed;
}
.active ~ .bottom {
margin-top: 386px;
padding-left: 100px;
}
.active ~ .bottom .menu {
position: fixed;
top: 200px;
bottom: 0;
left: 0;
}
/* end new rules */
.bottom {
display:flex;
min-height:1500px;
background:#CFC;
}
.menu {
min-width:100px;
background:#CCF;
}
Javascript
function scroll(e) {
var T = document.getElementById('top');
var B = document.getElementById('bottom');
var imgH = T.clientHeight; // header image height
var hH = 200; // fixed header height
if (imgH-e.pageY > hH) { // image is scrolling
T.classList.remove('active') // remove class active as applicable
T.style.top = '-'+e.pageY+'px';
T.style.position = 'sticky';
B.style['margin-top'] = '0';
} else { // image should remain fixed
T.classList.add('active') // add class active as applicable
T.style.top = '-'+(imgH-hH)+'px';
}
}
Remove
min-height:1500px;
The div height will stay 1500px;
Try this one
.bottom {
display:flex;
background:#CFC;
}
This should work.
Add margin-top:200px; on <div class='bottom'> part on scroll.