I am building a website using react
and react-router-dom
and I encountered a problem.
When I have a footer element that is being rendered on every web page like so:
<Router>
<Header />
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="shop/*" element={<ShopRoutes />} />
<Route path="cart" element={<CartPage />} />
<Route path="login" element={<LoginPage />} />
<Route path="register" element={<RegisterPage />} />
</Routes>
<Footer />
</Router>
On pages that you need to scroll down for the footer to be displayed at the bottom of the page, you need to add position: relative;
.
And on pages without the need to scroll down the footer to be displayed at the button you need to add position: absolute;
.
How do I make it that on every page the style is different depending on the page length?
I can set a useState
in the app.jsx
file that will do a conditional class naming to the footer element, and on every page, I will set the state to be true or false:
app.jsx:
const [pageBig, setPageBig] = useState(false);
<Router>
<Routes>
<Route path="/" element={<HomePage setPageSize={setPageBig}/>} />
..... more routs
</Routes>
<Footer pageSize={pageBig}/>
</Router>
footer.jsx:
<footer className={ props.pageSize ? "big-page" : "small-page"}>
<p>© Copyright {currentYear}</p>
</footer>
for example, if the homePage is a long page I will set the pageBig
to true and the footer class will change:
props.setPageSize(true);
I can also do the same with createContex
but in both solutions, I will need to make sure in every page I set the bigPage
to be the correct one.
How can I achieve this functonltiy?
CodePudding user response:
I came out with this solution, creating a custom hook that will check the size of the root div
relative to the window size this solution was inspired by an answer to a different question.
I used the custom hook that checks the window size from here, and created a custom hook that checks the root div
hight:
function useRootSize () {
const [rootSize, setRootSize] = useState([0, 0]);
useLayoutEffect(() => {
function updateRootSize() {
setRootSize([document.getElementById("root").offsetWidth, document.getElementById("root").offsetHeight]);
}
document.addEventListener('click', updateRootSize);
updateRootSize();
return () => document.removeEventListener('click', updateRootSize);
}, []);
return rootSize;
};
( I am listing to clicks because I couldn't think of abater event listener, every time you go to a new page you are going to click something to get there)
footer element:
const Footer = () => {
const [windowWidth, windowHight] = useWindowSize();
const [rootWidth, rootHight] = useRootSize();
const currentYear = new Date().getFullYear();
return (
<footer className={windowHight >= rootHight ? "small-page" : "big-page"}>
<p>© Copyright {currentYear}</p>
</footer>
)
};
CSS file:
.small-page {
position: absolute;
...morestyles
}
.big-page {
position: relative;
...morestyles
}
Now the footer will change the className without passing props or context.
If you have a better solution i would like to hear it :)
CodePudding user response:
You could create a better layout for your whole page to account for this, with just CSS and not rely on JS at all.
Incorporating your components into a structure like the following, utilizing the flexbox
html,
body {
padding: 0;
margin: 0;
}
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
color:#eee;
}
.header {
padding:0.5em;
background: #303080;
}
.main {
flex: 1;
background: #308030;
padding:0.5em;
}
.footer {
background: #803030;
padding:0.5em;
}
<div >
<div >
Header
</div>
<div >
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Velit aut et voluptatibus culpa iste earum fugit enim obcaecati doloremque recusandae, rerum ullam quod consectetur! Iure nulla, perferendis cumque. Id, quas, blanditiis! Facere eaque dolores accusamus
repudiandae sequi fugiat illo perspiciatis doloribus quo expedita possimus impedit, autem id adipisci voluptate reiciendis molestiae. Possimus facilis consectetur similique saepe ipsum, repellendus iusto ipsa iste quod mollitia distinctio quos ut
</div>
<div >
Footer
</div>
</div>