Changing header style on scroll using intersectionObserver and fullpage.js - javascript

I'm a newbie of front-end development. I'm currently working on a project trying to make my header style change while scrolling using intersectionObserver. I'm also using fullpage.js to create a full page transition effect. However, I encounter the problem that when I scroll, browser considers section 1 and section2 are the same section, which the header style will only change when I scroll to the section3.
Would anyone tell me what happened? Maybe I missed something.
The code I used is here:
<div class="header">
<a href="#">
<h1>logo<h1>
</a>
<nav>
<ul class="nav-link">
<li>projects</li>
<li>about</li>
</ul>
</nav>
</div>
<div id="fullpage">
<div class="section s1">
</div>
<div class="section s2">
</div>
<div class="section s3">
</div>
<div class="section s4">
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/3.0.9/fullpage.min.js"></script>```
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #070520;
}
.header {
--text: #fff;
--background: transparent;
position: fixed;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
width: 100%;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
z-index: 999;
padding: 1rem 6.5rem 0 1.5rem;
background-color: var(--background);
}
.header a {
font-size: 0.8rem;
text-decoration: none;
color: var(--text);
font-family: "Helvetica", sans-serif;
font-weight: 100;
letter-spacing: 0;
}
.header .nav-link {
list-style: none;
}
.header .nav-link li {
display: inline-block;
bottom: 0;
padding: 0px 10px;
}
.header-scrolled {
--text: #070520;
}
.s2 {
background-color: grey;
}
.s3 {
background-color: green;
}
.s4 {
background-color: blue;
}
new fullpage("#fullpage", {
scrollingSpeed: 1000,
});
const header = document.querySelector('.header');
const sectionOne = document.querySelector('.s1');
const sectionOneOptions = {};
const sectionOneObserver = new IntersectionObserver(function(entries,sectionOneObserver){
entries.forEach(entry=>{
if(!entry.isIntersecting){
header.classList.add('header-scrolled')
}else{
header.classList.remove('header-scrolled')
}
})
},sectionOneOptions);
sectionOneObserver.observe(sectionOne);
https://codepen.io/Austin020304/pen/WNwjqaO
Thank you!

Consider using fullPage.js state classes or callbacks for that.
Also, do not forget to check the callbacks examples:
https://github.com/alvarotrigo/fullPage.js/tree/master/examples
You might also want to check this video tutorial I did making use of the state classes to create animations.

Related

Why does my page width only stretch to 100% with "fit-content"?

