【JavaScript】特定の日時を過ぎたら要素を非表示にする方法|期間内表示・data属性で一括管理・タイムゾーン対応・完成形クラスまで解説

「セール終了後にバナーを自動で消したい」「キャンペーン期間中だけお知らせを表示したい」「公開日を過ぎたら告知ブロックを非表示にしたい」——特定の日時を基準に要素の表示を切り替えるニーズは多くあります。

この記事では new Date() を使った日時比較の基本から、表示開始・終了の期間管理、複数要素への一括適用、タイムゾーン対応、CSS トランジションを使ったスムーズな切り替えまで体系的に解説します。

スポンサーリンク

特定の日時を過ぎたら非表示にする基本実装

new Date() で現在の日時を取得し、目標日時と比較します。JavaScriptの Date オブジェクト同士は > / < で大小比較できます。

基本:期限を過ぎたら非表示
// 非表示にしたい期限(日本時間で指定)
const EXPIRE_DATE = new Date('2026-06-30T23:59:59+09:00');

const banner = document.getElementById('campaign-banner');

if (new Date() > EXPIRE_DATE) {
  // 期限切れ → 非表示
  banner.hidden = true;
} else {
  // 期限内 → 表示
  banner.hidden = false;
}
hidden 属性 vs display: none
el.hidden = truedisplay: none と同じ効果で、スクリーンリーダーにも読まれなくなります。アクセシビリティの観点では hidden 属性が推奨されます。CSSで hidden 属性を上書きしている場合は el.style.display = "none" を使うか、CSSの [hidden] { display: none !important; } を確認してください。

HTMLに最初から hidden を付けておき、期限内のときだけ表示する書き方の方がより安全です(JavaScriptが無効でも非表示のままになるため)。

HTML(初期状態は hidden)
<!-- hidden 属性を最初から付けておく(JSが無効でも表示されない) -->
<div id="campaign-banner" hidden>
  <p>夏のビッグセール開催中!</p>
</div>
期限内のときだけ表示する(より安全な書き方)
const EXPIRE_DATE = new Date('2026-06-30T23:59:59+09:00');
const banner = document.getElementById('campaign-banner');

// 期限内なら表示(hidden を外す)
if (new Date() <= EXPIRE_DATE) {
  banner.hidden = false;
}
// 期限切れのときは何もしない(hidden のまま)

表示開始日時と終了日時の両方を管理する

「○月○日から○月○日まで表示する」という期間管理は、開始日時と終了日時の両方と現在時刻を比較するだけで実現できます。

期間内だけ表示する(開始・終了の両方を管理)
const START_DATE  = new Date('2026-07-01T00:00:00+09:00'); // 表示開始
const EXPIRE_DATE = new Date('2026-08-31T23:59:59+09:00'); // 表示終了

/**
 * 要素を期間に応じて表示/非表示にする
 * @param {Element} el         - 対象要素
 * @param {Date}    start      - 表示開始日時
 * @param {Date}    end        - 表示終了日時
 */
function applySchedule(el, start, end) {
  const now = new Date();
  const isActive = now >= start && now <= end;
  el.hidden = !isActive;
}

applySchedule(
  document.getElementById('summer-campaign'),
  START_DATE,
  EXPIRE_DATE,
);
条件 現在時刻 表示状態
表示前 now < start 非表示
期間内 start <= now <= end 表示
期限切れ now > end 非表示

タイムゾーン対応:日本時間で期限を確実に指定する

サーバーやユーザーの端末のタイムゾーンに関わらず「日本時間の○月○日23:59」を正確に判定するには、ISO 8601 形式でオフセットを明示することが重要です。

タイムゾーンの落とし穴と正しい書き方
// NG: タイムゾーン不明(実行環境のローカル時刻として解釈される)
const bad1 = new Date('2026-08-31 23:59:59'); // 環境依存

// NG: 日付のみの形式はUTC 00:00:00 として解釈される(JST = UTC+9 なので9時間ずれる)
const bad2 = new Date('2026-08-31'); // UTC 0:00 = JST 9:00 になる

// OK: +09:00 を明示することで日本標準時と確定する
const good = new Date('2026-08-31T23:59:59+09:00');

// OK: UTC で指定(JST 23:59 = UTC 14:59)
const utc  = new Date('2026-08-31T14:59:59Z');

