タブメニューは、限られたスペースで複数のコンテンツを表示することができますが、クリックしないとその中身を見ることができません。
そんな時、そのメニューを目立たせてあげると良いですが、目立たせが強過ぎてもいけないので、なかなか難しいところです。
そこでこの記事では、クリックされるまで目立たせたいタブメニューに「New」を表示して、セッションが切れるまで非表示にするスニペットについて解説していきます。
Cookieよりもライトに使える sessionStorage でUIを作ります。
是非、最後までご覧いただけたら嬉しいです。
sessionStorage
JavaScriptの sessionStorage は、設置したページのセッションが続いている間、情報を保存しておけるブラウザの保存領域です。 
JavaScriptのコードで、sessionStorageの情報を保存・取得・削除することができます。
// sessionStorage にデータを保存
sessionStorage.setItem('key', 'value');
// sessionStorage に保存したデータを取得
var data = sessionStorage.getItem('key');
// sessionStorage に保存したデータを削除
sessionStorage.removeItem('key')
詳しくは、毎度お馴染み「MDN Web Docs」がわかりやすいので、上記をご覧ください。
タブのメニューNewを非表示設定にするサンプル
早速サンプルです。3つ並んだタブのメニューの中で、初回アクセス時に「Section1-2」のみ「New」の表示があります。それ以外には「New」の表示はありません。
この「Section1-2」を1回クリックすると「New」の表示が消えて、ブラウザを閉じるまで消える設定が継続します。
Section1-1
山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな
Section1-2
山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな
Section1-3
山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな
1度クリックすると、ページを閉じるまでNewの表示は出ません。
「セッションをリセット」のボタンクリックでセッションをクリアして、「New」を再表示できます。
もう一回見たい場合はボタンをクリックしてみてください。
実装の手順と方法
コードの解説の前に、ざっくりとした実装の手順と方法について解説します。
はじめに、HTMLを設置したい場所に記述します。
<section class="someTabs" data-tabs>
  <nav class="tabs__nav">
    <a href="#" class="tabs__item active" data-tab>Section1-1</a>
    <a href="#" id="newTabHead" class="tabs__item" data-tab>Section1-2<span id="newTxt">NEW</span></a>
    <a href="#" class="tabs__item" data-tab>Section1-3</a>
  </nav>
  <div class="tabs__body">
    <div class="tabs__content active" data-tab-content><p>Section1-1</p><p>山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな</p></div>
        <div class="tabs__content" data-tab-content><p>Section1-2</p><p>山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな</p></div>
        <div class="tabs__content" data-tab-content><p>Section1-3</p><p>山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな</p></div>
  </div>
