Sticky sidebar | Problems with content height - javascript

I am tring to create a sidebar or section that follows you as you scroll down the page.
It works fine but if height of content shorter than leftsidebar, page became not smooth and structure is broken. How to fix it?!
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6 && $('.sidebar').offset() != null) {
var top = $('.sidebar').offset().top - parseFloat($('.sidebar').css('margin-top').replace(/auto/, 0));
var height = $('.sidebar').height();
var winHeight = $(window).height();
var footerTop = $('#footer').offset().top - parseFloat($('#footer').css('margin-top').replace(/auto/, 0));
var gap = 0;
$(window).scroll(function (event) {
// what the y position of the scroll is
var y = $(this).scrollTop();
// whether that's below the form
if (y + winHeight >= top + height + gap && y + winHeight <= footerTop) {
// if so, ad the fixed class
$('.sidebar').addClass('leftsidebarfixed').css('top', winHeight - height - gap + 'px');
}
else if (y + winHeight > footerTop) {
// if so, ad the fixed class
$('.sidebar').addClass('leftsidebarfixed').css('top', footerTop - height - y - gap + 'px');
}
else {
// otherwise remove it
$('.sidebar').removeClass('leftsidebarfixed').css('top', '0px');
}
});
}
});
.scrollable {
height: 100%;
overflow: auto;
}
.max-height {
height: 100%;
}
.no-overflow {
overflow: hidden;
}
.sidebar {
display: none;
}
#media (min-width: 768px) {
.sidebar {
position: absolute;
top: 0;
height: 100vh;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
overflow-x: auto;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
background-color: #f5f5f5;
}
}
.main {
padding-top: 20px;
height:auto;
}
#media (min-width: 768px) {
.main {
padding-right: 20px;
padding-left: 20px;
}
}
.table{
font-size:x-small;
}
.HeaderStyle th{
text-align:center; /*Заголовки в таблице стоят по центру*/
background-color:#FFDEAD;
}
#wrapper {
margin: 0 auto;
width: 100%;
}
#contentHolder{
position:relative;
}
#header,#footer {
background: none repeat scroll 0 0 #CCFFFF;
color: #000000;
height: 150px;
width: 100%;
clear:both;
font-size:3em;
text-align:center;
}
.leftsidebarfixed {
position: fixed;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div id="header">...</div>
<div class="container-fluid max-height no-overflow">
<div class ="row max-height">
<div id="contentHolder">
<form runat="server">
<!--sidebar-->
<div runat="server" class="col-sm-3 sidebar">
</div>
<!--MAIN CONTENT-->
<div class="col-sm-offset-3 main scrollable">
</div>
</form>
</div>
</div>
</div>
<div id="footer">...</div>
</div>
Problem:

Related

How to show a div between the scroll height of 900-1200?

I am trying to make one CTA as a image, which will appear on some certain height and will disappear once a users crosses that scroll amount.
my codes-
$(document).scroll(function() {
var y = $(this).scrollTop();
if (y > 900) {
$('.cta-bg').fadeIn();
} else {
$('.cta-bg').fadeOut();
}
});
.wrapper {
height: 3000px;
}
.cta-bg {
display: none;
position: sticky;
bottom: 10%;
top: 60%;
width: 60%;
height: auto;
z-index: 1;
}
#media only screen and (max-width: 767px) {
.cta-bg {
display: none !important;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="cta-bg"><img src="https://via.placeholder.com/150" class="img-fluid"></div>
</div>
It's coming after a scroll amount of 900 but I want to make it disappear again at scroll amount of 1200, please guide me.
I see in your question you said it's coming after 900 but don't disappear after 1200.
Basically you only need to use and operator && in your if statement, if your y is between 900 and 1200 your image will fadeIn else will fadeOut, also you can change that limit ( 1200 ) by your preference.
$(document).scroll(function () {
var y = $(this).scrollTop();
if (y > 900 && y < 1200) {
$('.cta-bg').fadeIn();
} else {
$('.cta-bg').fadeOut();
}
});
.wrapper {
height: 3000px;
}
.cta-bg {
display: none;
position: sticky;
bottom: 10%;
top: 60%;
width: 60%;
height: auto;
z-index: 1;
}
#media only screen and (max-width: 767px) {
.cta-bg {
display: none !important;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="cta-bg"><img src="https://via.placeholder.com/150" class="img-fluid"></div>
</div>

Vertical Scroll Indicator

Trying to create a Scroll Indicator, which would not be horizontal, but vertical. The problem is that when I try to start scrolling the bar that indicated the position isn't scaling...
HTML
<div id="scrollbar">
<div id="bar">
</div>
<div>
CSS
#scrollbar
{
width: 1%;
height: 100%;
padding: 0;
margin: 0 0 0 auto;
right: 0;
top: 0;
position: fixed;
visibility: visible;
background-color: transparent;
}
#scrollbar #bar
{
width: inherit;
height: 0%;
background-color: #ccc;
}
JS
var bar = document.getElementById("bar");
window.onscroll = function () { scrollIndicator() };
window.onload = function () { scrollIndicator() };
function scrollIndicator()
{
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = 100;
if(height > 0)
{
scrolled = (winScroll / height) * 100;
}
bar.style.height = scrolled + "%";
}
I absolutely cannot find the problem...
your web page doesn't have enough content for it to scroll, hence scroll event isn't firing.
You need to fix the html, #scrollbar is missing a closing div tag and add enough content on the webpage so that it scrolls.
You also need to change the width of #bar from inherit to 100%.
var bar = document.getElementById("bar");
window.onscroll = function() {
scrollIndicator()
};
function scrollIndicator() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = 100;
if (height > 0) {
scrolled = (winScroll / height) * 100;
}
bar.style.height = scrolled + "%";
}
#scrollbar {
width: 1%;
height: 100%;
padding: 0;
margin: 0 0 0 auto;
right: 0;
top: 0;
position: fixed;
background-color: transparent;
}
#scrollbar #bar {
width: 100%;
height: 0%;
background-color: blue;
}
.section {
height: 100vh;
}
.section:nth-child(even) {
background: green;
}
.section:nth-child(odd) {
background: red;
}
<div id="scrollbar">
<div id="bar"></div>
</div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>