console.log(good.getTime() === utc.getTime()); // true(同じ瞬間)
new Date(“2026-08-31”) が日本時間の午前9時になる理由:
ECMAScript の仕様では、日付のみの形式(YYYY-MM-DD)は UTC の 00:00:00 として解釈されます。日本(UTC+9)からアクセスすると 9時間進んだ JST の 9:00 が「2026-08-31の開始時刻」になります。意図した時刻を正確に指定するには T00:00:00+09:00 のように時刻とオフセットを必ず付けてください。

data属性でHTMLに期限を書いて一括管理する

複数の要素にそれぞれ異なる期限がある場合、JavaScript側に個別に書くより、HTML側の data 属性に期限を持たせて一括処理する方法が管理しやすくなります。

HTML(data属性に開始・終了日時を書く)
<!-- data-show-from / data-show-until に ISO 8601 形式で日時を書く -->
<div class="scheduled"
     data-show-from="2026-07-01T00:00:00+09:00"
     data-show-until="2026-08-31T23:59:59+09:00">
  夏のキャンペーンバナー
</div>

<div class="scheduled"
     data-show-until="2026-09-30T23:59:59+09:00">
  秋の新作フェア(開始日時なし=即時表示)
</div>

<div class="scheduled"
     data-show-from="2026-10-01T00:00:00+09:00">
  冬の予告(終了日時なし=無期限表示)
</div>
data属性を読み取って全要素を一括処理
function applyAllSchedules() {
  const now = new Date();

  document.querySelectorAll('.scheduled').forEach(el => {
    const fromStr  = el.dataset.showFrom;
    const untilStr = el.dataset.showUntil;

    const from  = fromStr  ? new Date(fromStr)  : null;
    const until = untilStr ? new Date(untilStr) : null;

    const afterStart  = !from  || now >= from;   // 開始日時前でなければOK
    const beforeEnd   = !until || now <= until;  // 終了日時後でなければOK

    el.hidden = !(afterStart && beforeEnd);
  });
}

// ページ読み込み時に即時実行
applyAllSchedules();
この方法のメリット:

  • HTMLを見るだけで各要素の公開期間がわかる
  • JavaScriptを触らずにCMS(WordPressなど)のエディタから期限を管理できる
  • 新しい要素を追加するときも class="scheduled"data 属性を付けるだけ
  • data-show-from のみ(開始なし)・data-show-until のみ(終了なし)どちらも対応可能

setInterval で定期チェックする(長時間ページを開いている場合)

ページを読み込んだ時点では期限内でも、同じページを数時間開き続けると期限切れになる場合があります。setInterval で定期チェックすることで、リロードなしに表示を切り替えられます。

setInterval で1分おきに再チェック
// ページ読み込み時に即時実行
applyAllSchedules();

// その後は1分ごとに再チェック(ミリ秒単位: 60 * 1000 = 60000)
const intervalId = setInterval(() => {
  applyAllSchedules();

  // 全要素が期限切れになったらタイマーを止める
  const hasActive = [...document.querySelectorAll('.scheduled')]
    .some(el => !el.hidden);
  if (!hasActive) {
    clearInterval(intervalId);
  }
}, 60_000); // 1分おき
チェック間隔をどう設定するか:
毎秒チェックする必要はほとんどありません。「セールが終わる可能性がある」タイミングに合わせた間隔で十分です。1分おきならユーザー体験を損なわず、CPUへの負荷も最小です。ページが非アクティブなときは visibilitychange と組み合わせてタイマーを一時停止するとさらに効率的です。

CSSトランジションでスムーズに表示・非表示を切り替える

突然消えるのではなくフェードアウトで消したい場合、hidden 属性だけでは使えません。opacitytransition を組み合わせます。

CSSトランジションで非表示にする
.scheduled {
  transition: opacity 0.5s ease;
}

.scheduled.is-hidden {
  opacity: 0;
  pointer-events: none;  /* クリックも無効化 */
}

/* 完全に非表示にするときは transition 終了後に hidden を付ける */
トランジション付きの非表示処理
/**
 * フェードアウトして非表示にする
 * @param {Element} el
 * @param {number}  durationMs - トランジション時間(CSS と合わせる)
 */
function fadeHide(el, durationMs = 500) {
  el.classList.add('is-hidden');
  // トランジション完了後に hidden 属性を付ける
  setTimeout(() => {
    el.hidden = true;
    el.classList.remove('is-hidden'); // 次回表示時のために除去
  }, durationMs);
}

// 使用例
const EXPIRE_DATE = new Date('2026-06-30T23:59:59+09:00');
const banner = document.getElementById('campaign-banner');

