Skip to content
Advertisement

Full Page Layout with Bootstrap and Vue 3

I’m trying to create a Single Page Application with a simple layout of Header -> Content -> Footer using Vue3 and the Bootstrap 5 framework.

I am trying to get the Content to fill the space between header and footer and footer to flush to the bottom of page & content so there is no overlap. However the application just renders everything on the top half of the page leaving the bottom half a white space. I’ve tried a flexbox approach however something doesn’t seem to be clicking right.

App.vue

<template>
  <div id="app">
    <div>
      <HeaderBar></HeaderBar>
      <div class="content"><router-view></router-view></div>
      <FooterBar></FooterBar>
    </div>
  </div>
</template>

<script>
import HeaderBar from "@/components/HeaderBar.vue";
import FooterBar from "@/components/FooterBar.vue";

export default {
  components: {
    HeaderBar,
    FooterBar,
  },
};
</script>

<style>
body {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.content {
  background-image: url("../src/assets/background.png");
  background-repeat: no-repeat;
  background-attachment: scroll;
  background-position: center center;
  background-size: cover;
  flex-shrink: 0;
}
</style>

HeaderBar.vue

<template>
  <div>
    <header class="bg-dark bg-gradient d-flex justify-content-center">
      <ul class="nav nav-pill p-2">
        <li class="nav-item">
          <a class="nav-link fw-bold heading"> Title </a>
        </li>
      </ul>
    </header>
    <nav
      class="navbar navbar-expand-lg navbar-dark bg-dark"
      aria-label="Tenth navbar example"
    >
      <div class="container-fluid">
        <button
          class="navbar-toggler"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target="#navbarsExample08"
          aria-controls="navbarsExample08"
          aria-expanded="false"
          aria-label="Toggle navigation"
        >
          <span class="navbar-toggler-icon"></span>
        </button>

        <div
          class="collapse navbar-collapse justify-content-md-center"
          id="navbarsExample08"
        >
          <ul class="navbar-nav justify-content-around">
            <li class="nav-item pr-2">
              <router-link class="nav-link lead" style="font-size: 2em" to="/"
                >HOME</router-link
              >
            </li>
            <li class="nav-item pr-2">
              <router-link
                class="nav-link lead"
                style="font-size: 2em"
                to="/about"
                >ABOUT</router-link
              >
            </li>
            <li class="nav-item pr-2">
              <router-link
                class="nav-link lead"
                style="font-size: 2em"
                to="/gallery"
                >GALLERY</router-link
              >
            </li>
            <li class="nav-item pr-2">
              <router-link
                class="nav-link lead"
                style="font-size: 2em"
                to="/cms"
                >CMS</router-link
              >
            </li>
          </ul>
        </div>
      </div>
    </nav>
  </div>
</template>

<style scoped>
@font-face {
  font-family: "Mythical Snow";
  src: URL("../assets/fonts/MysticalSnow.ttf") format("truetype");
}

.heading {
  font-family: "Mythical Snow";
  font-size: 4em;
  color: #6a7363;
}

nav a {
  font-weight: bold !important;
  color: #2c3e50;
}

nav a.router-link-exact-active {
  color: #ffffe0 !important;
}
</style>

FooterBar.vue

<template>
  <div id="footer">
    <footer class="bg-dark text-center text-white mt-auto">
      <!-- Grid container -->
      <div class="container p-4 pb-0">
        <!-- Section: Social media -->
        <section class="mb-4">
          <!-- Home -->
          <router-link
            to="/"
            class="btn btn-outline-light btn-floating m-1"
            role="button"
            ><i class="bi bi-house-fill fa-2x"></i
          ></router-link>

          <!-- About -->
          <router-link
            to="/about"
            class="btn btn-outline-light btn-floating m-1"
            role="button"
            ><i class="bi bi-file-person fa-2x"></i
          ></router-link>
        </section>
        <!-- Section: Social media -->
      </div>
      <!-- Grid container -->

      <!-- Copyright -->
      <div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.2)">
        © 2022 Copyright:
        <a class="text-white"></a>
      </div>
      <!-- Copyright -->
    </footer>
  </div>
</template>

<style scoped>
.icon {
  color: #ffffff;
}

.icon:hover {
  color: #000000;
}

footer {
  position: sticky;
  width: 100%;
}
</style>

Advertisement

Answer

<style>
  #app {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    height: 98vh;
     font-family: Avenir, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }
  .content {
    /*  */
  }
</style>
<template>
      <HeaderBar></HeaderBar>
      <div class="content"><router-view></router-view></div>
      <FooterBar></FooterBar>
</template>

Strip the two div‘s around HeaderBar and FooterBar in App.vue.

Remove all styles from body and put them into #app, add justify-content: space-between. With height: 100vh you’ll get a scrollbar. Use 98 to avoid that.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement