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*/
}
Related
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%;
}
}
For some reason my NAV Links are being displayed at the bottom of the screen in hamburger view. Is there a way to display them at the top of the screen? Ive tried removing "justify-content:end" but as in doing so it also messes up the non mobile view. How do I fix this issue without effecting the full screen mode?
Navbar.js Below
import React, { useState, useEffect } from 'react';
import { Link } from "react-router-dom";
import { Button } from './Button';
import './Navbar.css';
function Navbar() {
const [click, setClick] = useState(false);
const [button, setButton] = useState(true);
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);
return (
<>
<nav className='navbar'>
<div className='navbar-container'>
<Link to='/' className='navbar-logo' onClick={closeMobileMenu}>
Voyage
<i class="fa-solid fa-anchor"/>
</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>
<Link
to='/sign-up'
className='nav-links-mobile'
onClick={closeMobileMenu}
>
Sign Up
</Link>
</li>
</ul>
{button && <Button buttonStyle='btn--outline'>SIGN UP</Button>}
</div>
</nav>
</>
);
}
export default Navbar;
NavBar.css Below
.navbar {
background: linear-gradient(90deg, rgb(28, 27, 27) 0%, rgb(26, 23, 23) 100%);
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;
}
.fa-anchor {
margin-left: 0.6rem;
font-size: 2.1rem;
}
.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;
}
}
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>
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 am trying to modify a CSS only menu that implements a horizontal flyout. The original code does it on hover. I am trying to achieve the same thing on touch/tap - that is: tap once to show it, tap again to close it.
Is this possible using pure CSS ?
I've inserted the code below, but please refer to the codepen - it renders better. The challenge I am facing is right now I have to keep it pressed for the menu to show - how do I toggle without using javascript?
The codepen: http://codepen.io/pliablepixels/pen/WwPgwg
/*
Forked from http://codepen.io/IanLunn/pen/NPapxy */
/*
sass flyout.scss >flyout.css (sudo gem install sass)
or sass flyout.scss --style compressed >flyout.min.css
"IL" logo Copyright (c) Ian Lunn Design Limited 2015
Modified by pliable pixels
*/
.drawer {
position: absolute;
z-index: 10;
top: 0;
left: 0;
/*height: 100%;*/
padding: .4em 0;
background: #7D294E;
color: white;
text-align: center;
/* Remove 4px gap between <li> */
font-size: 0;
}
.drawer li {
pointer-events: none;
position: relative;
display: inline-block;
vertical-align: middle;
list-style: none;
transform: translateZ(0);
}
.drawer a {
pointer-events: auto;
position: relative;
display: block;
min-width: 5em;
margin-bottom: .4em;
padding: .4em;
line-height: 100%;
/* Reset font-size */
font-size: 16px;
text-decoration: none;
color: white;
transition: background 0.2s;
}
.drawer a:active, .drawer a:focus {
background: #B44659;
}
.drawer i {
display: block;
margin-bottom: .2em;
font-size: 2em;
}
.drawer span {
font-size: .625em;
font-family: sans-serif;
text-transform: uppercase;
}
.drawer li:active ul {
/* Open the fly-out menu */
transform: translateX(0);
background: #B44659;
/* Enable this if you wish to replicate hoverIntent */
}
.drawer > li {
display: block;
/* Fly out menus */
}
.drawer > li > a {
background: #7D294E;
}
.drawer > li:active, .drawer > li:focus {
z-index: 100;
}
.drawer > li:active, .drawer > li:focus a {
background: #B44659;
}
.drawer > li a:active {
background: #F56356;
}
.drawer > li ul {
position: absolute;
/* Stack below the top level */
z-index: -1;
top: 0;
left: 100%;
/* height: 100%;*/
width: auto;
white-space: nowrap;
/* Close the menus */
transform: translateX(-100%);
background: #B44659;
transition: 0.2s transform;
}
<ul class="drawer">
<li>
<a href="">
<span>Info</span>
</a>
<ul>
<li>
<a href="http://www.google.com">
<span>Item 1</span>
</a>
</li>
<li>
<a href="http://www.google.com" >
<span>Item 2</span>
</a>
</li>
<li>
<a href="http://www.google.com">
<span>Item 3</span>
</a>
</li>
</ul>
</li>
</ul>
Check out the following code, that should work for you.
Show
<div id="something">Bingo!</div>
CSS:
#something {
display: none;
}
#something:target {
display: block;
}
Heres a codepen: http://codepen.io/anon/pen/EKreRy
The following code work for me
<!DOCTYPE html>
<html>
<body>
<a href="#something" id='target'>Show</a>
<div id="something">Bingo!hide</div>
<style>
#something {display: none;}
#something:target {display: block;}
#target:target #something{display: none;}
</style>
</div>
</body>