Edited at

Nuxt.jsに組み込んだBulmaでスティッキーフッター (sticky footer) を実現する

More than 1 year has passed since last update.


はじめに

前回書いた記事「:link: Nuxt.jsにBulmaを組み込んだら、Vuexストアが理解できた件」の続きみたいなものです。少なくとも設定は同じです。

Bulmaには :link: Footer が、ちゃんと1ページ使って説明されているのに、下部に固定化する方法についてはなにも言及していません。どうやって実現するのかなと調べたら、レイアウトファイルひとつで簡単に実現できたという、またまたアハ体験が待っておりました。


駆け足で、前回の記事を再現


  • create-nuxt-appコマンドを使ってavocadoという名前のNuxt.jsアプリを作成


  • pagesディレクトリにabout.vuecontact.vueの2つのファイルを作成し、インデックスページ以外のページを用意


  • componentsディレクトリにNavbar.vueを作成し、ナビゲーションメニューのコンポーネントを用意


  • layouts/default.vueファイルを編集し、ナビゲーションメニューのコンポーネントをレイアウトファイルに取り付け


  • npm run devコマンドを叩いて開発サーバーを起動

avocadoのディレクトリの中はこんな感じになっています

|--components/

| |--Logo.vue ... index.vueが使用するコンポーネント
| `--Navbar.vue ... ナビゲーションメニュー
|--layouts/
| `--default.vue ... デフォルトのレイアウトファイル
`--pages/
|--about.vue ... 新たに作成したページ
|--contact.vue ... 新たに作成したページ
`--index.vue ... 最初から用意されているトップページ

前回の記事ではページ遷移後のメニューのトグルにVuexストアを使っていましたが、@takanoripさんの貴重なコメントにより、Navbar.vueファイルだけで実現できるようになりました。store/index.jsファイルは登場しません。


フッターコンポーネントの作成

componentsディレクトリにBottom.vueファイルを作成します。


components/Bottom.vue

<template>

<footer class="footer">
<div class="container">
<div class="content has-text-centered">
<p>
&copy; 2018 Avocado
</p>
</div>
</div>
</footer>
</template>

今回は、新しいレイアウトファイルを用意します。

layoutsディレクトリにstickyfooter.vueファイルを作成します。

そこにフッターコンポーネントを取り付けます


layouts/stickyfooter.vue

<template>

<div>
<navbar/>
<nuxt/>
<bottom/>
</div>
</template>

<script>
import Navbar from '~/components/Navbar.vue'
import Bottom from '~/components/Bottom.vue'

export default {
components: {
Navbar,
Bottom
}
}
</script>


なぜFooter.vueではなく、Bottom.vueというファイル名にしたかというと、コンポーネントを取り付けるときに、<footer/>という要素名が、すでにHTML5で採用された要素とダブるからです。


話の流れとは直接関係ない修正

pages/index.vueファイルのスタイル定義が全ページに影響を及ぼしていて、こちらが意図したレイアウトの邪魔をするので、ローカルスコープにします。つまり「そのスタイル定義はそのページのみで有効」にさせます。


pages/index.vue

<!-- <style>を<style scoped>に変更 -->

<style scoped>
.container
{
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
...
</style>


すでにあるページに新しいレイアウトを適用

ページは何も指定しなければ、自動的にデフォルトのレイアウトが適用されますが、以下のように指定すればそのレイアウトファイルが適用されます。


pages/contact.vue

<template>

<div>
<section class="hero is-info is-bold">
<div class="hero-body">
<h1 class="title is-size-2">
Contact
</h1>
<h2 class="subtitle is-size-4">
お問い合わせ
</h2>
</div>
</section>
<div class="container">
お問い合わせ
</div>
  </div>
</template>

<script>
export default {
layout: 'stickyfooter'
}
</script>


その結果がこちらになります。

01a.png

はい、フッターが浮いております。フッターの下に何もない(恥ずかしい)空間がある。

Bulmaのフッターは特に極太仕様になっておりますが、それでも、スマホの縦長画面では浮いてしまいがちです。このフッターをどうやって下げるかが、本日のお題です。

やっと辿り着いた感が半端ないですが、間もなく終わります。


スティッキーフッター (sticky footer)の実現

layouts/stickyfooter.vueファイルを修正します。

sf-site-allsf-site-contentという2つのCSSクラスを追加します


layouts/stickyfooter.vue

<template>

<div class="sf-site-all">
<navbar/>
<nuxt class="sf-site-content"/>
<bottom/>
</div>
</template>

<script>
import Navbar from '~/components/Navbar.vue'
import Bottom from '~/components/Bottom.vue'

export default {
components: {
Navbar,
Bottom
}
}
</script>

<style>
.sf-site-all {
min-height: 100vh; /* 全体の高さを最低でもビューポートの100%にする */
display: flex; /* 子クラスを横並びにする */
flex-direction: column; /* 子クラスの横並びの方向を縦にする */
}
.sf-site-content {
flex: 1; /* flexに1つだけ数値を指定するとその要素は伸びる */
}
/* NavbarとBottomにはflexを指定しないので伸びない */
/* 結果としてページファイルの中味だけが伸びて、ビューポート100%を実現 */
/* Bottomは下に貼り付く。スティッキーフッターを実現 */
</style>


その結果がこちらです。

2a.png


私のアハ体験ふたつ

「flexboxを使うとこんなに簡単にスティッキーフッターが実現できてしまうのか!」というのがひとつ。今まで後生大事にとっておいたスティッキーフッターのためのCSSテンプレートは捨ててしまいました。

「レイアウトファイルとページファイルを組み合せるための目印になっている<nuxt/>にもクラス名を付加してよかったんだ!」というのがもうひとつ。どこにも書いてなかったので、できるとは思わなかったのですが、あとから考えてみたら、「どうしてできないと思ったのか?」のほうが不思議ですね。


最後に

冒頭にも書いた通り、Bulmaのフッターを下部に固定する方法はどこにも載っていないのですが、Bulmaの作者からすると「なんで、そんなことわざわざ書かなきゃいけないの?」って感じなんだと思います。「Flexboxを採用したBulmaを採用したあなたなら知ってて当然でしょう」という感覚。いずれ私もそっち側の人間になりたいなと思いつつ、その過程で生まれたアハ体験を、次の人のために記事にしておく次第です。

面白いと思っていただけたら「いいね」をクリックしてください。励みになります。