I am attempting to make a div change position on click and then revert to it's original position when clicked again. I cannot for the life of me figure out what the problem is.
$("#bottom").click(function() {
var $about = $('#bottom'),
top = $about.css('top') === '50%' ? '90%' : '50%';
$about.stop().animate({top: top}, 500);
});
my css is:
#bottom {
top: 90%;
left: 0; right: 0;
height: 100%;
}
When I click #bottom, the div positions itself at 50%, but when I hit it again, nothing happens.
.css('top') doesn't give you the literal CSS top declaration; it gives you the calculated pixel amount of the top. If your container for #bottom is 100px tall, then $('#bottom').css('top') will give you 90px, not 90%.
Here's a fiddle with a solution for you.
Related
How do I enlarge a div while scrolling from a size of 20% width and height in the center to 100% width and height?
I'm currently trying at my first website and I'm almost there. All that is missing is animations and improvements in CSS. One of my ideas is that you have a div with a background inside and while scrolling the picture gets bigger up to the whole viewpoint. I would be very grateful if someone could help me.
You can use transform scale to do it.
CSS part will set the element to take 100% of width and height (i use viewport units), and set it position to fixed (so you will see what happen when you scroll).
Since we gonna change it's scale while scroll, set it initial scale to be 20% of it's original size.
JS part will listen to scroll event and scale the div that it won't be less then 20% but also won't be larger then 100%.
Play with the numbers on the condition to get what you need:
const demoDiv = document.querySelector("#demo");
window.addEventListener('scroll', function() {
if (pageYOffset*0.0001 > 1 || pageYOffset*0.0001 < 0.2) { return; }
else { demo.setAttribute('style', 'transform: scale('+pageYOffset*0.0001+');'); }
});
body {height: 40000px; margin: 0; padding: 0;}
p {position: fixed; top: 0; left: 0; font-size: 40px;}
#demo {
text-align: center;
font-size: 10vw;
position: fixed; top: 0; left: 0;
width: 100vw;
height: 100vh;
background-color: black;
color: white;
transform: scale(0.2); /* since you ask for 20% */
}
<p style="">Scroll to see it grow.</p>
<div id="demo">My minumum width and height are 20% and i will stop grow when i get to 100%</div>
Firstly, Congratulations on your first website. Good luck on your coding journey.
You can do it by using CSS & JavaScript. There is many way, but I'm writing one here. I hope it will be some good.
Let us call the div with an CSS ID animatedDiv.
<div id="animatedDiv"></div>
Now, lets style it with CSS
#animatedDiv
{
margin-top: 200px;
background: #dc143c;
min-height: 350px;
min-width: 20%;
position: absolute;
}
Here, I gave the div a background color, Absolute type of position, and margin-top of 200px. You can change it according to your needs. I used min-height and min-width property because these value will not be any fixed value, they will change on scroll.
Now, lets write some JavaScript
var aDiv = document.getElementById("animatedDiv");
function changeWidth()
{
var scrollVal = window.pageYOffset;
var scrollSlow = (scrollVal / 4);
//Changing CSS Width
aDiv.style.width = Math.min(Math.max(scrollSlow, 20), 100) + "%";
}
window.addEventListener('scroll', function()
{
requestAnimationFrame(changeWidth);
}, false);
Here, on a user define function, I catch the div with it's ID and assign into aDiv variable. Then I catch the page offset on Y axis (How much pixel the page was scrolled) and store it into a variable scrollVal, Next I divide the value by four (you can use 5, 10 20). It will slow the changing effect.
I've use Math methods (min and max) to assign a value between 20 to 100%.
To make the function work on scroll, window.addEventListener is used, and the window.requestAnimationFrame() method will tell the browser that we wish to perform it as an animation.
I hope it will be some help to you. I don't know did I explain well the process to you or not. English is not my mother language, so please don't mind if I made any grammatically mistake.
Wish you all the best.
I am trying to use the new top and left of the child div inside a rotated parent to limit the draggable area of the rotated parent. Im using jquery draggable for this.
EDIT :
Here is the jsfiddle . Im planning to use the red dot on the rotated div to use as marker to check if it collided with the boundaries of the container. I need to get the new position(top and left) of that red marker to make use of my ready made function to contain the draggable.
In order to calculate the top or left offset for any element, you need to use .getBoundingClientRect(), in addition to accounting for the window scroll.
This is also the case for rotated elements, as can be seen in the following example:
function findTopLeft(element) {
var rec = document.getElementById(element).getBoundingClientRect();
return {
top: rec.top + window.scrollY,
left: rec.left + window.scrollX
};
}
console.log(findTopLeft('inner'));
#outer {
position: absolute;
top: 25%;
left: 25%;
width: 100px;
height: 50px;
border: 1px solid black;
transform: rotate(90deg);
}
<div id="outer">
<div id="inner">Text</div>
</div>
Hope this helps! :)
Would it be possible to have a DIV position: fixed, but if the content of that DIV extend beyond the viewing area of the screen then you could still scroll with the window? I've put everything I have thus far in this...
FIDDLE
This code sits inside a media query that gets triggered when the screen hits a max width and/or a max height, but I don't think that code is relevant to my question. This is the bit of code that I believe I need to modify to work correctly:
.expand {
display: block !important;
position: fixed;
-webkit-backface-visibility: hidden;
top: 50px;
left: 0;
background: rgba(31, 73, 125, 0.8);
width: 100%;
z-index: 999;
}
The reason I want this fixed is so the little hamburger menu stays statically in the upper left hand corner of the screen at all times, as at times the site I'm building could be rather lengthy, so I would like viewers to have a little more ease of access.
Thank you!
Yes, you just need to give the div a fixed height and the overflow: auto setting
(Demo)
.expand {
bottom: 0;
overflow: auto;
}
If you don't want to give it a minimum height, a simple (but not supported by old browsers) option would be to use css calc() like so
.expand {
max-height: calc(100% - 50px); // 100% viewport height minus the height of the nav.
}
I would suggest setting a fallback height before in case the browser does not support calc
JavaScript
To achieve what you really want you need javascript. Here it is.
Check to see if the menu is open, if not...
Define a check to see if the contents are larger than the viewport, if so then set bottom: 0px; and overflow: auto and remove scrolling from the body.
If so...
Remove all styles from the menu and the body that were added when opening the menu.
(Demo)
(function($) {
var menu = $('.responsive-menu'), open;
$('.menu-btn').click(function () {
if(!open) {
if(menu.height() > $(window).height()) {
open = true;
menu.css({'bottom': '0px', 'overflow': 'auto'});
document.body.style.overflow = 'hidden';
}
} else {
open = false;
menu.css({'bottom': '', 'overflow': ''});
document.body.style.overflow = '';
}
menu.toggleClass('expand');
});
})(jQuery);
I have a div with position: absolute and overflow: auto. Inside this div I have a div that should act sticky and should be fixed(top: 0, bottom: 0, overflow: auto) when I scroll.
I can fix this div, but I can't return it to original position because I can't attached the scroll event when this div is fixed.
$('.right').scroll(function() {
if ($('.scroll').offset().top <= 0) {
$('.scroll').css({
'position': 'fixed',
'top': 0,
'left': '20px',
'right': '0',
'overflow': 'auto'
})
}
})
Please check my JSFiddle for more info - JSFIDDLE
Thank you.
Here's how I would do it. This doesn't position it fixed but it has the same appearance. Once scrollTop is equal to or greater than where the top of the fixed content "should be" then we set the top absolutely to that of scrollTop, if you scroll upwards once the scrollTop reaches the point where the fixed content used to be, it will drop it again.
$(document).ready(function() {
oldOffset = $('.scroll').offset().top;
$('.right').scroll(function() {
if ($('.right').scrollTop() > oldOffset) {
$('.scroll').css({
'position': 'absolute',
'top': $('.right').scrollTop(),
'left': '20px',
'right': '0',
'overflow': 'auto'
});
}
});
});
(Demo)
Set the outside div to
position: relative;
Set the inside div to
position: absolute;
top: 15px;
right: 15px;
This will put the top right corner of the inside div at the designated location within the parent container. When setting position absolute, the image is set relative to the first parent container with position defined to anything other than default, I believe. If there is no DOM element assigned a position, the absolute element will be positioned relative to the viewport.
It is very strange task you want to accomplish :)
But anyway there is the problem:
When you set you inner div to position: fixed you positioned this div above your div.right and it is prevents scrolling event from fire.
So what you need is to set pointer-events: none to the div.scroll to allow your div.right listen scroll events without any problems.
But when you do that you will face another problem - when you set your div.scroll to position: fixed it will lose its place inside the div.right and div.right jumps to the top of the scroll automatically. To prevent that you need to create clone of the div.scroll and set his height to 0 initially, and to auto when your inner element is fixed.
Note pointer-events: none - disable all mouse events including the text selection.
There is the code:
JS
$(document).ready(function() {
var cnt = $('.right');
var scrollEl = $('.scroll');
var scrollClone = scrollEl.clone().addClass('clone');
scrollEl.before(scrollClone);
cnt.scroll(function() {
var expression = scrollClone.offset().top <= 0;
scrollEl.toggleClass('stick', expression);
scrollClone.toggleClass('stick-clone', expression);
})
})
CSS
.scroll {
background: yellow;
pointer-events: none;
overflow: hidden; /* Remove top offset from h1*/
}
.scroll.stick {
position: fixed;
left: 20px;
right: 0;
top: 0;
}
.scroll.clone {
height: 0;
overflow: hidden;
}
.scroll.clone.stick-clone {
height: auto;
}
JSFiddle
You can try the following example:
Firstly, instead of adding the css as inline styles, create a css class that you can add and remove from the .scroll element.
CSS
.fixed-top {
position:fixed;
top:0;
left:20px;
right:20px;
}
Wrap your .scroll element with another div which will be used in the javascript to keep track of the original height of your .scroll div.
HTML
<div class="scroll-wrapper">
<div class="scroll"></div>
</div>
Lastly, store the scrollTop value in a variable when the fixed position is applied for the first time. You can then use that value to determine when to remove the fixed styles from the .scroll div. Also set the height of the .scroll-wrapper element equal to the height of your .scroll element to make sure the content is scrollable.
Javascript
var startScrollTop = 0;
$('.right').scroll(function () {
var $scroll = $('.scroll');
if ($scroll.offset().top <= 0 && $('.right').scrollTop() > startScrollTop) {
if (startScrollTop === 0) {
startScrollTop = $('.right').scrollTop();
}
$('.scroll-wrapper').css("height", $('.scroll').height() + 300);
$scroll.addClass("fixed-top");
} else {
$scroll.removeClass("fixed-top");
}
})
Take a look at this fiddle.
http://jsfiddle.net/a924dcge/25/
Hope that helps!
Im trying to add a footer at the bottom of this content that doesn't overlay the content but moves it up.
The only way I can see it working would be something like, when browser is at the bottom remove 'fixed' class on the left red '#work'.
js fiddle DEMO
Updated js fiddle DEMO
HTML
<div id="header-block">
Header-block, this sits here in the background
</div>
<div id="content">
<div id="work">
This content should be fixed when at the top
</div>
<div id="description">
This content should scroll -
</div>
</div><!-- end content -->
<div id="footer">
This should appear at the bottom
</div>
CSS
body {
margin: 0px;
padding: 0px;
}
#header-block {
background: green;
width: 100%;
position: fixed;
z-index: 1;
height: 300px;
top: 0;
}
#content {
margin-top: 300px;
width: 100%;
position: relative;
z-index: 2;
}
#work {
background: red;
width: 50%;
height: 100vh;
float: left;
position: absolute;
}
#description {
background: blue;
width: 50%;
height: 1200px;
float: right;
font-size: 30px;
}
#footer {
background: black;
width: 100%;
height: 100px;
position: absolute;
z-index: 3;
bottom: 0;
}
If I understand your question correct, this should do the trick (although it depends very much on JavaScript unfortunately).
// Fix work column on scroll
contentStart = $("#content").offset().top ;
contentSize = $("#content").height() ;
window.onscroll = function(){
if( window.XMLHttpRequest ) {
var position=window.pageYOffset;
// calculate the position of the footer and the actual seen window
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $("#footer").offset().top;
if ( position > 300 && !(docViewBottom >= elemTop)) {
$('#work').css({'position':'fixed', 'top':'0', 'height':'100vh'});
} else {
// if the footer is visible on the screen
if(docViewBottom >= elemTop) {
$('#work').css({ 'top': 0 - (docViewBottom - elemTop) }); // scroll the #main div relative to the footer
} else {
$('#work').css({'position':'relative', 'top': 'auto'}) ;
}
}
}
}
For further informations about the calculations, perhaps this question on stackoverflow is useful.
Edit: Andrew Haining posted his answer in between of my answer, perhaps give his link a try and maybe it's a better (more proper) solution. Unfortunately I haven't actualised this page when I was testing your code in JSFiddle and I didn't see his answer.
If you want to use my script, make sure you can test it with different resolutions. It works just fine for my resolution in JSFiddle, I didn't test any other.
I'm not 100% sure what you want, but if you remove the position: absolute and the bottom: 0 from the footer, and put a div with class='clearboth' above the footer, it seems to do what you need.
CSS
.clearboth {
clear: both;
}
This is a drawing of what I see on your fiddle;
Do you want the red and the blue to always be touching the black?
I don't see the red overlying the black
You should use jQuery to add a class containing the position:fixed value when the scroll position of the page is less than the inline position of the #work div. Once it scrolls past the position, remove the class and have the element fall back in line.
You can achieve this using the following jQuery methods.. .scrollTop() .offset().top() and $(window).height().
This tutorial will give you an understanding of what you need to do to achieve the necessary results, you will just have to change the calculation slightly using $(window).height(), $('#footer').height() and a few other changes to get what you desire.
Based on the question you asked i think this is what you mean. The red div should be fixed when it gets to the top but be absolute when it is below the top for scrolling and the black footer should be below the red while scrolling, check this code i have done for you. just add this jquery script and run it.
<script type="text/javascript" src="js/jquery.js"></script>
<script>
$(document).ready(function() {
$(window).scroll(function () {
console.log($(window).scrollTop());
if ($(window).scrollTop() >= 322) {
$('#footer').css("z-index","1");
$('#work').css(
{
"background": "red",
"width": '50%',
'height': '100vh',
'float': 'left',
'position': 'fixed',
'top': '0'
});
}
if ($(window).scrollTop() <= 322)
{
$('#work').css(
{
"background": "red",
"width": "50%",
"height": "100vh",
"float": "left",
"position": "absolute"
});
};
});
});
</script>
If not exactly a parallax, this is somewhat close to how parallax works, containers moving at different speeds, and some containers sitting fixed or scrolling when they attain a particular top/bottom offset in the viewport.
There's plugin that can do it. Skrollr
You can use Skrollr along with skrollrcss, and it'll make sure how the containers take position on screen based on scrolltop of the window and the container specifically.