Navbar is not sticking - javascript

I am using materialize.css, materialize.js, and jquery 2.1.1.
I am trying to construct a sticky navbar after my .jumbotron1. I have the css all there but the jquery doesn't seem to be running.
I followed this tutorial : https://teamtreehouse.com/community/forum-tip-create-a-sticky-navigation-with-css-and-jquery-2
the css
body {
padding-top: 400px;
}
.row {
margin-bottom: 0;
}
.jumbotron1 {
width: 100%;
height: 400px;
background-color: #f5f5f5;
position: fixed;
top: 0;
}
/* navbar styling */
nav.navbarSticky {
margin-top: 0;
position: relative;
}
nav {
z-index: 998;
box-shadow: 0 0 0 rgba(0, 0, 0, 0.5);
}
/*sticky navbar styling*/
.jumbotron1 .stuck {
position: fixed;
width: 100%;
top: 0;
}
/*lineup styling*/
.lineup1position {
position: relative;
}
.lineup1 {
height: 800px;
background-color: #f5f5f5;
}
the html
<!--jumbotron 1-->
<div class="container">
<div class="row">
<div class="col s12 valign-wrapper jumbotron1">
<p class="valign center-block center-align">
Andrea + Fiance<br>
</p>
</div>
</div>
</div>
<!--navbar-->
<nav class="navbarSticky">
<div class="nav-wrapper">
<ul id="nav-mobile">
<li>line up</li>
<li>tickets</li>
<li>history</li>
<li>venue</li>
<li>details</li>
</ul>
</div>
</nav>
<!--lineup1-->
<div class="container lineup1position">
<div class="row">
<div class="col s8 offset-s2 lineup1">
<p class="center-align">
lineup<br>
andrea - fiance<br>
made of honor - best man<br>
bridesmaid - groomsman - bridesmaid - groomsman<br>
</p>
</div>
</div>
</div>
the javascript
var sticky = $(".navbarSticky")
var stuck = "stuck";
var hdr = $('.jumbotron1').height();
$(window).scroll(function() {
if( $(this).scrollTop() > hdr ) {
sticky.addClass(stuck);
} else {
sticky.removeClass(stuck);
}
});

position:relative is overriding position:fixed
In this css class
nav.navbarSticky {
margin-top: 0;
position: relative;
}
Here position relative is overriding position:fixed in stuck class
Take a look at this snippet
So I made this changes
New classes
#topContainer{
display:inline-block;
width:100%;
z-index:1001;
}
.stuck {
width: 100%;
display:inline-block;
top: 10px;
z-index:1001;
position:fixed !important;
}
.fixContainer{
position:fixed !important;
top:0px;
}
HTML
Added id attribute to top container
<div class="container" id ="topContainer">
// rest of code
JS
var sticky = $(".navbarSticky")
var stuck = "stuck";
var hdr = $('.jumbotron1').height();
$(window).scroll(function() {
console.log($(this).scrollTop(),hdr)
if( $(this).scrollTop() > hdr ) {
$("#topContainer").addClass("fixContainer") //Change here
sticky.addClass(stuck);
} else {
$("#topContainer").removeClass("fixContainer") //Change here
sticky.removeClass(stuck);
}
});
You can check this JSFIDDLE.
Currently the div.lineup1position is scrolling below li because of z-index property attached to li Since I am not sure how div.lineup1position is going to scroll so leaving it on you
Edit: addClass & removeClass are properly used.So removing that part