On horizontal scroll of overflown div, fill in progress bar

I have a div which contains an image. The container of this image has overflow:scroll, so that the user can scroll left or right to see the rest of the image.
I've also implemented a progress bar, which should indicate how much of the image remains to scroll. I.e. if the user has scrolled 5% to the right, it'll fill up 5% of the progress bar (and vice versa).
I can get the function working based on scrollHeight, but can't get it working based on scrollWidth.
Where am I going wrong?
window.onscroll = function() {myFunction()};
function myFunction() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var width = document.documentElement.scrollLeft - document.documentElement.clientWidth;
var scrolled = (winScroll / width) * 100;
document.getElementById("myBar").style.width = scrolled + "%";
}
.imgCont {
background: black;
overflow: scroll;
position: relative;
}
.imgCont img {
width: auto;
max-width: none;
}
.progress-container {
width: 100%;
height: 8px;
background: blue;
}
.progress-bar {
height: 8px;
background: red;
width: 0%;
}
<div class="imgCont">
<img src="https://i.imgur.com/KhWo66L.png">
</div>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
You need to add listeners on the .imgCont element and use it's scrollLeft, scrollWidth and clientWidth properties
let scrEl = document.getElementById("scr-el")
scrEl.addEventListener('scroll', event => {
let scrolled = (scrEl.scrollLeft / (scrEl.scrollWidth - scrEl.clientWidth) ) * 100
document.getElementById("myBar").style.width = scrolled + "%"
});
.imgCont {
background: black;
overflow-x: scroll;
position: relative;
}
.imgCont img {
width: auto;
max-width: none;
}
.progress-container {
width: 100%;
height: 8px;
background: blue;
}
.progress-bar {
height: 8px;
background: red;
width: 0%;
}
<div id="scr-el" class="imgCont">
<img src="https://i.imgur.com/KhWo66L.png">
</div>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
windows.onscroll won't emit any events while you scroll horizontally because scroll is happening in the element with class imgCont.
put an id imgCont
<div class="imgCont" id="imgCont">
<img src="https://i.imgur.com/KhWo66L.png">
</div>
and call the on scroll event as
document.getElementById("imgCont").onscroll
Jquery solution setps:
subtract the visible width of the image and the real image width
var winScroll = $(".imgCont img").width() - $(".imgCont").width();
get the left scroll position
var width = $(".imgCont").scrollLeft();
get the percentage from the width and position
var scrolled = ((width / winScroll) * 100);
Check the snippet:
$(function(){
$(".imgCont").scroll(function(){
var winScroll = $(".imgCont img").width() - $(".imgCont").width();
var width = $(".imgCont").scrollLeft();
var scrolled = ((width / winScroll) * 100);
$("#myBar").width(scrolled + "%");
});
});
.imgCont {
background: black;
overflow: scroll;
position: relative;
height:200px;
}
.imgCont img {
width: auto;
max-width: none;
}
.progress-container {
width: 100%;
height: 8px;
background: blue;
}
.progress-bar {
height: 8px;
background: red;
width: 0%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="imgCont">
<img src="https://static.toiimg.com/photo/msid-67868104/67868104.jpg?1368689">
</div>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
Another solution.
let div = document.getElementById("theDiv")
div.addEventListener('scroll', function(e) {
let inner = window.innerWidth
let left = div.scrollLeft
let sWidth = div.scrollWidth
let total = sWidth - inner
let width = 1 * left / total * 100
if (width >= 100) {
return document.getElementById("myBar").style.width = "100%";
}
document.getElementById("myBar").style.width = `${width}%`;
});
body {
margin: 0;
}
.imgCont {
background: black;
overflow: auto;
position: relative;
}
.imgCont img {
width: auto;
max-width: none;
}
.progress-container {
width: 100%;
height: 8px;
background: blue;
}
.progress-bar {
height: 8px;
background: red;
width: 0%;
}
<div class="imgCont" id="theDiv">
<img src="https://i.imgur.com/KhWo66L.png">
</div>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>

Cover image position relative to text

I am trying to set a text to overlap an image but the position should stay same on all screen sizes.
Example:
Here is an example of what I have tried demo
.c-txt-on-img{
position: relative;
}
.c-txt-on-img .txt{
font-size: 30px;
font-weight: bold;
font-family: arial, sans-serif;
max-width: 200px;
position: absolute;
top: 80px;
left: 158px;
}
.c-txt-on-img .img {
width: 100vw;
height: 100vh;
background-size: cover;
background-position: center center;
}
<div class="c-txt-on-img">
<div class="txt">Tony where are you !!!!</div>
<div class="img" style="background-image: url(http://theprojectstagingserver.com/stackoverflow/txt-on-img/comic.jpg)"></div>
</div>
It works on a specific screen-size only, I can fix this on different sizes using different media queries but that will take too much time!
There are 2 main challenges:
1) Align the image and text to always stay on the same spot.
2) Aligning will leave extra uneven space on top/bottom & left/right side of the image so we need to increase image size enough that it covers the whole screen.
For first part we can define same top left position to text and image, then give a negative translate percentage to image so that top left origin of image is the same spot where the text bubble is.
Next we can calculate the space on right/left/top/bottom of image & increase its width till no negative space is left.
Below is a GIF image to explain this better:
Here is the DEMO
var viewportOffset = [],
winWidth,
winHeight,
inLoop = false,
resizeTimeout;
$(function(){
init();
});
$(window).resize(function(){
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function(){
init();
}, 500);
});
function init() {
winWidth = $(window).width();
winHeight = $(window).height();
inLoop = false;
coverImage();
}
function coverImage() {
$('.js-cover-img').each(function (i) {
viewportOffset[i] = getViewportOffset($(this));
if(!inLoop){
$(this).width('auto');
$(this).height('auto');
}
var imgWidth = $(this).width();
var imgHeight = $(this).height();
viewportOffset[i].right = winWidth - imgWidth- (viewportOffset[i].left);
viewportOffset[i].bot = winHeight - imgHeight- (viewportOffset[i].top);
if(viewportOffset[i].top < 0){
var vertViewportOffest = viewportOffset[i].bot;
}else if(viewportOffset[i].bot <= 0){
var vertViewportOffest = viewportOffset[i].top;
}else{
var vertViewportOffest = viewportOffset[i].top + viewportOffset[i].bot;
}
if(viewportOffset[i].right < 0){
var horViewportOffest = viewportOffset[i].left;
}else if(viewportOffset[i].left < 0){
var horViewportOffest = viewportOffset[i].right;
}else{
var horViewportOffest = viewportOffset[i].left + viewportOffset[i].right;
}
if(horViewportOffest > 0 || vertViewportOffest > 0){
$(this).width(imgWidth + 20);
inLoop = true;
coverImage();
return false;
}
});
}
/* Get's the viewport position */
function getViewportOffset($e) {
var $window = $(window),
scrollLeft = $window.scrollLeft(),
scrollTop = $window.scrollTop(),
offset = $e.offset();
return {
left: offset.left - scrollLeft,
top: offset.top - scrollTop
};
}
body, html{
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
.c-txt-on-img {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.c-txt-on-img .txt {
font-size: 30px;
font-weight: bold;
font-family: arial, sans-serif;
max-width: 200px;
position: absolute;
top: 30%;
left: 30%;
z-index: 2;
transform: translate(-50%, -50%);
text-align: center;
}
.c-txt-on-img .img {
transform: translate(-28.5%, -23%);
z-index: 1;
position: absolute;
top: 30%;
left: 30%;
min-width: 870px;
}
.c-txt-on-img img{
display:block;
width: 100%;
}
<script
src="https://code.jquery.com/jquery-1.12.2.min.js"
integrity="sha256-lZFHibXzMHo3GGeehn1hudTAP3Sc0uKXBXAzHX1sjtk="
crossorigin="anonymous"></script>
<div class="c-txt-on-img">
<div class="txt">Tony where are you !!!!</div>
<div class="img js-cover-img">
<img src="http://theprojectstagingserver.com/stackoverflow/txt-on-img/comic.jpg">
</div>
</div>

Hide Sticky Div Once Scrolling Past Next Parent Div

I'm trying to hide a "sticky" div once it scrolls past the next parent div. I've currently successfully have it so it appears after scrolling "y > 100" but I'm having a lot of trouble getting the "Sticky Note" to disappear after scrolling past #break.
Example below.
http://codepen.io/anon/pen/BojKBx
$(document).scroll(function() {
var y = $(this).scrollTop();
if (y > 100) {
$('.bottomMenu').fadeIn();
} else {
$('.bottomMenu').fadeOut();
}
});
.bottomMenu {
display: none;
position: fixed;
bottom: 0;
width: 50%;
height: 60px;
border-bottom: 1px solid #000;
z-index: 1;
margin: 0 auto;
left: 50%;
margin-left: -500px;
text-align: center;
}
#header {
font-size: 50px;
text-align: center;
height: 60px;
width: 100%;
background-color: red;
}
#container {
height: 2500px;
}
#break {
text-align: center;
font-size: 30px;
margin-bottom: 300px;
width: 100%;
background-color: yellow;
}
#footer {
height: 60px;
background-color: red;
width: 100%;
bottom: 0;
}
<div id="header">Home</div>
<div class="bottomMenu">
<h2>Sticky Note</h2>
</div>
<div id="container"></div>
<div id="break">Should Not Be Seen After This Point</div>
<div id="footer"></div>
You can get Y position of a div (its vertical offset starting from the top of the page), and then add condition to show sticky note only when you're below the required "Y" coordinate, and above the required div. Example:
http://codepen.io/anon/pen/EVPKyP
Javascript code:
$(document).scroll(function () {
var bodyRect = document.body.getBoundingClientRect(),
elemRect = document.getElementById("break").getBoundingClientRect(),
offset = elemRect.top - bodyRect.top - window.innerHeight;
var y = $(this).scrollTop();
if (y > 100 && y < offset) {
$('.bottomMenu').fadeIn();
} else {
$('.bottomMenu').fadeOut();
}
});
Sources:
Retrieve the position (X,Y) of an HTML element
screen width vs visible portion

Categories

Resources