見せ方・演出

ヒーロー・ビフォーアフター・スライダーなど、見栄えを高めるパーツ

ヒーローセクション

背景画像に暗めのオーバーレイとキャッチコピー・CTAボタンを重ねた、トップページ向けのヒーローセクションです。

コード・使い方を見る
<div class="hs-hero">
  <div class="hs-media">
    <img class="hs-img" src="https://placehold.co/1600x700/2f8f9d/ffffff?text=Minato+General+Clinic" alt="みなと総合クリニックの外観" loading="lazy">
    <div class="hs-overlay-layer"></div>
  </div>
  <div class="hs-content">
    <p class="hs-eyebrow">みなと総合クリニック</p>
    <h1 class="hs-catch">地域のかかりつけ医として、<br class="hs-br">ていねいな診療を。</h1>
    <p class="hs-lead">東京都港区0-0-0 / 03-0000-0000</p>
    <a class="hs-cta" href="#reserve">診療予約はこちら</a>
  </div>
</div>
.hs-hero {
  --hs-overlay: 0.45;      /* 背景画像に重ねる暗さ(0〜1、大きいほど暗い) */
  --hs-accent: #2f8f9d;    /* CTAボタンの色(医院のテーマ色に変更してください) */
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 480px;
  overflow: hidden;
  border-radius: 14px;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  text-align: center;
  color: #fff;
}
.hs-media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hs-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hs-overlay-layer {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, var(--hs-overlay));
}
.hs-content {
  position: relative;
  z-index: 1;
  padding: 3rem 1.5rem;
  max-width: 640px;
}
.hs-eyebrow {
  margin: 0 0 .8rem;
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .18em;
  color: #fff;
  opacity: .9;
}
.hs-catch {
  margin: 0 0 1rem;
  font-size: 1.9rem;
  font-weight: 800;
  line-height: 1.5;
  letter-spacing: .03em;
  text-shadow: 0 2px 10px rgba(0, 0, 0, .35);
}
.hs-lead {
  margin: 0 0 1.8rem;
  font-size: .9rem;
  opacity: .92;
  letter-spacing: .04em;
}
.hs-cta {
  display: inline-block;
  background: var(--hs-accent);
  color: #fff;
  font-weight: 700;
  font-size: .95rem;
  padding: .9em 2.4em;
  border-radius: 999px;
  text-decoration: none;
  letter-spacing: .05em;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .25);
  transition: transform .15s, box-shadow .15s, opacity .15s;
}
.hs-cta:hover,
.hs-cta:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 10px 22px rgba(0, 0, 0, .3);
  opacity: .95;
  outline: none;
}
@media (max-width: 480px) {
  .hs-hero { min-height: 380px; border-radius: 10px; }
  .hs-content { padding: 2rem 1.2rem; }
  .hs-catch { font-size: 1.4rem; }
  .hs-lead { font-size: .8rem; }
  .hs-cta { font-size: .88rem; padding: .8em 2em; }
}

ビフォーアフター比較スライダー

スライダーを左右にドラッグして、施術前後や院内リニューアル前後の2枚の画像を比較できます。

コード・使い方を見る
<div class="ba-wrap">
  <p class="ba-title">院内リニューアル ビフォー・アフター</p>
  <div class="ba-slider">
    <div class="ba-frame">
      <img class="ba-img ba-img-before" src="https://placehold.co/800x500/cccccc/999999?text=Before" alt="リニューアル前の院内の様子">
      <img class="ba-img ba-img-after" src="https://placehold.co/800x500/2f8f9d/ffffff?text=After" alt="リニューアル後の院内の様子">
      <div class="ba-handle" aria-hidden="true">
        <span class="ba-handle-line"></span>
        <span class="ba-handle-grip">
          <svg viewBox="0 0 24 24" width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 6L2 12L8 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 6L22 12L16 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
        </span>
      </div>
      <span class="ba-label ba-label-before">Before</span>
      <span class="ba-label ba-label-after">After</span>
      <!-- 画像の上に透明な range を重ね、画像上を直接ドラッグして境界移動できるようにする -->
      <input class="ba-range" type="range" min="0" max="100" value="50" aria-label="ビフォー・アフターの比較位置">
    </div>
  </div>
</div>
.ba-wrap {
  --ba-accent: #2f8f9d;  /* ハンドル・ラベルのアクセントカラー(医院のテーマ色に変更してください) */
  --ba-position: 50%;    /* 初期の比較位置(0%〜100%) */
  max-width: 800px;
  margin: 0 auto;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
}
.ba-title {
  margin: 0 0 1rem;
  font-size: 1.05rem;
  font-weight: 700;
  color: #1f2937;
  text-align: center;
  letter-spacing: .04em;
}
.ba-slider {
  display: flex;
  flex-direction: column;
}
.ba-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 8 / 5;
  overflow: hidden;
  border-radius: 12px;
  box-shadow: 0 2px 14px rgba(0, 0, 0, .1);
  background: #eee;
  user-select: none;
}
/* input[type=range] を画像の上に透明に重ね、画像上を直接ドラッグして境界移動できるようにする */
.ba-frame:has(.ba-range:focus-visible) {
  outline: 2px solid var(--ba-accent);
  outline-offset: 2px;
}
.ba-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
.ba-img-before {
  position: absolute;
  inset: 0;
}
.ba-img-after {
  position: absolute;
  inset: 0;
  /* clip-path でフレーム幅に対する比較位置までを表示する(レイヤー分割より確実に等倍を保てる) */
  clip-path: inset(0 calc(100% - var(--ba-position, 50%)) 0 0);
}
.ba-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--ba-position, 50%);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.ba-handle-line {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  background: #fff;
  box-shadow: 0 0 6px rgba(0, 0, 0, .3);
  transform: translateX(-50%);
}
.ba-handle-grip {
  position: relative;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: #fff;
  color: var(--ba-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .3);
}
.ba-label {
  position: absolute;
  top: .7rem;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .06em;
  padding: .3em .8em;
  border-radius: 999px;
  pointer-events: none;
}
.ba-label-before { left: .7rem; }
.ba-label-after { right: .7rem; }
/* 画像フレームいっぱいに重ねる透明な range。ネイティブのつまみ・トラックは非表示にし、
   代わりに装飾用の .ba-handle を --ba-position に追従させて表示する。
   つまみは「縦いっぱい・幅40px」— トラックのクリックはネイティブのジャンプ動作が
   効くので、画像上のどこをクリック/タップしてもその位置まで境界が移動する */
.ba-range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  appearance: none;
  background: transparent;
  cursor: ew-resize;
  margin: 0;
  opacity: 0;
  touch-action: pan-y; /* 縦スワイプはページスクロールに渡す */
}
.ba-range::-webkit-slider-runnable-track {
  width: 100%;
  height: 100%;
  background: transparent;
}
.ba-range::-webkit-slider-thumb {
  appearance: none;
  width: 40px;
  height: 100%;
  background: transparent;
  border: none;
  box-shadow: none;
  cursor: ew-resize;
}
.ba-range::-moz-range-track {
  width: 100%;
  height: 100%;
  background: transparent;
  border: none;
}
.ba-range::-moz-range-thumb {
  width: 40px;
  height: 100%;
  background: transparent;
  border: none;
  box-shadow: none;
  cursor: ew-resize;
}
/* :has() 未対応ブラウザ向けフォールバック(focus-visible 時に range 自体へ枠線) */
.ba-range:focus-visible {
  opacity: 1;
  outline: 2px solid var(--ba-accent);
  outline-offset: -2px;
  background: rgba(255, 255, 255, .01);
}
@media (max-width: 480px) {
  .ba-title { font-size: .95rem; }
  .ba-label { font-size: .66rem; padding: .25em .65em; }
  .ba-handle-grip { width: 30px; height: 30px; }
}
(function () {
  var SELECTOR = '.ba-wrap';

  function setPosition(wrap, value) {
    wrap.style.setProperty('--ba-position', value + '%');
  }

  function init(wrap) {
    var range = wrap.querySelector('.ba-range');
    if (!range) return;
    setPosition(wrap, range.value);
    range.addEventListener('input', function () {
      setPosition(wrap, range.value);
    });
  }

  document.querySelectorAll(SELECTOR).forEach(init);
})();

数値カウントアップ

画面にスクロールで入ったタイミングで、0から目標の数字までカウントアップして見せる実績表示です。

