Hide when scroll down, immediately show when scroll up, pure css - javascript

I've prepared this fiddle, it uses css + js to reach the desired effect,
a top bar that hides when scrolling down ( like a div with the default css position value ), then immediately shows up when scroll up, regardless of the current scroll value.
I've tried to get the same look&feel using pure css, with different combinations of 'sticky' position, flexbox, containers inside containers, but without any result.
It is possible to achieve the same result with pure css?
My goal is to get rid of the 'scroll' event keeping the functionality, if possible.
var senseSpeed = 5;
var previousScroll = 0;
$(window).scroll(function(event){
var scroller = $(this).scrollTop();
if (scroller-senseSpeed > previousScroll){
$(".item").slideUp();
} else if (scroller+senseSpeed < previousScroll) {
$(".item").slideDown();
}
previousScroll = scroller;
});
body {
margin: 0px;
padding: 0px;
height: 5000px;
}
header {
width: 100%;
height: 50px;
position: sticky;
position: -webkit-sticky;
background: DeepSkyBlue;
top: 0;
z-index: 999;
}
.item {
position:fixed;
top:50px;
right:0;
background-color: Orchid;
width: 100%;
height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>Name</header>
<div class="item"></div>
<p>some content</p>
<p>some content</p>
<p>some content</p>

Related

How to set element to grow horizontally instead of breaking to a new line?

I'm facing problem with breaking the line on website. What do I mean?
HTML code
<main class="clearfix">
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
With such HTML code I'd like to have:
fixed height on main element (for example 80vh)
fixed height for all the elements first and third 40vh + second 80vh
fixed width for first and third element 50vw
fluid width for second element - but this is main problem - second element has to be in the same place and grow horizontally (to create scroll on the bottom of the site)
Please find my codepen
I've added button that'll add pixels to second element - but it destroys my website.
I'm not sure if flexbox is better than floats.
I'll appreciate any tip.
Here is the snippet:
let counter = 0;
document.querySelector("button").addEventListener("click", function() {
document.querySelector(".second").style.width = `calc(50% + ${counter}px)`;
console.log(counter);
counter++;
});
* {
padding: 0;
margin: 0;
}
main {
max-height: 80vh;
}
.first,
.third {
height: 40vh;
width: 50vw;
background-color: black;
float: left;
}
.third {
background-color: red;
}
.second {
height: 80vh;
width: 50%;
float: right;
background-color: blue;
}
.clearfix::after {
content: "";
display: table;
clear: both;
}
<main class="clearfix">
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
I would suggest you to go with position properties. Since you have a little difference between the order of your DOM element and their visual representation, like 1,2,3 in the DOM, but visually it's more like 1,3,2.
However, in such situation float is your enemy. I'm not 100% sure about flex, AFAIK flex would keep all the elements inside the parent element and prevent the scrolling.
If you go with absolute positioning, (since you already have the heights and widths defined)
Apply:
position: relative to the main element, it will be the base point of the child elements if they are set to absolute.
overflow-x: scroll to the main element. it will allow you to scroll horizontally when you increase the width of your second element.
position: absolute on .first, .second, .third, as you have the height and width defined, now set their position accordingly, check the snippet, you'll get it.
Finally you're good to add more value to your width of the target element.
Tip: always keep a consistency in your css units, for example, if used vh / vw use this for similar elements at least, or if px / em / rem is used, try to use the same accordingly.
Check the snippet in full page mode
let counter = 0;
document.querySelector("button").addEventListener("click", function() {
document.querySelector(".second").style.width = `calc(50vw + ${counter}vw)`;
document.querySelector("#added").textContent = counter;
counter++;
});
* {
padding: 0;
margin: 0;
}
main {
overflow-x: scroll;
position: relative;
min-height: 80vh;
}
.first,
.third {
height: 40vh;
width: 50vw;
background-color: black;
position: absolute;
left: 0;
top: 0;
}
.third {
background-color: red;
top: 40vh;
}
.second {
height: 80vh;
width: 50vw;
background-color: blue;
position: absolute;
left: 50vw;
top: 0;
}
button {
margin: 30px 5px;
border: 1px solid #cecece;
padding: 5px 10px;
}
<main>
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
<p><span id="added">0</span>vw Added to blue div's width</p>

Screen height issue with getting fixed bar to stop scrolling above footer

I used the top solution from this question: Stop fixed position at footer to keep a bar fixed until it runs into the footer. And everything is working fine, except for on pages where there is not enough content to scroll. Ideally, I would like the fixed bar to sit on top of the footer on such pages. However, I think I am running into issues with my footer, as it has these styles;
#footer {
position: absolute
bottom: 0
}
I used these styles to keep the footer on the bottom of the pages with very little content. On these pages, my fixed bar is hidden behind my footer.
Here is everything that I have.
CSS
#footer {
width: 100%;
height: 50px;
bottom: 0;
background-color: #D9D9D9; /* light gray */
color: #404040; /* gray */
position: absolute;
}
#fixed {
height: 50px;
position: fixed;
bottom: 0;
background-color: #4B99D3;
}
#fixed-parent {
position: relative;
margin-bottom: 50px;
}
jQuery
$(document).scroll(function() {
checkOffset();
});
function checkOffset() {
if($('#fixed').offset().top + $('#fixed').height() >= $('#footer').offset().top - 10)
$('#fixed').css('position', 'absolute');
if($(document).scrollTop() + window.innerHeight < $('#footer').offset().top)
$('#fixed').css('position', 'fixed'); // restore when you scroll up
}
HTML
<div id="fixed-parent">
<div id="fixed">
fixed content...
</div>
</div>
<div id="footer">
footer content...
</div>
Example here: http://jsfiddle.net/e5q04cv2/

