【发布时间】:2022-10-05 12:38:11
【问题描述】:
所以,我对如何在 Next.js 中实现响应式移动导航有点困惑。我的问题源于通过 Javascript 和 CSS 处理菜单切换状态。
我的导航菜单遵循following tutorial from Log Rocket,但本教程中使用的方法是为 React 编写的,并没有说明 Next.js 如何应用 CSS 类名称。简单的 React 示例依赖于动态更新 CSS,而大多数 Next.js 方法似乎建议使用 useState 切换元素。这可行,但我失去了能够通过媒体查询和切换按钮控制导航的粒度。
我当前的实现检查布尔值 useState 以显示菜单,我只想将其应用于 780 像素或更低的菜单。如果我以false 的状态开始,则不会呈现整个菜单,包括用于切换它的按钮。如果我以true 的状态开始,则移动菜单会自动呈现为展开,我想阻止这种情况。当用户不在移动设备上时,这也会导致切换完全移除菜单(例如,如果菜单未切换,并且用户转到大屏幕尺寸。
那么,问题就变成了如何防止这种意外行为?或者如何在保留点击切换功能的同时将移动菜单默认状态设置为隐藏?
import { useState } from "react";
import Link from "next/Link";
import SiteLogo from "../components/CompLogo";
import navStyles from "../styles/Nav.module.css";
const Nav = () => {
const [isNavExpanded, setIsNavExpanded] = useState(true);
return (
<div>
<nav className={navStyles.nav}>
<SiteLogo />
<button
className={navStyles.hamburger}
onClick={() => {
setIsNavExpanded(!isNavExpanded);
console.log("clicked");
console.log(isNavExpanded);
}}
>
{/* icon from heroicons.com */}
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M3 5a1 1 0 011-1h12a1 1 0 110
2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0
01-1- 1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
clipRule="evenodd"
/>
</svg>
</button>
<div className={navStyles.navigation}>
{isNavExpanded && (
<ul className={navStyles.menu}>
<li className={navStyles.links}>
<Link href="/">
<a className={navStyles.anchors}>Home</a>
</Link>
</li>
<li className={navStyles.links}>
<Link href="/map">
<a className={navStyles.anchors}>Map Page</a>
</Link>
</li>
<li className={navStyles.links}>
<Link href="/about">
<a className={navStyles.anchors}>About</a>
</Link>
</li>
</ul>
)}
</div>
</nav>
</div>
);
};
导出默认导航
这是我的CSS:
.one {
margin-top: 0;
height: 100vh;
width: 100%;
background-image: url("../../public/images/My\ project.jpg");
background-position: top;
background-repeat: no-repeat;
background-size: cover;
display: flex;
justify-content: left;
align-items: center;
}
.oneAppointment {
width: 55%;
margin-left: 10%;
text-align: left;
/* display: flex; */
/* justify-content: center; */
/* flex-direction: column; */
/* height: 40%; */
/* background-color: #fff; */
/* padding: 20px 40px; */
/* border-radius: 6px; */
}
.oneAppointment h1 {
font-size: 40px;
font-weight: 700;
/* color: #000; */
}
.abc {
font-size: 56px;
font-weight: 700;
/* color: blanchedalmond; */
}
.heading {
font-size: 40px;
font-weight: 700;
/* background-color: blueviolet; */
margin-bottom: 10px;
/* color: #000; */
}
.designer a {
margin-top: 16px;
}
.designer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 520px;
width: 100%;
background-image: url("../../public/images/fas.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: contain;
/* background-color: blueviolet; */
}
.blogs {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 520px;
width: 100%;
background-image: url("../../public/images/fas.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: contain;
/* background-color: blueviolet; */
}
.collection {
margin-top: 0;
height: 90vh;
width: 100%;
/* background-image: url("./website/images/pexels-yan-krukov-4458418.jpg"); */
background-image: url("../../public/images/collec.jpg");
background-position: top;
background-repeat: no-repeat;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
}
.collections {
width: 45%;
margin-left: 45%;
text-align: center;
margin-top: -100px;
}
.shop {
margin-top: 0;
height: 90vh;
width: 100%;
/* background-image: url("./website/images/pexels-yan-krukov-4458418.jpg"); */
background-image: url("../../public/images/shopp.jpg");
background-position: top;
background-repeat: no-repeat;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
}
.shopContent {
width: 45%;
margin-left: 45%;
text-align: center;
margin-top: -100px;
}
@media only screen and (min-width: 1px) and (max-width: 768px) {
.heading {
font-size: 36px;
font-weight: 700;
margin-bottom: 10px;
}
.one {
margin-top: 0;
background-image: url("../../public/images/mmy.jpg");
background-position: left;
}
.oneAppointment {
width: 30%;
margin-left: 5%;
text-align: left;
margin-top: -80px;
}
.oneAppointment h1 {
font-size: 28px;
font-weight: 700;
line-height: 55px;
}
.abc {
font-size: 40px;
font-weight: 700;
/* color: blanchedalmond; */
}
.designer {
text-align: center;
height: 600px;
width: 90%;
margin-left: 5%;
background-position: left;
background-size: cover;
}
.blogs {
margin-top: 100px;
text-align: center;
height: 600px;
width: 90%;
margin-left: 5%;
background-position: left;
background-size: cover;
}
.collection {
/* margin-top: 0;
height: 90vh;
width: 100%; */
/* background-image: url("./website/images/pexels-yan-krukov-4458418.jpg"); */
/* background-image: url("../public/images/collec.jpg"); */
background-image: url("../../public/images/colle.jpg");
background-position: left;
/* background-position: calc(-10px); */
/* background-repeat: no-repeat;
background-size: cover;
display: flex; */
justify-content: left;
/* align-items: center; */
}
.collections {
width: 70%;
margin-left: 25%;
/* background-color: aquamarine; */
text-align: right;
margin-top: -140px;
}
.shop {
margin-top: -100px;
/* margin-top: 0;
height: 90vh;
width: 100%; */
/* background-image: url("./website/images/pexels-yan-krukov-4458418.jpg"); */
/* background-image: url("../public/images/shopp.jpg"); */
background-position: calc(-280px);
/* background-repeat: no-repeat; */
/* background-size: cover; */
/* display: flex; */
justify-content: left;
/* align-items: center; */
}
.shopContent {
width: 70%;
margin-left: 25%;
/* background-color: chartreuse; */
text-align: right;
margin-top: 0px;
}
}
.nav {
background-color: white;
color: black;
width: 100%;
display: flex;
align-items: center;
position: relative;
padding: 0.5rem 0 rem;
}
.navigation {
margin-left: auto;
}
.menu {
display: flex;
padding: 0;
}
.links {
list-style-type: none;
margin: 0 1rem;
}
.links a {
text-decoration: none;
display: block;
width: 100%;
}
.hamburger {
border: 0;
height: 80px;
width: 80px;
padding: 0.5rem;
border-radius: 50%;
background-color: white;
cursor: pointer;
transition: background-color 0.2s ease-in-out;
position: absolute;
top: 50%;
right: 5px;
transform: translateY(-50%);
display: none;
}
@media screen and (max-width: 768px) {
.hamburger {
display: block;
}
.menu {
position: absolute;
top: 146px;
left: 0;
flex-direction: column;
width: 100%;
height: calc(100vh - 147px);
background-color: white;
border-top: 1px solid black;
}
.links {
text-align: center;
margin: 0;
}
.links a {
color: black;
width: 100%;
padding: 1.5rem 0;
}
.links:hover {
background-color: #eee;
}
.menu.expanded {
display: block;
}
}
【问题讨论】:
标签: next.js responsive-design media-queries