コード・使い方を見る
<div class="cu-wrap">
  <p class="cu-heading">数字で見る、みなと総合クリニック</p>
  <ul class="cu-grid">
    <li class="cu-item">
      <p class="cu-num"><span class="cu-value" data-target="48000">0</span><span class="cu-unit">人</span></p>
      <p class="cu-label">累計患者数</p>
    </li>
    <li class="cu-item">
      <p class="cu-num"><span class="cu-value" data-target="15">0</span><span class="cu-unit">年</span></p>
      <p class="cu-label">開院からの実績</p>
    </li>
    <li class="cu-item">
      <p class="cu-num"><span class="cu-value" data-target="4">0</span><span class="cu-unit">名</span></p>
      <p class="cu-label">在籍医師数</p>
    </li>
  </ul>
</div>
.cu-wrap {
  --cu-accent: #2f8f9d; /* 数字・見出しのアクセントカラー(医院のテーマ色に変更してください) */
  max-width: 960px;
  margin: 0 auto;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  text-align: center;
}
.cu-heading {
  margin: 0 0 1.8rem;
  font-size: 1.15rem;
  font-weight: 700;
  color: #1f2937;
  letter-spacing: .06em;
}
.cu-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.cu-item {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 14px;
  padding: 1.8rem 1rem;
  box-shadow: 0 2px 12px rgba(0, 0, 0, .05);
}
.cu-num {
  margin: 0 0 .5rem;
  display: flex;
  align-items: baseline;
  justify-content: center;
  flex-wrap: wrap;
  gap: .2em;
}
.cu-value {
  font-size: 2.3rem;
  font-weight: 800;
  color: var(--cu-accent);
  line-height: 1;
  font-feature-settings: "tnum";
}
.cu-unit {
  font-size: 1rem;
  font-weight: 600;
  color: var(--cu-accent);
}
.cu-label {
  margin: 0;
  font-size: .82rem;
  color: #6b7280;
  letter-spacing: .02em;
}
@media (max-width: 640px) {
  .cu-grid { grid-template-columns: repeat(3, 1fr); gap: .6rem; }
  .cu-item { padding: 1.1rem .4rem; }
  .cu-value { font-size: 1.3rem; }
  .cu-unit { font-size: .72rem; }
  .cu-label { font-size: .68rem; }
}
@media (max-width: 360px) {
  .cu-value { font-size: 1.1rem; }
}
(function () {
  var VALUE_SELECTOR = '.cu-value';
  var DURATION = 1500; // カウントアップにかける時間(ミリ秒)
  var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  function formatNumber(n) {
    return Math.round(n).toLocaleString('ja-JP');
  }

  function animate(el, target) {
    if (reduceMotion) {
      el.textContent = formatNumber(target);
      return;
    }
    var start = performance.now();
    function step(now) {
      var progress = Math.min((now - start) / DURATION, 1);
      var eased = 1 - Math.pow(1 - progress, 3); // easeOutCubic
      el.textContent = formatNumber(target * eased);
      if (progress < 1) {
        requestAnimationFrame(step);
      } else {
        el.textContent = formatNumber(target);
      }
    }
    requestAnimationFrame(step);
  }

  var elements = document.querySelectorAll(VALUE_SELECTOR);
  if (!elements.length) return;

  if (!('IntersectionObserver' in window)) {
    elements.forEach(function (el) {
      animate(el, Number(el.getAttribute('data-target')) || 0);
    });
    return;
  }

  var observer = new IntersectionObserver(
    function (entries) {
      entries.forEach(function (entry) {
        if (!entry.isIntersecting) return;
        var el = entry.target;
        var target = Number(el.getAttribute('data-target')) || 0;
        animate(el, target);
        observer.unobserve(el);
      });
    },
    { threshold: 0.4 }
  );

  elements.forEach(function (el) {
    observer.observe(el);
  });
})();

画像スライダー

前後ボタンとドットで切り替えられる、自動再生付きのシンプルな画像カルーセルです。

コード・使い方を見る
<div class="ss-slider">
  <div class="ss-viewport">
    <ul class="ss-track">
      <li class="ss-slide">
        <img class="ss-img" src="https://placehold.co/1000x500/2f8f9d/ffffff?text=Slide+1" alt="待合室の様子">
      </li>
      <li class="ss-slide">
        <img class="ss-img" src="https://placehold.co/1000x500/6b7280/ffffff?text=Slide+2" alt="診察室の様子">
      </li>
      <li class="ss-slide">
        <img class="ss-img" src="https://placehold.co/1000x500/cccccc/666666?text=Slide+3" alt="受付の様子">
      </li>
    </ul>
  </div>
  <button type="button" class="ss-btn ss-btn-prev" aria-label="前のスライドを表示">
    <svg viewBox="0 0 24 24" width="20" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 6L9 12L15 18" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
  </button>
  <button type="button" class="ss-btn ss-btn-next" aria-label="次のスライドを表示">
    <svg viewBox="0 0 24 24" width="20" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 6L15 12L9 18" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
  </button>
  <div class="ss-dots" role="tablist" aria-label="スライド切り替え">
    <button type="button" class="ss-dot" role="tab" aria-label="1枚目を表示" aria-selected="true"></button>
    <button type="button" class="ss-dot" role="tab" aria-label="2枚目を表示" aria-selected="false"></button>
    <button type="button" class="ss-dot" role="tab" aria-label="3枚目を表示" aria-selected="false"></button>
  </div>
</div>
.ss-slider {
  --ss-accent: #2f8f9d; /* 矢印ボタン・ドットのアクセントカラー(医院のテーマ色に変更してください) */
  position: relative;
  max-width: 800px;
  margin: 0 auto;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
}
.ss-viewport {
  overflow: hidden;
  border-radius: 14px;
  box-shadow: 0 2px 14px rgba(0, 0, 0, .1);
}
.ss-track {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  will-change: transform;
  transition: transform .5s ease;
}
.ss-slide {
  flex: 0 0 100%;
  aspect-ratio: 2 / 1;
}
.ss-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ss-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, .9);
  color: var(--ss-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
  transition: background-color .15s, transform .15s;
}
.ss-btn:hover,
.ss-btn:focus-visible {
  background: #fff;
  transform: translateY(-50%) scale(1.06);
  outline: none;
}
.ss-btn-prev { left: .7rem; }
.ss-btn-next { right: .7rem; }
.ss-dots {
  display: flex;
  justify-content: center;
  gap: .5rem;
  margin-top: .9rem;
}
.ss-dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: #d1d5db;
  cursor: pointer;
  transition: background-color .15s, transform .15s;
}
.ss-dot[aria-selected="true"] {
  background: var(--ss-accent);
  transform: scale(1.2);
}
.ss-dot:focus-visible {
  outline: 2px solid var(--ss-accent);
  outline-offset: 2px;
}
@media (max-width: 480px) {
  .ss-btn { width: 34px; height: 34px; }
  .ss-btn-prev { left: .4rem; }
  .ss-btn-next { right: .4rem; }
  .ss-dots { margin-top: .7rem; }
}
(function () {
  var AUTOPLAY_MS = 5000;
  var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  function SimpleSlider(root) {
    this.root = root;
    this.track = root.querySelector('.ss-track');
    this.slides = Array.prototype.slice.call(root.querySelectorAll('.ss-slide'));
    this.dots = Array.prototype.slice.call(root.querySelectorAll('.ss-dot'));
    this.prevBtn = root.querySelector('.ss-btn-prev');
    this.nextBtn = root.querySelector('.ss-btn-next');
    this.index = 0;
    this.timer = null;

    if (!this.track || this.slides.length === 0) return;

    this.bindEvents();
    this.render();
    this.startAutoplay();
  }

  SimpleSlider.prototype.render = function () {
    this.track.style.transform = 'translateX(-' + this.index * 100 + '%)';
    this.dots.forEach(function (dot, i) {
      dot.setAttribute('aria-selected', String(i === this.index));
    }, this);
  };

  SimpleSlider.prototype.goTo = function (index) {
    var count = this.slides.length;
    this.index = (index + count) % count;
    this.render();
  };

  SimpleSlider.prototype.next = function () {
    this.goTo(this.index + 1);
  };

  SimpleSlider.prototype.prev = function () {
    this.goTo(this.index - 1);
  };

  SimpleSlider.prototype.startAutoplay = function () {
    if (reduceMotion) return;
    var self = this;
    this.stopAutoplay();
    this.timer = window.setInterval(function () {
      self.next();
    }, AUTOPLAY_MS);
  };

  SimpleSlider.prototype.stopAutoplay = function () {
    if (this.timer) {
      window.clearInterval(this.timer);
      this.timer = null;
    }
  };

  SimpleSlider.prototype.bindEvents = function () {
    var self = this;

    if (this.nextBtn) {
      this.nextBtn.addEventListener('click', function () {
        self.next();
        self.startAutoplay();
      });
    }
    if (this.prevBtn) {
      this.prevBtn.addEventListener('click', function () {
        self.prev();
        self.startAutoplay();
      });
    }
    this.dots.forEach(function (dot, i) {
      dot.addEventListener('click', function () {
        self.goTo(i);
        self.startAutoplay();
      });
    });

    this.root.addEventListener('mouseenter', function () {
      self.stopAutoplay();
    });
    this.root.addEventListener('mouseleave', function () {
      self.startAutoplay();
    });

    this.root.setAttribute('tabindex', this.root.getAttribute('tabindex') || '0');
    this.root.addEventListener('keydown', function (e) {
      if (e.key === 'ArrowLeft') {
        e.preventDefault();
        self.prev();
        self.startAutoplay();
      } else if (e.key === 'ArrowRight') {
        e.preventDefault();
        self.next();
        self.startAutoplay();
      }
    });
  };

  document.querySelectorAll('.ss-slider').forEach(function (root) {
    new SimpleSlider(root);
  });
})();

