jQueryでナビゲーションの開閉状態をCookieで保持する方法

コードが書かれたモニター

サイドナビやアコーディオンメニューを開いても、ページを移動したりリロードしたりすると元に戻ってしまう。これだと訪問者にとってはちょっとしたストレスです。私も自分のサイトで「開いたままにしておきたいのに」と思う場面が何度もありました。

この開閉状態は、Cookieやブラウザのストレージに保存しておけば次に来たときも維持できます。この記事では、その具体的な実装方法を紹介します。

以前はjquery.cookie(jquery.cookie.js)というプラグインが定番でしたが、これはすでに開発が終了しており、後継の js-cookie に置き換えられています。同じ作者が引き継いで開発しているライブラリで、jQueryに依存しないのが特徴です(js-cookie 公式リポジトリ)。ここでは現行のやり方に沿って、js-cookie と素のJavaScriptの両方で書いていきます。

まずはCookieかlocalStorageかを決める

ナビの開閉状態のような「そのブラウザで覚えておければ十分な情報」は、サーバーに送る必要がありません。この場合、有効期限やパスの管理が必要なCookieよりも、localStorage のほうが扱いが簡単で向いているケースが多いです。

Cookieが向いているのは、同じ値をサーバー側でも読みたいときや、有効期限を細かく決めたいときです。逆に、クライアント側だけで完結する表示状態なら localStorage で十分、と考えておくと迷いません。この記事では両方のコードを載せるので、用途で選んでください。

js-cookieの基本的な使い方

js-cookie は、JavaScriptから手軽にCookieの読み書きができるライブラリです。CDNや npm で読み込むと、グローバルに Cookies オブジェクトが使えるようになります。基本は次の3つです。

1. Cookieの保存

Cookieを保存するには Cookies.set() を使います。

Cookies.set("cookie名", "値", { expires: 7, path: "/" });

第1引数がcookie名、第2引数が保存する値です。expires は有効期限(日数)、path は適用するパスを指定します。

2. Cookieの取得

保存したCookieは Cookies.get() で取り出します。

Cookies.get("cookie名");

指定したcookie名の値が返り、存在しなければ undefined になります。

3. Cookieの削除

削除は Cookies.remove() です。

Cookies.remove("cookie名", { path: "/" });

保存したときに pathdomain を指定していた場合は、削除時にも同じ値をそろえないと消えないので注意します。

ナビゲーションの状態を維持するソースコード

では、実際にナビの開閉状態を保存するコードです。ここでは、ナビを開いた状態のときにCookieを保存し、閉じたら削除する、という動きにしています。ページを読み込んだ時点でCookieがあれば、前回の状態を復元します。

実装例(jQuery + js-cookie)

$(function () {
  if (Cookies.get("open-navbar") === "open") {
    $("#nav-bar").removeClass("show-navbar");
  }
  $("#header-toggle").on("click", function () {
    if (Cookies.get("open-navbar")) {
      Cookies.remove("open-navbar", { path: "/" });
    } else {
      Cookies.set("open-navbar", "open", { expires: 7, path: "/", sameSite: "Lax" });
    }
    return false;
  });
});

読み込み時のチェック
2行目で、Cookie「open-navbar」が「open」かどうかを確認します。保存されていれば #nav-bar から show-navbar クラスを外して、前回の状態を再現します。

クリック時の切り替え
5行目からは、#header-toggle をクリックしたときの処理です。すでにCookieがあれば削除し、なければ新しく保存します。これでクリックのたびに状態が切り替わり、次回訪問時にも引き継がれます。

もとの jquery.cookie 時代のコードから変わったのは、$.cookie()Cookies.get() / Cookies.set() に、$.removeCookie()Cookies.remove() になった点です。API名がほぼそのまま対応しているので、置き換えは難しくありません。

jQueryを使わない書き方(localStorage)

表示状態を覚えるだけなら、Cookieを使わず localStorage でも同じことができます。こちらは外部ライブラリもjQueryも不要です。

document.addEventListener("DOMContentLoaded", function () {
  var navBar = document.getElementById("nav-bar");
  var toggle = document.getElementById("header-toggle");

  if (localStorage.getItem("open-navbar") === "open") {
    navBar.classList.remove("show-navbar");
  }
  toggle.addEventListener("click", function (e) {
    e.preventDefault();
    if (localStorage.getItem("open-navbar")) {
      localStorage.removeItem("open-navbar");
    } else {
      localStorage.setItem("open-navbar", "open");
    }
  });
});

localStorage は有効期限がなく、明示的に消すまで残ります。UIの表示状態を覚える用途にはむしろ都合がよいことが多いです。ちなみに、ライブラリを入れずCookieを直接触る場合は document.cookie で読み書きできますが、文字列を自分で組み立てる必要があり手間がかかります。手軽さでいえば js-cookie か localStorage をおすすめします。

現行のCookieで気をつけたいこと

Cookieは訪問者のブラウザに保存される仕組みなので、次の点に注意します。

  1. SameSite属性:クロスサイトでCookieを送るかどうかを制御する属性です。近年のChromeやEdgeでは指定しなくても Lax が既定になっています。同一サイト内で使うだけなら sameSite: "Lax" で問題ありません。外部サイトに埋め込む用途で None にする場合は、Secure(HTTPS必須)もあわせて指定する必要があります。
  2. 有効期限expires で設定した日数を過ぎると自動で削除されます。指定しなければブラウザを閉じたときに消えるセッションCookieになります。
  3. 保存容量:Cookieは1つあたり数KB程度と小さめです。まとまったデータを持ちたいときは localStorage のほうが向いています。
  4. セキュリティ:Cookieの中身は利用者から見えます。パスワードなどの機密情報は保存しないようにします。

まとめ

ナビの開閉状態を覚えておくだけなら、js-cookie でも localStorage でも数行で実装できます。私の感覚では、サーバーとやり取りしない表示状態は localStorage、有効期限やパスを細かく管理したいときは js-cookie、と使い分けるのがシンプルでおすすめです。

もし古い jquery.cookie を今も使っているなら、この機会に js-cookie へ置き換えておくと安心です。API名がほぼ同じなので移行の負担も小さく済みます。アコーディオンやフォームの表示状態など、いろいろな場面に応用できるので試してみてください。