</section>
次に、JavaScriptのコードをページに記述します。
コードは <body>〜</body> で、</body> の閉じタグ(クロージングタグ)の前に記述しましょう。
// アコーディオン
const tabsElems = document.querySelectorAll("[data-tabs]");
if(tabsElems.length > 0){
  for (let i = 0; i < tabsElems.length; i++) {
  let tab = tabsElems[i];
  let tabBtnElems = tab.querySelectorAll("[data-tab]");
  let tabContentElems = tab.querySelectorAll("[data-tab-content]");
  for (let i = 0; i < tabBtnElems.length; i++) {
    let tabBtn = tabBtnElems[i];
    let tabContent = tabContentElems[i];
    tabBtn.addEventListener("click", (e) => {
      e.preventDefault();
      for (let i = 0; i < tabBtnElems.length; i++) {
       tabBtnElems[i].classList.remove('active');
       tabContentElems[i].classList.remove('active');
      }
      tabBtn.classList.add('active');
      tabContent.classList.add('active');
    });
  }
}
}
// Newの表示切り替え
document.getElementById('newTabHead').addEventListener('click', () => {
const keyName = 'tabviewed';
const keyValue = true;
if (!sessionStorage.getItem(keyName)) {
    sessionStorage.setItem(keyName, keyValue);
    console.log("初回の閲覧");
	document.getElementById("newTxt").classList.add('nonActive');
} else {
    console.log("2回目以降の閲覧");
}
});
const keyName = 'tabviewed';
const keyValue = true;
if (!sessionStorage.getItem(keyName)) {
    console.log("初回の閲覧");
} else {
	document.getElementById("newTxt").classList.add('nonActive');
}
最後に、CSSを記述します。
/* タブの表示・非表示 */
[data-tab-content]{
  display: none
}
[data-tab-content].active{
  display: block;
}
/* section同士の余白 */
section.someTabs {
    margin-bottom: 40px;
    border-bottom: solid 1px #eee;
    padding-bottom: 30px;
}
section.someTabs:last-child {
    margin: 0;
    padding: 0;
    border: none;
}
/* タブの中身のpタグの余白 */
.tabs__content p {
    margin-bottom: 10px;
}
.tabs__content p:last-child {
    margin-bottom: 0;
}
/* タブの見出し */
nav.tabs__nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    width: 100%;
    padding: 0;
    margin: 0 0 1rem;
    border: none;
    box-shadow: 0 7px 34px rgb(50 50 93 / 10%), 0 3px 6px rgb(0 0 0 / 8%);
}
nav.tabs__nav a:first-child {
    border-radius: 3px 0 0 3px;
    border-right: solid 1px #eee;
}
nav.tabs__nav a:last-child {
    border-radius: 0 3px 3px 0;
    border-left: solid 1px #eee;
}
a.tabs__item {
    display: inline-block;
    width: calc(100%/3);
    text-align: center;
    transition: all 0.2s ease;
    padding: 0;
    line-height: 50px;
    text-decoration: none;
    background: #FFF;
}
a.tabs__item.active {
    background: linear-gradient( 45deg , #bdb9ff, #67b8ff);
    color: #FFF;
}
/* 表示のアニメーション */
@keyframes fadeIn {
  0% {
    opacity: 0;
    transform: translateY(30px);
  }
  100% {
    opacity: 1;
  }
}
.tabs__content.active {
    animation: fadeIn 0.7s ease 0s 1 normal;
}
/* New */
span#newTxt {
    color: #FFF;
    font-size: 0.8rem;
    padding: 3px 12px 2px;
    line-height: 1;
    vertical-align: middle;
    margin-left: 6px;
    border-radius: 9999px;
    background: linear-gradient( 45deg , #bdb9ff, #67b8ff);
    border: solid 1px #FFF;
}
/* New非表示 */
span#newTxt.nonActive {
    display: none;
}
これで完成です。
ざっくりとしたコードの解説
コードは、HTML・JavaScript・CSSの3種です。順に解説していきます。
HTML
HTMLは、親要素を section タグで作り、その中の nav がタブの見出し。そして、tabs__body のclass名をつけた div タグで、切り替えで表示される中身を作ります。
<section class="someTabs" data-tabs>
  <nav class="tabs__nav">
    <a href="#" class="tabs__item active" data-tab>Section1-1</a>
    <a href="#" id="newTabHead" class="tabs__item" data-tab>Section1-2<span id="newTxt">NEW</span></a>
    <a href="#" class="tabs__item" data-tab>Section1-3</a>
  </nav>
  <div class="tabs__body">
    <div class="tabs__content active" data-tab-content><p>Section1-1</p><p>山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな</p></div>
        <div class="tabs__content" data-tab-content><p>Section1-2</p><p>山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな</p></div>
        <div class="tabs__content" data-tab-content><p>Section1-3</p><p>山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。山路を登りな</p></div>
  </div>