スクロール表示アニメーション

スクロールして画面に入った要素が、ふわっとフェードイン+スライドアップして表示されます。

コード・使い方を見る
<div class="sr-demo">
  <div class="sr-item sr-card">
    <p class="sr-card-title">ていねいな問診</p>
    <p class="sr-card-text">お一人お一人のお話をしっかり伺い、納得いただける診療を心がけています。</p>
  </div>
  <div class="sr-item sr-card">
    <p class="sr-card-title">最新の設備</p>
    <p class="sr-card-text">検査機器を随時更新し、正確でスピーディーな検査をご提供します。</p>
  </div>
  <div class="sr-item sr-card">
    <p class="sr-card-title">地域との連携</p>
    <p class="sr-card-text">近隣の病院・薬局と連携し、切れ目のない医療をお届けします。</p>
  </div>
</div>
.sr-item {
  --sr-distance: 24px;  /* スライドインする距離 */
  --sr-duration: .7s;   /* アニメーションの長さ */
  opacity: 0;
  transform: translateY(var(--sr-distance));
  transition: opacity var(--sr-duration) ease, transform var(--sr-duration) ease;
}
.sr-item.sr-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .sr-item {
    transition: none;
  }
}

/* ここから下はデモ表示用のスタイルです(実際に貼り付ける際は不要であれば削除して構いません) */
.sr-demo {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.2rem;
  max-width: 960px;
  margin: 0 auto;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
}
.sr-card {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 14px;
  padding: 1.6rem 1.3rem;
  box-shadow: 0 2px 12px rgba(0, 0, 0, .05);
}
.sr-card-title {
  margin: 0 0 .6rem;
  font-size: 1rem;
  font-weight: 700;
  color: #2f8f9d;
}
.sr-card-text {
  margin: 0;
  font-size: .85rem;
  line-height: 1.8;
  color: #4b5563;
}
@media (max-width: 640px) {
  .sr-demo { grid-template-columns: 1fr; gap: .9rem; }
}
(function () {
  var ITEM_SELECTOR = '.sr-item';
  var VISIBLE_CLASS = 'sr-visible';
  var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  var items = document.querySelectorAll(ITEM_SELECTOR);
  if (!items.length) return;

  if (reduceMotion || !('IntersectionObserver' in window)) {
    items.forEach(function (el) {
      el.classList.add(VISIBLE_CLASS);
    });
    return;
  }

  var observer = new IntersectionObserver(
    function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add(VISIBLE_CLASS);
          observer.unobserve(entry.target);
        }
      });
    },
    { threshold: 0.15 }
  );

  items.forEach(function (el) {
    observer.observe(el);
  });
})();

特徴3カラムカード

アイコン・見出し・説明文をカード形式で並べる、医院の特徴紹介パーツです。カードにマウスを乗せるとふわっと浮き上がります。

コード・使い方を見る
<div class="ic-wrap">
  <h3 class="ic-title">みなと総合クリニックの特徴</h3>
  <ul class="ic-grid">
    <li class="ic-card">
      <span class="ic-icon" aria-hidden="true">🗓️</span>
      <p class="ic-heading">土曜も診療</p>
      <p class="ic-desc">平日お忙しい方でも通いやすいよう、土曜日も診療を行っています。</p>
    </li>
    <li class="ic-card">
      <span class="ic-icon" aria-hidden="true">🖥️</span>
      <p class="ic-heading">WEB予約対応</p>
      <p class="ic-desc">24時間いつでもスマホやパソコンから診療予約ができます。</p>
    </li>
    <li class="ic-card">
      <span class="ic-icon" aria-hidden="true">🚉</span>
      <p class="ic-heading">駅近3分</p>
      <p class="ic-desc">最寄駅から徒歩3分の好立地で、通院の負担を軽減します。</p>
    </li>
  </ul>
</div>
.ic-wrap {
  --ic-accent: #2f8f9d; /* アイコンの色(医院のテーマ色に変更してください) */
  --ic-columns: 3;      /* PC表示時の列数 */
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  max-width: 960px;
  margin: 0 auto;
  box-sizing: border-box;
}
.ic-wrap * { box-sizing: border-box; }
.ic-title {
  margin: 0 0 1.4em;
  text-align: center;
  font-size: 1.2rem;
  font-weight: 700;
  color: #2d3339;
  letter-spacing: .06em;
}
.ic-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--ic-columns), 1fr);
  gap: 1.2em;
}
.ic-card {
  background: #fff;
  border: 1px solid #eef0f2;
  border-radius: 14px;
  padding: 2em 1.6em;
  text-align: center;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .05);
  transition: transform .2s ease, box-shadow .2s ease;
}
.ic-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 22px rgba(0, 0, 0, .08);
}
.ic-icon {
  display: block;
  font-size: 2rem;
  line-height: 1;
  margin-bottom: .7em;
}
.ic-heading {
  margin: 0 0 .5em;
  font-size: 1.02rem;
  font-weight: 700;
  color: #2d3339;
}
.ic-desc {
  margin: 0;
  font-size: .85rem;
  line-height: 1.8;
  color: #6b7280;
}

@media (max-width: 720px) {
  .ic-grid { grid-template-columns: repeat(2, 1fr); gap: 1em; }
}

@media (max-width: 480px) {
  .ic-grid { grid-template-columns: 1fr; gap: .9em; }
  .ic-card { padding: 1.6em 1.3em; }
}

@media (prefers-reduced-motion: reduce) {
  .ic-card {
    transition: none;
  }
}

縦型タイムライン(沿革)

医院の沿革・ストーリーを、中央の線を軸に左右交互のカードで見せる縦型タイムラインです。スマホでは1カラムに切り替わります。

コード・使い方を見る
<div class="tl-wrap">
  <h3 class="tl-title">みなと総合クリニックのあゆみ</h3>
  <ol class="tl-list">
    <li class="tl-item">
      <div class="tl-content">
        <span class="tl-year">2010</span>
        <p class="tl-text">東京都港区にて、みなと総合クリニックを開院。地域のかかりつけ医としてスタート。</p>
      </div>
    </li>
    <li class="tl-item">
      <div class="tl-content">
        <span class="tl-year">2015</span>
        <p class="tl-text">検査設備を拡充し、健康診断・予防接種にも対応できる体制を整備。</p>
      </div>
    </li>
    <li class="tl-item">
      <div class="tl-content">
        <span class="tl-year">2019</span>
        <p class="tl-text">WEB予約システムを導入。より通いやすいクリニックを目指して体制を刷新。</p>
      </div>
    </li>
    <li class="tl-item">
      <div class="tl-content">
        <span class="tl-year">2024</span>
        <p class="tl-text">開院15周年。累計来院患者数が4万人を突破し、地域医療への貢献を続けています。</p>
      </div>
    </li>
  </ol>
</div>
.tl-wrap {
  --tl-accent: #2f8f9d; /* 中央の線・年号・ドットの色(医院のテーマ色に変更してください) */
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  max-width: 760px;
  margin: 0 auto;
  box-sizing: border-box;
}
.tl-wrap * { box-sizing: border-box; }
.tl-title {
  margin: 0 0 1.8em;
  text-align: center;
  font-size: 1.2rem;
  font-weight: 700;
  color: #2d3339;
  letter-spacing: .06em;
}
.tl-list {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}
.tl-list::before {
  content: "";
  position: absolute;
  top: 6px;
  bottom: 6px;
  left: 50%;
  width: 2px;
  margin-left: -1px;
  background: var(--tl-accent);
  opacity: .3;
}
.tl-item {
  position: relative;
  width: 50%;
  padding: 0 2.4em 2.2em 0;
}
.tl-item:last-child { padding-bottom: 0; }
.tl-item::before {
  content: "";
  position: absolute;
  top: 4px;
  right: -6px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--tl-accent);
  border: 2px solid #fff;
  box-shadow: 0 0 0 2px var(--tl-accent);
  z-index: 1;
}
.tl-item:nth-child(even) {
  margin-left: 50%;
  padding: 0 0 2.2em 2.4em;
}
.tl-item:nth-child(even)::before {
  right: auto;
  left: -6px;
}
.tl-content {
  background: #fff;
  border: 1px solid #eef0f2;
  border-radius: 12px;
  padding: 1.2em 1.4em;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .05);
}
.tl-year {
  display: block;
  margin-bottom: .3em;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--tl-accent);
  font-variant-numeric: tabular-nums;
}
.tl-text {
  margin: 0;
  font-size: .86rem;
  line-height: 1.8;
  color: #6b7280;
}

