💨

tailwindとvue.jsを利用してヘッダーナビゲーションメニューを作る

2022/01/23に公開

laravelでvue.jsとtailwindを使った際の勉強記録になります。
tailwindでヘッダーナビゲーションメニューの形を作って、vue.jsでメニューの開閉を行います。

ヘッダーナビゲーションメニューを作成

ヘッダーナビゲーションメニューを作成します。
ヘッダーナビゲーションメニューは横並びに配置されております。画像のようになります。

PC画面

スマホ画面

レスポンシブデザインにて利用するボタンについてはvue.jsを利用して開閉を行います。

横並びの基本を抑える

コンテンツを横に並べたい場合はflexを利用します。
以下のようにした場合は、画像のように横並びになります。

<div class="flex">
    <div>左コンテンツ</div>
    <div>右コンテンツ</div>
</div>

この状態から見た目で分かりやすくするために、borderとmarginとpaddingを設定しておきます。

border-2でborder-width: 2px;が設定されます。
p-5でpadding: 1.25rem;が設定されます。
m-5で margin: 1.25rem;が設定されます。

<div class="flex border-2 p-5 m-5">
    <div class="">左コンテンツ</div>
    <div class="">右コンテンツ</div>
</div>

これで余白と枠線を持ったボックスにコンテンツが並びます。

コンテンツ幅の指定

横幅の指定は様々な方法があります。
ドキュメント

今回は%で指定できるw-11/12のような記載を利用します。
例えばw-11/12の場合はwidth: 91.666667%;になります。

今回はそれぞれw-3/12を指定します。

<div class="flex border-2 p-5 m-5">
    <div class="w-3/12 border-2">左コンテンツ</div>
    <div class="w-3/12 border-2">右コンテンツ</div>
</div>

この場合は6/12を左と右のコンテンツが占めていることになります。

コンテンツの折り返し

以下のような場合はどうなるのか見ていきます

<div class="flex border-2 p-5 m-5">
    <div class="w-3/12 border-2">左コンテンツ</div>
    <div class="w-3/12 border-2">右コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
</div>

無理矢理コンテンツが縮小されています。
本来ならば4つのコンテンツしか一行に入らない想定なのですが、横並びを指定しているので無理矢理横に並んでいる状態です。

ここでflex-wrapを使ってみます。
これは折り返しを行ってくれるので4つ並んだら折り返してくれるようになります。

<div class="flex flex-wrap border-2 p-5 m-5">
    <div class="w-3/12 border-2">左コンテンツ</div>
    <div class="w-3/12 border-2">右コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
    <div class="w-3/12 border-2">コンテンツ</div>
</div>

コンテンツが折り返されています。

→実際にはこんなとんでもないことが発生しないように作成します。

コンテンツの間隔を設定する

コンテンツに間隔をあけることで以下を実現します。

  • 左にはトップページのリンク
  • 右にはナビゲーション

そのためにjustify-betweenを指定します。
これで2つのコンテンツの間には適当な間隔が空くことになります。

<div class="flex flex-wrap justify-between border-2 p-5 m-5">
    <div class="w-3/12 border-2">左コンテンツ</div>
    <div class="w-3/12 border-2">右コンテンツ</div>
</div>

コンテンツに間隔を持たせたので、次にナビゲーションの体裁を整えていきます。
右側のコンテンツの中に、さらにflexを持ったulを入れます。
これはjustify-endを付与させて右寄せにします。

<div class="flex flex-wrap justify-between border-2 p-5 m-5">
    <div class="w-3/12 border-2"><a href="/">HOME</a></div>
    <div class="w-5/12 border-2">
        <ul class="flex justify-end border-2">
            <li>リンク1</li>
            <li>リンク2</li>
            <li>リンク3</li>
        </ul>
    </div>
</div>

画面サイズによって表示を切り替える

通常このようなナビメニューはスマホなどの画面サイズによってトグルボタンのようなものを表示して、レスポンシブなデザインにします。