Your sticky class is not on the correct element
CSS (only works if .jumbotron1 has .stuck):
/*sticky navbar styling*/
.jumbotron1 .stuck {
position: fixed;
width: 100%;
top: 0;
}
jQuery (is stetting .stuck to .navbarSticky)
sticky.addClass(stuck);
Edit: In response to the comment below.
You want .navbarSticky to be stuck, and you are using the same styling as .jumbotron1, so you need a CSS selector like
.jumbotron1,
.stuck {
Also bear in mind that since your jumbotron is set to width: 100%; that once you add the comma, your nav may be under the jumbotron. I forget the natural z-index order of html, but in any case, to fix it, add:
.stuck {
z-index: 10;
}
This, BTW, you only add to .stuck do not add it to .jumbotron1.

Related

Sticky element that stops when reaches a element

I want to make a fixed element (like sticky) when I scroll and reach the top of another element. The fixed element will increase the bottom property of css to don't pass the top of the element I set as bound (the element you can't pass the point, like a ground). I did a pen that shows what I want, hope that helps: https://codepen.io/vendramini/pen/xNWpPK. I really don't know which calculation I need to do to achieve this. Please, help me.
https://codepen.io/vendramini/pen/xNWpPK
The best I could do to exemplify this.
*{
margin: 0;
padding: 0;
}
section{
height: 100vh;
width: 100vw;
background: #eee;
position: relative;
max-width: 100%;
}
.a{
background: #faa;
}
.b{
background: #ffa;
}
.c{
background: #afa;
}
.d{
background: #aaf;
}
.sticky{
width: 100%;
position: fixed;
height: 100px;
background: blue;
opacity: 0.5;
bottom: 0;
z-index: 1;
}
.ground{
height: 2000px;
background: black;
}
//jQuery required
(function($){
$('[data-bound]').each(function(){
const $elem = $(this);
const $bound = $( $elem.data('bound') );
$(window).scroll(function(){
const scrollTop = $(window).scrollTop();
const boundTop = $bound.offset().top;
const boundHeight = $bound.height();
const delta = (scrollTop - boundTop); //+ boundHeight;
console.log({
scrollTop,
boundTop,
delta,
});
if( delta > 0 ){
$elem.css('bottom', delta);
}
else{
$elem.removeAttr('style');
}
});
});
})(jQuery);
<div class="sticky" data-bound="#ground"></div>
<section class="a"></section>
<section class="b"></section>
<section class="c"></section>
<section class="d"></section>
<footer class="ground" id="ground"></footer>
<section class="a"></section>
<section class="b"></section>
<section class="c"></section>
<section class="d"></section>
I expect to have a fixed element that doesn't pass the ground element. That's it.
I'm not sure I understand exactly what you want, but I think you can achieve this with only CSS using position: sticky on the footer.
https://codepen.io/anon/pen/jozzPq
the relevante changes:
add a wrapper to the elements with the sticky footer:
<div>
<section class="a"></section>
<section class="b"></section>
<section class="c"></section>
<section class="d"></section>
<footer class="ground" id="ground"> </footer>
</div>
position the footer at the bottom and set it to sticky
.ground{
height: 100px;
background: black;
position: sticky;
bottom: 0;
}
Check the codepen cause a lot of CSS and (all) JS can be removed.
I finally found the answer:
https://codepen.io/vendramini/pen/xNWpPK
The solution is add the window's height in to the delta calculation:
const windowHeight = $(window).height();
const delta = (scrollTop - boundTop) + windowHeight;
Thanks everyone that contributed to this thread!
Replace
if( delta > 0 ){
$elem.css('bottom', delta);
}
else{
$elem.removeAttr('style');
}
with
$elem.css('bottom', 0);
to stick the element always to the bottom.
The thing that I want is next to what UIKit does:
https://getuikit.com/docs/sticky
But the problem is that UIKit uses top instead of bottom.

Scroll to bottom of hidden div?

