反应多级推送菜单 SCSS 后退按钮不起作用
React Multi-level push menu SCSS Back button not working
我正在开发适用于我网站上的移动用户的多级推送导航菜单。它基于我的 GitHub 帐户上的项目动态创建链接。我使用的推送菜单来自 codepen https://codepen.io/vixxofsweden/pen/xxGGYOE,我试图让它在 React 中工作,而不仅仅是普通的 HTML、CSS。到目前为止,除了后退按钮以外的所有东西都可以。
但具有讽刺意味的是,当我转到页面底部并按“Shell”下的任何空 space 时,它就像一个后退按钮,将我带到上一个菜单.此推送菜单未使用任何 javascript,但如果它能够解决此问题,我愿意使用它。我已经多次尝试解决这个问题,但其中一些 SCSS 对我来说是陌生的。
我的网站使用 React 在 next.js 上 运行。我将在下面附上我的渲染图和 sass。如果您有任何问题或需要更多信息,请告诉我
这是 index.jsx
中的 render()
render() {
return (
<div className={`${this.renderCSS()}`}>
<div className="nav">
<nav>
<a className="mobile-menu-trigger">Open mobile menu</a>
{/* <button className={'mobile-menu-trigger'} >Mobile Menu</button> */}
<ul className="menu menu-bar">
<li>
<a className="menu-link menu-bar-link" aria-haspopup="true">Projects</a>
<ul className="mega-menu mega-menu--multiLevel">
<li className="mobile-menu-back-item">
<a className="menu-link mobile-menu-back-link">Back</a>
</li>
{Object.keys(this.props.languages).map(language => {
const allProjects = this.props.languages[language];
return (
<li key={language}>
<a className="menu-link mega-menu-link" aria-haspopup="true">{language}</a>
<ul className="menu menu-list">
{allProjects.map((item, index) => {
const project = this.props.projects[item];
const openGithubRepo = () => {
window.open(project.svn_url, "_blank");
}
const openGithubPages = () => {
window.open(`https://ngwessels.github.io/${project.name}/`, "_blank");
}
if (project.has_pages) {
return (
<li key={project.id}>
<a className="menu-link menu-list-link"
aria-haspopup="true">{project.name}</a>
<ul className="menu menu-list">
<li>
<a className="menu-link menu-list-link" onClick={openGithubRepo}>Open Github</a>
</li>
<li>
<a className="menu-link menu-list-link" onClick={openGithubPages}>Visit Live Example</a>
</li>
</ul>
</li>
);
} else {
return (
<li key={project.id}>
<a className="menu-link menu-list-link" onClick={openGithubRepo}>{project.name}</a>
</li>
)
}
})}
</ul>
</li>
)
})}
</ul>
</li>
<li>
<a className="menu-link menu-bar-link">Static link</a>
</li>
{/* <li className="mobile-menu-header">
<a className="">
<span>Home</span>
</a>
</li> */}
</ul>
</nav>
</div>
</div>
)
}
这里是 styles.scss
$color-accent: black;
$color-light: #ffffff;
$color-dark: black;
$menu-link-padding: 20px 25px;
$breakpoint: 950px;
$mega-menu-multiLevel-colWidth: 100/3 + 0%;
$mobile-menu-back-height: "calc(1.4em + 40px)";
$mobile-menu-back-offset: "calc(0px - (1.4em + 40px))";
$menu-mobile-width: 350px;
// ------------------ SHARED STYLES
nav {
ul, li {
list-style: none;
padding: 0;
margin: 0;
}
a {
display: block;
text-decoration: none;
&:hover, &:visited {
text-decoration: none;
}
}
}
.nav {
a {
font-family: 'Arial Black';
}
}
.menu-bar {
background: $color-light;
display: flex;
}
.menu-link {
padding: $menu-link-padding;
background: $color-light;
color: $color-accent;
transition: background .2s, color .2s;
position: relative;
z-index: 1;
&[aria-haspopup="true"] {
padding-right: 40px;
&:after {
content: "";
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/1397521/arrowRight.svg#accent');
background-size: 14px;
width: 14px;
height: 14px;
font-size:12px;
position: absolute;
right: 10px;
top:50%;
transform: translateY(-50%);
}
}
}
.mega-menu-header {
font-size: 1.2em;
text-transform: uppercase;
font-weight: bold;
color: darken($color-accent, 5%);
}
.mega-menu {
background: $color-light;
z-index: 10;
}
.mega-menu--multiLevel {
flex-direction: column;
}
// ------------------ MEDIA QUERIES
@media all and (max-width: $breakpoint) {
.nav {
padding: 20px;
}
.mobile-menu-trigger, .mobile-menu-header, .mobile-menu-back-item {
display: block;
}
.mobile-menu-trigger {
background: $color-accent;
color: $color-light;
border: 0;
padding: 10px;
font-size: 1.2em;
border-radius: 4px;
}
.mobile-menu-header {
order: -1;
background: grey;
a {
padding: $menu-link-padding;
color: $color-light;
visibility: visible;
}
}
.menu-bar {
flex-direction: column;
position: fixed;
top: 0;
left: -100%;
height: 100vh;
width: $menu-mobile-width;
max-width: $menu-mobile-width;
max-width: 90%;
overflow-x: hidden;
transition: left .3s;
box-shadow: 1px 0px 2px 0px rgba(0,0,0,0.25);
background-color: white;
z-index: 1000;
> li {
> [aria-haspopup="true"] {
~ ul {
display: flex;
flex-direction: column;
background: $color-light;
position: absolute;
left: 100%;
top: 0;
max-height: 100vh;
width: 100%;
transition: left .3s;
// Second level
> li {
> [aria-haspopup="true"] {
font-size: 1.2em;
~ ul {
a {
padding-left: 40px;
}
// Third level
> li {
> [aria-haspopup="true"] {
~ ul {
a {
padding-left: 80px;
}
}
}
}
}
}
}
[aria-haspopup="true"] {
color: $color-dark;
&:after {
content: "+";
background: none;
font-size: 1em;
font-weight: normal;
height: 20px;
line-height: 1;
}
~ ul {
max-height: 0px;
transform-origin: top;
transform: scaleY(0);
transition: max-height .1s;
}
}
}
}
}
}
.mega-menu-content {
padding: $menu-link-padding;
}
.mobile-menu-back-item {
order: -1;
z-index: 1000000000;
a {
background: tint(grey, 70%);
color: $color-dark;
max-height: $mobile-menu-back-height;
margin-top: $mobile-menu-back-offset;
pointer-events: none;
&:before {
z-index: 1000000000;
content: "";
width: 14px;
height: 12px;
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/1397521/arrowLeft.svg#default');
background-size: 14px;
margin-right: 10px;
display: inline-block;
}
}
}
// ------------------------ ALL DEVICES
.mobile-menu-trigger {
// FUNCTIONALITY: Open mobile menu
&:focus {
~ ul {
left: 0;
}
}
}
.menu-bar {
// FUNCTIONALITY: Keep menu open
&:hover, &:focus-within {
left: 0;
}
> li {
> [aria-haspopup="true"] {
// FUNCTIONALITY: Open mega menu
&:focus {
~ ul {
left: 0;
}
}
~ ul {
// STYLING: Back button offset
margin-top: $mobile-menu-back-height;
// FUNCTIONALITY: Keep mega menu open
&:hover, &:focus-within {
left: 0;
}
// FUNCTIONALITY: Open dropdowns
[aria-haspopup="true"] {
&:focus {
~ ul {
max-height: 500px;
animation: dropdown .3s forwards;
}
}
}
// FUNCTIONALITY: Keep dropdowns open
li {
&:focus-within {
> [aria-haspopup="true"] {
~ ul {
max-height: 500px;
transform: scaleY(1);
}
}
}
}
}
}
// FUNCTIONALITY: Prevent clicks on link behind back button
// &:focus-within ~ .mobile-menu-header a {
// visibility: visible;
// }
}
}
// ------------------------ TOUCH DEVICES
@media (hover: none) {
// FUNCTIONALITY: Open mobile menu
.mobile-menu-trigger {
&:hover {
~ ul {
left: 0;
}
}
}
// FUNCTIONALITY: Open mega menu
.menu-bar {
> li {
> [aria-haspopup="true"] {
&:hover {
~ ul {
left: 0;
}
}
~ ul {
&:hover {
left: 0;
}
// FUNCTIONALITY: Open dropdowns
[aria-haspopup="true"] {
&:hover {
~ ul {
max-height: 500px;
animation: dropdown .3s forwards;
}
}
~ ul {
&:hover {
max-height: 500px;
transform: scaleY(1);
}
}
}
}
}
// &:hover ~ .mobile-menu-header {
// a {
// visibility: hidden;
// }
// }
}
}
}
}
// ------------------ ANIMATIONS
@keyframes dropdown {
0% {
opacity: 0;
transform: scaleY(0);
}
50% {
opacity: 1;
}
100% {
transform: scaleY(1);
}
}
@keyframes flyout {
0% {
opacity: 0;
transform: scaleX(0);
}
100% {
opacity: 1;
transform: scaleX(1);
}
}
所以我找到了一个涉及使用 javascript 向元素添加样式的解决方案。如果有人找到只涉及添加 css 的解决方案,请告诉我。这是代码:
render() {
return (
<div className={`${this.renderCSS()}`}>
<div className="nav">
<nav>
<a className="mobile-menu-trigger">Open mobile menu</a>
<ul className="menu menu-bar" id={'menu-bar'}>
<li>
<a className="menu-link menu-bar-link" aria-haspopup="true" onClick={() => {
const el = document.getElementById('popup');
el.style.left = '0';
}}>Projects</a>
<ul className="mega-menu mega-menu--multiLevel" id={'popup'}>
<li className="mobile-menu-back-item">
<a className="menu-link mobile-menu-back-link" onClick={() => {
const el = document.getElementById('popup');
el.style.left = '100%';
}}>Back</a>
</li>
{Object.keys(this.props.languages).map(language => {
const allProjects = this.props.languages[language];
return (
<li key={language}>
<a className="menu-link mega-menu-link" aria-haspopup="true">{language}</a>
<ul className="menu menu-list">
{allProjects.map((item, index) => {
const project = this.props.projects[item];
const openGithubRepo = () => {
window.open(project.svn_url, "_blank");
}
const openGithubPages = () => {
window.open(`https://ngwessels.github.io/${project.name}/`, "_blank");
}
if (project.has_pages) {
return (
<li key={project.id}>
<a className="menu-link menu-list-link"
aria-haspopup="true">{project.name}</a>
<ul className="menu menu-list">
<li>
<a className="menu-link menu-list-link" onClick={openGithubRepo}>Open Github</a>
</li>
<li>
<a className="menu-link menu-list-link" onClick={openGithubPages}>Visit Live Example</a>
</li>
</ul>
</li>
);
} else {
return (
<li key={project.id}>
<a className="menu-link menu-list-link" onClick={openGithubRepo}>{project.name}</a>
</li>
)
}
})}
</ul>
</li>
)
})}
</ul>
</li>
<li>
<a className="menu-link menu-bar-link">Static link</a>
</li>
{/* <li className="mobile-menu-header">
<a className="">
<span>Home</span>
</a>
</li> */}
</ul>
</nav>
</div>
</div>
)
}
我正在开发适用于我网站上的移动用户的多级推送导航菜单。它基于我的 GitHub 帐户上的项目动态创建链接。我使用的推送菜单来自 codepen https://codepen.io/vixxofsweden/pen/xxGGYOE,我试图让它在 React 中工作,而不仅仅是普通的 HTML、CSS。到目前为止,除了后退按钮以外的所有东西都可以。
但具有讽刺意味的是,当我转到页面底部并按“Shell”下的任何空 space 时,它就像一个后退按钮,将我带到上一个菜单.此推送菜单未使用任何 javascript,但如果它能够解决此问题,我愿意使用它。我已经多次尝试解决这个问题,但其中一些 SCSS 对我来说是陌生的。 我的网站使用 React 在 next.js 上 运行。我将在下面附上我的渲染图和 sass。如果您有任何问题或需要更多信息,请告诉我
这是 index.jsx
中的 render()render() {
return (
<div className={`${this.renderCSS()}`}>
<div className="nav">
<nav>
<a className="mobile-menu-trigger">Open mobile menu</a>
{/* <button className={'mobile-menu-trigger'} >Mobile Menu</button> */}
<ul className="menu menu-bar">
<li>
<a className="menu-link menu-bar-link" aria-haspopup="true">Projects</a>
<ul className="mega-menu mega-menu--multiLevel">
<li className="mobile-menu-back-item">
<a className="menu-link mobile-menu-back-link">Back</a>
</li>
{Object.keys(this.props.languages).map(language => {
const allProjects = this.props.languages[language];
return (
<li key={language}>
<a className="menu-link mega-menu-link" aria-haspopup="true">{language}</a>
<ul className="menu menu-list">
{allProjects.map((item, index) => {
const project = this.props.projects[item];
const openGithubRepo = () => {
window.open(project.svn_url, "_blank");
}
const openGithubPages = () => {
window.open(`https://ngwessels.github.io/${project.name}/`, "_blank");
}
if (project.has_pages) {
return (
<li key={project.id}>
<a className="menu-link menu-list-link"
aria-haspopup="true">{project.name}</a>
<ul className="menu menu-list">
<li>
<a className="menu-link menu-list-link" onClick={openGithubRepo}>Open Github</a>
</li>
<li>
<a className="menu-link menu-list-link" onClick={openGithubPages}>Visit Live Example</a>
</li>
</ul>
</li>
);
} else {
return (
<li key={project.id}>
<a className="menu-link menu-list-link" onClick={openGithubRepo}>{project.name}</a>
</li>
)
}
})}
</ul>
</li>
)
})}
</ul>
</li>
<li>
<a className="menu-link menu-bar-link">Static link</a>
</li>
{/* <li className="mobile-menu-header">
<a className="">
<span>Home</span>
</a>
</li> */}
</ul>
</nav>
</div>
</div>
)
}
这里是 styles.scss
$color-accent: black;
$color-light: #ffffff;
$color-dark: black;
$menu-link-padding: 20px 25px;
$breakpoint: 950px;
$mega-menu-multiLevel-colWidth: 100/3 + 0%;
$mobile-menu-back-height: "calc(1.4em + 40px)";
$mobile-menu-back-offset: "calc(0px - (1.4em + 40px))";
$menu-mobile-width: 350px;
// ------------------ SHARED STYLES
nav {
ul, li {
list-style: none;
padding: 0;
margin: 0;
}
a {
display: block;
text-decoration: none;
&:hover, &:visited {
text-decoration: none;
}
}
}
.nav {
a {
font-family: 'Arial Black';
}
}
.menu-bar {
background: $color-light;
display: flex;
}
.menu-link {
padding: $menu-link-padding;
background: $color-light;
color: $color-accent;
transition: background .2s, color .2s;
position: relative;
z-index: 1;
&[aria-haspopup="true"] {
padding-right: 40px;
&:after {
content: "";
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/1397521/arrowRight.svg#accent');
background-size: 14px;
width: 14px;
height: 14px;
font-size:12px;
position: absolute;
right: 10px;
top:50%;
transform: translateY(-50%);
}
}
}
.mega-menu-header {
font-size: 1.2em;
text-transform: uppercase;
font-weight: bold;
color: darken($color-accent, 5%);
}
.mega-menu {
background: $color-light;
z-index: 10;
}
.mega-menu--multiLevel {
flex-direction: column;
}
// ------------------ MEDIA QUERIES
@media all and (max-width: $breakpoint) {
.nav {
padding: 20px;
}
.mobile-menu-trigger, .mobile-menu-header, .mobile-menu-back-item {
display: block;
}
.mobile-menu-trigger {
background: $color-accent;
color: $color-light;
border: 0;
padding: 10px;
font-size: 1.2em;
border-radius: 4px;
}
.mobile-menu-header {
order: -1;
background: grey;
a {
padding: $menu-link-padding;
color: $color-light;
visibility: visible;
}
}
.menu-bar {
flex-direction: column;
position: fixed;
top: 0;
left: -100%;
height: 100vh;
width: $menu-mobile-width;
max-width: $menu-mobile-width;
max-width: 90%;
overflow-x: hidden;
transition: left .3s;
box-shadow: 1px 0px 2px 0px rgba(0,0,0,0.25);
background-color: white;
z-index: 1000;
> li {
> [aria-haspopup="true"] {
~ ul {
display: flex;
flex-direction: column;
background: $color-light;
position: absolute;
left: 100%;
top: 0;
max-height: 100vh;
width: 100%;
transition: left .3s;
// Second level
> li {
> [aria-haspopup="true"] {
font-size: 1.2em;
~ ul {
a {
padding-left: 40px;
}
// Third level
> li {
> [aria-haspopup="true"] {
~ ul {
a {
padding-left: 80px;
}
}
}
}
}
}
}
[aria-haspopup="true"] {
color: $color-dark;
&:after {
content: "+";
background: none;
font-size: 1em;
font-weight: normal;
height: 20px;
line-height: 1;
}
~ ul {
max-height: 0px;
transform-origin: top;
transform: scaleY(0);
transition: max-height .1s;
}
}
}
}
}
}
.mega-menu-content {
padding: $menu-link-padding;
}
.mobile-menu-back-item {
order: -1;
z-index: 1000000000;
a {
background: tint(grey, 70%);
color: $color-dark;
max-height: $mobile-menu-back-height;
margin-top: $mobile-menu-back-offset;
pointer-events: none;
&:before {
z-index: 1000000000;
content: "";
width: 14px;
height: 12px;
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/1397521/arrowLeft.svg#default');
background-size: 14px;
margin-right: 10px;
display: inline-block;
}
}
}
// ------------------------ ALL DEVICES
.mobile-menu-trigger {
// FUNCTIONALITY: Open mobile menu
&:focus {
~ ul {
left: 0;
}
}
}
.menu-bar {
// FUNCTIONALITY: Keep menu open
&:hover, &:focus-within {
left: 0;
}
> li {
> [aria-haspopup="true"] {
// FUNCTIONALITY: Open mega menu
&:focus {
~ ul {
left: 0;
}
}
~ ul {
// STYLING: Back button offset
margin-top: $mobile-menu-back-height;
// FUNCTIONALITY: Keep mega menu open
&:hover, &:focus-within {
left: 0;
}
// FUNCTIONALITY: Open dropdowns
[aria-haspopup="true"] {
&:focus {
~ ul {
max-height: 500px;
animation: dropdown .3s forwards;
}
}
}
// FUNCTIONALITY: Keep dropdowns open
li {
&:focus-within {
> [aria-haspopup="true"] {
~ ul {
max-height: 500px;
transform: scaleY(1);
}
}
}
}
}
}
// FUNCTIONALITY: Prevent clicks on link behind back button
// &:focus-within ~ .mobile-menu-header a {
// visibility: visible;
// }
}
}
// ------------------------ TOUCH DEVICES
@media (hover: none) {
// FUNCTIONALITY: Open mobile menu
.mobile-menu-trigger {
&:hover {
~ ul {
left: 0;
}
}
}
// FUNCTIONALITY: Open mega menu
.menu-bar {
> li {
> [aria-haspopup="true"] {
&:hover {
~ ul {
left: 0;
}
}
~ ul {
&:hover {
left: 0;
}
// FUNCTIONALITY: Open dropdowns
[aria-haspopup="true"] {
&:hover {
~ ul {
max-height: 500px;
animation: dropdown .3s forwards;
}
}
~ ul {
&:hover {
max-height: 500px;
transform: scaleY(1);
}
}
}
}
}
// &:hover ~ .mobile-menu-header {
// a {
// visibility: hidden;
// }
// }
}
}
}
}
// ------------------ ANIMATIONS
@keyframes dropdown {
0% {
opacity: 0;
transform: scaleY(0);
}
50% {
opacity: 1;
}
100% {
transform: scaleY(1);
}
}
@keyframes flyout {
0% {
opacity: 0;
transform: scaleX(0);
}
100% {
opacity: 1;
transform: scaleX(1);
}
}
所以我找到了一个涉及使用 javascript 向元素添加样式的解决方案。如果有人找到只涉及添加 css 的解决方案,请告诉我。这是代码:
render() {
return (
<div className={`${this.renderCSS()}`}>
<div className="nav">
<nav>
<a className="mobile-menu-trigger">Open mobile menu</a>
<ul className="menu menu-bar" id={'menu-bar'}>
<li>
<a className="menu-link menu-bar-link" aria-haspopup="true" onClick={() => {
const el = document.getElementById('popup');
el.style.left = '0';
}}>Projects</a>
<ul className="mega-menu mega-menu--multiLevel" id={'popup'}>
<li className="mobile-menu-back-item">
<a className="menu-link mobile-menu-back-link" onClick={() => {
const el = document.getElementById('popup');
el.style.left = '100%';
}}>Back</a>
</li>
{Object.keys(this.props.languages).map(language => {
const allProjects = this.props.languages[language];
return (
<li key={language}>
<a className="menu-link mega-menu-link" aria-haspopup="true">{language}</a>
<ul className="menu menu-list">
{allProjects.map((item, index) => {
const project = this.props.projects[item];
const openGithubRepo = () => {
window.open(project.svn_url, "_blank");
}
const openGithubPages = () => {
window.open(`https://ngwessels.github.io/${project.name}/`, "_blank");
}
if (project.has_pages) {
return (
<li key={project.id}>
<a className="menu-link menu-list-link"
aria-haspopup="true">{project.name}</a>
<ul className="menu menu-list">
<li>
<a className="menu-link menu-list-link" onClick={openGithubRepo}>Open Github</a>
</li>
<li>
<a className="menu-link menu-list-link" onClick={openGithubPages}>Visit Live Example</a>
</li>
</ul>
</li>
);
} else {
return (
<li key={project.id}>
<a className="menu-link menu-list-link" onClick={openGithubRepo}>{project.name}</a>
</li>
)
}
})}
</ul>
</li>
)
})}
</ul>
</li>
<li>
<a className="menu-link menu-bar-link">Static link</a>
</li>
{/* <li className="mobile-menu-header">
<a className="">
<span>Home</span>
</a>
</li> */}
</ul>
</nav>
</div>
</div>
)
}