Search code examples
htmlcssreactjsreact-router-domnavbar

I'm using react-router-dom and created a fixed navbar that keeps changing size on each webpage and I don't know why


I'm using react-router-dom to make a multi-page website and I'm trying to add a fixed navbar to the top.

My navbar component and css file:

import { NavLink } from "react-router-dom";
import styles from "./NavBar.module.css";

const NavBar = () => {
  return (
    <nav className={styles.nav}>
      <ul>
        <li>
          <NavLink
            className={({ isActive }) => (isActive ? styles.active : undefined)}
            to="/"
          >
            Home
          </NavLink>
        </li>
        <li>
          <NavLink
            className={({ isActive }) => (isActive ? styles.active : undefined)}
            to="/Menu"
          >
            Menu
          </NavLink>
        </li>
        <li>
          <NavLink
            className={({ isActive }) => (isActive ? styles.active : undefined)}
            to="/Contact"
          >
            Contact
          </NavLink>
        </li>
      </ul>
    </nav>
  );
};

export default NavBar;
.nav {
  position: fixed;
  width: 100%;
  z-index: 10;
  background-color: white;
  display: flex;
  justify-content: center;
}

.nav ul {
  list-style-type: none;
  display: flex;
  gap: 1rem;
}

.nav a {
  color: grey;
  font-weight: bold;
  text-decoration: none;
  padding-bottom: 10px;
  transition: color 0.15s border-bottom 0.15s;
  font-size: 1.15rem;
}

.nav a.active {
  color: black;
  border-bottom: 2px solid black;
}

.nav a:hover {
  color: black;
}

I added the navbar to my website with this:

import { Outlet } from "react-router-dom";
import NavBar from "../components/NavBar/NavBar";

const Root = () => {
  return (
    <div>
      <NavBar />
      <Outlet />
    </div>
  );
};

export default Root;

Basically the contents of Outlet is changing the size of my navbar. For example on the homepage the navbar is 690px wide but on the contact page its 710px wide. It appears the issue is with the size of the elements in Outlet because when I decrease the height the size change becomes less severe. But navbar is fixed so I'm not sure why Outlet is affecting it.

Here is my homepage component and css files:

import styles from "./Home.module.css";
import img from "../../img/spread.jpg";
import { Link } from "react-router-dom";
import Map from "../../components/Map/Map";
import HomeContact from "./HomeContact/HomeContact";

const Home = () => {
  return (
    <div>
      <div className={styles.home}>
        <div>
          <h5>Welcome to</h5>
          <h1>Spring Garden</h1>
          <Link to="/Menu">View Menu</Link>
        </div>
        <img src={img} alt="A table full of Chinese food."></img>
      </div>
      <HomeContact />
      <Map />
    </div>
  );
};

export default Home;
.home {
  display: flex;
  height: 60vh;
  align-items: center;
}

.home div {
  width: 50%;
  padding-left: 2rem;
  padding-right: 2rem;
}

.home img {
  width: 50%;
  height: 100%;
  object-fit: cover;
}

.home h1 {
  font-size: 4rem;
  line-height: 5rem;
  margin-top: 0rem;
}

.home h5 {
  font-size: 1.25rem;
  margin-bottom: 1rem;
}

.home a {
  text-decoration: none;
  font-weight: bold;
  background-color: rgb(205, 7, 30);
  color: white;
  padding: 1rem;
  transition: background-color 0.15s;
}

.home a:hover {
  background-color: rgb(231, 9, 35);
}

I'm trying to add a fixed navbar that won't change on every page of my website. However through inspect element I see that on each page the size of nav slightly changes. This causes my navbar to offset slightly. I don't understand why this happens because the navbar should not be part of the document flow.

The entire project is on github: https://github.com/iamgeeyuh/spring-garden-website

Here's a running codesandbox demo.


Solution

  • The UI doesn't have a consistent application of the CSS across the different routes that are rendered. I'd suggest specifying a more static layout in the Root component. Instead of making the Navbar position fixed use a grid layout to position the nav bar in the first row and then a scrollable content row that the Outlet and routed content is then rendered into.

    Root

    import { Outlet } from "react-router-dom";
    import NavBar from "../components/NavBar/NavBar";
    import styles from "./Root.module.css";
    
    const Root = () => {
      return (
        <div className={styles.container}>
          <NavBar />
          <div className={styles.scrollContainer}>
            <Outlet />
          </div>
        </div>
      );
    };
    
    export default Root;
    

    Root.module.css

    .container {
      display: grid;
      grid-template-rows: auto 1fr;
      overflow: hidden;
      height: 100vh;
    }
    
    .scrollContainer {
      overflow: auto;
    }
    

    Navbar.module.css - Remove the position: fixed and bottom padding rules.

    .nav {
      list-style-type: none;
      text-align: center;
      background-color: white;
      /* position: fixed; */ <-- remove
      width: 100%;
      z-index: 10;
      margin-top: 0;
      /* padding-bottom: 1rem; */ <-- remove
    }
    

    Edit im-using-react-router-dom-and-created-a-fixed-navbar-that-keeps-changing-size-o

    enter image description here enter image description here enter image description here