</section>
新着の「New」を出したい a タグの中に、id名「newTabHead」を付けます。そしてid名を付けた a タグの中に、<span id="newTxt">NEW</span> を記述します。
ここでつけたid名と span タグを対象に、JavaScriptのコードでclass名を操作して表示・非表示を切り替えます。
JavaScript
JavaScriptは、大きく分けて「アコーディオン」と「クリックでNewの非表示と sessionStorage の追加」「sessionStorage の有無で表示・非表示」の3種類です。
// アコーディオン
const tabsElems = document.querySelectorAll("[data-tabs]");
if(tabsElems.length > 0){
  for (let i = 0; i < tabsElems.length; i++) {
  let tab = tabsElems[i];
  let tabBtnElems = tab.querySelectorAll("[data-tab]");
  let tabContentElems = tab.querySelectorAll("[data-tab-content]");
  for (let i = 0; i < tabBtnElems.length; i++) {
    let tabBtn = tabBtnElems[i];
    let tabContent = tabContentElems[i];
    tabBtn.addEventListener("click", (e) => {
      e.preventDefault();
      for (let i = 0; i < tabBtnElems.length; i++) {
       tabBtnElems[i].classList.remove('active');
       tabContentElems[i].classList.remove('active');
      }
      tabBtn.classList.add('active');
      tabContent.classList.add('active');
    });
  }
}
}
// Newの表示切り替え
document.getElementById('newTabHead').addEventListener('click', () => {
const keyName = 'tabviewed';
const keyValue = true;
if (!sessionStorage.getItem(keyName)) {
    sessionStorage.setItem(keyName, keyValue);
    console.log("初回の閲覧");
	document.getElementById("newTxt").classList.add('nonActive');
} else {
    console.log("2回目以降の閲覧");
}
});
const keyName = 'tabviewed';
const keyValue = true;
if (!sessionStorage.getItem(keyName)) {
    console.log("初回の閲覧");
} else {
	document.getElementById("newTxt").classList.add('nonActive');
}
後半の sessionStorage で、keyNameがある場合とない場合で if で条件分岐して動作を分けます。
CSS
CSSは、HTMLで記述するアコーディオンの見た目を整える内容がほとんどで、「New」の span タグは「.nonActive」のclassを付け替えて表示・非表示を切り替えます。
/* タブの表示・非表示 */
[data-tab-content]{
  display: none
}
[data-tab-content].active{
  display: block;
}
/* section同士の余白 */
section.someTabs {
    margin-bottom: 40px;
    border-bottom: solid 1px #eee;
    padding-bottom: 30px;
}
section.someTabs:last-child {
    margin: 0;
    padding: 0;
    border: none;
}
/* タブの中身のpタグの余白 */
.tabs__content p {
    margin-bottom: 10px;
}
.tabs__content p:last-child {
    margin-bottom: 0;
}
/* タブの見出し */
nav.tabs__nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    width: 100%;
    padding: 0;
    margin: 0 0 1rem;
    border: none;
    box-shadow: 0 7px 34px rgb(50 50 93 / 10%), 0 3px 6px rgb(0 0 0 / 8%);
}
nav.tabs__nav a:first-child {
    border-radius: 3px 0 0 3px;
    border-right: solid 1px #eee;
}
nav.tabs__nav a:last-child {
    border-radius: 0 3px 3px 0;
    border-left: solid 1px #eee;
}
a.tabs__item {
    display: inline-block;
    width: calc(100%/3);
    text-align: center;
    transition: all 0.2s ease;
    padding: 0;
    line-height: 50px;
    text-decoration: none;
    background: #FFF;
}
a.tabs__item.active {
    background: linear-gradient( 45deg , #bdb9ff, #67b8ff);
    color: #FFF;
}
/* 表示のアニメーション */
@keyframes fadeIn {
  0% {
    opacity: 0;
    transform: translateY(30px);
  }
  100% {
    opacity: 1;
  }
}
.tabs__content.active {
    animation: fadeIn 0.7s ease 0s 1 normal;
}
/* New */
span#newTxt {
    color: #FFF;
    font-size: 0.8rem;
    padding: 3px 12px 2px;
    line-height: 1;
    vertical-align: middle;
    margin-left: 6px;
    border-radius: 9999px;
    background: linear-gradient( 45deg , #bdb9ff, #67b8ff);
    border: solid 1px #FFF;
}
/* New非表示 */
span#newTxt.nonActive {
    display: none;
}
さいごに
このようにタブメニューの表示を切り替えることができますが、見せたいコンテンツは予め開いておいたりと色んな表現方法があるので、是非参考にしてみてください。
					
