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.