Make div stick to top of page after scrolling past another div?

<div id="header"></div>
<div id="sticky"></div>
<div id="section"></div>
<div id="footer"></div>
<style>
body { margin: 0px; background-color: #e3e3e3; }
#header { background-color: #cb5454; height: 140px; }
#sticky { background-color: #546bcb; height: 70px; }
#section { height: 1500px; }
#footer { background-color: #cb5454; height: 140px; }
</style>
Here is my code: http://jsfiddle.net/uaqh018d/
I want #sticky to stick to the top of the page after scrolling past #header. I also want it hidden until stuck. And then of course have it unstick+hide again after scrolling back up to #header.
How can I achieve this?
I would recommend adding a class to #sticky when it's ready to be fixed to the top of the screen, and then removing that class when you want to 'unstick' it. Then you can manipulate that class in CSS.
e.g. for a class fixed you'd put the following in your CSS:
#sticky {
display: none;
background-color: #546bcb;
height: 70px;
}
#sticky.fixed {
display: block;
position: fixed;
top: 0;
width: 100%;
}
And then your jQuery would look like this:
$(window).scroll(function() {
var distanceFromTop = $(this).scrollTop();
if (distanceFromTop >= $('#header').height()) {
$('#sticky').addClass('fixed');
} else {
$('#sticky').removeClass('fixed');
}
});
Here's an updated FIDDLE
I might also recommend some jQuery fade or slide effects (see the fiddle).
You can use position: fixed and in js detect when user scroll like this:
$(document).scroll(function() {
//detect when user scroll to top and set position to relative else sets position to fixed
$("#sticky").css({
"top": "0",
"position": $(this).scrollTop() > 140 ? "fixed" : "relative"
});
});
body {
margin: 0px;
background-color: #e3e3e3;
}
#header {
background-color: #cb5454;
height: 140px;
}
#sticky {
background-color: #546bcb;
height: 70px;
width: 100%;
position: fixed;
}
#section {
height: 1500px;
}
#footer {
background-color: #cb5454;
height: 140px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="header"></div>
<div id="sticky"></div>
<div id="section"></div>
<div id="footer"></div>
References
.scroll()
In my case, the div I wanted to be sticky was inside of another div (ie. not stuck to the page, but in another fixed div on the side of the page). Here's my adaptation of #bowhart's answer to solving this problem given a React component (sticky_adapter.js):
module.exports.makeItSticky = function(thisReactComponent, parentScrollNode = window) {
const thisNode = $(ReactDOM.findDOMNode(thisReactComponent));
const position = thisNode.position();
// Uncomment for verbose logging
//console.log("Initial position: " + UIUtils.stringify(position));
const scrollContainer = $(parentScrollNode);
scrollContainer.scroll(() => {
const distanceFromTop = scrollContainer.scrollTop();
// Uncomment for verbose logging
//console.log("ScrollTop: " + distanceFromTop);
if (distanceFromTop > position.top) {
thisNode.addClass("stick-to-top");
} else {
thisNode.removeClass("stick-to-top");
}
});
};
Now, to make any React component sticky, I just add to the class:
componentDidMount() {
StickyAdapter.makeItSticky(this, ".some-other-div-which-is-the-container");
}
Finally, the css for the sticky class:
.stick-to-top {
display: block;
position: sticky;
top: 0;
z-index: 10;
}
Hey this is and old question but for new visitors I think u just need to add this css code to #sticky:
#sticky { position:sticky;top:0; }
and no need for javascript.
sticky toggles between relative and fixed, depending on the scroll position.
and don't forget that, the parent also should not have overflow property