@media (max-width: 720px) {
  .tl-list::before { left: 6px; }
  .tl-item,
  .tl-item:nth-child(even) {
    width: auto;
    margin-left: 0;
    padding: 0 0 1.6em 2em;
  }
  .tl-item:last-child { padding-bottom: 0; }
  .tl-item::before,
  .tl-item:nth-child(even)::before {
    left: 1px;
    right: auto;
  }
}

@media (max-width: 375px) {
  .tl-content { padding: 1em 1.1em; }
  .tl-text { font-size: .82rem; }
}

左右分割ヒーロー

左にテキスト・右に画像を配置した2分割構成のヒーローセクションで、スマホでは自動的に縦積みに切り替わります。

コード・使い方を見る
<div class="sh-hero">
  <div class="sh-text">
    <p class="sh-eyebrow">みなと総合クリニック</p>
    <h1 class="sh-catch">あなたと家族の毎日に、<br class="sh-br">寄り添う医療を。</h1>
    <p class="sh-lead">内科・小児科・生活習慣病の診療を中心に、地域のかかりつけ医として一人ひとりに丁寧に向き合います。</p>
    <p class="sh-info">東京都港区0-0-0 / 03-0000-0000</p>
    <a class="sh-cta" href="#reserve">診療予約はこちら</a>
  </div>
  <div class="sh-media">
    <img class="sh-img" src="https://placehold.co/800x600/2f8f9d/ffffff?text=Minato+Clinic" alt="みなと総合クリニックの院内の様子" loading="lazy">
  </div>
</div>
.sh-hero {
  --sh-accent: #2f8f9d;    /* CTAボタン・見出しのアクセントカラー(医院のテーマ色に変更してください) */
  --sh-bg: #f7fafb;        /* テキスト側の背景色 */
  display: flex;
  align-items: stretch;
  max-width: 1080px;
  margin: 0 auto;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 4px 24px rgba(0, 0, 0, .08);
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  background: #fff;
}
.sh-text {
  flex: 1 1 50%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 3rem 2.8rem;
  background: var(--sh-bg);
  box-sizing: border-box;
}
.sh-eyebrow {
  margin: 0 0 .8rem;
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .18em;
  color: var(--sh-accent);
}
.sh-catch {
  margin: 0 0 1.1rem;
  font-size: 1.9rem;
  font-weight: 800;
  line-height: 1.5;
  letter-spacing: .02em;
  color: #1f2937;
}
.sh-lead {
  margin: 0 0 1.2rem;
  font-size: .95rem;
  line-height: 1.8;
  color: #4b5563;
}
.sh-info {
  margin: 0 0 1.8rem;
  font-size: .85rem;
  color: #6b7280;
  letter-spacing: .02em;
}
.sh-cta {
  display: inline-block;
  align-self: flex-start;
  background: var(--sh-accent);
  color: #fff;
  font-weight: 700;
  font-size: .95rem;
  padding: .9em 2.4em;
  border-radius: 999px;
  text-decoration: none;
  letter-spacing: .05em;
  box-shadow: 0 6px 18px rgba(47, 143, 157, .3);
  transition: transform .15s, box-shadow .15s, opacity .15s;
}
.sh-cta:hover,
.sh-cta:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 10px 22px rgba(47, 143, 157, .38);
  opacity: .95;
  outline: none;
}
.sh-media {
  flex: 1 1 50%;
  min-height: 320px;
}
.sh-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
@media (max-width: 780px) {
  .sh-hero {
    flex-direction: column;
    border-radius: 12px;
  }
  .sh-text {
    padding: 2.2rem 1.6rem;
    order: 2;
  }
  .sh-media {
    order: 1;
    min-height: 220px;
  }
  .sh-catch {
    font-size: 1.5rem;
  }
}
@media (max-width: 480px) {
  .sh-text {
    padding: 1.8rem 1.2rem;
  }
  .sh-catch {
    font-size: 1.3rem;
  }
  .sh-lead {
    font-size: .88rem;
  }
  .sh-cta {
    width: 100%;
    text-align: center;
    padding: .85em 1.5em;
  }
}

画像ホバーズームギャラリー

マウスを乗せると画像がふわっと拡大表示される、院内写真向けのギャラリーグリッドです。

コード・使い方を見る
<div class="iz-gallery">
  <p class="iz-heading">院内のご案内</p>
  <ul class="iz-grid">
    <li class="iz-item">
      <div class="iz-frame">
        <img class="iz-img" src="https://placehold.co/600x450/2f8f9d/ffffff?text=Reception" alt="みなと総合クリニックの受付">
      </div>
      <p class="iz-caption">受付</p>
    </li>
    <li class="iz-item">
      <div class="iz-frame">
        <img class="iz-img" src="https://placehold.co/600x450/6b7280/ffffff?text=Waiting+Room" alt="みなと総合クリニックの待合室">
      </div>
      <p class="iz-caption">待合室</p>
    </li>
    <li class="iz-item">
      <div class="iz-frame">
        <img class="iz-img" src="https://placehold.co/600x450/cccccc/666666?text=Exam+Room" alt="みなと総合クリニックの診察室">
      </div>
      <p class="iz-caption">診察室</p>
    </li>
    <li class="iz-item">
      <div class="iz-frame">
        <img class="iz-img" src="https://placehold.co/600x450/2f8f9d/ffffff?text=Exterior" alt="みなと総合クリニックの外観">
      </div>
      <p class="iz-caption">外観</p>
    </li>
  </ul>
</div>
.iz-gallery {
  --iz-accent: #2f8f9d;  /* 見出し・キャプションのアクセントカラー(医院のテーマ色に変更してください) */
  --iz-zoom: 1.12;       /* ホバー時の拡大率 */
  max-width: 1080px;
  margin: 0 auto;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
}
.iz-heading {
  margin: 0 0 1.2rem;
  font-size: 1.15rem;
  font-weight: 700;
  color: #1f2937;
  text-align: center;
  letter-spacing: .05em;
}
.iz-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.2rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.iz-item {
  text-align: center;
}
.iz-frame {
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  aspect-ratio: 4 / 3;
  background: #eee;
  box-shadow: 0 2px 12px rgba(0, 0, 0, .07);
}
.iz-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .45s ease;
  will-change: transform;
}
.iz-frame:hover .iz-img,
.iz-frame:focus-within .iz-img {
  transform: scale(var(--iz-zoom));
}
.iz-caption {
  margin: .7rem 0 0;
  font-size: .85rem;
  font-weight: 600;
  color: var(--iz-accent);
  letter-spacing: .04em;
}
@media (max-width: 720px) {
  .iz-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: .9rem;
  }
}
@media (max-width: 480px) {
  .iz-heading {
    font-size: 1rem;
  }
  .iz-caption {
    font-size: .78rem;
  }
}
@media (prefers-reduced-motion: reduce) {
  .iz-img {
    transition: none;
  }
}

タブ切り替えコンテンツ

診療科目などをタブで切り替えて表示できる、キーボード操作にも対応したタブパーツです。

コード・使い方を見る
<div class="tc-tabs">
  <p class="tc-heading">診療のご案内</p>
  <div class="tc-tablist" role="tablist" aria-label="診療内容の切り替え">
    <button type="button" class="tc-tab" role="tab" aria-selected="true">内科</button>
    <button type="button" class="tc-tab" role="tab" aria-selected="false" tabindex="-1">小児科</button>
    <button type="button" class="tc-tab" role="tab" aria-selected="false" tabindex="-1">生活習慣病</button>
  </div>
  <div class="tc-panel" role="tabpanel">
    <h3 class="tc-panel-title">内科</h3>
    <p class="tc-panel-text">発熱・咳・腹痛などの体調不良から、健康診断の事後相談まで幅広く対応します。まずはお気軽にご相談ください。</p>
  </div>
  <div class="tc-panel" role="tabpanel" hidden>
    <h3 class="tc-panel-title">小児科</h3>
    <p class="tc-panel-text">お子さまの発熱・予防接種・乳幼児健診に対応しています。保護者の方にも分かりやすい説明を心がけています。</p>
  </div>
  <div class="tc-panel" role="tabpanel" hidden>
    <h3 class="tc-panel-title">生活習慣病</h3>
    <p class="tc-panel-text">高血圧・糖尿病・脂質異常症などの継続的な管理を、検査データをもとに丁寧にサポートします。</p>
  </div>
