Right so I had a question to help with the first bit of this and that was just getting a div to follow the slider knob. After messing around with it for a while we came up with the solution. Now I have a div following the slider knob I need it centred on it at all times.
So to keep this an simple as possible here is a image of what I am trying to fix.
In the image above you can see the slider and the div that is following the slider knob. Under that I have places | so you can see that its not fully centred with slider knob. I need this to be centred under the slider knob at all times (in the image it should be under/in the middle of the gray bit). It tends to start to mess up when going 40% and below as well as 60% and above.
What I have tried:
I can't think of an easy way to fix this (hence this post) but I did try a little cheat by doing the following:
if (pct >= 80) {
// Position the follow div and arrow
$('#follow').css('left', (o.value * 0.98) + '%');
} else if (pct >= 70) {
$('#follow').css('left', (o.value * 0.99) + '%');
} else if (pct <= 50 & pct >= 40) {
$('#follow').css('left', (o.value * 1.02) + '%');
} else if (pct <= 40 & pct >= 30) {
$('#follow').css('left', (o.value * 1.04) + '%');
} else if (pct <= 30 & pct >= 20) {
$('#follow').css('left', (o.value * 1.08) + '%');
}
Now what this does it trys to keep the div on track with the slider by changing the % as it moves along. This does work (kinda) but leads to the div not being smooth and it goes all jumpy due to the calculation corrections.
Here is an example of what I have so far:
HTML:
<div class="slider-container">
<div id="follow-container">
<div id="follow">I am following the slider!
<br />
<div id="percentage"></div>
<br />|</div>
</div>
<div id="testslider"></div>
</div>
CSS:
#testslider {
position: absolute;
top: 50px;
left: -40px;
background-size: 100%;
background-position: center;
}
.slider-container {
padding: 55px;
}
#follow-container {
position: relative;
left: -65px;
bottom: 2px;
}
#follow {
position: absolute;
width: 193px;
height:40px;
margin-left: -77px;
/* half width */
text-align: center;
color: black;
border: 1px solid;
}
JAVASCRIPT:
$('#testslider').sGlide({
height: 16,
startAt: 70,
colorStart: '#C6F1F8',
colorEnd: '#C6F1F8',
drag: function (o) {
var pct = Math.round((o.value));
$('#percentage').html(pct);
// Position the follow div and arrow
$('#follow').css('left', o.value + '%');
},
onButton: function (o) {
var pct = Math.round(o.value) + '%';
$('#percentage').html(pct);
}
});
DEMO HERE
Any help here would be great and as people before have said "so what is your question".
Overall question: How can I keep the following div aligned with the slider knob?
Only way i can see it work is to wrap the | inside span class!!
working fiddle
HTML
<span class="vline"><br />|</span>
CSS
#follow > span.vline {
position: relative;
left:4%;
}
EDIT
as per the comments discussion, this is probably your treasure!!
solution (based on you question fiddle, not my 1st attempted fiddle)
css
#follow-container {
position: fixed; /*changed*/
left:50%; /* change as per your need, left:60%; would make it
center to the full 100% width*/
margin-left:-96px; /*half of divs width*/
}
After all this it turns out to solve my problem I needed to give #follow-container a width.
Giving this the correct with of the slider allowed the child div to align correctly with the slider knob.
Example:
#follow-container {
position: relative;
bottom: 2px;
width: 760px;
left: -100px;
}
This seems to have fixed my problem on my real project, thanks for all the help NoobEditor and Mr.Alien.
Related
I'm working on a Video editing tool, and I need to maintain the 16:9 aspect ratio of the video when resizing the screen horizontally and vertically. So far I got it to work as expected when resizing horizontally, and when resizing down vertically, but can't get it to work when sizing up vertically. The Javascript code I used to calculate the height of the video and resize it is below (notice how the else clause is empty because that's where the code should go):
const calculateHeight = () => {
// Get the other elements on the page
const header = document.querySelector('.main-navigation');
const meshTopBar = document.querySelector('.mesh__top-bar');
const footer = document.querySelector('.mesh__bottom-bar');
// Get the section to apply the window height to it
const mainSection = document.querySelector('.insert-level-container');
// Get the video elements
const editor = document.querySelector('.mesh__insert-editor-container');
const video = document.querySelector('.mesh__insert-editor-video-container');
// Apply the height to the main section by calculating the window height minus the other elements' height
if(mainSection !== null) {
mainSection.style.height = (window.innerHeight - header.offsetHeight - meshTopBar.offsetHeight - footer.offsetHeight) + 'px';
}
// This should be the ideal height for the video
video.style.minHeight = ((video.offsetWidth * 9) / 16) + 'px';
// If the video height is bigger than the section height (calculated above), then resize it
if(video.offsetHeight + 115 > mainSection.offsetHeight) {
video.style.minHeight = video.offsetHeight - 1 + 'px';
editor.style.maxWidth = video.offsetHeight * 16 / 9 + 'px';
} else {
// This is where the logic for the vertical resizing should go
}
}
The relevant CSS for these items is:
.mesh__insert-editor-container {
margin-left: auto;
margin-right: auto;
}
.mesh__insert-editor-video-container {
position: relative;
width: 100%:
}
And the HTML:
<section class="mesh__insert-editor-container flex__one flex-container flex-column horizontally-left-aligned" id="video-main-container">
<div class="mesh__insert-editor-video-container flex-container horizontally-right-aligned flex-wrap">
<video class="mesh__insert-editor-video-placeholder"></video>
</div>
</section>
All this code is:
Get the height of all the elements on the page, sum them and calculate the main section height by subtracting that height;
If the video height gets bigger than the section height, I reduce its height by -1px each time the window gets resized, and calculate the new width.
All the above code is giving me this result, which works great for most scenarios, but I need the video to size up when the condition on the if statement is not met. Everything I tried inside the else statement gets "jumpy".
Any better alternatives to solve this would be much appreciated. Thanks all!
The CSS aspect ratio trick might be a good solution: https://css-tricks.com/aspect-ratio-boxes/
The approach takes advantage of a quirk in CSS where padding based on a percentage value will be relative to the element's width. Create a container using this trick, the important bit is this line:
padding-top: calc(9/16 * 100%);
The value is calculating the correct height based on the aspect ratio you want (9 tall over 16 wide in this case) and generating it relative to the width of the element by multiplying by 100%.
With the container maintaining aspect ratio, just place the content inside an absolute positioned inner div and you should be good. This solution is fully responsive at that point.
* { box-sizing: border-box }
.outer-max-width {
max-width: 960px;
margin: 0 auto;
}
.aspect-ratio-box {
width: 100%;
padding-top: calc(9/16 * 100%);
position: relative;
border: 2px solid red; /* for demo visibility, remove */
}
.aspect-ratio-box-content {
position: absolute;
width: 100%;
top: 0;
left: 0;
border: 2px solid blue; /* for demo visibility, remove */
}
.video-placeholder {
display: block;
width: 100%;
height: auto;
}
<div class="outer-max-width">
<div class="aspect-ratio-box">
<div class="aspect-ratio-box-content">
<img class="video-placeholder" src="https://placeimg.com/640/360/nature" />
</div>
</div>
</div>
Got it to work! I used this amazing CSS-only solution: https://codepen.io/EightArmsHQ/pen/BvNzrm similar to BugsArePeopleToo's suggestion, from eightarmshq:
.content{
position: absolute;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
background: #555;
box-shadow: inset 1vh 1vh 10vh 0 rgba(0,0,0,0.5);
display: flex;
box-sizing: border-box;
border: 25px solid #cecece;
}
I'd like to create a horizontal navigation which animates to a vertical navigation on scroll.
I've tried to do that with animate, but there I can only provide it like after 50 px scrolled animate in xxx seconds.
$(window).scroll(function() {
if (ScrolledFromTop > 50) {
$('nav').animate({CSS CHANGES});
}
});
But I would like to do it like begin at 50px scrolled and the animation should be finished when I scrolled 100px. Any ideas? thanks
Could you clarify more ?
I think you need a swipe like function but this time as a mouse event handler ?
Whats the use case behind this ? Seems inpractical that a menu is stuck inbetween some transition when the user stops scrolling between 50 and 100 px.
Anyways you would need to map your current scrolled pixel value to the animation, like so:
$(window).scroll(function() {
if (window.pageYOffset >= 50 && window.pageYOffset <= 100) {
var percent = (window.pageYOffset - 50 ) * 2;
animateMenu(percent);
}else if(window.pageYOffset < 50) {
animateMenu(0);
}else if(window.pageYOffset > 100) {
animateMenu(100);
}
});
function animateMenu(percent){
$('.menu').css({
width: 100 - percent + "%",
height: percent + "%"
});
}
.menu{
background: red;
height: 50px;
width: 100%;
min-width: 50px;
position: fixed;
top: 0;
left: 0;
transition: 0.2s all ease-in;
min-height: 50px;
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="menu"></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><br><br><br><br><br><br>
I've been working on a scrolling effect for my site that has been driving me crazy, and it's probably not even worth it but I can't stop now.
I have been able to simulate the effect using adobe edge and muse. Can anyone think of a simpler method of creating this effect? The animation can be seen here. As you scroll, the header shape changes and resizes. I have tried doing this with svg animate, div rotation animate, etc. with no luck.
Any help would be appreciated.
Normally we don't provide full solutions for questions, but I had some free time and this was a pretty fun project. If my answer works for you I hope you'll accept it.
I'm sure there are more efficient ways to do this (manipulating an SVG for example), but I kept this as succinct as I possibly could. This is using CSS and Javascript / jQuery. I'll let the comments in the javascript portion do the explaining.
HTML
<div id="animation">
<div id="box"></div>
<div id="ang"></div>
</div>
CSS
#animation {
width: 500px;
position: fixed;
top: 0;
left: 50%;
margin-left: -250px;
}
#box {
width: 500px;
height: 125px;
background: #333;
}
#ang {
width: 0;
height: 0;
border-top: 175px solid #333;
border-right: 500px solid transparent;
}
Javascript
$(window).scroll(function() {
var pos = $(window).scrollTop(), // Current scroll position
max = 300, // How quickly we want the animation to finish (in pixels)
box = 50, // Collapsed height of the box
ang = 0; // Collapsed height of the angle
/* Only make changes if we are within the limit of our max variable
* If this condition is not met, the box and angle will be collapsed
* I found this necessary because scrollTop doesn't produce consistent
* values and quite often the box wouldn't fully collapse */
if (pos <= max) {
// Max height - (scroll percentage x (max height - min height))
box = 125 - (pos / max * 75);
ang = 175 - (pos / max * 175);
}
// Adjust the height of the box and the angle
$('#box').css({ 'height': box + 'px' });
$('#ang').css({ 'border-top-width': ang + 'px' });
});
See my JS Bin for a demo.
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.
I have a client who wants to have an X-Ray effect that reveals clickable data points. A slider would be used to move a viewing window over an image, that would reveal an x-ray, or secondary image as the slider is moved. I've adapted Eli Kirk's X-Ray effect (http://elikirk.com/2013/12/02/draggable-x-ray-effect-using-css-javascript/) to get what I have so far: http://jsfiddle.net/xfxLx/3/. The jQuery UI portion of it is easy enough:
var artWidth = 300;
$(document).ready(function() {
$('.xraySlider').slider({
slide: function(e, ui) {
var newLeft = (ui.value / 100) * (artWidth - 100);
$('.xrayWindow').css({'background-position': (newLeft * -1) + 'px 0px', "left": newLeft + "px" });
}
});
});
The problem I'm having is making clickable data points that would be revealed by the window as it is slid across the main image. The data points would be fairly simple shapes (like, say, a black circle), that the user could click on once revealed by the x-ray window, to reveal a popup with more info. I've beat my head against the wall trying to come up with a workable solution (if this wasn't bad enough, it all has to work in IE7, so I've ruled out canvas as well).
If this effect won't work under the confines listed (which I've told them might be the case, since I have yet to come up with a viable solution), that's fine, but I just want to make sure I'm not missing anything.
I have changed yoput HTML, setting an inner element to the xray, that will hold the points
<div class="artifact-hold">
<div class="artifact">
<div class="xrayUpper"></div>
<div class="xrayWindow">
<div class="innerXray">
<div class="point" id="brain"></div>
<div class="point" id="heart"></div>
</div>
</div>
<br />
<div class="xraySlider"></div>
</div>
</div>
Then, the JavaScript changes slightly
var artWidth = 300;
$(document).ready(function() {
$('.xraySlider').slider({
slide: function(e, ui) {
var newLeft = (ui.value / 100) * (artWidth - 100);
$('.xrayWindow').css({"left": newLeft + "px" });
$('.innerXray').css({"left": -newLeft + "px" });
}
});
});
And CSS is changed to make the xray clip the contents (with overflow hidden), and the inner has the background image instead of the xraywindow. also, some styling to the points.
.innerXray {
width: 300px;
height: 490px;
position: absolute;
background: url(http://s21.postimg.org/tpg6me1vb/bones.jpg) no-repeat;
background-position: 0px 0px;
}
.point {
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: red;
}
#heart {
left: 150px;
top: 130px;
}
#brain {
left: 150px;
top: 30px;
}
.xrayWindow {
width: 100px;
height: 490px;
border: 2px solid rgba(255,255,255,0.5);
position: absolute;
top: 0px;
left: 0px;
overflow: hidden;
}
result