text not showing up over background image

I am making a landing page, and this might sound like a stupid question, but my <h2> and <form> elements are not showing up anywhere on my page. I have tried everything I can think of and still, nothing. I'm baffled.
The photo I am using for my full screen background image is one off of photoshop with a grey square in the center (which looks like what some people do with z-index). In the background, it is cycling logo's in js as a kind of throwback design.
I am not sure if I am doing something wrong, or if there is something in my css, html, js making it so the text/form is not showing up.
index.html
<section id="bg">
<img src="img/bg.jpg">
<div class="container">
<div class="row">
<div class="col-lg-12" id="rotating-img-wrapper">
<img class="rotating-img" src="img/corona.png">
<img class="rotating-img" src="img/mc.png">
<img class="rotating-img" src="img/mtv.png">
<img class="rotating-img" src="img/op.png">
<img class="rotating-img" src="img/supercell.png">
</div>
</div>
<div class="text">
<h2>To learn more about our services, drop us a line</h2>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Email Address</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword3" placeholder="Password">
</div>
</div>
</div>
</section>
css
#bg {
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
}
#bg img {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
min-width: 50%;
min-height: 50%;
}
#rotating-img-wrapper img {
position: fixed;
width: 250px;
height: 750px;
}
.rotating-img {
display: none;
position: absolute;
top: 0;
left: 0;
}
h2 {
color: #000000;
position: absolute;
}
javascript
$(window).load(function() {
var InfiniteRotator =
{
init: function()
{
//initial fade-in time (in milliseconds)
var initialFadeIn = 1000;
//interval between items (in milliseconds)
var itemInterval = 5000;
//cross-fades time (in milliseconds)
var fadeTime = 2500;
//number of items
var numberOfItems = $('.rotating-img').length;
//current item
var currentItem = 0;
//show first item
$('.rotating-img').eq(currentItem).fadeIn(initialFadeIn);
//loop through the items
var infiniteLoop = setInterval(function(){
$('.rotating-img').eq(currentItem).fadeOut(fadeTime);
if(currentItem == numberOfItems -1){
currentItem = 0;
}else{
currentItem++;
}
$('.rotating-img').eq(currentItem).fadeIn(fadeTime);
}, itemInterval);
}
};
InfiniteRotator.init();
});
If anyone can see an error(s) in my code that I cannot see, I would love to know. Thanks for the help.
I have some insight into how you might approach this layout.
I simplified your HTML slightly (removed the form and put in a simple line of text) so
as to concentrate on the various stacking layers due to the fixed and absolutely
positioned elements.
The key is that since your #bg element is fixed, it sets the reference point for
positioning any other positioned child elements, be it fixed or absolute.
In your original post, you set the offsets to be top: -50% and left: -50%, which
places the origin of the block outside of the visible viewing area.
As a result, h2 was positioned at the top left corner of #bg, hence not visible,
and the p text, which is in regular content flow, would also start to the top left
of the container block (#bg).
As a start, set the offsets to top: 0 and left: 0 with 100% for the width and height,
and then rethink about how to size your images in your image rotator and the background
image.
Now that you see where the elements are, you will make be able to make progress
with your layout.
body {
margin: 0; /* get rid of 10px border from default browser style sheet */
}
#bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#bg img {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
min-width: 50%;
min-height: 50%;
}
#rotating-img-wrapper img {
position: fixed;
width: 250px;
height: auto;
}
.rotating-img {
display: block;
position: absolute;
top: 0;
left: 0;
}
h2 {
color: #000000;
position: absolute;
top: 30%;
left: 50%;
}
<section id="bg">
<img src="http://placehold.it/500x500">
<div class="container">
<div class="row">
<div class="col-lg-12" id="rotating-img-wrapper">
<img class="rotating-img" src="http://placekitten.com/2000/4000">
</div>
</div>
<div class="text">
<h2>To learn more about our services, drop us a line</h2>
<p>Some other words ...</p>
</div>
</section>
You can use background-image: url(img/bg.jpg); in #bg, instead of adding the image directly and try to add something on it.
In your image CSS, do this in the CSS:
z-index:-1000;
The z-index controls what elements overlap other elements. The higher the z-index, the more in front an element will be. See if that clears anything up. Otherwise, there is another issue. I am also curious as to why you are using absolute positioning on all those elements.
In CSS try this code:
#bg {
background-image:url('img/bg.jpg');
}
And then remove the tag from the HTML page. I would also take a look at simplifying your code since you seem to have a ton of divs all wrapped within each other. Perhaps consider using a table if it suits your needs.

