javascript - 如何在顶部导航栏部分下方添加粘性导航栏?反应JS
问题描述
使用 ReactJS,我正在尝试制作第二个(较小的)导航栏,就像Airtable 在他们的产品页面上所做的那样。我的第一个导航栏在顶部,一旦我滚动就会从透明变暗。当我希望它位于标题背景图像的正下方时,第二个栏(屏幕截图中的紫色很容易看到)当前位于第一个导航栏的后面。
第一个(主)导航栏 - “Header.js”
import React, { useEffect, useState } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { AppBar, IconButton, Toolbar, Collapse } from '@material-ui/core';
import SortIcon from '@material-ui/icons/Sort';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { Link as Scroll } from 'react-scroll';
import ScrollToColor from './ColorChangeOnScroll';
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
fontFamily: 'Nunito',
},
appbar: {
background: 'none',
},
appbarTitle:{
flexGrow: '1',
},
appbarWrapper:{
width: '80%',
margin: '0 auto',
},
icon: {
color: '#fff',
fontSize: '2rem',
},
colorText: {
color: '#34cbc2',
},
container: {
textAlign: 'center',
},
title: {
color: '#fff',
fontSize: '4rem',
},
goDown: {
color: '#34cbc2',
fontSize: '4rem',
},
}));
export default function Header() {
const classes = useStyles();
const [checked, setChecked] = useState(false);
useEffect(() => {
setChecked(true);
}, []);
return (
<section>
<div className={classes.root} id="header">
<ScrollToColor>
<AppBar className={classes.appbar} elevation={0}>
<Toolbar className={classes.appbarWrapper}>
<h1 className={classes.appbarTitle}>
Logo <span className={classes.colorText}>Colored</span>
</h1>
<IconButton>
<SortIcon className={classes.icon} />
</IconButton>
</Toolbar>
</AppBar>
</ScrollToColor>
<Collapse
in={checked}
{...(checked ? { timeout: 1000 } : {})}
collapsedHeight={50}>
<div className={classes.container}>
<h1 className={classes.title}>
Main header <br />
at <span className={classes.colorText}>title.</span>
</h1>
<Scroll to="info-card" smooth={true}>
<IconButton>
<ExpandMoreIcon className={classes.goDown} />
</IconButton>
</Scroll>
</div>
</Collapse>
</div>
</section>
);
}
第二个导航栏 - “StickyHeader.js”
import React, { useEffect, useState } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { AppBar, IconButton, Toolbar, Collapse } from '@material-ui/core';
import SortIcon from '@material-ui/icons/Sort';
const useStyles = makeStyles((theme) => ({
root: {
top: '1000px',
display: 'flex',
position: 'sticky',
justifyContent: 'center',
alignItems: 'center',
fontFamily: 'Nunito',
},
appbar: {
background: 'purple',
},
list: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
}));
export default function Header() {
const classes = useStyles();
const [checked, setChecked] = useState(false);
useEffect(() => {
setChecked(true);
}, []);
return (
<section>
<div className={classes.root} style={{ top: "72px" }} id="stickyheader">
<AppBar className={classes.appbar} elevation={4}>
<Toolbar className={classes.appbarWrapper}>
<ul className={classes.list} style={{ listStyleType: "none" }}>
<li>
<a href="#product" data-id="product" data-is-active="true">Database</a>
</li>
</ul>
</Toolbar>
</AppBar>
</div>
</section>
);
}
着陆页片段
export default function Landing() {
const classes = useStyles();
return (
<div className={classes.root}>
<CssBaseline />
<Header />
<StickyHeader />
<InfoCards />
</div>
);
}
尝试调整:
- 将每个组件分成各自的文件以充当“部分”,因此一个组件将位于另一个组件之上
- 调整
margin
中marginTop
_useStyles
_position: relative
- 与上面相同
position: sticky
- 添加
style={{ top: "##px" }}
到导航栏div
以查看是否将其向下推
所需结果的 Photoshop 视图(其中第二个导航栏是粘性的,并且在滚动过去时“加入”第一个导航栏)
我不确定我是否在这些导航栏的样式中遗漏了一些简单的东西,或者这是否需要更复杂的东西。提前感谢任何建议。
注意 徽标和标题标题是第一个导航栏的一部分。第二个(紫色)导航栏有一个非常小的“数据库”可点击文本,在前几个屏幕截图中很难看到,就在“徽标颜色”的顶部。
解决方案
编辑
这是我找到的唯一解决方案...
PS:
1/ 使用position: "fixed"
代替position: "sticky"
2/还有其他修改要做...(添加滚动侦听器,...)
页眉.js
import React, { useEffect, useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { AppBar, IconButton, Toolbar, Collapse } from "@material-ui/core";
import SortIcon from "@material-ui/icons/Sort";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import { Link as Scroll } from "react-scroll";
const useStyles = makeStyles(theme => ({
root: {
fontFamily: "Nunito"
},
appbar: {
position: "fixed",
zIndex: "9999",
background: "black"
},
appbarTitle: {
flexGrow: "1"
},
appbarWrapper: {
width: "80%",
margin: "0 auto"
},
icon: {
color: "#fff",
fontSize: "2rem"
},
colorText: {
color: "#34cbc2"
},
container: {
textAlign: "center",
height: "100vh",
marginTop: "80px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center"
},
title: {
color: "#333",
fontSize: "4rem"
},
goDown: {
color: "#34cbc2",
fontSize: "4rem"
}
}));
export default function Header() {
const classes = useStyles();
const [checked, setChecked] = useState(false);
useEffect(() => {
setChecked(true);
}, []);
return (
<div className={classes.root} id="header">
<AppBar className={classes.appbar} elevation={0}>
<Toolbar className={classes.appbarWrapper}>
<h1 className={classes.appbarTitle}>
Logo <span className={classes.colorText}>Colored</span>
</h1>
<IconButton>
<SortIcon className={classes.icon} />
</IconButton>
</Toolbar>
</AppBar>
<Collapse
in={checked}
{...(checked ? { timeout: 1000 } : {})}
collapsedHeight={50}
>
<div id="mainheader" className={classes.container}>
<h1 className={classes.title}>
Main header <br />
at <span className={classes.colorText}>title.</span>
</h1>
<Scroll to="info-card" smooth={true}>
<IconButton>
<ExpandMoreIcon className={classes.goDown} />
</IconButton>
</Scroll>
</div>
</Collapse>
</div>
);
}
StickyHeader.js
import React, { useEffect, useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { AppBar, IconButton, Toolbar, Collapse } from "@material-ui/core";
const useStyles = makeStyles(theme => ({
root: {
fontFamily: "Nunito"
},
appbar: {
background: "purple"
},
list: {
display: "flex",
justifyContent: "center",
alignItems: "center"
}
}));
export default function StickyHeader() {
const classes = useStyles();
const [checked, setChecked] = useState(false);
const [scrollY, setScrollY] = useState({ position: "relative" });
useEffect(() => {
window.addEventListener("scroll", () => {
const heightVh = document.querySelector("#mainheader").offsetHeight / 100;
if (window.scrollY > heightVh * 100) {
setScrollY({ position: "fixed", top: "80px" });
} else {
setScrollY({ position: "relative" });
}
});
return () => {
window.removeEventListener("scroll");
};
}, [scroll]);
useEffect(() => {
setChecked(true);
}, []);
return (
<>
{console.log(scrollY)}
<div className={classes.root} id="stickyheader">
<AppBar className={classes.appbar} style={scrollY} elevation={4}>
<Toolbar className={classes.appbarWrapper}>
<ul className={classes.list} style={{ listStyleType: "none" }}>
<li>
<a href="#product" data-id="product" data-is-active="true">
Database
</a>
</li>
</ul>
</Toolbar>
</AppBar>
</div>
</>
);
}
演示:stackblitz
推荐阅读
- apache-kafka - Kafka AMQ 流 - 主题命令
- javascript - 用于方括号组和逗号 javascript 的正则表达式
- c# - HTML“复选框”与 asp.net core MVC 连接,将模型连接到复选框按钮
- rust - 借用哈希图而不借用他的内容
- asp.net - 如何在 Azure 托管网站中使用 people-picker-component 而无需任何 Sharepoint 参考
- python-3.x - 这种设计模式是不好的做法吗?有没有更好的方法在 Python 中实现相同的结果?
- android - 材质组件 1.1.0 中未显示 TabItem 图标
- css - 将 Flask/Dash 应用程序链接到本地 Bootstrap 样式表
- python - Python 正则表达式函数以降序排列键:值。其中键是字母数字,值是数字
- snowflake-cloud-data-platform - 集群并行运行重叠期间扩展期间的雪花信用计算