I have a simple chat JS application, with a div.chat-holder holding all chat messages within a pane on the overall window. I set height of '.chat-holder so it remains fixed in size, and allows for scrolling of all the messages.
<style>
.chat-holder {
height: 30px;
overflow-y: scroll;
}
</style>
<div class="pane">
<div class="chat-holder">
<div class="chat-item">
first msg
</div>
<div class="chat-item">
second msg
</div>
....
<div class="chat-item">
last msg
</div>
</div>
</div>
On page load, I scroll to the bottom by setting the scrollTop of the holder:
var $holder = $('.chat-holder');
$holder.scrollTop($holder[0].scrollHeight);
and this works fine.
Problem occurs when I start with div.pane set to display:none. Ideally, I look to have a separate event to "show/hide" the chat pane, and start with the pane hidden.
When the parent pane is hidden, the .chat-holder scrollHeight is 0, so on load, the hidden pane won't be scrolled to the bottom. Which means when the pane is displayed, the chats are not scrolled to the most recent chats. You can see this in the following snippet: with .pane initially not displayed, scroll isn't set. If you set .pane to start displayed, then scroll works fine.
Is there anyway to "scroll to the bottom" while parent is hidden? (Yes, I know I could do this by detecting when the chat-holder is exposed & then scroll to the bottom, but I'm looking to do it on load.)
$(function() {
var $holder = $('.chat-holder');
$holder.scrollTop($holder[0].scrollHeight);
$('button').click(function() {
$('.pane').toggleClass('active');
});
});
.chat-holder {
height: 30px;
overflow-y: scroll;
border: thin solid black;
}
.chat-item {
font-size: 20px;
}
.pane {
display: none;
}
.pane.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="pane">
<div class="chat-holder">
<div class="chat-item">first msg</div>
<div class="chat-item">second msg</div>
<div class="chat-item">last msg</div>
</div>
</div>
<button>Toggle pane</button>
You can get creative and use opacity or visibility rules instead of display: none:
$(function() {
var $holder = $('.chat-holder');
$holder.scrollTop($holder[0].scrollHeight);
$('button').click(function() {
$('.pane').toggleClass('active');
});
});
.chat-holder {
height: 30px;
overflow-y: scroll;
border: thin solid black;
}
.chat-item {
font-size: 20px;
}
.pane {
opacity: 0;
position: absolute;
z-index: 1;
}
.pane.active {
opacity: 1;
position: relative;
}
button {
z-index: 2;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="pane">
<div class="chat-holder">
<div class="chat-item">first msg</div>
<div class="chat-item">second msg</div>
<div class="chat-item">last msg</div>
</div>
</div>
<button>Toggle pane</button>

How to make vertical "slide" scroll?

I have a landing page, consisting of three frames, this frames always take 100% of viewport height and width.
I need to make transitions between frames, like "powerpoint presentation" etc. User scroll's, frame-1 slides up above viewport and frame-2 becomes in his place from bottom of viewport. I have almost zero experience in javascript/jquery. Have some ideas, that you can see in the code, but this ideas not works.
HTML:
<div class="wrapper" id="wrapper">
<div class="frame frame-1">
<!-- Content here -->
</div>
<div class="frame frame-2">
<!-- Content here -->
</div>
<div class="frame frame-3">
<!-- Content here -->
</div>
</div>
CSS:
.wrapper {
height: 300vh;
}
.frame {
position: fixed;
height: 100vh;
transition: all 1s ease;
}
.frame-1 {
top: 0vh;
}
.frame-2 {
top: 100vh;
}
.frame-3 {
top: 200vh;
}
JS:
var $document = $(document),
$element1 = $('.frame-1'),
$element2 = $('.frame-2'),
$element3 = $('.frame-3');
$(window).scroll(function () {
if ($(this).scrollTop() >= 50) {
$element1.css("top", "-100vh");
$element2.css("top", "0vh");
$element3.css("top", "100vh");
} else if ($(this).scrollTop() >= 100) {
$element1.css("top", "-200vh");
$element2.css("top", "-100vh");
$element3.css("top", "0vh");
} else {
$element1.css("top", "0vh");
$element2.css("top", "100vh");
$element3.css("top", "200vh");
}
});
If you have a set number of frames, I would suggest placing them all in a single div, and changing the top value of that. that way, only one value need be modified.
Like this: http://jsfiddle.net/xkh4D/10/
(Note that, though px are used, vh or whichever other unit should work just as well... haven't tried %, though...)
HTML
<div id='yo' class='view'>
<div>
<div class='frame red'></div>
<div class='frame green'></div>
<div class='frame blue'></div>
</div>
</div>
<input type='button' value='Scroll' onclick='scrollFrame()'/>
CSS
.view {
position:relative;
width:300px;
height:250px;
border:1px solid black;
overflow:hidden;
}
.view > div {
position:absolute;
width:inherit;
height:inherit;
top:0px;
}
.frame {
width:inherit;
height:inherit;
}
.red { background-color:#faa }
.green { background-color:#afa }
.blue { background-color:#aaf }
JavaScript
scrollFrame = function()
{
var h = $('#yo').height();
var y = parseFloat($('.view > div').css('top'));
var hsum = $('.view .frame').length * h;
console.log('h,y,hsum',h,y,hsum);
if (hsum-h == -1*y)
$('.view > div').animate({'top':0});
else
$('.view > div').animate({top:y-h},500);
}
This js could be your solution
http://alvarotrigo.com/fullPage/

Scrollbars showing up over header and footer on page load

I'm developing a mobile application to look like it's running on an iPad. When the page initially loads, if the body of the page is beyond the window/screen size, the scrollbars for the page show up "over" the header and footer. But after you refresh the page, then the scrollbars show up BETWEEN the header and the footer (aka it's only over the body), which is what I want.
I'm not able to duplicate the exact behavior (where the scrollbars only show up over the body after a refresh) on jsfiddle, but it at least shows you the scrollbar over the entire page.
Any help is appreciated...
Here's the jsfiddle...
Here's the code that I have:
CSS:
.locationListItem {
margin-bottom: 5px;
}
.locationListPrimary {
color: blue;
font-weight: bold;
font-size: medium;
}
.locationListSecondary {
font-weight: bold;
font-size: smaller;
}
HTML:
#section header {
#*
Recommeneded to use an h1 element, but can contain any kind of element, but make sure to add the TrailsHeaderPrimary class to get the proper styling...
Using an h1 element will get the proper padding around the header line. To see the difference, try doing an h1 vs p *#
<h1 class="testHeaderPrimary">Search Locations</h1>
}
<div style="top: 15px; left: 15px; width: 100%; z-index: 2">
<ul data-role="listview" data-filter="true" data-filter-placeholder="Search/Filter Locations...">
#foreach (var location in Model.AvailableLocations)
{
<li>
<a href="#">
<div class="ui-grid-b">
<div class="ui-block-a"><span class="locationListPrimary" style="width: 20%">#location.Thing</span></div>
<div class="ui-block-b"><span class="locationListPrimary" style="width: 20%">#location.Person</span></div>
<div class="ui-block-c"><span class="locationListSecondary" style="width: 60%">#location.Year | #location.Stuff | #location.Type</span></div>
</div>
</a>
</li>
}
</ul>
</div>
#section navBar1 {
Search
}
#section navBar2 {
Location
}
#section navBar3 {
LocationStrip
}
#section navBar4 {
StackOverflow
}
#section navBar5 {
NA
}
Javascript (from the Layout):
$(document).ready(function () {
resetScreenSize();
});
$(window).resize(function () {
resetScreenSize();
});
var resetScreenSize = function () {
var windowHeight = $(window).height();
var header = $('#testHeader');
var headerHeight = header.outerHeight();
var footer = $("#testFooter");
var footerHeight = footer.outerHeight() - 1;
$(".ui-grid-a").height(windowHeight - footerHeight - headerHeight);
$("#panelMain").height(windowHeight - footerHeight - headerHeight);
};
Update 1:
Here's the body from the layout file...
<body style="height: 100%">
<div id="main" role="main" class="ui-content jqm-content" style="padding: 0; height: 100%;">
<div id="testHeader" data-role="header" data-theme="b" data-position="fixed">
#RenderSection("header", false)
</div>
<div class="ui-grid-a" data-theme="a">
<div id="panelMain" style="overflow: auto;">
<div class="ui-content">
#RenderBody()
</div>
</div>
</div>
<div id="testFooter" data-role="footer" data-theme="b" data-position="fixed" data-tap-toggle="false" style="height: 60px; display: block;">
<div data-role="navbar">
<ul>
<li>#RenderSection("navBar1", true)</li> <!-- Home/1 should be reserved for the home screen -->
<li>#RenderSection("navBar2", true)</li>
<li>#RenderSection("navBar3", true)</li>
<li>#RenderSection("navBar4", true)</li>
<li>#RenderSection("navBar5", true)</li>
</ul>
</div>
</div>
</div>
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
</body>
Update 2:
One of the tabs at the bottom goes to a page where it's split 20%/80%. That page uses a different layout to do the 20/80. When that page first loads, it does NOT incorporate my style in the "head" tag that looks like this:
#panelLeft {
width: 20%;
border-right: 3px solid
}
#panelMain {
width: 80%;
}
But as soon as I refresh the page, all of the styling is applied. I'm beginning to wonder if it's not applying my custom styling that I specify in each of the "head" tags in my layout pages. Should I be placing those in a separate css file instead?
The only idea I have that I can give is. Make the body's height fixed and have a property of overflow-y:auto;.
Also, ideally, you want to make the header, body and footer's total height the same with the height of the view height, browser's height.
So fix height = ((header's height + footer's height) - browser's current height). That's my formula.
To do that, either javascript/jQuery or css.
EDIT
Here's a fiddle.
http://jsfiddle.net/4RLZv/
Forgot my JS/JQ
$( document ).ready(function() {
var height = $('#head').outerHeight() + $('#foot').outerHeight();
height = $(window).innerHeight() - height;
$('#body').css('height',height);
});
You can try something like this:
.ui-grid-a {
position: absolute;
top: 68px;
bottom: 63px;
left: 0;
right: 0;
overflow-y: auto;
}
Also you can play with property width + property margin:auto
.ui-grid-a {
position: absolute;
top: 68px;
bottom: 63px;
left: 0;
right: 0;
overflow-y: auto;
margin: auto;
width: 900px;
}
Where width you should set for each size of display separately, e.g.
#media screen and (min-width: 768px) {
.ui-grid-a {
width: 600px;
}
}
#media screen and (min-width: 968px) {
.ui-grid-a {
width: 800px;
}
}
Just play with it!