jQuery: Position a div to fill the visible portion of a container div with overflow

I'm having trouble getting an overlay to appear on top of the visible portion of another div. The problem is, the container div has overflow, and if the user has scrolled inside that div, the overlay will not cover the scrolled portion. My question is: how can you position a div to fill the visible portion of another div using jQuery - or, alternatively, is there a way to accomplish this using just CSS?
Here is a jsFiddle demonstration, and here's the markup:
HTML
<div class="container">
<div class="overlay"></div>
<div class="content">
<p>Content here</p>
<p>Overflow content here</p>
</div>
</div>
CSS
div.container { position: absolute; height: 100px; width: 100px; overflow-y: auto; }
div.overlay { display: none; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #F00; opacity: 0.5; }
div.content p { margin-bottom: 100px; }
and JS (load on DOM Ready)
$('div.container').click(function(){
$('div.overlay').toggle();
});
In order to achieve what you were asking for I did the following
CSS
.container {
/* setting this to relative means
overlay is positioned relative to its parent */
position: relative;
}
.overlay {
/* element taken out of normal flow */
position: absolute;
/* removed bottom and right properties otherwise
updating top property has no effect */
height: 100px;
/* When scrollbar appears width decreases to less than
100px hence having to set to 100% to allow automatic calculation */
width: 100%;
}
JavaScript
Using jQuery I now set the top property appropriately
$(".container").scroll( function( ) {
$(".overlay").css({ top: $(this).scrollTop( ) });
});
Fiddle here
Assuming you really want to cover only the visible portion:
http://jsfiddle.net/GNCaT/1/
<style type="text/css">
div.overlay {
display: none;
position: absolute;
top: 0;
left: 0;
right: 0;
height:100px; /* fixed height, set by CSS or javascript, no bottom */
background: #F00;
opacity: 0.5;
}
</style>
<script>
$('div.container').click(function(){
$('div.overlay').css('top', $('div.container').scrollTop() + 'px').toggle();
});​
</script>
This will position the overlay to the top of the visible portion of the container.
You can use the DOM property scrollHeight :
$('div.container').click(function(){
$('div.overlay').css("height", this.scrollHeight).toggle();
});
http://jsfiddle.net/p6k2Z/1/
EDIT :
In order to just overlay the visible portion, you can use this :
$('div.container').click(function(){
$('div.overlay').css({
top: this.scrollTop,
height: $('div.container').css("height")})
.toggle();
});
http://jsfiddle.net/p6k2Z/3/

Categories

Resources