Dec 26, 2020

Nuxtで作成したブログをスマホ対応にしてみた。

今回も Nuxt ネタです。Google Search Console で URL 検査してみたら、「このページはモバイル フレンドリーではありません」との結果でした。この赤いビックマークが気に食わない、おじさんに火をつけたようです。このホームページをレスポンシブに対応したいと思います。また スタイルシートを CSS から SCSS に変更したいと思います。

Google Search Console -URL Cherk-!

Nuxt に SCSS を導入してみます。

SCSS に必要なモジュールをインストールします。

  yarn add sass-loader node-sass
    :

次に nuxt.config.js ファイルを修正していきたいと思います。メインとなる scss ファイルを設定します。 この main.scss から複数の scss ファイルから読むようにしたいと思います。

/nuxt.config.js
/*
  ** Global CSS
  */
  css: [{src:'~/assets/sass/main.scss',lang:'scss'}],
/*
/assets/sass/main.scss
@import 'defaultstyle';
@import 'header';
@import 'article';
@import 'articles';
@import 'card';
@import 'footerNavi';
* {
  margin: 0;
  padding: 0;
}

scss では変数が使えるので、defaultstyle.scss ファイルにディフォルトスタイルの属性を変数としてまとめて設定したいと思います。今回、PC のナビゲーションメニューのフォントサイズは、0.7rem にしてスマートフォンのナビゲーションメニューのフォントサイズは、2 倍の 1.4rem にしたいと思います。

/assets/sass/default.scss
/* default style */
$main_font_size: 1.1rem;
$header_font_size: 0.8rem;
$navi_font_size: 0.7rem;
$sp_navi_font_size: 1.4rem;

PC もスマートフォンも横幅に合わせてページのレイアウトを配置し、同じスタイルを利用することにしました。縮小してもブラウザの横スクロールが出ないように親子要素の構成や width を気にしながら微調整します。私の場合は、画像ファイルや nuxt-content-highlight のところでちょっと苦戦しました。結局 Vue ファイルの親要素の配置を再設計して scss を再定義しました。

次は、ナビゲーションメニューをレスポンシブに対応していきたいと思います。

メディアクエリを作成してみる。

レスポンシブ対応するためにメディアクエリを書きたいと思います。ブレークポイントに合わせて横幅を決定したいので、まずはこのブレークポイントをマップ型変数に登録します。

/assets/sass/default.scss
/* breakpoints */
$screen-xl: 1200px;
$screen-lg: 992px;
$screen-md: 768px;
$screen-sm: 544px;
$screen-xs: 480px;
$bp-list: (
  xs: screen and
    (
      max-width: #{$screen-xs},
    ),
  sm: screen and
    (
      max-width: #{$screen-sm},
    ),
  md: screen and
    (
      max-width: #{$screen-md},
    ),
  lg: screen and
    (
      max-width: #{$screen-lg},
    ),
  xl: screen and
    (
      max-width: #{$screen-xl},
    ),
) !default;

次に@mixin でメディアクエリを呼び出す処理を追加します。

/assets/sass/default.scss
@mixin screen-mq($bp-key) {
  @media #{map-get($bp-list, $bp-key)} {
    @content;
  }
}

呼び出し方は、@include でおこないます。sm をブレークポイントに pc-menu は非表示にして sp-menu を表示するようにしています。

/assets/sass/head.scss
header {
  display: flex;
  width: 100%;
  :
  @include screen-mq(sm) {
    display: flex;
    :
    .menu {
      display: flex;
      nav {
        .pc-menu {
          display: none;
        }
        .sp-menu {
          display: flex;

ハンバーガーメニューを作成します。

スマートフォン向けにハンバーガーメニューを作成したいと思います。メニューコンポーネントにスマートフォ向けのメニューを追加して、その中でハンバーガーメニーをクリックするとメニューリストを表示するようにします。

<template>
  <nav>
    <div class="pc-menu">
      <ul class="menu-list">
        <div v-for="menu of menus" :key="menu.link">
          <li>
            <nuxt-link :to="menu.link"><fa-icon :icon="menu.icon" />{{ menu.text }} </nuxt-link>
          </li>
        </div>
      </ul>
    </div>
    <div class="sp-menu">
      <div class="hamburger">
        <div class="hamburger-line" @click="naviOpen" :class="{ 'is-active': active }">
          <span></span>
          <span></span>
          <span></span>
        </div>
      </div>
      <ul class="menu-list" v-show="navi">
        <div v-for="menu of menus" :key="menu.link">
          <li>
            <nuxt-link :to="menu.link"> <fa-icon :icon="menu.icon" />{{ menu.text }} </nuxt-link>
          </li>
        </div>
      </ul>
    </div>
  </nav>
</template>

スクリプトは、naviOpen 関数を定義します。関数を呼ばるたびにステータスを変化させています。

/components/Menu.vue
<script lang="ts">
import { defineComponent, reactive, computed } from '@nuxtjs/composition-api';
import { utility } from '@/composables/utility.ts';
type Menu = {
  link: string;
  icon: string;
  text: string;
};
export default defineComponent({
  setup() {
    const state = reactive<{
      menus: Menu[];
      active: boolean;
      navi: boolean;
    }>({
      menus: [],
      active: false,
      navi: false,
    });
    const menus = computed(() => state.menus);
    const active = computed(() => state.active);
    const navi = computed(() => state.navi);
    const { getMenu } = utility();
    state.menus = getMenu();
    function naviOpen() {
      state.active = !state.active;
      state.navi = !state.navi;
    }
    return { menus, active, navi, naviOpen };
  },
});
</script>

最後にハンバーガーメニューのスタイルを作成します。全て scss で表現しています。三本線をクリックすると上の線からから 45 度傾け、非表示、-45 度傾けて X に変化させてます。

/assets/sass/head.scss
.hamburger {
  width: 60px;
  height: 60px;
  position: fixed;
  top: 0;
  right: 0;
  .hamburger-line {
    width: 36px;
    height: 30px;
    margin-top: 15px;
    margin-left: auto;
    margin-right: auto;
    position: relative;
    cursor: pointer;
    span {
      width: 100%;
      height: 2px;
      background: $main_font_color;
      display: block;
      transition: 0.6s;
      position: absolute;
      &:first-child {
        top: 0;
      }
      &:nth-child(2) {
        top: 14px;
      }
      &:last-child {
        bottom: 0;
      }
    }
    &.is-active {
      span {
        transition: 0.6s;
        &:first-child {
          transform: rotate(45deg);
          top: 50%;
        }
        &:nth-child(2) {
          opacity: 0;
        }
        &:last-child {
          transform: rotate(-45deg);
          top: 50%;
        }
      }
    }
  }
}

ナビゲーションメニューをスマートフォン対応にできました。

hamburger menu!

最後に Google Search Console で URL 再度検査したいと思います。

hamburger menu!