I have tried looking around for this but can't seem to find a question to match my current problem. I am trying to build a mock ecommerce website to practice using React. I have a header component. I want this component to be 100% of the screen width, so that the elements inside this component shrink whenever the page shrinks. I have some global css that sets the height and width of the html and body to 100%:
html, body{
background-color: rgb(167, 72, 72);
height: 100%;
min-width: 100%;
}
I am currently facing two problems, neither of which I understand very well the causes of. When I set my header component (the outermost component) to have a width of 100%, the page shrinks correctly. But when I open up developer tools to check the responsiveness, something goes wrong so that the right side of my header is shrinking faster than the page header_shrink
I am able to fix this by setting the width of my header to "fit-content" instead of "100%". Here is what the header looks like when I shrink the page using developer tools.header_fixed But when I do it this way, the components inside of my header don't shrink correctly. For example, my search bar is supposed to decrease in width as I shrink the page, but when I use "fit-content", it just stays set to whatever size it is. search-bar-constant. When I have the width set to 100% instead of fit content, it looks the way it's supposed to search-bar-fixed.
Sorry for the long explanation, but this is the bulk of my problem. "Width: 100%" allows the items in my header component to shrink correctly, but not the component itself. And "width: fit-content" allows the outer header component to shrink correctly, but not the items inside of it.
Here is the JSX I have for reference:
import React from 'react'
import './Header.css'
import { BiSearchAlt2 as SearchIcon} from "react-icons/bi";
import {RiArrowDropDownLine as DropDownIcon} from "react-icons/ri";
import { CgProfile as Profile } from "react-icons/cg";
import { CgShoppingCart as Cart } from "react-icons/cg";
const Header = () => {
const texts = [
'ORDERS OF $5K SHIP FREE',
'FREE SHIPPING ON SELECT ITEMS: SHOP NOW',
'BUY A RIG AND YOUR ENTIRE ORDER SHIPS FREE'
];
let currentTextIndex = 0;
setInterval(() => {
const shippingDealsText = document.querySelector('.shipping-deals-text');
shippingDealsText.classList.add('out');
setTimeout(() => {
shippingDealsText.textContent = texts[currentTextIndex];
shippingDealsText.classList.remove('out');
currentTextIndex = (currentTextIndex + 1) % texts.length;
}, 1000);
}, 5000);
return (
<div className="header">
<div className="header-top">
<div className="top-logo">
<h5 className='small-logo'>LEVIATHAN</h5>
</div>
<div className="space"></div>
<div className="link-container">
<div className="link-wrap">
Gift Cards
</div>
<div className="link-wrap">
Contact Us
</div>
<div className="link-wrap">
Order Status
</div>
<div className="link-wrap">
Live Chat
</div>
</div>
</div>
<div className="header-middle">
<div className="middle-logo">
<h5 className='big-logo'>LEVIATHAN</h5>
</div>
<div className="search-container">
<div className="search-wrapper">
<input
type="text"
id="search-bar"
placeholder="Search"
className='search'
/>
<div className="search-icon-wrapper">
<SearchIcon className='search-icon'/>
</div>
</div>
</div>
<div className="shipping-deals-container">
<div className="button-container">
<div className="shipping-deals-button">
<span className="deals-text">DAILY SHIPPING DEALS </span>
</div>
</div>
<div className="text-container">
<div className="text-slideshow">
<p className="shipping-deals-text">BUY A RIG AND YOUR ENTIRE ORDER SHIPS FREE</p>
</div>
</div>
</div>
<div className="icons-right">
<Profile className='login-pic'/>
<span>Log In</span>
<Cart className='shopping-cart'/>
</div>
</div>
<div className="header-bottom">
<div className="nav-bar">
<ul className='navigation'>
<li className='menu-items'>
<a href="/" className='button drop-down red'>Shop <DropDownIcon className='drop-icon'/></a>
<a href="/" className='button'>Equipment for Crossfit</a>
<a href="/" className='button'>New Gear</a>
<a href="/" className='button'>Barbells</a>
<a href="/" className='button'>Plates</a>
<a href="/" className='button'>Rigs and Racks</a>
<a href="/" className='button'>Shoes</a>
<a href="/" className='button'>Apparel</a>
<a href="/" className='button'>3 Ships Free</a>
<a href="/" className='button'>Zeus</a>
<a href="/" className='button drop-down'>The Index</a>
</li>
</ul>
</div>
</div>
</div>
)
}
export default Header
Here is the styling I am currently applying:
.header {
min-width: 100%;
margin: 0;
padding: 0;
}
.header-top {
background-color: white;
display: flex;
height: 2.5rem;
width: 100%;
}
.top-logo {
position: relative;
margin-left: 3rem;
}
.space {
flex-grow: 1;
}
.small-logo {
padding-top: 0.5em;
position: relative;
font-size: larger;
color: rgb(133, 133, 133)
}
.link-container {
display: flex;
/*border: 1px solid red;*/
margin-right: 3rem;
}
.link-wrap {
/*border: 1px solid green;*/
font-size: 14px;
padding-left: 1rem;
padding-top: 0.75rem;
}
.link-wrap a {
text-decoration: none;
color:#666666;
cursor: pointer;
}
/* Large section of header, black background */
.header-middle {
background-color: black;
height: 7rem;
display: flex;
}
/* Big LEVIATHAN text */
.middle-logo {
/*border: 1px solid red;*/
position: relative;
margin-left: 3rem;
display: flex;
justify-content: center;
align-items: center;
cursor: co;
}
.big-logo {
font-size: 48px;
/*padding-top: 2rem;*/
position: relative;
color: white;
}
.big-logo:hover {
color: rgb(210, 0, 0);
}
.search-container {
position: relative;
width: 40%;
display: flex;
flex-basis: 60%;
margin-left: 3rem;
align-items: center;
justify-content: center;
}
/*This is what has the appearance of the search bar*/
.search-wrapper {
min-width:100%;
height: 35%;
position: relative;
background-color: white;
display: flex;
flex-basis: 50%;
}
.search-icon-wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 3rem;
}
.search-icon {
color: black;
font-size: 20px;
}
/*This is the actual search bar tucked inside*/
.search {
width: 100%;
height: 100%;
border: none;
outline: none;
margin-left: 1em;
font-size: 17px;
}
.search::placeholder {
color:rgb(94, 94, 94);
}
/* This holds onto both our daily shipping deals button */
/* and our text slideshow */
.shipping-deals-container{
width: 18em;
margin-left: 2.5em;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
/*border: 2px solid rgb(136, 77, 255);*/
}
.shipping-deals-button {
width: 65%;
height: 44%;
background-color: rgb(234, 2, 2);
position: relative;
display: flex;
justify-content: center;
align-items: center;
margin-top: 1.5em;
}
.button-container {
width: 100%;
height: 50%;
/*border: 2px solid magenta;*/
}
.deals-text {
color: white;
font-size: 12px;
position: relative;
text-align: center;
align-items: stretch;
width: 100%;
}
.text-container {
/*border: 2px solid rgb(20, 182, 11);*/
width: 100%;
height: 50%;
}
.text-slideshow {
color: white;
width: 100%;
height: 50%;
font-size: 12px;
}
.shipping-deals-text {
transition: opacity 1s;
opacity: 1;
font-size: 13px;
}
.out {
opacity: 0;
transition: opacity 1s;
}
.shipping-deals-text-red{
color: red;
}
.navigation {
display: flex;
align-items:flex-start;
height: 3rem;
}
.menu-items {
height: 100%;
margin-left: 1.5rem;
padding-right: 1.5rem;
display: flex;
align-items: flex-start;
flex: 1;
}
ul {
list-style-type: none;
background-color: #333333;
}
.button {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
text-decoration: none;
color: white;
text-transform: uppercase;
white-space: nowrap;
padding: 1em;
font-weight: bold;
}
.button:hover {
color:rgb(210, 0, 0)
}
.red {
background-color: rgb(210, 0, 0);
}
.red:hover {
color: white;
}
.drop-icon {
font-size: 25px;
}
.icons-right {
height: 50%;
margin-top: 2em;
min-width: 10%;
display: flex;
justify-content: center;
align-items: center;
margin-right: 1rem;
}
.login-pic {
color: white;
font-size: 20px;
}
.shopping-cart {
color: white;
font-size: 20px;
margin-left: 1rem;
}
.icons-right span {
color: white;
margin-left: 0.5em;
}
#media (max-width: 1025px) {
.shipping-deals-container {
display: none;
}
.header-top {
display: none;
}
.header-middle {
height: 50%;
}
.search-wrapper {
border: 2px solid white;
height: 2rem;
}
.icons-right {
margin-bottom: 2rem;
}
}
I have tried altering the width of my body, and html, but nothing seems to be giving me the solution I am looking for
With width: 100% on .header it shrinks the header the way you want it. That seems to be correct actually.
The element that prevents shrinking is <li class="menu-items"></li> because of display: flex;. Flexbox is by default not wrapping (flex-wrap: nowrap;).
Add flex-wrap. wrap; and you'll see everything will shrink with fit-content or width: 100%;
Hope this helps.
On another note: You shouldn't use <li> (List-Element) as the list. Thats what <ul> (Unsorted list) is for.
It should look more like this ->
<ul>
<li>
Shop
</li>
<li>
Equipment for Crossfit
</li>
<li>
New Gear
</li>
<!-- ... -->
</ul>

