I have made a responsive navbar and have added an animation to be played when ".nav-toggle" is clicked for the mobile size of the navbar.
When I am scaling down my browser window, for a split second at screen size 768px you can see the animation playing in reverse. The animation I am asking about is the "transform: scale(1, 0);".
How do I get the animation to not play when the user is scaling down the window size from desktop to mobile? Again, the animation in question occurs when you get to 768px, it animates in reverse for like a second then it works normally.
Thank you for your help!!
const mainNav = document.querySelector('.main-nav');
const navToggle = document.querySelector('.nav-toggle');
const navLinks = document.querySelectorAll('.main-nav li');
navToggle.addEventListener('click', function () {
mainNav.classList.toggle('main-nav-active');
navLinks.forEach((links, index) => {
if (links.style.animation) {
links.style.animation = '';
} else {
links.style.animation = `navLinksFade .3s ease forwards ${index / 10 + .2}s`
};
});
});
:root {
--clr-primary-200: #f3eed9;
--clr-primary-400: #824936;
--clr-neutral-100: #FFF;
--clr-neutral-900: #222c2a;
--ff-primary: 'Roboto', sans-serif;
--ff-accent: 'Playfair Display SC', sans-serif;
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--ff-primary);
font-size: 1.3175;
}
.navbar {
background-color: var(--clr-neutral-900);
display: flex;
justify-content: space-around;
align-items: center;
min-height: 10vh;
}
.logo {
color: var(--clr-neutral-100);
text-decoration: none;
font-size: 2rem;
text-transform: uppercase;
letter-spacing: 3px;
}
.main-nav {
display: flex;
width: 60%;
justify-content: space-around;
}
.main-nav li {
list-style: none;
}
.nav-links {
text-decoration: none;
color: var(--clr-neutral-100);
font-size: 1.4rem;
}
.nav-toggle {
color: var(--clr-neutral-100);
font-size: 2rem;
display: none;
cursor: pointer;
}
#media (max-width: 768px) {
.main-nav {
position: absolute;
background-color: var(--clr-neutral-900);
top: 10vh;
width: 100%;
height: 40%;
display: flex;
flex-wrap: nowrap;
flex-direction: column;
align-items: center;
transform: scale(1, 0);
transform-origin: top;
transition: all 200ms ease-in;
}
.main-nav li {
opacity: 0;
}
.logo {
margin-right: auto;
margin-left: 2rem;
}
.nav-toggle {
display: block;
margin-right: 2rem;
}
.main-nav-active {
transform: scale(1, 1);
}
}
#keyframes navLinksFade {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<nav class="navbar">
Logo
<ul class="main-nav">
<li>
Home
</li>
<li>
Products
</li>
<li>
Contact Us
</li>
<li>
Blog
</li>
</ul>
<div class="nav-toggle">
<div>+</div>
</div>
</nav>
Related
I'm new in nextJs and for a projet, I try to create a menu with a hover effect with this code:
import Link from 'next/link';
const MenuItem = ({ href, label }) => (
//This Link has a className that doesn't get styled.
<Link href={href} className="menu-item">
{label}
</Link>
);
function MainNavigation() {
return (
<>
<style jsx>{`
.header {
height: 5rem;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #ffffff;
padding: 0 10%;
font-family: system-ui, sans;
font-size: 2.5rem;
font-weight: 800;
}
.logo {
font-size: 2rem;
color: white;
font-weight: bold;
}
.header ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
align-items: baseline;
}
.header li {
margin-left: 3rem;
}
.menu-item {
color: #000;
position: relative;
text-decoration: none;
}
.menu-item::before {
background: hsl(45 100% 70%);
content: "";
inset: 0;
position: absolute;
transform: scaleX(0);
transform-origin: right;
transition: transform 0.5s ease-in-out;
z-index: -1;
}
.menu-item:hover::before {
transform: scaleX(1);
transform-origin: left;
}
`}</style>
<header className='header'>
<div className='logo'>React Meetups</div>
<nav>
<ul>
<li>
<MenuItem href='/' label='menu item 1' />
</li>
<li>
<MenuItem href='/' label='menu item 2' />
</li>
</ul>
</nav>
</header>
</>
);
}
export default MainNavigation;
According nextJs 13 documentation, we don't need anymore to put in the Link the tag but I wonder how I can do the hover effect on the menu item? Currently the style is not apply on my menu-item.
Someone could explain what's wrong in this piece of code?
Thanks
try this in your style
.header > nav > ul > li > a:hover{
/*put your CSS here*/
}
<body>
<header class="main-header">
<div class="container">
<img src="images/logo.svg" alt="Manage">
<button class="toggle-button">
<span class="toggle-button__bar"></span>
<span class="toggle-button__bar"></span>
<span class="toggle-button__bar"></span>
</button>
<nav class="main-nav">
<ul role="list" class="main-nav__list">
<li class="main-nav__list--item">Pricing</li>
<li class="main-nav__list--item">Product</li>
<li class="main-nav__list--item">About Us</li>
<li class="main-nav__list--item">Careers</li>
<li class="main-nav__list--item">Community</li>
</ul>
</nav>
<button class="button button-header">Get Started</button>
</div>
</header>
<script type="module" src="/script/script.js"></script>
/* CSS/SASS code
I do not know why my logo/image is being placed in the middle of the header, instead of
the top left corner of the header. I do not know how to fix this.
If anybody has some nice suggestions, feel free to tell */
#mixin display-flex() {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
align-items: center;
}
#mixin media-min-width($width) {
#media (min-width: $width) {
#content;
}
}
.main-header {
position: relative;
padding: $pad-header 0;
.container {
#include display-flex();
justify-content: space-around;
a {
display: inline-block;
text-decoration: none;
font-size: $fs-nav;
font-weight: $fw-semi-bold;
}
.main-nav {
display: none;
#include media-min-width(50rem) {
display: block;
}
}
.button {
color: hsl(0deg, 0%, 98%);
font-weight: 700;
background: hsl(12deg, 88%, 59%);
padding: 0.7rem 1rem;
border: 0;
border-radius: 100vmax;
&:hover {
cursor: pointer;
}
:focus {
outline: none;
}
}
.button-header {
display: none;
#include media-min-width(50rem) {
display: block;
}
}
.toggle-button {
position: absolute;
top: 50%;
right: 2%;
transform: translateY(-50%);
background: transparent;
border: 0;
cursor: pointer;
#include media-min-width(50rem) {
display: none;
}
.toggle-button__bar {
display: block;
background: $clr-secondary;
width: 2rem;
height: 0.3rem;
margin: 0.3rem 0;
&:last-of-type {
margin: 0;
}
}
}
}
}
.main-nav__list {
#include display-flex();
justify-content: center;
gap: clamp(1.7rem, 1.9rem, 2.5rem);
.main-nav__list--item a {
cursor: pointer;
}
}
I'm struggling to get my react menu toggler to close on click of a list item. For instance, once someone opens the menu I would like it to close when they click "about", "solutions", etc. Also for some reason, the entire menu is not opening on my phone but in dev tools mobile view it works fine. On mobile it's stuck at the top and only shows what seems to be a strip of the bottom of the menu but nothing more. Any reason this may be happening?
const [active, setActive] = useState("nav__menu");
const [icon, setIcon] = useState("nav__toggler");
const navToggle = () => {
if (active === "nav__menu") {
setActive("nav__menu nav__active");
} else setActive("nav__menu");
// Icon Toggler
if (icon === "nav__toggler") {
setIcon("nav__toggler toggle");
} else setIcon("nav__toggler");
};
return (
<div className="header">
<nav className="nav">
<Link className='nav-logo' to='/'>
<img src={NavLogo} alt="Home" className="nav-logo-img" />
</Link>
<ul className={active}>
<li className="nav__item">
<NavLink exact="true" to="/about">
<div className="nav-link">About</div>
</NavLink>
</li>
<li className="nav__item">
<NavLink exact="true" to="/solutions">
<div className="nav-link">Solutions</div>
</NavLink>
</li>
<li className="nav__item">
<Link to="/consultation" className='menu-consult-btn'>
<img src={BtnDroplet}className="btn-droplet" />
<h4>Free Consultation</h4>
</Link>
</li>
</ul>
<div onClick={navToggle} className={icon}>
<div className="line1"></div>
<div className="line2"></div>
<div className="line3"></div>
</div>
</nav>
</div>
);
/* Header Component */
.header{
width: 100%;
height: 100px;
background-color: var(--bg-color);
position: fixed;
z-index: 1000000000;
}
.nav {
display: flex;
align-items: center;
justify-content: space-between;
width: 80%;
margin: auto;
padding: 25px 0;
z-index: 999999;
}
.nav-logo-img{
width: 35%;
}
.nav__menu {
display: flex;
align-items: center;
gap: 2rem;
white-space: nowrap;
}
.nav__toggler {
display: none;
}
.nav__toggler div {
width: 2.5rem;
height: 0.2rem;
margin: 0.4rem;
background: var(--text-color);
transition: 0.3s ease-in;
}
/* Media Queries */
/* Header Component */
#media screen and (max-width: 900px) {
.nav__toggler {
display: block;
cursor: pointer;
z-index: 10;
background: none;
}
.nav__menu {
position: fixed;
top: 0;
right: 0;
height: 100vh;
width: 100vw;
background: var(--sapphire);
flex-direction: column;
transform: translateX(100%);
transition: 0.5s ease-in;
z-index: 9;
padding: 0;
}
.nav__menu li:first-child{
margin-top: 125px;
}
.nav__menu li{
padding: 25px 0;
}
/* Active Class */
.nav__active {
transform: translateX(0%);
}
/* Toggle Icon Animation */
.toggle .line1 {
transform: rotate(-45deg) translate(-4px, 5px);
}
.toggle .line2 {
opacity: 0;
}
.toggle .line3 {
transform: rotate(45deg) translate(-8px, -10px);
}
}
#media(max-width: 500px){
.nav{
padding: 25px 0;
}
.nav-logo-img{
width: 30%;
}
}
I have created a navbar. This navbar should change color when scrolling. I have only managed so far that the background color changes. However, I also want the text colors to change as well as the icons. I would make now with each className the query, whether active or not. But this is very redundant. Is there an option that covers everything? By saying if the user scrolls and the navbar changes color, then the textcolor and everything else should also change? Would it make sense to say if navbar changes then call another new css? Is that possible? If so how do I do that?
Is there an option that makes this easier?
Navbar.js
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { Button } from '../buttons/Button';
import './Navbar.css';
function Navbar() {
const [click, setClick] = useState(false);
const [button, setButton] = useState(true);
const [navbar, setNavbar ] = useState(false);
const handleClick = () => setClick(!click);
const closeMobileMenu = () => setClick(false);
const showButton = () => {
if(window.innerWidth <= 960) {
setButton(false);
}
else {
setButton(true);
}
};
useEffect(() => {
showButton();
}, []);
window.addEventListener('resize', showButton);
const changeBackground = () => {
if(window.scrollY >= 80) {
setNavbar(true);
}
else {
setNavbar(false);
}
};
window.addEventListener('scroll', changeBackground);
return (
<>
<nav className={navbar ? 'navbar active' : 'navbar'}>
<div className="navbar-container">
<Link to="/" className="navbar-logo" onClick={closeMobileMenu}>
APPNAME<i className="fab fa-typo3"></i>
</Link>
<div className="menu-icon" onClick={handleClick}>
<i className={click ? 'fas fa-times': 'fas fa-bars'} />
</div>
<ul className={click ? 'nav-menu active' : 'nav-menu'}>
<li className='nav-item'>
<Link to="/" className='nav-links' onClick={closeMobileMenu}>
Home
</Link>
</li>
<li className='nav-item'>
<Link to="/services" className='nav-links' onClick={closeMobileMenu}>
Services
</Link>
</li>
<li className='nav-item'>
<Link to="/products" className='nav-links' onClick={closeMobileMenu}>
Products
</Link>
</li>
<li className='nav-item'>
<Link to="/sign-up" className='nav-links-mobile' onClick={closeMobileMenu}>
Sign up
</Link>
</li>
</ul>
{button && <Button buttonStyle='btn--outline'>GET STARTED</Button>}
</div>
</nav>
</>
)
}
export default Navbar
Navbar.css
.navbar {
background: #2b41cb;
height: 80px;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
position: sticky;
top: 0;
z-index: 999;
}
/* AS YOU CAN SEE HERE IS THE ACTIVE PART */
.navbar.active {
/*background: linear-gradient(90deg, rgb(66, 2, 194) 0%, rgb(0, 78, 194) 100%)*/
background: #fff;
}
.navbar-container {
display: flex;
justify-content: center;
align-items: center;
height: 80px;
max-width: 1500px;
}
.navbar-logo {
color: #fff;
justify-self: start;
margin-left: 20px;
cursor: pointer;
text-decoration: none;
font-size: 2rem;
display: flex;
align-items: center;
}
.navbar-logo.active {
color: #232323;
}
.fa-typo3 {
margin-left: 0.5rem;
font-size: 1.8rem;
}
.nav-menu {
display: grid;
grid-template-columns: repeat(4, auto);
grid-gap: 10px;
list-style: none;
text-align: center;
width: 60vw;
justify-content: end;
margin-right: 2rem;
}
.nav-item {
height: 80px;
}
.nav-links {
color: #fff;
display: flex;
align-items: center;
text-decoration: none;
padding: 0.5rem 1rem;
height: 100%;
}
.nav-links:hover {
border-bottom: 4px solid #fff;
transition: all 0.2s ease-out;
}
.fa-bars {
color: #fff;
}
.nav-links-mobile {
display: none;
}
.menu-icon {
display: none;
}
#media screen and (max-width: 960px) {
.NavbarItems {
position: relative;
}
.nav-menu {
display: flex;
flex-direction: column;
width: 100%;
height: 90vh;
position: absolute;
top: 80px;
left: -100%;
opacity: 1;
transition: all 0.5s ease;
}
.nav-menu.active {
background: #242222;
left: 0;
opacity: 1;
transition: all 0.5s ease;
z-index: 1;
}
.nav-links {
text-align: center;
padding: 2rem;
width: 100%;
display: table;
}
.nav-links:hover {
background-color: #fff;
color: #242424;
border-radius: 0;
}
.navbar-logo {
position: absolute;
top: 0;
left: 0;
transform: translate(25%, 50%);
}
.menu-icon {
display: block;
position: absolute;
top: 0;
right: 0;
transform: translate(-100%, 60%);
font-size: 1.8rem;
cursor: pointer;
}
.fa-times {
color: #fff;
font-size: 2rem;
}
.nav-links-mobile {
display: block;
text-align: center;
margin: 2rem auto;
border-radius: 4px;
width: 80%;
text-decoration: none;
font-size: 1.5rem;
background-color: transparent;
color: #fff;
padding: 14px 20px;
border: 1px solid #fff;
transition: all 0.3s ease-out;
}
.nav-links-mobile:hover {
background: #fff;
color: #242424;
transition: 250ms;
}
}
What I would like is for the entire navbar to be in white and the text and icons to be in black when scrolled. If not it should stay as it is, blue background and white font color.
But this is very redundant. Is there an option that covers everything?
Yes, just add a new class name for the element state and then use that class to style everything including the child elements. So in your case you can do:
.navbar {
background: #2b41cb;
height: 80px;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
position: sticky;
top: 0;
z-index: 999;
}
.navbar-container {
display: flex;
justify-content: center;
align-items: center;
height: 80px;
max-width: 1500px;
}
.navbar-logo {
color: #fff;
justify-self: start;
margin-left: 20px;
cursor: pointer;
text-decoration: none;
font-size: 2rem;
display: flex;
align-items: center;
}
/* Active style overrides */
.navbar.active {
background: #fff;
}
.navbar.active .navbar-logo {
color: #232323;
}
Would it make sense to say if navbar changes then call another new css? Is that possible? If so how do I do that?
I think that is also possible, you can use JS to do that but I think adding a state class name is simpler and easier to reason about.
I have a drop-down menu on a site that I have been working on I and I need to get rid of this gap above the drop-down menu. It is quite bothersome.
Figure A
So, in an attempt to fix it, I changed the li line-height from 50px to 47px and got this:
Figure B
Almost what I want, but not quite. The problem? The li is higher causing the little animation I have under the li to no longer touch the image.
Then, I tried giving the li a relative position. But now, the drop-down is the same width as the 'Patient Info' link.
Figure C
Here is my jsfiddle link if you would like to fiddle around with it. There is no rush. Thank you!
Code:
body {
font-family: 'Source Sans Pro', sans-serif;
max-width: 2500px;
margin: 0 auto 30px auto;
}
#import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: normal;
}
img#profile {
width: 100%;
max-width: 64px;
border-radius: 100%;
}
.header,
.menu,
.hero,
.slider,
.img-display {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
::selection {
background: #11b5e4;
color: white;
}
::-moz-selection {
background: #11b5e4;
color: white;
}
/* HEADER & MENU STYLE START */
.header {
height: 100px;
padding: 15px 10px 10px 10px;
display: flex;
justify-content: center;
align-items: center;
}
.header h1 {
margin: 0px 25px 0px 25px;
}
.header img {
height: 100%;
pointer-events: none;
}
.header a i {
font-size: 30px;
margin: 0px 0px 0px 15px;
color: black;
transition: .15s color;
}
.header a i:hover {
color: #11b5e4;
}
.menu-wrapper {
height: 50px;
display: flex;
justify-content: center;
}
.menu li {
display: inline-block;
line-height: 50px;
}
.menu li a {
display: inline-block;
font-size: 23px;
margin: 0px 10px;
transition: .2s cubic-bezier(.5, 3, .5, .5) background;
color: black;
background: linear-gradient(#11b5e4, #11b5e4) 50% 100%/100% 0px no-repeat;
text-decoration: none;
}
.menu li a:hover {
background: linear-gradient(#11b5e4, #11b5e4) 50% 100%/100% 5px no-repeat;
}
.menu-wrapper #toggle-menu {
display: none;
}
/* FOR STACK OVERFLOW */
.menu li ul {
margin: 0;
padding: 0;
display: none;
background: white;
}
ul li a {
display: block;
text-decoration: none;
color: #ffffff;
padding: 5px 15px 5px 15px;
}
li:hover ul {
display: flex;
flex-direction: column;
position: absolute;
}
/* END OF FOR STACK OVERFLOW */
#media only screen and (max-width: 1000px) {
.menu {
opacity: 0;
position: relative;
top: 50px;
transition: .25s opacity;
pointer-events: none;
}
.menu-wrapper #toggle-menu:checked~.menu {
opacity: 1;
pointer-events: all;
}
.menu li {
display: block;
text-align: center;
background-color: white;
padding: 0px 15px;
}
.menu-wrapper label {
align-self: center;
width: 32px;
height: 32px;
position: absolute;
left: 0;
right: 0;
margin: auto;
}
.menu-wrapper label:hover {
cursor: pointer;
}
.menu-wrapper label#open-menu {
transition: opacity .5s, transform .3s;
background: url(http://ianspence.us/stack/menu-open-icon.png) center center/cover no-repeat;
}
.menu-wrapper label#close-menu {
transition: opacity .5s, transform .3s;
background: url(http://ianspence.us/stack/menu-close-icon.png) center center/cover no-repeat;
opacity: 0;
}
.menu-wrapper #toggle-menu:checked~label#open-menu {
opacity: 0;
transform: rotate(360deg);
}
.menu-wrapper #toggle-menu:checked~label#close-menu {
opacity: 1;
transform: rotate(360deg);
}
}
#media only screen and (max-width: 750px) {
.header {
height: 75px;
}
.header h1 {
margin: 0px 5px;
font-size: 20px;
}
.header a i {
font-size: 20px;
margin: 0px 0px 0px 5px;
}
}
/* HEADER & MENU STYLE END */
/* HERO START */
.hero {
display: flex;
justify-content: center;
height: calc(150px + 20vw);
width: 100%;
}
.hero h1 {
text-align: center;
font-size: 35px;
padding: 8px;
margin: 15px;
background: rgba(17, 181, 228, .75);
border-radius: 10px;
color: white;
font-weight: bolder;
}
.hero.a {
align-items: flex-end;
background: url(http://ianspence.us/stack/hero.a.jpg) center/cover no-repeat;
}
.hero.b {
align-items: flex-end;
background: url(media/hero.b.jpeg) center/cover no-repeat;
}
#media only screen and (max-width: 900px) {
.hero.a,
.hero.b {
height: 300px;
}
.hero.a h1,
.hero.b h1 {
font-size: 26px;
}
}
#media only screen and (max-width: 400px) {
.hero.a,
.hero.b {
height: 250px;
}
.hero.a h1,
.hero.b h1 {
font-size: 16px;
}
}
/* HERO END */
<!DOCTYPE html>
<html>
<head>
<title>#pfcainc | Home</title>
<link rel='shortcut icon' href='http://ianspence.us/stack/icon.png'>
<link rel='stylesheet' href='style.css'>
<link rel='stylesheet' href='media/fontawesome/css/fontawesome-all.css'>
<meta name='description' content=''>
<meta name='keywords' content=''>
<meta name='robots' content='index, follow'>
<meta name='revisit-after' content='3 days'>
<meta name='viewport' content='initial-scale=1'>
</head>
<body>
<div class='header'>
<img src='http://ianspence.us/stack/icon.png'>
<h1>Panhandle Family Care Associates</h1>
<a href='https://facebook.com/panhandlefamilycareassociates/'><i class='fab fa-facebook-square'></i></a>
<a href='https://twitter.com/pfcainc'><i class='fab fa-twitter'></i></a>
</div>
<div class='menu-wrapper'>
<input type='checkbox' id='toggle-menu'>
<label for='toggle-menu' id='open-menu'></label>
<label for='toggle-menu' id='close-menu'></label>
<!--Start Menu Display-->
<div class='menu'>
<li><a href='=./'>Home</a></li>
<li><a href='services'>Services</a></li>
<li><a href='physicians'>Physicians</a></li>
<li>Patient Info
<ul>
<li><a href='patient-forms'>Patient Forms</a></li>
<li><a href='patient-education'>Patient Education</a></li>
<li><a href='http://myhealthrecord.com'>Patient Portal</a></li>
</ul>
</li>
<li><a href='office-info'>Office Info</a></li>
</div>
<!--End Menu Display-->
</div>
<div class='hero a'>
<h1>Treating your family like ours since 2002</h1>
</div>
</body>
</html>
Notes:
In jsfiddle, make sure you increase the width of the preview so that the
full menu is there, not the hamburger menu.
I am trying to avoid Javascript completely.
margin-top: -3px for submenu seems to fix the issue across all (major) browsers, however I'd recommend fix from my Codepen, with flex and defined height for li elements.
Fast & simple
HTML:
<ul class="submenu">
<li><a href='patient-forms'>Patient Forms</a></li>
<li><a href='patient-education'>Patient Education</a></li>
<li><a href='http://myhealthrecord.com'>Patient Portal</a></li>
</ul>
CSS:
.submenu {
margin-top: -3px !important;
}
More clean approach
Codepen