I'm trying to make a sticky, transparent div, that changes color based on the div behind it. So, I've got a couple of dark and light div's, and the sticky div should change text-color (white on the dark, black on the light).
In HTML
<div id="sticky">Menu</div>
<div class="content light"></div>
<div class="content dark"></div>
<div class="content light"></div>
<div class="content dark"></div>
<div class="content light"></div>
I've already found a partial solution here:
var stickyOffset = $("#sticky").offset();
var $contentDivs = $(".content");
$(document).scroll(function() {
$contentDivs.each(function(k) {
var _thisOffset = $(this).offset();
var _actPosition = _thisOffset.top - $(window).scrollTop();
if (_actPosition < stickyOffset.top && _actPosition + $(this).height() > 0) {
$("#current").html("Current div under sticky is: " + $(this).attr("class"));
$("#sticky").removeClass("light dark").addClass($(this).hasClass("light") ? "light" : "dark");
return false;
}
});
});
No the problem is, that when my stikcy div get's property top:50%, it doesn't work.
Anyone got a solution?
You don't need JavaScript to do this. Just use mix-blend-mode:
#sticky {
position: fixed;
top: 10px;
left: 10px;
right: 10px;
height: 50px;
color: #fff;
mix-blend-mode: exclusion;
}
Related
I've got a header that I want to disappear (move above the top of the browser screen) when the user scrolls down, then when the user scrolls back up I want the header to reappear (move back down) and also to gain a solid white background behind it.
All of this is working fine, but then I want the white background to be removed if the user scrolls back up to the very top of the page again (so it's just the header visible but with no white background).
I've cobbled together the code for this, and it's pretty much working - but, for some reason, in certain circumstances, the white background isn't being removed?!
It seems to be if you've scrolled back up enough to make the header reappear with the white background, but not all the way top the top, and then scroll the rest of the way then the white background doesn't disappear for some reason.
Sorry, I've probably not explained that very well, but here's my code. If someone is able to replicate the bug I'm getting and offer an explanation I'd be very grateful!
Thanks
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 30;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 30);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('header-down').addClass('header-up').removeClass('header-solid');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('header-up').addClass('header-down').addClass('header-solid');
}
}
lastScrollTop = st;
};
$(function () {
$(window).scroll(function () {
var top_offset = $(window).scrollTop();
if (top_offset == 0) {
$('header').removeClass('header-solid');
}
})
});
body {
margin: 0;
background: url('https://images.unsplash.com/3/doctype-hi-res.jpg?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=2246&q=80');
background-size: cover;
}
.wrapper {
width: 100%;
height: 3000px;
}
header {
display: flex;
width: 100%;
padding: 20px 50px;
position: fixed;
box-sizing: border-box;
transition: 300ms all ease-in-out;
margin-top: 0px;
}
.header-logo {
width: 200px;
}
.header-nav {
flex-grow: 1;
text-align: center;
}
.header-socials {
width: 200px;
text-align: right;
}
.header-up {
margin-top: -60px;
}
.header-down {
margin-top: 0px;
}
.header-solid {
background-color: #FFFFFF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<header class="header-down">
<div class="header-logo">
<img src="#" class="img-header-logo"/>
</div>
<div class="header-nav">
One Two Three Four Five
</div>
<div class="header-socials">
Social Links
</div>
</header>
</div>
I have a a page with a textarea in between fixed headers and a fixed footer. I use some jquery to ensure the viewport shows the new textarea lines at the bottom as you type. Without the fixed footer (white background), the jquery works as it supposed to and the new lines stay in view as you type at the bottom. But with the fixed footer, I have to manually scroll to see the new content at the bottom. It is hidden behind the footer. I have found that if I hit enter while I type however, it will auto scroll the content to stay in view even with the footer. But if I type continuously, I have to scroll to see the new hidden content. I want to have the fixed footer and auto scroll down in the textarea so the new content is always showing above the fixed footer, no matter how much is typed. How can I accomplish this?
$(document).ready(function() {
$('#close-post-modal').click(function() {
$("#main-container").load("mobile/mobile.view.php");
$("#main-content-mobile").load("mobile/feed.php");
document.location.hash = "feed";
});
$('#post-comment-textarea-mobile').on('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
});
#post-comment-textarea-mobile {
border: none;
overflow: auto;
outline: none;
resize: none;
width: 100%;
}
#post-modal-header {
position: fixed;
top: 0;
}
#post-modal-sub-header {
position: fixed;
}
#post-modal-footer {
position: fixed;
bottom: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="width-100p">
<div id="post-modal-header" class="bg-white width-100p height-2r space-evenly-x padding-top-1">
<div id="close-post-modal">X</div>
<div>New Post</div>
<div id="save-post-modal">Save</div>
</div>
<div id="post-modal-sub-header" class="bg-white padding-left-1 width-100p height-2r left padding-top-2">
<div class="padding-right-5px">Image</div>
<div>Username</div>
</div>
<div class="padding-left-2 padding-right-2 padding-bottom-1 padding-top-5">
<textarea id="post-comment-textarea-mobile" placeholder="Your Thoughts?"></textarea>
</div>
<div id="post-modal-footer" class="bg-white width-100p space-evenly-x padding-top-2 padding-bottom-1">
<div>Image</div>
<div>Video</div>
<div>Tag</div>
</div>
</div>
I was able to get it to work by adding 100 to the scroll height for the textarea height AND window.scrollTo on input to the textarea's ScrollHeight.
I'm not sure if the 100 is the needed number, you can play with that with your design, its one that worked for me.
$(document).ready(function() {
$('#close-post-modal').click(function() {
$("#main-container").load("mobile/mobile.view.php");
$("#main-content-mobile").load("mobile/feed.php");
document.location.hash = "feed";
});
$('#post-comment-textarea-mobile').on('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight + 100) + 'px';
window.scrollTo(0,document.querySelector("#post-comment-textarea-mobile").scrollHeight);
});
});
body{padding:0;}
#post-comment-textarea-mobile {
border: none;
overflow: auto;
outline: none;
resize: none;
width: 100%;
}
#post-modal-header {
position: fixed;
top: 0;
}
#post-modal-sub-header {
position: fixed;
background:#000;
}
#post-modal-footer {
position: fixed;
bottom: 0;
width:100%;
background:#000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="width-100p">
<div id="post-modal-header" class="bg-white width-100p height-2r space-evenly-x padding-top-1">
<div id="close-post-modal">X</div>
<div>New Post</div>
<div id="save-post-modal">Save</div>
</div>
<div id="post-modal-sub-header" class="bg-white padding-left-1 width-100p height-2r left padding-top-2">
<div class="padding-right-5px">Image</div>
<div>Username</div>
</div>
<div class="padding-left-2 padding-right-2 padding-bottom-1 padding-top-5">
<textarea id="post-comment-textarea-mobile" placeholder="Your Thoughts?"></textarea>
</div>
<div id="post-modal-footer" class="bg-white width-100p space-evenly-x padding-top-2 padding-bottom-1">
<div>Image</div>
<div>Video</div>
<div>Tag</div>
</div>
</div>
It's the same problem as with fixed header and html anchors. Properties like fixed, absolute and relative pulls an element out of page flow and places it in another dimension (not a professional term).
Just tell jquery where is the end of view. It believes the view ends at screen end.
I am trying to create a "see-also" button that is located on the bottom of the page.
When the user reaches the bottom and decides to scroll back up, I want it to stick to the bottom of the viewport.
I have been trying with position:sticky but then it is already sticked to the bottom of the viewport when the page just loaded. I only want this after a complete scroll down.
Any clues?
Thanks in advance.
This is an example with javascript (see result sticky button on scroll top
const DIRECTION_BOTTOM = 1;
const DIRECTION_TOP = 0;
let previousScroll = 0;
let direction = scrollY === 0 ? DIRECTION_BOTTOM : DIRECTION_TOP;
window.addEventListener('scroll', function(){
const scrollY = window.scrollY;
if(direction === DIRECTION_TOP && previousScroll < scrollY){
direction = DIRECTION_BOTTOM;
// remove sticky
document.getElementById("sticky").classList.remove("show");
}
else if(direction === DIRECTION_BOTTOM && previousScroll > scrollY ){
direction = DIRECTION_TOP;
// Add sticky
document.getElementById("sticky").classList.add("show");
}
previousScroll = scrollY;
})
You can create this functionality with JQuery by creating a function which calculates when an element is in the viewport. If the button enters the viewport, add a class which makes the element position: sticky. There are different ways to approach this problem but one solution is something like this:
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementBottom > viewportTop && elementTop < viewportBottom;
};
$(window).on("scroll", function() {
if($('#button').isInViewport()) {
$('#button').addClass('sticky');
}
});
body {
text-align: center;
}
.button {
padding: 6px 12px;
}
.div {
width: 100%;
height: 250px;
color: #fff;
}
.div1 {
background: blue;
}
.div2 {
background: red;
}
.div3 {
background: purple;
}
.sticky {
position: sticky;
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
height: 100%;
bottom: 5px;
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<div class="div div1">Filler div 1</div>
<div class="div div2">Filler div 2</div>
<div class="div div3">Filler div 3</div>
<button type="button" class="button" id="button">See Also</button>
Scrambled everything together and this is working now:
window.onscroll = function(ev) {
if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
document.getElementById("see-also").classList.add("sticky");
}
};
Thanks you everyone
I am using this for my header that changes in a one page scroll up and down page. I noticed that it's not responsive so i am asking you if you maybe know a way to make that responsive. Like changing the 0-690 into a percentage so that it will work on mobile and also on a tv screen.
HTML
<div class="header header-1" data-visible-range="0-690">Portfolio</div>
<div class="header header-2" data-visible-range="691-2100">Services</div>
<div class="header header-3" data-visible-range="2101-">Contact</div>
CSS
.header-1 {
background-color:dimgray;
display: block;
}
.header-2 {
background-color:dimgray;
}
.header-3 {
background-color:dimgray;
}
.header {
position: fixed;
top: 0;
left: 0;
height:8vmax;
width: 100%;
display: none;
visibility:hidden;
transition: visibility .4s, opacity .4s ease-in-out;opacity:0;
font-size:4vmax;padding:1.58vmax;color:white;
}
What if, instead of basing it off pixels, you just checked to see if an element hit the top of the page, and then changed the header?
We'll call these elements "triggers." See my code below for an example of how they work.
let updateHeader = () => {
let scrollTop = $(window).scrollTop(),
triggerTitle = "Hi";
$('.trigger').each((i, el) => {
let topPos = $(el).offset().top,
distance = topPos - scrollTop;
if (distance < 0)
triggerTitle = $(el).data('title');
});
$('header h2').text(triggerTitle);
}
$(window).scroll(updateHeader);
$(window).on('touchmove', updateHeader);
body {
margin: 0;
}
#container {
height: 1000px;
}
header {
width: 100%;
position: fixed;
top: 0;
background-color: red;
}
p {
margin: 200px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<header><h2>Hi</h2></header>
<p class="trigger" data-title="section1">
trigger1
</p>
<p class="trigger" data-title="section2">
trigger2
</p>
<p class="trigger" data-title="section3">
trigger3
</p>
</div>
As you scroll down the page, each trigger hits the top of the page, and the text in the header will change to the the value of the latest trigger's data-title. You could position these triggers appropriately above each of your website's sections, so that, no matter what size the screen, the header should update at the right time. Here's a codepen.
EDIT
Try this JS instead for maximum compatibility (no es6 involved).
function updateHeader() {
var scrollTop = $(window).scrollTop(),
triggerTitle = "Hi";
$('.trigger').each(function(i, el) {
var topPos = $(el).offset().top,
distance = topPos - scrollTop;
if (distance < 0)
triggerTitle = $(el).data('title');
});
$('header h2').text(triggerTitle);
}
$(window).scroll(updateHeader);
$(window).on('touchmove', updateHeader);
The site below uses a fixed background-image in each section, but how do I add fixed content (text, images) to each sections and keep the same scrolling effect?
http://tympanus.net/Blueprints/ScrollingLayout/
Have a look at my example to get a better idea of what I want:
http://jsfiddle.net/w919y0gb/
My try:
#wrapper {
position: relative;
height: 500px;
width: 500px;
overflow: scroll;
}
.section {
position: relative;
height: 100%;
width: 100%;
}
.content {
position: fixed;
}
#s1 {
background-color: #f00;
}
#s2 {
background-color: #0f0;
}
#s3 {
background-color: #00f;
}
#s1 .content {
}
#s2 .content {
margin-top: -400px;
}
#s3 .content {
margin-top: -800px;
}
<div id="wrapper">
<div class="section" id="s1">
<div class="content">hello1</div>
</div>
<div class="section" id="s2">
<div class="content">hello2</div>
</div>
<div class="section" id="s3">
<div class="content">hello3</div>
</div>
</div>
What I want:
The first section (red) should only display "hello1"
The second (green) only "hello2"
The third (blue) only "hello3"
something like this maybe? little hacky, but does the trick if you have set section heights:
$(document).ready(function(){
$('.div3').hide();
$('.div2').hide();
$('.div1').show();
$('#wrapper').scroll(function(){
console.log($('#wrapper').scrollTop());
if($('#wrapper').scrollTop() > 945){
$('.div3').show();
$('.div2').hide();
$('.div1').hide();
}
else if ($('#wrapper').scrollTop() > 465) {
$('.div3').hide();
$('.div2').show();
$('.div1').hide();
}
else {
$('.div3').hide();
$('.div2').hide();
$('.div1').show();
}
});
});
updated fiddle: http://jsfiddle.net/w919y0gb/3/
with this, you could also modify the placement of the "hello1/hello2/hello3" to be in the same position instead of in different places. or you could just have one div in which you modify/replace the text from hello1/hello2/hello3 depending on the scroll position. hope this helps!
That reference site is simply using a background-image set to fixed like so:
FIDDLE
UPDATE
Ok I understand. You would need to do something like this with jquery and $(window).scroll() function:
NEW FIDDLE
using positon: fixed just breaks the element out of the flow of the document and it can't be contained by a parent so you need to use absolute and position it based on the scrollTop to give the appearance that it's fixed.
You could also set the height of your webpage, and then make divs appear as you scroll up or down.
Heres a working example: http://jsfiddle.net/ZyKar/1738/
$(document).scroll(function () {
var y = $(this).scrollTop();
if (y > 0 && y < 400) {
$('#s1').fadeIn();
$('#s3').fadeOut();
$('#s2').fadeOut();
} else if (y > 400 && y < 800) {
$('#s1').fadeOut();
$('#s2').fadeIn();
$('#s3').fadeOut();
}else if (y > 800) {
$('#s3').fadeIn();
$('#s2').fadeOut();
}
});
After you scroll a certain amount of pixels, divs will begin to appear and replace each other.
You may alter the value of y by setting the height of your body in css, as shown in the fiddle. You can then set the pixels conditions in the jQuery to whatever you like.