</div>
.tc-tabs {
  --tc-accent: #2f8f9d;  /* タブ・見出しのアクセントカラー(医院のテーマ色に変更してください) */
  max-width: 720px;
  margin: 0 auto;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
}
.tc-heading {
  margin: 0 0 1rem;
  font-size: 1.15rem;
  font-weight: 700;
  color: #1f2937;
  text-align: center;
  letter-spacing: .05em;
}
.tc-tablist {
  display: flex;
  gap: .5rem;
  border-bottom: 2px solid #e5e7eb;
}
.tc-tab {
  flex: 1;
  appearance: none;
  border: none;
  background: transparent;
  padding: .8em .5em;
  font-size: .92rem;
  font-weight: 600;
  font-family: inherit;
  color: #6b7280;
  cursor: pointer;
  position: relative;
  transition: color .15s;
}
.tc-tab::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  background: var(--tc-accent);
  transform: scaleX(0);
  transition: transform .2s ease;
}
.tc-tab:hover {
  color: var(--tc-accent);
}
.tc-tab:focus-visible {
  outline: 2px solid var(--tc-accent);
  outline-offset: 2px;
}
.tc-tab[aria-selected="true"] {
  color: var(--tc-accent);
}
.tc-tab[aria-selected="true"]::after {
  transform: scaleX(1);
}
.tc-panel {
  padding: 1.6rem .2rem;
  animation: tc-fade .25s ease;
}
@keyframes tc-fade {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
.tc-panel-title {
  margin: 0 0 .6rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--tc-accent);
}
.tc-panel-text {
  margin: 0;
  font-size: .9rem;
  line-height: 1.8;
  color: #374151;
}
@media (max-width: 480px) {
  .tc-tab {
    font-size: .8rem;
    padding: .7em .3em;
  }
  .tc-panel-text {
    font-size: .85rem;
  }
}
@media (prefers-reduced-motion: reduce) {
  .tc-panel {
    animation: none;
  }
  .tc-tab::after {
    transition: none;
  }
}
(function () {
  var instanceCount = 0;

  function TabContent(root) {
    instanceCount += 1;
    this.uid = 'tc-auto-' + instanceCount;
    this.root = root;
    this.tablist = root.querySelector('.tc-tablist');
    this.tabs = Array.prototype.slice.call(root.querySelectorAll('.tc-tab'));
    this.panels = Array.prototype.slice.call(root.querySelectorAll('.tc-panel'));

    if (!this.tablist || this.tabs.length === 0 || this.tabs.length !== this.panels.length) return;

    this.setupIds();
    this.bindEvents();
  }

  // HTML側に id を書かせないため、JS側で一意な id を生成して
  // role="tab" と role="tabpanel" を aria-controls / aria-labelledby で結びつける
  TabContent.prototype.setupIds = function () {
    var self = this;
    this.tabs.forEach(function (tab, i) {
      var tabId = self.uid + '-tab-' + i;
      var panelId = self.uid + '-panel-' + i;
      tab.id = tabId;
      tab.setAttribute('aria-controls', panelId);
      self.panels[i].id = panelId;
      self.panels[i].setAttribute('aria-labelledby', tabId);
    });
  };

  TabContent.prototype.select = function (index, options) {
    var focusTab = options && options.focusTab;
    var count = this.tabs.length;
    var next = (index + count) % count;

    this.tabs.forEach(function (tab, i) {
      var isActive = i === next;
      tab.setAttribute('aria-selected', String(isActive));
      tab.setAttribute('tabindex', isActive ? '0' : '-1');
    });
    this.panels.forEach(function (panel, i) {
      panel.hidden = i !== next;
    });

    if (focusTab) {
      this.tabs[next].focus();
    }
  };

  TabContent.prototype.bindEvents = function () {
    var self = this;

    this.tabs.forEach(function (tab, i) {
      tab.addEventListener('click', function () {
        self.select(i);
      });
    });

    this.tablist.addEventListener('keydown', function (e) {
      var current = self.tabs.findIndex(function (tab) {
        return tab.getAttribute('aria-selected') === 'true';
      });
      if (current === -1) current = 0;

      if (e.key === 'ArrowRight') {
        e.preventDefault();
        self.select(current + 1, { focusTab: true });
      } else if (e.key === 'ArrowLeft') {
        e.preventDefault();
        self.select(current - 1, { focusTab: true });
      } else if (e.key === 'Home') {
        e.preventDefault();
        self.select(0, { focusTab: true });
      } else if (e.key === 'End') {
        e.preventDefault();
        self.select(self.tabs.length - 1, { focusTab: true });
      }
    });
  };

  document.querySelectorAll('.tc-tabs').forEach(function (root) {
    new TabContent(root);
  });
})();

達成率プログレスバー

満足度・継続率などの実績を、画面に入ったタイミングで0%から目標値までアニメーションする横棒グラフで見せるパーツです。

コード・使い方を見る
<div class="pb-bars">
  <p class="pb-heading">みなと総合クリニックの実績</p>
  <ul class="pb-list">
    <li class="pb-row">
      <div class="pb-row-head">
        <span class="pb-label">患者さま満足度</span>
        <span class="pb-percent"><span class="pb-percent-num">0</span>%</span>
      </div>
      <div class="pb-track">
        <div class="pb-fill" data-value="96"></div>
      </div>
    </li>
    <li class="pb-row">
      <div class="pb-row-head">
        <span class="pb-label">再診・継続率</span>
        <span class="pb-percent"><span class="pb-percent-num">0</span>%</span>
      </div>
      <div class="pb-track">
        <div class="pb-fill" data-value="88"></div>
      </div>
    </li>
    <li class="pb-row">
      <div class="pb-row-head">
        <span class="pb-label">予約時間どおりの診療率</span>
        <span class="pb-percent"><span class="pb-percent-num">0</span>%</span>
      </div>
      <div class="pb-track">
        <div class="pb-fill" data-value="92"></div>
      </div>
    </li>
  </ul>
