I have a child <div> which has position: fixed; applied by adding a class of is-active when you scroll past the top of it's parent <div>.
Is it possible to fix the position of the child at the end of the parent as you scroll beyond the end of the parent? And then re-apply the class 'is-active' to the child when you scroll back up above the end of the parent?
Essentially I'd like the fixed position of the child to only be active within it's parent. I want to achieve what position: sticky; can do without the polyfill overhead and lack of browser support. Is this possible?
Here's what I have currently:
HTML:
<div class="outer">
<div class="nav">
</div>
</div>
<div class="end">
</div>
CSS:
.outer {
position: relative;
width: 100%;
height: 200rem;
margin: 10rem 0 0;
background: red;
}
.end {
width: 100%;
height: 40rem;
background: green;
}
.nav {
position: absolute;
top: 0;
left: 0;
width: 10rem;
height: 30rem;
background: blue;
&.is-active {
position: fixed;
top: 2rem;
left: 2rem;
}
}
jQuery:
var $nav = $('.nav');
var $outer = $('.outer');
$(function(){
$(window).scroll(function() {
var $scroll = $(window).scrollTop();
var $parentOffset = $outer.offset().top;
var $parentHeight = $outer.height();
var $navHeight = $nav.height();
if($scroll > $parentOffset && $scroll < ($parentHeight - $navHeight)) {
$nav.addClass('is-active');
}
else {
$nav.removeClass('is-active');
});
});
Here's Codepen with a working example also: https://codepen.io/abbasarezoo/pen/BwXBLv
Thanks for any help in advance!
i just changed it now sticky header is working
https://codepen.io/anon/pen/OxKPbj
if($scroll > $parentOffset && $scroll ) {
$nav.addClass('is-active');
}
Related
Good day,
I'm having trouble with jquery. i found a topic here that i want to learn using jquery slide right to left div http://jsfiddle.net/PXLJG/2/.
what i want to achieve is when hover, show hidden content on specific div.
i tried adding .addClass('active'); to the script.
here is the script i made
$(document).ready(function(){
$('.holdingbox').hover(function(){
var rightbox = $('.rightbox');
if (rightbox.hasClass('active')){
rightbox.stop().animate({width: '-0px'}, 1000).removeClass('active');
} else {
rightbox.stop().animate({width: '90px'}, 1000).addClass('active');
}
});
});
The problem now is when i hover on one div, all div shows up.Please see attached image.
Hope you guys can point me to right direction. thank you
You need to target the rightbox element in current element context i.e. this
You can either use context or .find() to target child element.
$('.holdingbox').hover(function() {
var rightbox = $('.rightbox', this); //$(this).find('.rightbox')
});
$(document).ready(function() {
$('.holdingbox').hover(function() {
var rightbox = $('.rightbox', this);
if (rightbox.hasClass('active')) {
rightbox.stop().animate({
width: '-0px'
}, 1000).removeClass('active');
} else {
rightbox.stop().animate({
width: '90px'
}, 1000).addClass('active');
}
});
});
div {
display: inline-block;
}
.holdingbox {
position: relative;
top: 0;
margin-left: 100px;
}
.leftbox {
position: relative;
top: 0;
left: 0;
display: inline-block;
font-size: 24px;
background-color: #ac193d;
color: #FFF;
font-weight: bold;
padding: 1px;
}
.rightbox {
position: relative;
display: inline-block;
overflow: hidden;
width: 0;
height: 30px;
vertical-align: top;
margin-right: 0;
}
.content {
width: 100px;
position: absolute;
background-color: #ac193d;
height: 29px;
left: 0;
top: 0;
right: 0;
color: #FFF;
padding-left: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="holdingbox">
<span class="rightbox"><span class="content">Kenyér</span></span>
<span class="leftbox">></span>
</div>
<div class="holdingbox">
<span class="rightbox">
<span class="content">Kenyér</span>
</span>
<span class="leftbox">></span>
</div>
Change code to this
You'll get children of the hovered element this way. Without using $(this) you target all '.rightbox' elements in document.
$('.holdingbox').hover(function(){
$(this).find('.rightbox').stop().animate({width: '90px'}, 1000)
}, function(){
$(this).find('.rightbox').stop().animate({width: '-0'}, 1000)
});
How can it be made so that a div scrolls with the page but only in a certain area of the page?
I can't work out how to do this with CSS for only part of the page, I think javascript may be the only option.
For e.g. There's three sections of a page, Top, Middle and Bottom.
There's a right floated div which should scroll with the user in the middle section and stop scrolling to be 'left in place' at the top of the middle section as well as the bottom of the middle section.
#Top {
background-color: grey;
width: 100%;
height: 400px;
}
#Middle {
background-color: green;
width: 100%;
height: 800px;
}
#Bottom {
background-color: blue;
width: 100%;
height: 400px;
}
#scrolling-section {
background-color: yellow;
width: 30%;
height: 150px;
float: right;
}
<div id="Top">
</div>
<div id="Middle">
<div id="scrolling-section">
This box should scroll along the green section but 'cut-off' and stop scrolling at the top and bottom of the green section
</div>
</div>
<div id="Bottom">
</div>
JSFiddle: fiddle
So here you have solution using jquery:
Listen to the scroll event and calculate how much the scrolling-section goes outside the Middle section while scrolling up / down.
Added position: relative to the scrolling-section.
Adjust the position of the scrolling-section accordingly.
$(document).scroll(function() {
var wrapper = $('#Middle');
var box = $('#scrolling-section');
var offsetTop = - wrapper.offset().top + $(window).scrollTop();
var offsetBottom = wrapper.offset().top - $(window).scrollTop() + wrapper.outerHeight() - box.outerHeight();
if (offsetBottom > 0 && offsetTop < 0) {
box.css({
'top': 0
});
} else if (offsetBottom > 0 && offsetTop > 0) {
box.css({
'top': offsetTop + 'px'
});
} else {
box.offset({
'top': $(window).scrollTop() + offsetBottom
});
}
});
#Top {
background-color: grey;
width: 100%;
height: 400px;
}
#Middle {
background-color: green;
width: 100%;
height: 800px;
}
#Bottom {
background-color: blue;
width: 100%;
height: 400px;
}
#scrolling-section {
position: relative;
background-color: yellow;
width: 30%;
height: 150px;
float: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="Top">
</div>
<div id="Middle">
<div id="scrolling-section">
This box should scroll along the green section but 'cut-off' and stop scrolling at the top and bottom of the green section
</div>
</div>
<div id="Bottom">
</div>
Let me know your feedback on this. Thanks!
Some Javascript is needed in order to read the point where you want to change the state of the div you wish to address. You can do this with the getBoundingClientRect() method. I have worked out a fiddle that will show you.
What happens is that you read the position of #Middle. I have added an input field that shows you the value. The change will be when the position hits zero. You then change the CSS properties of the #scrolling-section.
You will see some added readings of the element to ensure that it can be positioned in place and will keep its original width;
var scrollposition = document.getElementById("Middle");
var scrollsection = document.getElementById("scrolling-section");
var scrollsection_offsetLeft = scrollsection.offsetLeft;
var scrollsection_width = scrollsection.offsetWidth;
var valy = document.getElementById("posy");
window.addEventListener("scroll", function(event) {
valy.value = scrollposition.getBoundingClientRect().y || scrollposition.getBoundingClientRect().top;
if (valy.value <= 0) {
scrollsection.style.position = "fixed";
scrollsection.style.top = "0px";
scrollsection.style.left = scrollsection_offsetLeft + "px";
scrollsection.style.width = scrollsection_width + "px";
} else {
scrollsection.style.position = "static";
scrollsection.style.top = "auto";
scrollsection.style.left = "auto";
}
}, false)
#posy {
position: fixed;
top: 0;
}
#Top {
background-color: grey;
width: 100%;
height: 400px;
}
#Middle {
background-color: green;
width: 100%;
height: 800px;
}
#Bottom {
background-color: blue;
width: 100%;
height: 400px;
}
#scrolling-section {
background-color: yellow;
width: 30%;
height: 150px;
float: right;
}
<input type="text" id="posy" />
<div id="Top">
</div>
<div id="Middle">
<div id="scrolling-section">
This box should scroll along the green section but 'cut-off' and stop scrolling at the top and bottom of the green section
</div>
</div>
<div id="Bottom">
</div>
I'm on my mobile but if you add
#scrolling-section {
position: fixed;
background-color: yellow;
width: 30%;
height: 150px;
right: 8px;
}
This will scroll with the page but really there will need to be an event listener that will trigger when #scrolling-section appears on the screen possibly adding the attribute position:fixed; then another event listener when the #bottom appears calculates the size of #middle set margin-top & position:absolute; hope this helps point in the right direction.
I have a fixed header and menu bar and there is a container div when i scroll down the container div does not hide itself below the menu bar as shown in image below is the jquery code i am using. Please help to solve my issue.
var header= $('.header');
var start_div = $(header).offset().top;
var menu_div = $('.menu');
var menu = $(menu_div ).offset().top;
$.event.add(window, "scroll", function() {
var p = $(window).scrollTop();
$(header).css('position',((p)>start_div ) ? 'fixed' : 'static');
$(header).css('top',((p)>start_div ) ? '0px' : '');
$(header).css('width','840px');
$(header).css('min-height','108px');
});
$.event.add(window, "scroll", function() {
var p = $(window).scrollTop()+100;
$(menu_div).css('position',((p)>menu) ? 'fixed' : 'static');
$(menu_div).css('top',((p)>menu) ? '110px' : '');
$(menu_div).css('width','575px');
$(menu_div).css('height','57px');
});
Unless I'm missing something you don't need jQuery or even JS to do that.
Check the snippet (codePen here)
html,
body {
width: 100%;
height: 100%;
background-color: white;
}
.header-wrapper {
top: 0;
right: 0;
left: 0;
position: fixed;
height: 160px;
background-color: white;
}
.header {
background-color: cyan;
height: 100px;
width: 100%;
}
.menu {
width: 100%;
height: 50px;
background-color: green;
margin-top: 10px;
}
.content {
color: #fff;
background-color: black;
margin-top: 170px; /* same as height of header + nav + margins + 10px for coolness*/
}
<body>
<div class="header-wrapper">
<div class="header">Blue Header</div>
<div class="menu">Green Menu</div>
</div>
<div class="content">
My content<br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
blabla
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
blabla
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</body>
Use the css z-index property.
.header, .menu {
z-index: 2
}
.container {
z-index: 1
}
http://www.w3schools.com/cssref/pr_pos_z-index.asp
I'm trying to display a right / left navigation arrow within a container (the arrows replace the existence of a scrollbar) when the corresponding edge of the content overlaps the container's sides.
Also, when the content is scrolled all the way to the end and can't scroll any further, the arrow should disappear.
My problem is, I'm confused as to how I write the function to check whether the element's contents are overlapping one edge or the other to hide one arrow or the other.
I started writing logic like this:
function setArrows(elem){
if (elem.scrollLeft() > 0) { //scroll position is greater than zero
// show left arrow
}
if () { //scroll position is less than zero
//show right arrow
}
}
but that doesn't seem to be the right logic. It sounded simpler in my head before I went to actually write the function.
How do I check whether the right/left edge of an element is overlapping the side of it's container?
Here's a Stack Snippet:
$('#wrapper').scroll(function(){
//check edges
});
div {
padding: 0px;
margin: 0px;
}
#wrapper {
width: 500px;
height: 100px;
background-color: blue;
overflow-x: scroll;
overflow-y:hidden;
}
#content {
width: 1000px;
height: 100px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="wrapper">
<div id="content">
</div>
</div>
You need to check if the content width minus the scrollLeft is greater than the wrapper width. If it is show the right scroller..
Something like this
$(function() {
var content = $('#content'),
arrows = $('.arrow'),
wrapper = $('#wrapper').scroll(function() {
//check edges
// handle left arrow
if (this.scrollLeft > 0) {
arrows.filter('.left').addClass('visible');
} else {
arrows.filter('.left').removeClass('visible');
};
// handle right arrow
if (content.outerWidth() - this.scrollLeft > wrapper.width()) {
arrows.filter('.right').addClass('visible');
} else {
arrows.filter('.right').removeClass('visible');
};
});
arrows.on('click', function() {
if ($(this).is('.left')) {
wrapper[0].scrollLeft -= 100;
} else {
wrapper[0].scrollLeft += 100;
}
return false;
});
// initialize
wrapper.trigger('scroll');
});
div {
padding: 0px;
margin: 0px;
}
#wrapper {
width: 500px;
height: 100px;
background-color: blue;
overflow-x: hidden;
overflow-y: hidden;
position: relative;
}
#content {
width: 1000px;
height: 100px;
background: url('http://lorempixel.com/1000/100/abstract/2') 0 0 no-repeat;
}
#full-container {
position: relative;
display: inline-block;
}
.arrow {
position: absolute;
top: 0;
bottom: 0;
width: 40px;
background-color: black;
display: none;
z-index: 100;
cursor: pointer;
color: #fff;
text-align: center;
line-height: 100px;
}
.arrow.visible {
display: block;
}
.arrow.left {
left: 0
}
.arrow.right {
right: 0
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="full-container">
<div class="arrow left"><</div>
<div id="wrapper">
<div id="content"></div>
</div>
<div class="arrow right">></div>
</div>
Well, i'm starting to write this webpage and i've run into a few problems that i just cannot quite find the answers to.
The basic idea of the code I have is:
Open menu when the mouse is on "explore webpage"
Menu "links" highlight on mouseover
When user clicks on menu item, the menu moves to the top of the page and the "link" stays highlighted until the user clicks a different link.
When the menu moves to the top, a div opens below, displaying the content for that section.
I am having two main problems. Firstly, whenever I click on the menu item, it does not stay highlighted (number 3). Secondly, the div is not opening below the menu after the click(number 4). I would greatly appreciate any insight into these issues.
I am including all of my code, as I believe it is all relevant to my problems.
<!DOCTYPE html>
<html>
<head>
<style>
body
{
background-color: #000000;
}
#container
{
z-index: -1;
background: #000000;
width: 900px;
height: 900px;
position: absolute;
top: 0px;
left: 50%;
margin-left: -450px;
}
#explore
{
z-index: 1;
background: #000000;
width: 300px;
height: 150px;
position: absolute;
top: 41.666%;
left: 33.333%;
opacity: 1;
}
#explore-text
{
z-index: 1;
color: #eb56bd;
font-size: 50px;
font-family: sans-serif;
font-weight: bold;
text-align: center;
position: absolute;
top: 5px;
left: 0%;
opacity: 1;
}
.title
{
z-index: 2;
width: 300px;
height: 150px;
text-align: center;
font-size: 60px;
font-family: sans-serif;
font-weight: bold;
color: #000000;
display: none;
}
#news
{
background: #eb56bd;
position: absolute;
top: 41.666%;
left: 33.333%;
}
#about
{
background: #eb56bd;
position: absolute;
top: 41.666%;
left: 0%;
}
#events
{
background: #eb56bd;
position: absolute;
top: 41.666%;
left: 66.666%;
}
.content
{
z-index: 0;
background: #b0408d;
width: 900px;
position: absolute;
top: 21.666%;
left: 0px;
height : 900;
}
#news-content
{
display: none;
}
#about-content
{
display: none;
}
#events-content
{
display: none;
}
</style>
</head>
<body>
<div id="container">
<div id="explore" onmouseover="overExplore()" onmouseout="outExplore()">
<div id="explore-text">Explore Webpage</div>
</div>
<div id="news" class="title" onmouseover="overTitle(news)" onmouseout="outTitle(news)" onclick="titleClick(news)">news</div>
<div id="about" class="title" onmouseover="overTitle(about)" onmouseout="outTitle(about)" onclick="titleClick(about)">about</div>
<div id="events" class="title" onmouseover="overTitle(events)" onmouseout="outTitle(events)" onclick="titleClick(events)">events</div>
<div id="news-content" class="content">
</div>
<div id="about-content" class="content">
</div>
<div id="events-content" class="content">
</div>
</div>
<script>
var titleClicked = false;
var isClicked;
var newsContent = document.getElementById('news-content');
var aboutContent = document.getElementById('about-content');
var eventsContent = document.getElementById('events-content');
var title = document.getElementsByTagName('title');
var news = document.getElementById('news');
var about = document.getElementById('about');
var events = document.getElementById('events');
var explore = document.getElementById('explore');
var exploreText = document.getElementById('explore-text');
function overExplore() {
explore.style.width="900px";
explore.style.left="0%";
explore.style.background="#eb56bd";
explore.style.cursor="pointer";
explore.style.cursor="hand";
explore.style.opacity="0";
news.style.display="block";
about.style.display="block";
events.style.display="block";
}
function outExplore() {
explore.style.width="300px";
explore.style.left="33.333%";
explore.style.background="#000000";
exploreText.style.left="0%";
exploreText.style.top="5px";
explore.style.opacity="1";
news.style.display="none";
about.style.display="none";
events.style.display="none";
}
function overTitle(div) {
if (div!= isClicked) {
div.style.background="#b0408d";
}
if (titleClicked == false) {
div.style.display="block";
news.style.display="block";
about.style.display="block";
events.style.display="block";
}
explore.style.cursor="pointer";
explore.style.cursor="hand";
}
function outTitle(div) {
if (div!= isClicked) {
div.style.background="#eb56bd";
}
if (titleClicked == false) {
div.style.display="none";
news.style.display="none";
about.style.display="none";
events.style.display="none";
}
}
function titleClick(div) {
div.style.background="#b0408d";
var isClicked = div;
if (div == news)
{
about.style.background="#eb56bd";
events.style.background="#eb56bd";
newsContent.style.display="block";
aboutContent.style.display="none";
eventsContent.style.display="none";
}
else if (div == about)
{
news.style.background="#eb56bd";
events.style.background="#eb56bd";
newsContent.style.display="none";
aboutContent.style.display="block";
eventsContent.style.display="none";
}
else
{
news.style.background="#eb56bd";
about.style.background="#eb56bd";
newsContent.style.display="none";
aboutContent.style.display="none";
eventsContent.style.display="block";
}
explore.style.top="5%";
news.style.top="5%";
about.style.top="5%";
events.style.top="5%";
titleClicked=true;
}
</script>
</body>
</html>
Thanks so much for your help.
A secondary issue: how do I prevent the cursor from changing from the pointer when directed at the text in my menu?
Thank again!
I've never managed to get the pseudo-classes (like :hover) to behave the way you want. If you can use jQuery, you can add a click function to the menu class:
$('.title').click(function() {
$('.title').css({'background':'#eb56bd'});
$(this).css({'background':'#b0408d'});
});
First you set all backgrounds to the non-clicked color, then apply the highlight color to the clicked item. This ensure a previously clicked item has the highlight removed when you click on another item.
JSFiddle
You should use css classes to style your menu links:
.selected{background:rgb(176, 64, 141);}
When a menu link is clicked, then you apply the selected class to the that menu link
function titleClick(div) {
//div.style.background="#b0408d";
div.className='selected';
var isClicked = div;
Following that you'll need to clear the 'selected' class from the other menu links so that they are no longer selected, example:
about.className="";
events.className="";
Instead of using mouseover and mouse out to style your menu links, use css :hover instead:
#news:hover{
background:"#eb56bd";
}
As for the div not showing, I'm guessing it's because the divs are empty. I've filled it up with some random text and it does show.