I'm trying to animate a slide in menu using CSS/JavaScript (SASS/CoffeSript). It works like this, the only problem is that the width of the menu which slides in is hardcoded (233px). How can I dynamically get the width of the div and set it back, when I need to set the width of the div to 0 in CSS on start? Can I somehow calculate what the div width should be and set this again?
Any ideas how I might solve this to get the width dynamically, so that I can add/remove items to the menu without changing a hardcoded value in the CoffeScript?
HTML/PUG:
// Module: Header
.header
.header--logo
a(href="/", class="link-logo")
img(src="/img/logo.svg")
.header--menu#menu
a(href="#", class="link-menu")
img(src="/img/menu.svg", id="clicked-menu-item")
ul#nav
li: a(href="") projects
li: a(href="") contact
li: a(href="") self
CSS/SASS:
.header
position: sticky
top: 0
left: 0
background-color: $lightColor
display: flex
justify-content: space-between
padding: $baselineHeight
&--menu
display: flex
align-items: center
ul
width: 0px
overflow-x: hidden
transition: width ease-in-out 300ms
li
display: inline
margin-left: $baselineHeight
JavaScript/CoffeScript:
element = document.getElementById('clicked-menu-item')
element.onclick = (obj) ->
if (obj.srcElement.classList.contains('clicked'))
document.getElementById("nav").style.width = "0px"
else
document.getElementById("nav").style.width = "233px"
obj.srcElement.classList.toggle('clicked')
false
Related
I'm making a nextjs app ,
I want to change the navbar active button according the the visible sections in the viewport
the page children look like this
<div id="section1" > </div>
<div id="section2" > </div>
...
<div id="faq" > </div>
<div id="contact" > </div>
for example when the user scrolls and the current div in the screen is the contact form
I set it the route to /#contact
My main problem is how to detect the current viewable element in the viewport
How can I achieve this ?
You can use Intersection Observer. Here is a live demo, where the list items on the header are automatically highlighted as you scroll over each section.
Javascript:
// simple function to use for callback in the intersection observer
const changeNav = (entries, observer) => {
entries.forEach((entry) => {
// verify the element is intersecting
if(entry.isIntersecting && entry.intersectionRatio >= 0.55) {
// remove old active class
document.querySelector('.active').classList.remove('active');
// get id of the intersecting section
var id = entry.target.getAttribute('id');
// find matching link & add appropriate class
var newLink = document.querySelector(`[href="#${id}"]`).classList.add('active');
}
});
}
// init the observer
const options = {
threshold: 0.55
}
const observer = new IntersectionObserver(changeNav, options);
// target the elements to be observed
const sections = document.querySelectorAll('section');
sections.forEach((section) => {
observer.observe(section);
});
HTML:
nav
ul
li
a(href='#one').active One
li
a(href='#two') Two
li
a(href='#three') Three
li
a(href='#four') Four
li
a(href='#five') Five
section#one
p Slide One
section#two
p Slide Two
section#three
p Slide Three
section#four
p Slide Four
section#five
p Slide Five
CSS:
nav
position fixed
width 100%
top 0
left 0
right 0
background-color white
ul
list-style-type none
display flex
align-items center
justify-content space-around
width 100%
max-width 800px
height 50px
margin 0 auto
padding 0
li
display inline-block
padding 5px
a
display block
height 40px
padding 0 20px
line-height 40px
text-decoration none
text-transform uppercase
color #323232
font-weight bold
border-radius 4px
transition background-color 0.3s ease-in
&:hover
&:active
&:focus
background-color rgba(#B8D6A8, 0.5)
&.active
background-color rgba(#B8D6A8, 0.5)
section
display flex
align-items center
justify-content center
min-height 100vh
p
text-align center
color white
font-size 3.5em
font-weight bold
text-transform uppercase
#one
background-color #6CA392
#two
background-color #FFA58C
#three
background-color #FF4F30
#four
background-color #576B51
#five
background-color #392A1B
I've had a problem with scrolling div with using flex-direction: column-reverse;
Here is my 'visible' part of code:
.messagesBox {
overflow-y: scroll;
padding: 10px;
row-gap: 2px !important;
overflow: auto;
display: flex;
flex-direction: column-reverse;
width: "100%";
}
<div
id="messagesBox"
onScroll={onScroll}
className={styles.messagesBox}
>
{renderContent()}
</div>
I create this div to display an array of object, set vertically with scrool sticky to bottom thanks to column-reverse (i need to use this because i have no contact with server side).
Here is my onScroll function:
const onScroll = () => {
const box = document.getElementById("messagesBox");
console.log(box.scrollTop);//-267 on top div, 0 on bottom div, I need reverse this values
}
when I scroll my div to top the scrollTop function return me bad values, when I'm on top she return me some negative values like -267.7, but when i scroll to bottom then return me 0.
Can someone tell me how to get correct values and get 0 from scrollTop when scrool is on top?
Thanks for any help!
////////////////////////////
I have a div container that is about 70% of the height of the page. The 30% which is outside the div is dim lighted (greyed out).
I am trying to implement a functionality where scrolling down within this container div causes the container div to fill up more of the page (less vertical space is greyed out) and eventually all of it (so 100% height).
Vica versa, when scrolling upward within the container and reaching the top should cause of the greyed out space to become bigger. What is the easiest way to implement this, possibly with the help of a library?
Using the scroll event and a combination of scrollTop, scrollHeight and clientHeight properties, we could get something that resembles your need:
let elem = document.querySelector('div');
elem.addEventListener('scroll', () => {
if(elem.scrollTop == 0) {
elem.style.height = `${elem.clientHeight + 10}px`;
}
if(elem.scrollHeight - elem.clientHeight == elem.scrollTop) {
elem.style.height = `${elem.clientHeight + 1}px`;
}
});
body {
background: #555;
height: 100vh;
margin: 0;
display: flex;
align-items: center;
overflow-y: hidden;
}
div {
background: #ccc;
height: 70%;
width: 100%;
overflow-y: scroll;
}
<body>
<div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</body>
I've being trying to get a consistent horizontal scroll with flex-box.
http://codepen.io/sheriffderek/pen/NABzdQ
Things were going great, but I did that thing ~ where you forget to look at it in Safari and FireFox. Things aren't working great there. Normally, if something works in web-kit but not firefox, webkit is smoothing out something that isn't right / where as firefox follows the rules. So, it's not a bug or anything... but the flexy things aren't really expanding around their child images.
That being said, I can't figure out which part is the pivotal thing that needs to change.
I'm using flex-box for the header and 'content' area where the content area grows to fill the remaining space. So, a global column
Within the 'content' area, there is a list that is flex and row. In the list there are items with either text or an image. The images should be 100% height of the list, and then auto width.
I would have thought that I could set the images to 100% height and width auto (similar to how I do the opposite for small-screens) - but the affect is not the same.
img {
display: block;
height: 100%;
width: auto;
}
to deal with this, I use JS to find the height of the 'content' area and set the images to that height.
http://s.codepen.io/sheriffderek/debug/NABzdQ (version with no editor for testing / on iPad etc.)
Works great in Chrome.
So... Does anyone have any advice? My real project is small-screen first, so more complex - but this is a clear example of where things go awry.
Styles
ul
list-style: none
margin: 0
padding: 0
body
display: flex
flex-direction: column
height: 100vh // ?
.header
//
.section // content
display: flex
flex-grow: 1
.item-list
display: flex
flex-direction: row
flex-grow: 1
max-width: 100%
overflow: auto
.item
display: flex
flex-grow: 1
a //
display: block
display: flex
.image-w
width: auto // should stretch to fit the child / image
max-height: 100%
overflow: hidden //?
img
display: block
width: auto
// height to be set by JS
.text-w
width: 400px
padding: 1rem
Scripts
var setUp = function() {
$('.item').each( function() {
var $this = $(this);
// var $thisFigure = $this.find('.image-w');
var $thisImage = $this.find('img');
var thisHeight = $this.outerHeight();
$thisImage.css({
height: thisHeight
});
});
};
$(window).resize( setUp ).trigger('resize');
Goal
To have the page navigation positioned lower on the page when initially loaded. So that it looks like pictured below.
Background
I created a navigational element that is using Headroom.js to control its position. The point of the library is that it moves the desired navigational item out of view when a user is scrolling down so that you can see more content. Then the item shows up when you scroll back up to make it convenient to click on a link if that is what you needed to do.
Current State
I have this current demo on codepen.
That navigational item is at the top of the page but on a lower z-index. So not initially visible.
when you scroll down the element is out of view.
But when you scroll up, it is where it needs to be
Code
HTML
<nav id="page-menu" class="link-header header--fixed slide slide--reset" role="banner">
<ul>
<li>Products</li>
<li>Features</li>
<li>Testimonials</li>
<li>Cases</li>
</ul>
</nav>
CSS
#page-menu {
background-color: #BA222B;
list-style-type: none;
width: 100%;
z-index:10;
}
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
#page-menu ul li a {
text-decoration: none;
color: #fff;
}
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
jQuery
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
classes: {
initial: "slide",
pinned: "slide--reset",
unpinned: "slide--up"
}
}).init();
}());
Full demo on codepen.
Goal :
From what you are describing, you want the read navigation to appear as such on page load:
And move with the gray bar, but and down, as the user scrolls, until it cutoff point reaches the bottom of the gray bar. Then you want things to kick in, and have the red bar slide up and out of view, and then up and down depending on scroll. You want the transition to be smooth.
Method:
The thing to keep in mind for a smooth transition is that you have two states: A top state and a bottom state. You have to design both, you have to figure out the exact height to change over, and you have to make sure that they will be identical at that spot, so appear seamless.
Top State:
We don't need any sort of extra positioning here. We want it to be static in fact, as odd as that might sound.
Bottom State:
We want fixed positioning here. Since we want the changeover to occur right when the red bar touches the top of the window, your CSS in fixed-header is perfect already.
Changeover Height:
The header and the gray nav bar combined are 180px, so that number will be our change over.
Code:
1. Statechange
Lets work backwards and take the state change first. You will need to change from 150px to 180px in a lot of places. For example, your JS code:
Existing JS:
if ($(window).scrollTop() >= 150) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
New JS:
if ($(window).scrollTop() >= 180) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 180,
And your header will need an updated height, or a removal of height entirely.
Existing CSS:
header {
height:150px;
position: relative;
z-index:30;
}
New CSS:
header {
position: relative;
z-index:30;
}
2. Top State
The big thing here messing you up is that for some reason the library you are using is applying .header--fixed and link-header on page load. I don't know how to prevent this, but we can just neutralize is by removing them from your CSS.
Remove This CSS:
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
Second, we need to tweak the ul inside your red nav.
Existing CSS:
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
New CSS:
#page-menu ul {
list-style-type: none;
margin: 0 auto;
padding:0;
width:960px;
max-width:100%;
text-align:right;
}
3. Bottom State
Everything works really well here aleady, except that the fixed-header class is getting added to the gray nav as well. We need to tweak our jQuery selector bit.
Existing JS:
if ($(window).scrollTop() >= 180) {
$('nav#page-menu').addClass('fixed-header');
}
else {
$('nav#page-menu').removeClass('fixed-header');
}
NewJS:
if ($(window).scrollTop() >= 180) {
$('header nav').addClass('fixed-header');
}
else {
$('header nav').removeClass('fixed-header');
}
4. Misc Cleanup
Everything looks really good here, except that the lis inside our two navs don't line up. We need to fix some margin-right to bring them into line.
Existing CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
New CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
}
Finally, I noticed that there's a missing closing bracket in your HTML, in the gray nav. It's not hurting much, but it could:
<nav>
<ul>
<li>Dentists</li>
<li>Labs</li>
<li>Patients</li>
<ul> <--- ( Should be </ul> )
</nav>
End Result:
http://codepen.io/anon/pen/qIrhx