</div>
.pb-bars {
  --pb-accent: #2f8f9d;  /* バーの色(医院のテーマ色に変更してください) */
  --pb-track-bg: #eef1f3; /* バーの背景(未達成部分)の色 */
  max-width: 640px;
  margin: 0 auto;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
}
.pb-heading {
  margin: 0 0 1.4rem;
  font-size: 1.1rem;
  font-weight: 700;
  color: #1f2937;
  text-align: center;
  letter-spacing: .05em;
}
.pb-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 1.3rem;
}
.pb-row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: .5rem;
}
.pb-label {
  font-size: .9rem;
  font-weight: 600;
  color: #374151;
}
.pb-percent {
  font-size: .95rem;
  font-weight: 800;
  color: var(--pb-accent);
  font-feature-settings: "tnum";
}
.pb-track {
  width: 100%;
  height: 12px;
  border-radius: 999px;
  background: var(--pb-track-bg);
  overflow: hidden;
}
.pb-fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--pb-accent), color-mix(in srgb, var(--pb-accent) 70%, #fff));
  transition: width 1.1s cubic-bezier(.22, .9, .28, 1);
}
@media (max-width: 480px) {
  .pb-heading {
    font-size: 1rem;
  }
  .pb-label {
    font-size: .82rem;
  }
  .pb-percent {
    font-size: .86rem;
  }
  .pb-track {
    height: 10px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .pb-fill {
    transition: none;
  }
}
(function () {
  var DURATION = 1100; // アニメーションにかける時間(ミリ秒。CSSのtransitionと概ね揃えています)
  var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  function animateBar(fillEl, numEl, target) {
    if (reduceMotion) {
      fillEl.style.width = target + '%';
      if (numEl) numEl.textContent = String(target);
      return;
    }

    // 実際に幅が変化して見えるよう、次のフレームで目標幅をセットする
    requestAnimationFrame(function () {
      fillEl.style.width = target + '%';
    });

    if (!numEl) return;
    var start = performance.now();
    function step(now) {
      var progress = Math.min((now - start) / DURATION, 1);
      var eased = 1 - Math.pow(1 - progress, 3); // easeOutCubic
      numEl.textContent = String(Math.round(target * eased));
      if (progress < 1) {
        requestAnimationFrame(step);
      } else {
        numEl.textContent = String(target);
      }
    }
    requestAnimationFrame(step);
  }

  var rows = document.querySelectorAll('.pb-row');
  if (!rows.length) return;

  function handleRow(row) {
    var fillEl = row.querySelector('.pb-fill');
    if (!fillEl) return;
    var numEl = row.querySelector('.pb-percent-num');
    var target = Number(fillEl.getAttribute('data-value')) || 0;
    animateBar(fillEl, numEl, target);
  }

  if (!('IntersectionObserver' in window)) {
    rows.forEach(handleRow);
    return;
  }

  var observer = new IntersectionObserver(
    function (entries) {
      entries.forEach(function (entry) {
        if (!entry.isIntersecting) return;
        handleRow(entry.target);
        observer.unobserve(entry.target);
      });
    },
    { threshold: 0.4 }
  );

  rows.forEach(function (row) {
    observer.observe(row);
  });
})();

コーナーリボン/バッジ付きカード

「人気No.1」などの目印を付けられる、CSSのみで作る見出しカードです。回転帯タイプと三角バッジタイプの2種類を収録しています。

コード・使い方を見る
<div class="rb-grid">
  <div class="rb-card rb-ribbon">
    <span class="rb-ribbon-tag">人気No.1</span>
    <h3 class="rb-title">一般内科</h3>
    <p class="rb-text">発熱・風邪症状から体調不良まで、まず相談したいときの窓口です。</p>
    <p class="rb-price">初診料 2,900円〜</p>
  </div>
  <div class="rb-card">
    <h3 class="rb-title">生活習慣病外来</h3>
    <p class="rb-text">高血圧・糖尿病・脂質異常症の継続管理をサポートします。</p>
    <p class="rb-price">初診料 2,900円〜</p>
  </div>
  <div class="rb-card rb-badge-corner">
    <span class="rb-corner-triangle" aria-hidden="true"></span>
    <span class="rb-corner-text">おすすめ</span>
    <h3 class="rb-title">健康診断</h3>
    <p class="rb-text">各種健診・人間ドックに対応。結果は当日中に一部ご説明します。</p>
    <p class="rb-price">10,000円〜</p>
  </div>
</div>
.rb-grid {
  --rb-accent: #2f8f9d;   /* リボン・バッジの色(医院のテーマ色に変更してください) */
  --rb-ribbon-text: #fff; /* リボン・バッジの文字色 */
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.4rem;
  max-width: 1080px;
  margin: 0 auto;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
}
.rb-card {
  position: relative;
  overflow: hidden;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 14px;
  padding: 2rem 1.5rem 1.6rem;
  box-shadow: 0 2px 12px rgba(0, 0, 0, .06);
  transition: box-shadow .2s, transform .2s;
}
.rb-card:hover {
  box-shadow: 0 10px 24px rgba(0, 0, 0, .1);
  transform: translateY(-3px);
}
.rb-title {
  margin: 0 0 .6rem;
  font-size: 1.05rem;
  font-weight: 700;
  color: #1f2937;
}
.rb-text {
  margin: 0 0 1rem;
  font-size: .86rem;
  line-height: 1.75;
  color: #4b5563;
}
.rb-price {
  margin: 0;
  font-size: .92rem;
  font-weight: 800;
  color: var(--rb-accent);
}

/* 回転させた帯タイプのコーナーリボン */
.rb-ribbon {
  border-color: var(--rb-accent);
}
.rb-ribbon-tag {
  position: absolute;
  top: 1.1rem;
  right: -2.8rem;
  width: 11rem;
  padding: .35em 0;
  background: var(--rb-accent);
  color: var(--rb-ribbon-text);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-align: center;
  transform: rotate(45deg);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .2);
}

/* 三角形+バッジ文字を重ねるタイプのコーナーバッジ */
.rb-badge-corner {
  padding-top: 1.7rem;
}
.rb-corner-triangle {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 3.6rem 3.6rem 0 0;
  border-color: var(--rb-accent) transparent transparent transparent;
}
.rb-corner-text {
  position: absolute;
  top: .55rem;
  left: -.05rem;
  width: 3.2rem;
  font-size: .64rem;
  font-weight: 700;
  color: var(--rb-ribbon-text);
  text-align: center;
  letter-spacing: 0;
  transform: rotate(-45deg);
  white-space: nowrap;
}

@media (max-width: 860px) {
  .rb-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 560px) {
  .rb-grid {
    grid-template-columns: 1fr;
  }
  .rb-ribbon-tag {
    top: .9rem;
    right: -3rem;
    width: 10rem;
    font-size: .72rem;
  }
  .rb-corner-triangle {
    border-width: 3rem 3rem 0 0;
  }
  .rb-corner-text {
    top: .4rem;
    width: 2.6rem;
    font-size: .56rem;
  }
}

引用ハイライト

装飾的な引用符と話者名を添えた、患者さまの声などを大きく見せる引用ブロックです。

コード・使い方を見る
<figure class="qh-quote">
  <span class="qh-mark" aria-hidden="true">&ldquo;</span>
  <blockquote class="qh-body">
    <p>説明が丁寧で、毎回安心して通えます。<br class="qh-br">家族みんなでお世話になっています。</p>
  </blockquote>
  <figcaption class="qh-source">
    <span class="qh-name">港区在住・40代女性</span>
    <span class="qh-role">みなと総合クリニック 通院患者さま</span>
  </figcaption>
</figure>
.qh-quote {
  --qh-accent: #2f8f9d;  /* 引用符・名前のアクセントカラー(医院のテーマ色に変更してください) */
  position: relative;
  max-width: 640px;
  margin: 0 auto;
  padding: 2.6rem 2.2rem 2.2rem;
  background: #f7fafb;
  border-radius: 16px;
  text-align: center;
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
}
.qh-mark {
  display: block;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 4.5rem;
  line-height: 1;
  font-weight: 700;
  color: var(--qh-accent);
  opacity: .28;
  margin: 0 0 -1.2rem;
}
.qh-body {
  margin: 0;
  padding: 0;
}
.qh-body p {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.85;
  color: #1f2937;
  letter-spacing: .02em;
}
.qh-source {
  display: flex;
  flex-direction: column;
  gap: .2rem;
  margin-top: 1.6rem;
}
.qh-name {
  font-size: .95rem;
  font-weight: 700;
  color: var(--qh-accent);
  letter-spacing: .03em;
}
.qh-role {
  font-size: .78rem;
  color: #6b7280;
  letter-spacing: .02em;
}
@media (max-width: 480px) {
  .qh-quote {
    padding: 2.2rem 1.4rem 1.8rem;
    border-radius: 12px;
  }
  .qh-mark {
    font-size: 3.6rem;
  }
  .qh-body p {
    font-size: 1.05rem;
  }
  .qh-name {
    font-size: .86rem;
  }
  .qh-role {
    font-size: .72rem;
  }
}

開閉リスト(アコーディオン)

クリックで開閉する汎用の質問・回答リストです。ブラウザ標準機能のみで動作し、JavaScriptは使用していません。

コード・使い方を見る
<div class="al-wrap">
  <p class="al-heading">よくあるご質問</p>
  <details class="al-item" open>
    <summary class="al-summary">
      <span class="al-summary-text">初診でも予約は必要ですか?</span>
      <span class="al-marker" aria-hidden="true"></span>
    </summary>
    <div class="al-body">
      <p>初診の方も事前のご予約をおすすめしております。WEB予約またはお電話(03-0000-0000)にて承っております。当日予約に空きがある場合は直接ご来院いただくことも可能です。</p>
    </div>
  </details>
  <details class="al-item">
    <summary class="al-summary">
      <span class="al-summary-text">保険証は毎回持参が必要ですか?</span>
      <span class="al-marker" aria-hidden="true"></span>
    </summary>
    <div class="al-body">
      <p>月が変わった際の初回受診時にご提示をお願いしております。マイナ保険証をご利用の方はカードリーダーでの読み取りのみで受診いただけます。</p>
    </div>
  </details>
  <details class="al-item">
    <summary class="al-summary">
      <span class="al-summary-text">駐車場はありますか?</span>
      <span class="al-marker" aria-hidden="true"></span>
    </summary>
    <div class="al-body">
      <p>院内に3台分の専用駐車場をご用意しております。満車の場合は近隣のコインパーキングをご案内しますので、受付までお声がけください。</p>
    </div>
  </details>
  <details class="al-item">
    <summary class="al-summary">
      <span class="al-summary-text">紹介状がなくても受診できますか?</span>
      <span class="al-marker" aria-hidden="true"></span>
    </summary>
    <div class="al-body">
      <p>紹介状がない場合でもご受診いただけます。症状によっては、より適した医療機関をご紹介させていただくこともございますので、あらかじめご了承ください。</p>
    </div>
  </details>