Can't get transition to work for accordion menu

I'm having a problem where I want to have an accordion menu that automatically expands to fit content that is dynamically added. I want the accordion body to expand its height to accommodate more comments as they are added. The accordion works, but it will not take a transition.
Can somebody assist me with what I am doing wrong? Thanks.
const accordionItemHeader = document.querySelector(".accordionItemHeader");
accordionItemHeader.addEventListener("click", event => {
accordionItemHeader.classList.toggle("active");
const accordionItemBody = document.querySelector(".accordionItemBody");
if (accordionItemHeader.classList.contains("active")) {
accordionItemBody.style.setProperty("max-height", "100%");
} else {
accordionItemBody.style.setProperty("max-height", "0");
}
})
.accordionItemHeader {
padding: 0 10px;
cursor: pointer;
position: relative;
background-color: $spruce;
display: flex;
align-items: center;
h5 {
color: $iceBlue;
}
}
.accordionItemHeader::after, .accordionItemHeader.active::after {
font-size: 3.5rem;
position: absolute;
right: 0;
top: 0;
display: flex;
justify-content: flex-end;
align-items: center;
height: 100%;
padding: 0 10px;
color: $iceBlue;
}
.accordionItemHeader::after {
content: "\25BC";
}
.accordionItemHeader.active::after {
content: "\25B2";
}
.accordionContent {
padding: 10px;
}
.accordionItemBody {
max-height: 0;
overflow: hidden;
border: 1px $spruce solid;
padding: 0;
// transition: max-height 0.5s; <-- this is what won't work
}
<div class="accordion">
<div class="accordionItem">
<div class="accordionItemHeader">
<h5>Comments</h5>
</div>
<div class="accordionItemBody">
<div class="accordionContent">
<ul class="commentsPosted">
<!--dynamic comments posted go here-->
<li class="placeholderComment">
<p>No comments yet</p>
</li>
</ul>
</div><!--accordionContent div end -->
</div> <!--accordionitembody div end-->
</div><!--accordionItem div end-->
</div><!--accordion div end-->

