Sticky navbar react.js - javascript

i found a video on YouTube for how to make a navbar, but cant figure out how to get it to stay at the top of the screen, can anyone help
function Navbar():
const navRef = useRef();
const showNavbar = () => {
navRef.current.classList.toggle("responsive_nav");
};
return (
<header className="nav">
<h3>.HamishMcd()</h3>
<nav ref={navRef}>
.Home()
.MyWork()
.AboutMe()
<button
className="nav-btn nav-close-btn"
onClick={showNavbar}>
<FaTimes />
</button>
</nav>
<button className="nav-btn" onClick={showNavbar}>
<FaBars />
</button>
</header>
function App():
return (
<Router>
<Navbar/>
<Routes>
<Route path="/" exact element={<Home/>} />
<Route path="/work" element={<MyWork/>} />
<Route path="/about" element={<AboutMe/>} />
</Routes>
</Router>

.nav{
position: sticky;
top: 0;
}
do this css it's worked.

if you want to useful help, please add your css codes, however if you want the Navbar to be top, you can use :
.navbar {
background-color: #333;
position: fixed;
top: 0;
width: 100%;
}

Related

React navbar renders components separately with react-router-dom

I am using react router dom to render a website with react and tailwindcss. The navbar when clicked refreshes and renders the component on it's own without the other components. This is not what I want.
I want the components rendered in a single page in the way it is structured in my App.js file
I have tried using normal hrefs and now Link from react-router-dom, But I still get the same result
App.js
const App = () => {
return (
<div className="max-w-[1440px] mx-auto bg-page overflow-hidden relative">
<Header />
<Routes>
<Route path="/" element={<Banner />} />
<Route path="/home" element={<Banner />} />
<Route path="/about" element={<About />} />
<Route path="/hero" element={<Hero />} />
<Route path="/featured" element={<Featured />} />
<Route path="/gallery" element={<GallerySection />} />
<Route path="/testimonies" element={<Testimony />} />
<Route path="/join" element={<Join />} />
<Route path="/footer" element={<Footer />} />
<Route path="/copy" element={<Copyright />} />
</Routes>
</div>
);
};
export default App;
Index.js
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>
);
Navbar.js
const Nav = () => {
return (
<nav className="hidden lg:flex">
<ul className="flex gap-x-8 text-white">
{["home", "about", "featured", "gallery", "testimonies", "join"].map(
(item) => {
return (
<li key={`link-${item}`}>
<Link to={`/${item}`} className="capitalize">
{item}
</Link>
</li>
);
}
)}
</ul>
</nav>
);
};
export default Nav;
I would appreciate any help please
You need to use hashtags instead different routes.
So you have to use only one index route
<Route path="/" element={<IndexPage />} />
and render section components in IndexPage component one by one
const IndexPage = () => (
<>
<Banner />
...
</>
)
then add into each section component wrapper id attribute
const Banner = () => (
<div id="banner">
...content...
</div>
)
and use hashtag links in you Nav component:
<Link to={`#${item}`} className="capitalize">
{item}
</Link>
links will be looks like domain.com/#banner and if use open it then browser will scroll down to specific element with id
also I suggest to add some css to make scrolling smooth:
html {
scroll-behavior: smooth;
}

navigation in react router dom version 6.3.0 doesn't work proplery

I'm working on react website and I have a problem while navigating to any page
that when I scroll to a certain point in a home page for example then I try to navigate to another page I find the other page is rendered from the the bottom of the page not the top
routes.tsx file
const App: React.FC = () => (
<BrowserRouter>
<Layout className="layout">
<div style={{ marginBottom: "64px" }}>
<Header>
<AppHeader />
</Header>
</div>
<Content>
<div className="site-layout-content">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/offers" element={<Login />} />
<Route path="/aboutUs" element={<AboutUs />} />
<Route path="/contactUs" element={<ContactUs />} />
<Route path="/placeDetails/:id" element={<PlaceDetails />} />
<Route path="/advantages" element={<Advantages />} />
</Routes>
</div>
</Content>
<Footer style={{ textAlign: "center" }}>
<AppFooter />
</Footer>
</Layout>
</BrowserRouter>
);
export default App;
header.tsx
const Index = () => {
const navigate = useNavigate();
return (
<Row className="header">
<Col span={12} className="header__logo">
<div className="header__logo--imgContainer" onClick={() => navigate("/")}>
<img src={logoImg} alt="logo" />
</div>
</Col>
<Col span={12} className="header__menu">
<ul className="ant-menu-overflow ant-menu ant-menu-root ant-menu-horizontal ant-menu-light ant-menu-rtl">
<li className="ant-menu-item">
<span onClick={() => navigate("/offers")}>{strings.header.offers}</span>
</li>
<li className="ant-menu-item">
<span onClick={() => navigate("/advantages")}>{strings.header.services}</span>
</li>
</ul>
</Col>
</Row>
);
};
export default Index;
you can simply use this helper component for this use case:
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function ScrollToTop() {
const { pathname } = useLocation();
useEffect(() => {
// "document.documentElement.scrollTo" is the magic for React Router Dom v6
document.documentElement.scrollTo({
top: 0,
left: 0,
behavior: "instant", // Optional if you want to skip the scrolling animation
});
}, [pathname]);
return null;
}
and then you can change above code like this:
const App: React.FC = () => (
<BrowserRouter>
<ScrollToTop/> // this is new helper component
<Layout className="layout">
<div style={{ marginBottom: "64px" }}>
<Header>
<AppHeader />
</Header>
</div>
<Content>
<div className="site-layout-content">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/offers" element={<Login />} />
<Route path="/aboutUs" element={<AboutUs />} />
<Route path="/contactUs" element={<ContactUs />} />
<Route path="/placeDetails/:id" element={<PlaceDetails />} />
<Route path="/advantages" element={<Advantages />} />
</Routes>
</div>
</Content>
<Footer style={{ textAlign: "center" }}>
<AppFooter />
</Footer>
</Layout>
</BrowserRouter>
);
export default App;
This will reset the scroll position on top whenever route changes.

How to open the Sidebar so that it sits on over of the main information page

My website has a sidebar (FiltersSideBar in my code) with filters. The sidebar is on the left.
I also made a functionality that would hide the Sidebar at certain sizes of the browser window. The sidebar hides and a button appears with which (I assume) Sidebar can be opened again.
This is where I have a problem. I can't figure out how to open the Sidebar so that it sits on over of the main information page.
App.js
export default function App() {
const [filters, setFilters] = useState({.....})
const size = WindowSize();
const [setHideSidebar] = useState(false);
return (
<ThemeProvider theme={theme}>
<BrowserRouter>
<Header/>
<button style={{display: size.width > 600 ? "none" : "inline"}}
onClick={() => {setHideSidebar((prev) => !prev);}}>Toggle Sidebar
</button>
<AppContext.Provider value={{ filters, setFilters}}>
<div style={{display: 'flex'}} >
{size.width > 600 && <FiltersSideBar />}
<Routes>
<Route exact path='/devices/:deviceId/:userId/:sessionId' element={<Records />} />
<Route exact path='/devices/:deviceId/:userId/:sessionId/:recordId' element={<Record />} />
<Route path="*" element={<Navigate to="/devices" replace />} />
</Routes>
</div>
</AppContext.Provider>
<Footer />
</BrowserRouter>
</ThemeProvider>
);
}
FiltersSideBar.jsx
export default function FiltersSideBar() {
return (
<CardContent>
<Table>
<TableBody>
......
</TableBody>
</Table>
</CardContent>
);
}
Start by actually using the value set by setHideSidebar
const [filters, setFilters] = useState({.....})
const size = WindowSize();
// Actually use the state here
const [hideSidebar, setHideSidebar] = useState(true);
And then below that, where you are checking if the sidebar can be shown above a certain width, add the following
{size.width > 600 && <FiltersSideBar />}
{size.width <= 600 && !hideSidebar && <FiltersSideBar className="overlay" />}
You'll need to augment your FiltersSideBar component to use the className when it's available:
export default function FiltersSideBar(props) {
return (
<CardContent className={props.className}>
{/* ... */}
</CardContent>
);
}
And also you'll need to add the following css somewhere
.overlay {
position: absolute;
top: 0;
left: 0;
z-index: 9999;
}

Can you override boostrap grid for just one component?

My entire app is nested within a bootstrap container along with row and cols
App.js
export default class App extends Component{
componentDidMount() {
store.dispatch(loadUser());
};
render() {
return (
<Provider store={store}>
<Router>
<NavigationBar />
<Container>
<Row className="justify-content-sm-center justify-content-md-center">
<Col sm="7" md="7" lg="5" xl="5">
<ProfileSidebar />
</Col>
<Col sm="7" md="7" lg="7" xl="7">
<Switch>
<Route path="/tournaments/edit/:id" component={EditTournament} />
<Route exact path="/tournaments/:id" component={TournamentShow} />
<Route exact path="/tournaments" render={ () => <Redirect to="/" /> } />
<Route path="/player/:id" component={PlayerProfile} />
<Route exact path="/players" component={PlayerDirectory} />
<Route path="/users" render={ () => <Redirect to="/players" /> } />
<Route path="/smash-news" component={SmashNews} />
<Route exact path="/" component={TournamentIndex} />
</Switch>
</Col>
</Row>
</Container>
</Router>
</Provider>
);
};
};
This is a tournament app, and the profile side bar is on the left-side of each page (as I wanted) but that means it restricts EVERYTHING to the right-hand side.
This is fine with me, except for my tournament bracket component.
It doesn't have it's own route or anything, as it is a child-component of TournamentShow.
I want to display everything in TournamentShow as is, but simply stretch the Bracket out to the whole screen, ignoring the constraints of bootstrap's grid.
Is this possible?
This is how it looks right now, bracket trailing off to side
This is how it looks when I try some CSS
CSS file
.bracket-position {
width: 100%;
position: absolute;
right: 50%;
}
but that screws it up for mobile size, moving the bracket to far-left without scrollable
I'm sure there's some easy solution but my CSS abilities are lacking.

How to change style of a different component on button click in react?

I would like to apply a width of 100% to my navbar on click of a button. Intially, it would be 0% (hidden).
To do this, I use a state to keep track of the navbar width, However, it seems that my state wouldn't change onclick.
class Navbar extends Component {
constructor(){
super();
this.state = {
sidenav: {
width: '0%',
}
}
}
showNavBar = () => {
this.setState({
sidenav: {
width: '100%',
}
})
}
render(){
return(
<div>
<div className ="sidenav" style ={{width : this.state.sidenav.width}}>
<NavLink exact to="/">Home</NavLink>
<NavLink exact to="/about">About</NavLink>
<NavLink exact to="/portfolio">Portfolio</NavLink>
<NavLink exact to="/contacts">Contacts</NavLink>
<div className="content">
<Route exact path="/" component={Home} />
<Route exact path="/about" component={About} />
<Route exact path="/portfolio" component={Portfolio} />
<Route exact path="/contacts" component={Contacts} />
</div>
</div>
<NavbarButton onClick={this.showNavBar}/>
</div>
)
}
};
Can anyone point out where I went wrong?
EDIT:
So I followed the examples you guys posted and got it working only when I explicitly give the in the render function.
So here is my code for the NavBarbutton, maybe someone can see why it's wrong?
const NavbarButton = (props) => {
return (
<button style = {style} onClick = {props.showNavBar}>☰</button>
)
}
Your code works fine, that is the width is getting from 0% to 100%.
Here is a codesandbox derived from the code you provided.
https://codesandbox.io/s/lx24555w8z
If you want to show the navbar on click, then probably use the display property instead of the width.
Use CSS display property instead.
import React, { Component } from "react";
class Navbar extends Component {
constructor() {
super();
this.state = {
showNavBar: false
};
}
showNavBar = () => {
this.setState({
showNavBar: true
});
};
render() {
return (
<div>
<div
className="sidenav"
style={{ display: this.state.showNavBar ? "block" : "none" }}
>
<NavLink exact to="/">
Home
</NavLink>
<NavLink exact to="/about">
About
</NavLink>
<NavLink exact to="/portfolio">
Portfolio
</NavLink>
<NavLink exact to="/contacts">
Contacts
</NavLink>
<div className="content">
<Route exact path="/" component={Home} />
<Route exact path="/about" component={About} />
<Route exact path="/portfolio" component={Portfolio} />
<Route exact path="/contacts" component={Contacts} />
</div>
</div>
<NavbarButton onClick={this.showNavBar} />
</div>
);
}
}
export default Navbar;
So the problem is because I don't know how to properly pass props to the child component.
const NavbarButton = (props) => {
return (
<button style = {style} onClick = {props.showNavBar}>☰</button>
)
}
My code should have been
<NavbarButton showNavBar={this.showNavBar}/>
Gosh I feel so stupid now!

Categories