</div>
.al-wrap {
  --al-accent: #2f8f9d;   /* 見出し・アイコンの色(医院のテーマ色に変更してください) */
  --al-border: #e5e7eb;   /* 区切り線の色 */
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  max-width: 640px;
  margin: 0 auto;
}
.al-heading {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--al-accent);
  margin: 0 0 .8em;
  letter-spacing: .06em;
}
.al-item {
  border-bottom: 1px solid var(--al-border);
}
.al-item:first-child {
  border-top: 1px solid var(--al-border);
}
.al-summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8em;
  padding: 1em .3em;
  font-weight: 600;
  color: #22303c;
  -webkit-tap-highlight-color: transparent;
}
.al-summary::-webkit-details-marker {
  display: none;
}
.al-summary-text {
  flex: 1;
  line-height: 1.5;
}
.al-marker {
  position: relative;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1.5px solid var(--al-accent);
}
.al-marker::before,
.al-marker::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--al-accent);
  transform: translate(-50%, -50%);
  transition: transform .2s ease;
}
.al-marker::before {
  width: 10px;
  height: 2px;
}
.al-marker::after {
  width: 2px;
  height: 10px;
}
.al-item[open] .al-marker::after {
  transform: translate(-50%, -50%) rotate(90deg) scale(0);
}
.al-body {
  padding: 0 .3em 1.1em;
  color: #4b5563;
  font-size: .92rem;
  line-height: 1.8;
}
.al-body p {
  margin: 0;
}
@media (max-width: 480px) {
  .al-heading { font-size: 1.05rem; }
  .al-summary { font-size: .95rem; padding: .85em .2em; }
  .al-body { font-size: .86rem; }
}

追従サイドナビ(現在地ハイライト)

スクロールに合わせて今読んでいる項目を自動でハイライトする、ページ内アンカーの追従ナビゲーションです。スマホでは上部の横並びメニューになります。

コード・使い方を見る
<div class="ssn-wrap" data-ssn-root>
  <nav class="ssn-nav" aria-label="ページ内メニュー">
    <ul class="ssn-list">
      <li><a class="ssn-link" data-ssn-link data-ssn-target="ssn-about" href="#ssn-about">クリニックについて</a></li>
      <li><a class="ssn-link" data-ssn-link data-ssn-target="ssn-dept" href="#ssn-dept">診療科目</a></li>
      <li><a class="ssn-link" data-ssn-link data-ssn-target="ssn-flow" href="#ssn-flow">受診の流れ</a></li>
      <li><a class="ssn-link" data-ssn-link data-ssn-target="ssn-access" href="#ssn-access">アクセス</a></li>
    </ul>
  </nav>
  <div class="ssn-content">
    <section class="ssn-section" data-ssn-section="ssn-about" id="ssn-about">
      <h3 class="ssn-section-title">クリニックについて</h3>
      <p class="ssn-section-text">みなと総合クリニックは、地域のかかりつけ医として内科・小児科を中心に診療しています。お子様からご年配の方まで、安心して通っていただける医院を目指しています。</p>
    </section>
    <section class="ssn-section" data-ssn-section="ssn-dept" id="ssn-dept">
      <h3 class="ssn-section-title">診療科目</h3>
      <p class="ssn-section-text">内科・小児科・生活習慣病外来を中心に、健康診断や予防接種にも対応しております。専門的な検査が必要な場合は近隣の医療機関と連携してご案内します。</p>
    </section>
    <section class="ssn-section" data-ssn-section="ssn-flow" id="ssn-flow">
      <h3 class="ssn-section-title">受診の流れ</h3>
      <p class="ssn-section-text">WEB予約またはお電話でご予約のうえご来院ください。受付にて保険証をご提示いただき、問診票をご記入いただいたのち診察となります。</p>
    </section>
    <section class="ssn-section" data-ssn-section="ssn-access" id="ssn-access">
      <h3 class="ssn-section-title">アクセス</h3>
      <p class="ssn-section-text">東京都港区0-0-0。最寄り駅から徒歩5分、院内には駐車場も3台分ご用意しております。お車でお越しの際もご利用ください。</p>
    </section>
  </div>
</div>
.ssn-wrap {
  --ssn-accent: #2f8f9d;    /* 現在地ハイライトの色(医院のテーマ色に変更してください) */
  --ssn-text: #4b5563;      /* 通常時の文字色 */
  --ssn-border: #e5e7eb;    /* 区切り線の色 */
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  display: flex;
  align-items: flex-start;
  gap: 2.4em;
  max-width: 920px;
  margin: 0 auto;
}
.ssn-nav {
  position: sticky;
  top: 1.5em;
  flex: 0 0 180px;
  align-self: flex-start;
}
.ssn-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 2px solid var(--ssn-border);
}
.ssn-link {
  display: block;
  padding: .55em 0 .55em 1em;
  margin-left: -2px;
  border-left: 2px solid transparent;
  color: var(--ssn-text);
  text-decoration: none;
  font-size: .9rem;
  font-weight: 600;
  transition: color .15s ease, border-color .15s ease;
}
.ssn-link:hover {
  color: var(--ssn-accent);
}
.ssn-link.is-active {
  color: var(--ssn-accent);
  border-left-color: var(--ssn-accent);
}
.ssn-content {
  flex: 1;
  min-width: 0;
}
.ssn-section {
  padding: 1.6em 0;
  border-bottom: 1px solid var(--ssn-border);
  scroll-margin-top: 1.2em;
}
.ssn-section:last-child {
  border-bottom: none;
}
.ssn-section-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: #22303c;
  margin: 0 0 .5em;
}
.ssn-section-text {
  font-size: .92rem;
  line-height: 1.9;
  color: var(--ssn-text);
  margin: 0;
}
@media (max-width: 680px) {
  .ssn-wrap {
    flex-direction: column;
    gap: 0;
  }
  .ssn-nav {
    position: sticky;
    top: 0;
    width: 100%;
    flex: none;
    background: #fff;
    z-index: 10;
    border-bottom: 1px solid var(--ssn-border);
  }
  .ssn-list {
    display: flex;
    overflow-x: auto;
    border-left: none;
    -webkit-overflow-scrolling: touch;
  }
  .ssn-link {
    flex: 0 0 auto;
    white-space: nowrap;
    padding: .8em 1em;
    border-left: none;
    border-bottom: 2px solid transparent;
  }
  .ssn-link.is-active {
    border-left-color: transparent;
    border-bottom-color: var(--ssn-accent);
  }
  .ssn-section {
    scroll-margin-top: 3.2em;
  }
}
(function () {
  var roots = document.querySelectorAll('[data-ssn-root]');
  if (!roots.length) return;

  roots.forEach(function (root) {
    var links = Array.prototype.slice.call(root.querySelectorAll('[data-ssn-link]'));
    var sections = Array.prototype.slice.call(root.querySelectorAll('[data-ssn-section]'));
    if (!links.length || !sections.length) return;

    var linkByTarget = {};
    links.forEach(function (link) {
      linkByTarget[link.getAttribute('data-ssn-target')] = link;
    });

    function activate(key) {
      links.forEach(function (link) {
        var isActive = link.getAttribute('data-ssn-target') === key;
        link.classList.toggle('is-active', isActive);
        if (isActive) {
          link.setAttribute('aria-current', 'true');
        } else {
          link.removeAttribute('aria-current');
        }
      });
    }

    if (!('IntersectionObserver' in window)) {
      // 非対応ブラウザでは先頭の項目をハイライトしたままにする
      var firstKey = sections[0].getAttribute('data-ssn-section');
      activate(firstKey);
      return;
    }

    var visibleRatios = {};

    var observer = new IntersectionObserver(
      function (entries) {
        entries.forEach(function (entry) {
          var key = entry.target.getAttribute('data-ssn-section');
          visibleRatios[key] = entry.isIntersecting ? entry.intersectionRatio : 0;
        });

        var bestKey = null;
        var bestRatio = 0;
        sections.forEach(function (section) {
          var key = section.getAttribute('data-ssn-section');
          var ratio = visibleRatios[key] || 0;
          if (ratio > bestRatio) {
            bestRatio = ratio;
            bestKey = key;
          }
        });

        if (bestKey && linkByTarget[bestKey]) {
          activate(bestKey);
        }
      },
      { threshold: [0, 0.25, 0.5, 0.75, 1], rootMargin: '-10% 0px -60% 0px' }
    );

    sections.forEach(function (section) {
      observer.observe(section);
    });

    // 初期表示時に一番上のセクションをハイライト
    activate(sections[0].getAttribute('data-ssn-section'));
  });
})();