show divs one after the other

I have a popup where I show notifications. The user can delete notifications at any time. The day the notification arrives and the delete button will appear one after the other. No matter what I did, I couldn't.
How can I show these two divs under each other, as can be seen in the marked area in the picture?
<div className="notificationlist__container only-desktop">
{props.notification.notificationList.map((e) => {
return (
<div className="notificationlist__item">
<div className="notificationlist__info">
<div className="notificationlist__content">
Lorem, ipsum.
</div>
<div className="notificationlist__detail">
<Link to="/profil">
<div>Profile</div>
<AS.KeyboardArrowRightIcon />
</Link>
</div>
</div>
<div className="notificationlist__time">Today
<div className="delete__button">
<AS.IconButton >
<AS.DeleteIcon />
</AS.IconButton>
</div>
</div>
</div>
);
})}
</div>
.notificationlist__container.only-desktop {
font-size: 1.2rem;
// padding-right: 2em;
max-height: 400px;
overflow: auto;
.notificationlist__item {
padding: 0.5em 0;
border-bottom: 1px solid #d1d1d1;
&:last-of-type {
border-bottom: none;
}
display: flex;
justify-content: space-between;
align-items: flex-start;
.notificationlist__info {
margin-right: 1em;
max-width: 400px;
.notificationlist__content {
color: gray;
}
.notificationlist__detail {
margin-top: 1em;
color: var(--palette-blue-300);
display: flex;
align-items: center;
font-size: 1.1rem;
font-weight: 600;
svg {
font-size: 1.5rem !important;
}
a {
display: contents;
}
}
}
.notificationlist__time{
display: flex;
.delete__button {
float: left;
}
}
}
}
display: flex is putting divs next to each other. You can delete display: flex or just add flex-direction: column; to put them under each other. To center them horizontally add align-items: center;
You should move delete button out of notificationlist_time content, then it would be easy to manipulate it
<div className="notificationlist__right">
<div className="notificationlist__time">today</div>
<div className="delete__button">
<AS.IconButton >
<AS.DeleteIcon />
</AS.IconButton>
</div>
</div>
So since it would be two different blocks, you would have an ability to position them like you want.

Overflow X Hidden not working on Mobile devices for my Navbar