ドキュメント

特定の画面サイズによってスタイルを変える場合は
sm: / min-width: 768px
md: / min-width: 768px
lg: / min-width: 1024px
xl: / min-width: 1280px
を使います。

例えばmdサイズ以上では要素を消したい場合はmd:hiddenのように書きます。
ボタンを追加してmdサイズ以上でボタンを非表示にするようにしてみます。

buttonのクラスがmd:hiddenにしてbuttonを追加します。

<div class="flex flex-wrap justify-between border-2 p-5 m-5">
    <div class="w-3/12 border-2"><a href="/">HOME</a></div>
    <div class="w-5/12 border-2">
        <button class="md:hidden">開く</button>
        <ul class="flex justify-end border-2">
            <li>リンク1</li>
            <li>リンク2</li>
            <li>リンク3</li>
        </ul>
    </div>
</div>

画面サイズが小さくなると開くボタンが表示されるようになっています。

次にやることは現在右側に出ているメニューの表示を切り替えることです。
予めhiddenにしておいてmd以降では表示にするということをすれば解決できます。


<div class="flex flex-wrap justify-between border-2 p-5 m-5">
    <div class="w-3/12 border-2"><a href="/">HOME</a></div>
    <div class="w-5/12 border-2">
        <button class="md:hidden">開く</button>
        <ul class="hidden md:flex justify-end border-2">
            <li>リンク1</li>
            <li>リンク2</li>
            <li>リンク3</li>
        </ul>
    </div>
</div>

これで画面サイズによってボタンを表示したり、メニューを表示したりというのができました。

vueからボタンを操作する

ボタンを押してメニューを開閉できるようようにします。

  • 右メニューの表示非表示はvue.jsを利用してisCloseがtrueの時は非表示、falseの時は表示とするように修正します。
  • ボタンをクリックしたらisCloseの真偽値を逆転させる

<div class="flex flex-wrap justify-between border-2 p-5 m-5">
    <div class="w-3/12 border-2"><a href="/">HOME</a></div>
    <div class="w-5/12 border-2">
        <div class="text-right">
          <button class="md:hidden" @click="toggle">開く</button>
        </div>
        <ul v-bind:class="{ 'hidden' : isClose }" class="flex-col md:flex md:flex-row justify-end border-2">
            <li class="p-5 md:p-0">リンク1</li>
            <li class="p-5 md:p-0">リンク2</li>
            <li class="p-5 md:p-0">リンク3</li>
        </ul>
    </div>
</div>

ちょっと解説をします。

<div class="text-right">
 <button class="md:hidden" @click="toggle">開く</button>
</div>

ボタンは右寄せで表示したいのでtext-rightを設定します。

<ul v-bind:class="{ 'hidden' : isClose }" class="flex-col md:flex md:flex-row justify-end border-2">

は、通常は"縦"並び(flex-col)にして要素を表示するが、md以上の場合は"横"並び(md:flex-row)にして表示するようにしています。
縦並びメニューは、開くボタンを押してisCloseがfalseになっているときに画面に表示されます。

<li class="p-5 md:p-0">

は通常(縦並びの時)はpaddingを設定して、横並びの時はpaddingを0にしています。
こうすることで小画面では開くボタンを押したときは以下のようになって

閉じているときは以下のようになります。

最後にvueのscript部分を確認します。
Laravelで書いているので余計な個所があるのですが、
isCloseをtrueで宣言しておき、toggleメソッドでこのisCloseを切り替える処理を記載しています。

<script>
    import { defineComponent } from 'vue'

    export default defineComponent({
        components: {

        },
        props: {
            info : Object,
        },
        data() {
            return {
              isClose: true,
            }
        },
        methods: {
          toggle(){
            this.isClose = !this.isClose;
          },
        }
    })
</script>

cssを知っていると直感的に使えるのでtailwindは使いやすいと思いますが、HTMLが長くなってしまうので、サンプルとか見て勉強するのが大変ですよね。

Discussion