大きな番号付き特徴リスト

01・02・03と大きな番号を添えて、医院の強みや特徴を縦に並べて紹介するリストです。

コード・使い方を見る
<div class="nf-wrap">
  <p class="nf-heading">選ばれる3つの理由</p>
  <ol class="nf-list">
    <li class="nf-item">
      <span class="nf-num">01</span>
      <div class="nf-body">
        <h3 class="nf-title">丁寧なカウンセリング</h3>
        <p class="nf-text">お一人おひとりの症状や不安にじっくり向き合い、納得いただけるまで分かりやすくご説明します。</p>
      </div>
    </li>
    <li class="nf-item">
      <span class="nf-num">02</span>
      <div class="nf-body">
        <h3 class="nf-title">最新設備による検査</h3>
        <p class="nf-text">院内に検査機器を完備し、その日のうちに結果をお伝えできる体制を整えています。</p>
      </div>
    </li>
    <li class="nf-item">
      <span class="nf-num">03</span>
      <div class="nf-body">
        <h3 class="nf-title">通いやすい立地と時間</h3>
        <p class="nf-text">駅から徒歩5分、平日夜間・土曜午後も診療しており、お仕事帰りにもお立ち寄りいただけます。</p>
      </div>
    </li>
  </ol>
</div>
.nf-wrap {
  --nf-accent: #2f8f9d;   /* 番号の色(医院のテーマ色に変更してください) */
  --nf-border: #e5e7eb;   /* 区切り線の色 */
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  max-width: 680px;
  margin: 0 auto;
}
.nf-heading {
  font-size: 1.2rem;
  font-weight: 700;
  color: #22303c;
  margin: 0 0 1em;
  letter-spacing: .06em;
  text-align: center;
}
.nf-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.nf-item {
  display: flex;
  align-items: flex-start;
  gap: 1.1em;
  padding: 1.3em 0;
  border-bottom: 1px solid var(--nf-border);
}
.nf-item:first-child {
  border-top: 1px solid var(--nf-border);
}
.nf-num {
  flex: 0 0 auto;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 2.2rem;
  font-weight: 700;
  line-height: 1;
  color: var(--nf-accent);
  opacity: .85;
  min-width: 1.6em;
}
.nf-body {
  padding-top: .2em;
}
.nf-title {
  font-size: 1.02rem;
  font-weight: 700;
  color: #22303c;
  margin: 0 0 .4em;
}
.nf-text {
  font-size: .9rem;
  line-height: 1.8;
  color: #4b5563;
  margin: 0;
}
@media (max-width: 480px) {
  .nf-heading { font-size: 1.05rem; }
  .nf-num { font-size: 1.7rem; min-width: 1.3em; }
  .nf-title { font-size: .96rem; }
  .nf-text { font-size: .84rem; }
  .nf-item { gap: .8em; padding: 1.1em 0; }
}

提携先ロゴストリップ

連携医療機関や取扱いメーカーなどのロゴを横並びで紹介します。普段はグレースケール表示で、マウスを乗せると色が付きます。

コード・使い方を見る
<div class="ls-wrap">
  <p class="ls-heading">連携・提携先について</p>
  <ul class="ls-list">
    <li class="ls-item">
      <img src="https://placehold.co/160x60?text=Partner+A" alt="提携先A" loading="lazy" />
    </li>
    <li class="ls-item">
      <img src="https://placehold.co/160x60?text=Partner+B" alt="提携先B" loading="lazy" />
    </li>
    <li class="ls-item">
      <img src="https://placehold.co/160x60?text=Partner+C" alt="提携先C" loading="lazy" />
    </li>
    <li class="ls-item">
      <img src="https://placehold.co/160x60?text=Partner+D" alt="提携先D" loading="lazy" />
    </li>
    <li class="ls-item">
      <img src="https://placehold.co/160x60?text=Partner+E" alt="提携先E" loading="lazy" />
    </li>
  </ul>
</div>
.ls-wrap {
  --ls-heading-color: #6b7280;  /* 見出し文字の色 */
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  max-width: 880px;
  margin: 0 auto;
  text-align: center;
}
.ls-heading {
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .12em;
  color: var(--ls-heading-color);
  margin: 0 0 1.4em;
}
.ls-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 2.2em;
}
.ls-item img {
  display: block;
  max-width: 140px;
  height: auto;
  filter: grayscale(100%);
  opacity: .55;
  transition: filter .2s ease, opacity .2s ease;
}
.ls-item img:hover {
  filter: grayscale(0%);
  opacity: 1;
}
@media (max-width: 480px) {
  .ls-list { gap: 1.4em; }
  .ls-item img { max-width: 110px; }
  .ls-heading { font-size: .78rem; }
}

SVGドーナツ統計(複数指標)

再診率や予約利用率など複数の指標を、SVGの小さなドーナツグラフで並べて見せる実績表示です。

コード・使い方を見る
<div class="st2-wrap">
  <p class="st2-heading">みなと総合クリニックの実績</p>
  <ul class="st2-grid">
    <li class="st2-item">
      <svg class="st2-svg" viewBox="0 0 120 120" role="img" aria-label="再診率 92%">
        <circle class="st2-track" cx="60" cy="60" r="50" />
        <circle class="st2-bar" cx="60" cy="60" r="50" stroke-dasharray="314.16" stroke-dashoffset="25.13" />
      </svg>
      <p class="st2-num">92<span class="st2-unit">%</span></p>
      <p class="st2-label">再診率</p>
    </li>
    <li class="st2-item">
      <svg class="st2-svg" viewBox="0 0 120 120" role="img" aria-label="待ち時間短縮率 78%">
        <circle class="st2-track" cx="60" cy="60" r="50" />
        <circle class="st2-bar" cx="60" cy="60" r="50" stroke-dasharray="314.16" stroke-dashoffset="69.12" />
      </svg>
      <p class="st2-num">78<span class="st2-unit">%</span></p>
      <p class="st2-label">待ち時間短縮率</p>
    </li>
    <li class="st2-item">
      <svg class="st2-svg" viewBox="0 0 120 120" role="img" aria-label="紹介継続率 85%">
        <circle class="st2-track" cx="60" cy="60" r="50" />
        <circle class="st2-bar" cx="60" cy="60" r="50" stroke-dasharray="314.16" stroke-dashoffset="47.12" />
      </svg>
      <p class="st2-num">85<span class="st2-unit">%</span></p>
      <p class="st2-label">ご紹介による来院</p>
    </li>
    <li class="st2-item">
      <svg class="st2-svg" viewBox="0 0 120 120" role="img" aria-label="オンライン予約利用率 64%">
        <circle class="st2-track" cx="60" cy="60" r="50" />
        <circle class="st2-bar" cx="60" cy="60" r="50" stroke-dasharray="314.16" stroke-dashoffset="113.1" />
      </svg>
      <p class="st2-num">64<span class="st2-unit">%</span></p>
      <p class="st2-label">WEB予約利用率</p>
    </li>
  </ul>
</div>
.st2-wrap {
  --st2-accent: #2f8f9d;  /* ドーナツの色(医院のテーマ色に変更してください) */
  --st2-track: #f3f4f6;   /* ドーナツの背景(未達成分)の色 */
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
  max-width: 760px;
  margin: 0 auto;
  text-align: center;
}
.st2-heading {
  font-size: 1.15rem;
  font-weight: 700;
  color: #22303c;
  margin: 0 0 1.4em;
  letter-spacing: .06em;
}
.st2-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.2em;
}
.st2-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.st2-svg {
  width: 100%;
  max-width: 108px;
  height: auto;
  transform: rotate(-90deg);
}
.st2-track {
  fill: none;
  stroke: var(--st2-track);
  stroke-width: 12;
}
.st2-bar {
  fill: none;
  stroke: var(--st2-accent);
  stroke-width: 12;
  stroke-linecap: round;
}
.st2-num {
  margin: .6em 0 0;
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--st2-accent);
  line-height: 1;
  font-feature-settings: "tnum";
}
.st2-unit {
  font-size: .85rem;
  font-weight: 700;
  margin-left: .05em;
}
.st2-label {
  margin: .4em 0 0;
  font-size: .78rem;
  color: #6b7280;
  line-height: 1.5;
}
@media (max-width: 560px) {
  .st2-grid { grid-template-columns: repeat(2, 1fr); gap: 1.6em 1em; }
}
@media (max-width: 480px) {
  .st2-heading { font-size: 1.02rem; }
  .st2-num { font-size: 1.2rem; }
  .st2-label { font-size: .72rem; }
}