100% width (of page) drop down/drawer menu with JQuery?

I've been stuck trying to figure out how to code a menu much like what you see on the Playstation website: http://us.playstation.com/
EDIT: Fiddle: http://jsfiddle.net/jjcarlson/7q64A/
So far I have a number of issues. The first is that I have been unable to create the 100% width, because, I am assuming, of the parent/child relationship.
The second issue I have is that my Timeout works on all class elements rather than only the currently hovered element. In other words, if all elements have slid down and one is hovered over, they all will remain open until none of them have been hovered for 1.5 seconds. I admit that my inability to come up with a solution may be due to my limited experience with the language. Below is the CSS:
.accordion-container {
width: 90%;
padding-bottom: 5px;
margin: 20px 0 0 20px;
}
.accordion {
width: 40%;
padding: 20px;
margin: 0 15px 35px;
position: relative;
float: left;
display: inline-block;
}
.accordion-question {
margin: 0;
padding: 0 0 5px 20px;
display: inline-block;
color: #06F;
background-color: #9F0;
cursor: pointer;
}
.accordion-answer-container {
padding: 0 20px;
overflow: hidden;
color: #999;
background: #F00;
}
.accordion-answer {
margin: 0;
padding: 0;
color: #0C0;
}
Then, the JQuery:
$(document).ready(function () {
var menu = $('.accordion-answer')
var timeout = 0;
var hovering = false;
menu.hide();
$('.accordion-question').hover(function () {
hovering = true;
// Open the menu
$(this).closest('.accordion').find('.accordion-answer')
.stop(true, true)
.delay(400).slideDown(600);
if (timeout > 0) {
clearTimeout(timeout);
}
})
.on("mouseleave", function () {
resetHover();
});
$('.accordion-answer').hover(function () {
hovering = true;
startTimeout();
})
.on("mouseleave", function () {
resetHover();
});
function startTimeout() {
timeout = setTimeout(function () {
closeMenu();
}, 1500);
};
function closeMenu() {
if (!hovering) {
$('.accordion-answer').stop(true, true).slideUp(400);
}
};
function resetHover() {
hovering = false;
startTimeout();
};
});
And finally, the HTML:
<div class="accordion-container">
<div class="accordion">
<div class="accordion-question">
<h2>Is this a question?</h2>
</div>
<div class="accordion-answer-container">
<div class="accordion-answer">
<p>To be honest, I am not sure</p>
<ul>
<li>List item one</li>
<li>List item two</li>
</ul>
<p>That is all.</p>
</div>
</div>
</div><!-- /accordion -->
<div class="accordion" id="testanchor">
<div class="accordion-question">
<h2>What would be a good second question?</h2>
</div>
<div class="accordion-answer-container">
<div class="accordion-answer">
<p>I don’t know, man!</p>
<p>That is all.</p>
</div>
</div>
</div><!-- /accordion -->
</div>
Styling is minimal right now (sorry) as I'm just trying to get this figured out. Thank you for any help you can provide.
To get a width of 100% you should not display them as inline-block and set the width of .accordion to 100%.
In the hover-event you set hovering to true. If the next hover-event occurs prior to the call of closeMenu, then the if clause will already be false.
You should be able to accomplish the 100% width of your dropdown by altering the css of your .according-answer-container to a fixed position along with setting left and right to 0:
.accordion-answer-container {
padding: 0 20px;
overflow: hidden;
color: #999;
background: #F00;
position: fixed;
left: 0;
right: 0;
}
An update to your fiddle shows this working

Categories