見せ方・演出

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

ヒーローセクション

背景画像に暗めのオーバーレイとキャッチコピー・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; }
}