The overflow x in my react Navbar not working as expected. The navbar is meant to slide in only when the Hamburger is clicked and not to show when not clicked. Everything works well except the fact that the overflow X that was supposed to hide keeps scrolling. Have tried a few things but yet not working.
Here is the link to the CodeSandbox
My Navbar and my CSS code are here below. Kindly help me look into this.
import React, { useState } from "react";
import { IconContext } from "react-icons";
import { MdMenu } from "react-icons/md";
// import { MdClose } from "react-icons/md";
export default function Navbar() {
const[navLinkOpen, navLinkToggle] = useState(false)
const handleNavLinksToggle = () =>{
navLinkToggle(!navLinkOpen)
}
const renderClasses = () =>{
let classes = "navlinks";
if(navLinkOpen){
classes += " active"
}
return classes;
}
return (
<div>
<div className="container">
<nav>
<div className="logo">
Edie
</div>
<ul className={renderClasses()}>
<li className="link"> Home </li>
<li className="link"> Services </li>
<li className="link"> Our Works </li>
<li className="link"> Clients </li>
<li className="link"> Contacts </li>
</ul>
<IconContext.Provider value={{ color: "#000000", size: "30px", className: "icon" }}>
<div onClick={handleNavLinksToggle} className="hamburger-toggle">
<MdMenu/>
</div>
</IconContext.Provider>
</nav>
</div>
</div>
)
}
CSS
#import url('https://fonts.googleapis.com/css2?family=Heebo&family=Poppins&display=swap');
nav{
display: flex;
justify-content: space-between;
align-items: center;
}
.navlinks{
display: flex;
justify-content: space-evenly;
width: 50%;
align-items: center;
}
.logo{
width: 70px;
height: 53px;
}
.logo > a{
font-family: 'Heebo', sans-serif;
text-decoration: none;
font-style: normal;
font-weight: 800;
font-size: 36px;
line-height: 53px;
color: #333333;
}
.navlinks > li > a{
text-decoration: none;
font-family: 'Poppins', sans-serif;
font-style: normal;
font-weight: 500;
font-size: 24px;
line-height: 36px;
color: #333333;
}
.hamburger-toggle{
cursor: pointer;
display: none;
}
#media screen and (max-width: 1024px){
body{
overflow-x: hidden;
}
.hamburger-toggle{
display: block;
}
.navlinks{
display: none;
position: absolute;
right: 0;
display: flex;
flex-direction: column;
height: 92vh;
align-items: center;
width: 100%;
top: 10vh;
background-color: red;
transform: translateX(100%);
transition: transform 0.5s ease-in;
}
.active{
transform: translateX(0%);
}
}
For that you can use the position relative and additional width for html and body in global css.
It appears that browsers that parse the tag simply ignore overflow attributes on the html and body tags.
on Global CSS
html, body{
width: 100%;
position: relative;
}

How Do I Make Transparent Navbar Have Background Color After Scroll?

I want to give my navbar the effect of being transparent initially, but upon scrolling is given a black background color. I understand that Javascript is best suited for the job, but I have tried window.addEventListener and have remained unsuccessful. Any tips at all are greatly appreciated.
<script>
window.addEventListener( 'scroll', function () {
let nav = document.querySelector('nav');
nav.classList.toggle('scrolling-active');
});
</script>
#header {
height: 100vh;
}
#header nav {
display: flex;
background-color: transparent;
justify-content: space-between;
position: fixed;
width: 100vw;
}
#header nav .name {
display: flex;
width: fit-content;
color: white;
padding-left: 30px;
align-items: center;
font-size: 30px;
}
#header nav .name span {
color: rgb(182, 18, 18);
}
#header nav ul {
display: flex;
list-style: none;
width: fit-content;
}
#header nav ul li {
padding: 30px;
}
#header nav ul li a {
text-decoration: none;
font-size: 25px;
color: white;
font-family: "Yanone Kaffeesatz", sans-serif;
}
.scrolling-active {
background-color: black;
}
<header id="header">
<section class="hero">
<nav class="nav">
<div class="name"><h1><span>D</span>ave <span>A</span>nthony</h1></div>
<ul>
<li>Home</li>
<li>About</li>
<li>Recent Posts</li>
</ul>
</nav>
this comes down to CSS specificity. You have this in your css:
#header nav {
display: flex;
background-color: transparent;
justify-content: space-between;
position: fixed;
width: 100vw;
}
ids are more specific than classes and have higher importance so it will use this background color, which is transparent. One way to solve it is by adding an !important clause to your added class:
.scrolling-active {
background-color: black !important;
}
However, this isn't the best approach since it doesn't really need it if you just simply rework your ID usage (but it will work).

Categories

Resources