I'm encountering a weird (maybe not) behaviour that I want to avoid because the end result is a horrible user experience. To help you understand the problem I put together the code snippet below.
var counter;
var counterDisplay;
var intervalRef;
window.onload = function(){
console.log("loading");
counter = 11;
counterDisplay = document.getElementById("spCounter");
intervalRef = setInterval(tickHandler, 1000);
};
function tickHandler(){
counter--;
counterDisplay.innerHTML = counter.toString();
if(counter == 0){
stop();
return;
}
}
function stop(){
clearInterval(intervalRef);
document.getElementById("daddyLongLegs").style.display = "block";
}
html,body{
width:100%;
height:100%;
font-family:Arial;
font-size:16px;
}
.page-wrapper{
height:100%;
background-color:#eee;
}
.growing-element{
height:800px;
display:none;
margin: 100px 100px 0 100px;
background-color:#ddd;
}
<div class="page-wrapper">
<div class="container-element">
<!--This element's height never changes once the page has been rendered-->
<div>
The hidden child element below will magically appear in: <span id="spCounter">10</span> seconds
</div>
<!--This element's height changes anytime after the page has been loaded-->
<div id="daddyLongLegs" class="growing-element">
Now you see me...
</div>
</div>
</div>
The code snippet is pretty simple, all the javascript does is to display a child element (#daddyLongLegs) after ten seconds. Make the "problem" more visual colored the parent element (div.container-element) different to the child element.
Problem
Now, when the child element (#daddyLongLegs) is displayed after 10 seconds, it doesn't seem to "stretch" the parent element (div.container-element). This is not the behaviour I'd like to achieve. I would like the parent element to re-adjust its height when its contents change. However, it is important that the height of the parent element ALWAYS cover the whole document
Question
How can I make the parent readjust its height once the content has changed? Is there a pure css solution to this?
.container-element has a defined height of 100%
If you remove that, or set it to auto, it should calculate the height based on its content.
Or you could change from height to min-height, which would calculate the height based on its content, but no shorter than 100% of its parent's height.
As described on MDN, you can use min-height attribute instead of height so whenever your <div>'s child rises, it will extend parent as well
so from my comment:
use min-height: 100% instead of height: 100% on your
.page-wrapper
Change height to 100% and margin to 0;
var counter;
var counterDisplay;
var intervalRef;
window.onload = function(){
console.log("loading");
counter = 5;
counterDisplay = document.getElementById("spCounter");
intervalRef = setInterval(tickHandler, 1000);
};
function tickHandler(){
counter--;
counterDisplay.innerHTML = counter.toString();
if(counter == 0){
stop();
return;
}
}
function stop(){
clearInterval(intervalRef);
document.getElementById("daddyLongLegs").style.display = "block";
}
html,body{
width:100%;
height:100%;
font-family:Arial;
font-size:16px;
}
.page-wrapper{
height:100%;
background-color:#eee;
}
.growing-element{
height:100%;
display:none;
background-color:#ddd;
}
<div class="page-wrapper">
<div class="container-element">
<!--This element's height never changes once the page has been rendered-->
<div>
The hidden child element below will magically appear in: <span id="spCounter">10</span> seconds
</div>
<!--This element's height changes anytime after the page has been loaded-->
<div id="daddyLongLegs" class="growing-element">
Now you see me...
</div>
</div>
</div>
Related
I am developing a web application using AngularJS. I find myself in a situation where I have a bar (with the css I created a line) that must dynamically lengthen and shorten.
I know that JQuery scripts are sufficient to do this. For example, if my css is like this:
.my_line{
display:block;
width:2px;
background: #FFAD0D;
height: 200px; /*This is the part that needs to dynamically change*/
}
I could in the controller resize the line (of my_line class) simply with:
$(".my_line").css("height", someExpression*100 + 'px');
The thing is, I would like to dynamically resize the line based on the size of another div element (Or, in general, any HTML element of my choice).
I don't know how to get (at run-time) the size of a certain page element in terms of height.
Only in this way I would be able to create a line that dynamically lengthens or shortens as the size of a div (or some other element) changes!
How do you do this? So I will avoid writing hard-coded the measures but I want make sure that they vary as the dimensions of other elements on the page vary
I hope this is helping:
$(".my_line").css("height", $("#referenceElement").height()*5 + 'px');
.my_line{
display:inline-block;
width:2px;
background: #FFAD0D;
}
#referenceElement {
display:inline-block;
background: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="my_line"></div>
<div id="referenceElement">Hi, I'm 5 time smaller than the orange line!</div>
Here I am using the setInterval to track the div's height (you can do width as well) and storing it in a previousHeight variable and comparing it every interval
Then according to the comparison, it will determine if the height of the div has changed. If it has then it will change the height of the other div according to the height of the first div
You can create multiple variables and track multiple elements in the same setInterval
$(document).ready(function(){
var previousHeight = parseInt($("#my-div").css("height"));
setInterval(function(){ checkHeight(); }, 100);
function checkHeight() {
// Check height of elements here
var currentHeight = parseInt($("#my-div").css("height"));
if(currentHeight != previousHeight) {
previousHeight = currentHeight;
$("#dynamic-div").css("height", parseInt(currentHeight) + "px");
}
}
$("#button").click(function() {
$("#my-div").css("height", parseInt(previousHeight) + 5 + "px");
})
})
#my-div{
background: #000000;
height: 20px;
width: 20px;
}
#dynamic-div{
background: teal;
height: 20px;
width: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="my-div">
</div>
<button id="button">Increase div height</button>
<div id="dynamic-div">
</div>
I've tried searching to see if there's already a question about this but can't find anything - so apologies if this is in fact a duplicate!
I've seen on some websites a feature where, when scrolling, the scroll stop point is forced to stop at a specific element rather than just wherever the user actually stopped scrolling.
I imagine this can be achieved via jQuery, but can't seem to find any documentation or help articles about it.
So, here's some example HTML...
<div id="one" class="block"></div>
<div id="two" class="block"></div>
<div id="three" class="block"></div>
With this as the CSS...
#one {
background: red;
}
#two {
background: green;
}
#three {
background: yellow;
}
.block {
width: 200px;
height: 100vh;
}
And what I'm looking to achieve is that when the user scrolls their browser from div 'one' to div 'two', once they've started scrolling over div 'two' and they then stop scrolling the browser automatically jumps them so that they see div 'two' in full, rather than a bit of the bottom of div 'one' and then most of div 'two' - I've definitely seen it done before but no idea how!
I hope this makes sense, and thanks in advance for any help or insight anyone can offer...
I don't remember too well, but I guess there are many ways to achieve what you want. One thing that came to my mind is to wrap around your divs and make a separate hidden div with full height. I did this adhoc solution below:
Once scroll approaches a threshold, I move to the div I should be looking at and vice versa. Here is a working solution FIDDLE:
HTML
<div id="phantom"></div>
<div id="wrapper">
<div id="one" class="block"></div>
<div id="two" class="block"></div>
<div id="three" class="block"></div>
</div>
CSS
#one {
background: red;
}
#two {
background: green;
}
#three {
background: yellow;
}
.block {
width: 200px;
height: 100vh;
}
#wrapper {
overflow:hidden;
position:fixed;
top:0px;
}
#phantom {
visibility:hidden;
}
JS
!function(){
//the array of divs
var divs = Array.prototype.slice.call(document.getElementsByClassName("block")), count = divs.length,
wrapper = document.getElementById("wrapper"),
phantom = document.getElementById("phantom"),
//the speed of scroll
scrollStep = 5,
//total length of phantom div
totalLength = Array.prototype.slice.call(wrapper.children).reduce(function(ac,d,i,a){return ac += d.clientHeight},0),
//store the animation frame here
currentFrame;
//wrapper is overflow hidden
wrapper.style.height = totalLength/count + "px";
//phantom has full height
phantom.style.height = totalLength + "px";
//add listener for scroll
window.addEventListener("scroll",function(){
//throttle the function
if(this._busy){return};
this._busy = true;
var that = this;
window.requestAnimationFrame(function(){
that._busy = false;
var heightOfDocument = Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),
totalScroll = Math.max(document.body.scrollTop,document.documentElement.scrollTop),
//which element should we look at?
whichElement = Math.round(totalScroll/heightOfDocument*count);
//if we are already around, don't do anything
if(divs[whichElement]._current){
return;
} else {
//cancel the last animation if any and start a new one
window.cancelAnimationFrame(currentFrame);
divs.forEach(function(d,i){delete d._current});
moveTo(divs[whichElement]);
}
});
},false);
//helper function to linearly move to elements
function moveTo(node){
node._current = true;
var top = node.offsetTop,
current = node.parentNode.scrollTop,
distance = top - current,
step = distance < 0 ? -scrollStep : scrollStep;
if(Math.abs(distance) < scrollStep){
node.parentNode.scrollTop = top;
return;
} else {
node.parentNode.scrollTop += step;
}
//store the current frame
currentFrame = window.requestAnimationFrame(function(){
moveTo(node);
});
}
}();
You obviously need to attach 'resize' event to update the values of the totalLength and set the correct new length on wrapper and phantom. You can also implement a easing function to modify the scrolling behavior to your taste. I leave them to you as homework.
I'm having an issue resetting a div's left position with jquery after an animation. I'm trying to animate a div from off the screen(left) to on the screen. However, I only want to trigger this animation if the value of scrollTop of the window is greater than a certain value. once the value of scrollTop is less than the value, I want the div's position to change so that it is offscreen again. This is working but only sometimes and I'm not sure why. I am also setting the position of the div to absolute at the same time I am setting it to go off the screen and this change always works!. Below is the code as well as the CSS of the div I'm trying to animate. Thank you!
Function to change position on scroll
$(window).scroll(function() {
if( $(this).scrollTop() > 500 {
$(".animated-logo").css({position:'fixed'});
$(".animated-logo").animate({left: '20px'},500);
}
else{
$('.animated-logo').css({position: 'absolute',left:'-150px'});
}
});
CSS for the animated-logo element
.animated-logo
{
position:absolute;
top:0;
left:-150px;
width:100px;
z-index:2;
}
So first off, you have a syntax error.
I would approach this with using classes instead of doing it like this. At best you're going to have a buggy transition. You can adjust the css transition to make it your desired timing.
JS:
$(window).scroll(function() {
if( $(this).scrollTop() > 500) {
$(".animated-logo").addClass('visible');
}
else{
$(".animated-logo").removeClass('visible');
}
});
CSS:
.animated-logo{
position:absolute;
top:0;
left:-150px;
width:100px;
z-index:2;
transition:0.5s;
}
.animated-logo.visible{
position:fixed;
left:20px;
}
https://jsfiddle.net/783z9rhm/6/
When you say This is working but only sometimes and I'm not sure why, it's not sure what the problem is so I'll assume you are having issues with the animation after the first time it runs. The is maybe because you are firing it ON EVERY USER SCROLL ACTION, which is a lot. Using a flag to fire it only once every time the 500px threshold is crossed will get rid of the glitch
HIH
var visible = false;
$(window).scroll(function() {
if( $(this).scrollTop() > 500) {
if(!visible){
visible = true;
$(".animated-logo").css({position:'fixed'});
$(".animated-logo").animate({left: '20px'},500);
}
}
else{
visible = false;
$('.animated-logo').css({position: 'absolute',left:'-150px'});
}
});
.animated-logo
{
position:absolute;
top:0;
left:-150px;
width:100px;
height:100px;
z-index:2;
background: red
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="animated-logo"></div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
I have a parent div called lyricpadding, and inside I have a lot of <h4>'s with a unique ID. Anyways, what I need to do us, by using preferably Jquery or Javascript or CSS, is to keep the <h4> marked with the class of highlighted in the middle of the parent container, but I don't want it to stretch over the whole thing, I just want the text to be centered by an automatic scroll until it gets to the bottom. So the div with the class highlighted will always be visible, preferably in the center.
Here is a jQuery example. It uses position absolute and then adjusts according to the scroll position and window size. See this fiddle.
HTML:
<div class='lyricpadding'>
<h4 class='highlighted'>Highlighted</h4>
<h4>Other</h4>
<h4>Other</h4>
<h4>Other</h4>
<h4>Other</h4>
</div>
CSS:
.lyricpadding
{
height:1000px;
width:100%;
background-color:lightblue;
}
.highlighted
{
display:inline-block;
position:absolute;
}
jQuery:
function positionMiddle()
{
var $highlighted = $('.highlighted');
$highlighted.css({
left: ($(window).width() - $highlighted.outerWidth())/2,
top: $(window).scrollTop() + ($(window).height() - $highlighted.outerHeight())/2
});
}
$(window).resize(function(){
positionMiddle();
});
$(window).scroll(function(){
positionMiddle();
});
// To initially run the function:
positionMiddle();
I need to create two divs with same height. The height of each div is different on every page (height depends on content). Is there any way how to lock the height of two divs together? Here is a jsfiddle (I need to increse the height of div C based on div A and conversely).
Note: I cant use table or parent div. I am a newbie in JavaScript, so I hope that it can be done without it.
<div class="a">
<brdsds><br><br><br><bdsdsr><br><br><br>ds<br>dsds<br>dsd
</div>
<div class="b">
dsdds
</div>
<div class="c">
dsdds
</div>
You can use display:table-cell, first remove the float and add this:
div {
width 30px;
display:table-cell;/*Add this*/
/*float:left; Remove this*/
}
Check this Demo http://jsfiddle.net/8zPD2/1/
Before use this check the Compatibility
Just need to use this CSS:
.a,
.c {
max-height: 200px;
}
try this:
<div class="divmaster">
<div class="divchild">
<brdsds><br><br><br><bdsdsr><br><br><br>ds<br>dsds<br>dsd
</div>
<div class="divchild">
dsdds
</div>
<div class="divchild">
dsdds
</div>
and the css:
.divmaster{
display:table;
}
.divChild{
height: 100%;
}
If you want to try this in JavaScript , Use this code:
DEMO
$(function(){
setHeight = function (src, target) {
h = src.height();
target.css('height', h + 'px');
}
content = $('.a');
imagediv = $('.b');
setHeight(content, imagediv);
});
Just set your div to display: table-cell, and then remove the float: left.
CSS
div {
display: table-cell;
width 30px;
}
.a {
background-color: #e9d8b7;
}
.b {
background-color:blue;
}
Check this: http://jsfiddle.net/8zPD2/6/
Set min height to height of the div which has high height. Say if your div A has highest height the use that height to all divs. Its not possible with css if you dont know which div might have heigest div. As you asked how to do it only with css here it is
.a,.b,.c{ min-height:200px; max-height:400px; }