if (new Date() > EXPIRE_DATE) {
  fadeHide(banner);
}

完成形:ScheduledDisplay クラス

これまでの実装をまとめた汎用クラスです。data属性での期間管理・定期チェック・フェード対応を含みます。

ScheduledDisplay クラス
class ScheduledDisplay {
  #intervalId = null;
  #selector;
  #checkIntervalMs;

  /**
   * @param {string} selector        - 対象要素のCSSセレクタ
   * @param {number} checkIntervalMs - 定期チェックの間隔(ms)。0で無効
   */
  constructor(selector = '.scheduled', checkIntervalMs = 60_000) {
    this.#selector = selector;
    this.#checkIntervalMs = checkIntervalMs;

    this.#apply();

    if (checkIntervalMs > 0) {
      this.#startInterval();
      document.addEventListener('visibilitychange', () => {
        if (document.hidden) {
          this.#stopInterval();
        } else {
          this.#apply();
          this.#startInterval();
        }
      });
    }
  }

  #apply() {
    const now = new Date();
    document.querySelectorAll(this.#selector).forEach(el => {
      const from  = el.dataset.showFrom  ? new Date(el.dataset.showFrom)  : null;
      const until = el.dataset.showUntil ? new Date(el.dataset.showUntil) : null;
      const active = (!from || now >= from) && (!until || now <= until);
      el.hidden = !active;
    });
  }

  #startInterval() {
    if (this.#intervalId) return;
    this.#intervalId = setInterval(() => this.#apply(), this.#checkIntervalMs);
  }

  #stopInterval() {
    clearInterval(this.#intervalId);
    this.#intervalId = null;
  }

  /** タイマーを破棄する */
  destroy() {
    this.#stopInterval();
  }
}

// 使用例
document.addEventListener('DOMContentLoaded', () => {
  new ScheduledDisplay('.scheduled', 60_000); // 1分おきに再チェック
});

よくある質問(FAQ)

Qユーザーが端末の時計を変更して期限切れを回避できませんか?
A回避できます。フロントエンドの日時判定は常にユーザーの端末時刻に依存するため、厳密な期限管理はサーバーサイドで行う必要があります。UIの非表示切り替えはあくまで視覚的な演出として使い、重要なビジネスロジック(購入可否・ダウンロード権限など)はAPIやサーバーで判定してください。
Qhidden 属性と display: none のどちらを使えばいいですか?
Aアクセシビリティの観点では hidden 属性が推奨されます。スクリーンリーダーにも読まれなくなり、DOMからも意味的に除外されます。ただし、CSSで [hidden] { display: block !important; } のような上書きをしているテーマやライブラリがある場合は style.display = "none" の方が確実です。
QJavaScriptが無効の環境ではどうなりますか?
Aこの記事の「期限内なら hidden を外す」アプローチでは、HTMLに最初から hidden を付けておくことでJavaScriptが無効でも要素が非表示になります。セキュリティ上重要な非表示(管理者限定コンテンツなど)はサーバーサイドで出力制御してください。
QReact や Vue では同じ方法を使えますか?
AReactなら const isActive = new Date() <= expireDate; を状態として持ち {isActive && <Banner />} で条件レンダリングします。定期チェックには useEffect 内で setInterval を使い、クリーンアップ関数で clearInterval を呼びます。Vue 3 なら ref + watchEffect で同様に実装できます。
QWordPressでCMSから期限を管理する方法はありますか?
Aカスタムフィールドに期限日時を設定し、PHPテンプレートで data-show-until="" のように出力する方法が一般的です。この記事の ScheduledDisplay クラスと組み合わせることで、管理画面から期限を設定してJavaScriptで自動制御できます。

まとめ

要件 実装ポイント
期限切れで非表示 new Date() > expireDate で比較、el.hidden = true
期間内だけ表示 開始と終了の両方を比較(now >= from && now <= until
日本時間で期限指定 +09:00 オフセット付きISO 8601 形式
複数要素を一括管理 data-show-from / data-show-until 属性 + querySelectorAll
長時間閲覧への対応 setInterval で1分おきに再チェック
スムーズな切り替え CSS opacity + transition でフェードアウト後に hidden

日付の計算(日時の足し算・引き算)はJavaScriptで日時の計算をマスターしようを、セール終了までのカウントダウン表示を組み合わせたい場合はカウントダウンタイマーの作り方もあわせて参照してください。