First CH Designs
BLK-10Blocks

CTA(スプリット帯)

本文の流れに差し込む横長のCTA帯。左に和文ラベル+見出し+短い説明、右にPrimary/Secondaryの2ボタンを置き、内側は縦罫1本だけで分割する。極薄アンバー(bg-amber-50/60)は行動側のカラムにだけ敷き、左は白のまま余白で押す。既存 cta-banner(BLK-01・中央寄せのグラデ面)と対になる「罫線」型で、ページ末の締めではなく通過点のCTAに効く。画像素材ゼロ(他社コーポレートサイトに見られる下部コンバージョン帯の構図を参考にブランド再構築・2026-08-04)。

追加日:
2026-08-04
依存:
なし
tags
#cta #section #block #split #hairline #brand #motion #no-image

プレビュー

サイト改善のご相談

直す順番だけ、
30分で決めませんか。

制作のご依頼が前提でなくて構いません。現在のアクセス・問い合わせ導線・更新体制を伺い、 先に手を付けるべき箇所をその場でお伝えします。

ご返信は1営業日以内平日 10:00–19:00

"use client";

import { useEffect, useRef, useState } from "react";
import { Montserrat } from "next/font/google";

const montserrat = Montserrat({
  weight: ["600", "700"],
  subsets: ["latin"],
  display: "swap",
});

/**
 * CTA(スプリット帯) / Split-Band CTA
 * 参考: 他社コーポレートサイトに見られる下部コンバージョン帯(横長・左右分割・面ではなく罫線で切る)。
 * 構図だけ借りて First CH のブランド(白 + アンバー #d97706 / Montserrat + Noto Sans JP)で
 * 再構築したもので、見た目のコピーではない。画像素材ゼロ。
 *
 * 既存 cta-banner(BLK-01)との対: あちらは「面」(アンバーのグラデ面・中央寄せ・縦積み)。
 * こちらは「罫線」(白地・左右分割・横長帯)。同じCTAでもページ内での役割が違う:
 * 中央寄せの面は"締め"の1枚、横長の帯は本文の流れを止めずに差し込む"通過点"に効く。
 *
 * 汎用技法メモ(web-design-playbook 還流用):
 * - 分割は「箱を2つ並べる」のではなく「1本の縦罫で切る」: 左右それぞれに border / bg / radius を
 *   与えるとカード2枚に見え、CTAの一体感が消える。外枠だけを持ち、内側は右カラムの
 *   border-l(SPでは border-t)1本で切る。ブレークポイントで罫の向きだけ入れ替える。
 * - 極薄アンバーは「行動する側」にだけ敷く: 帯の全面に色を敷くと cta-banner と同じ"面"になる。
 *   bg-amber-50/60 を右カラム(ボタン側)だけに限定すると、色が装飾ではなく
 *   「ここが行動の場所」という機能の印になる。左は白のまま余白で押す。
 * - 見出しの中の1語だけをアンバーの下線でワイプする: 見出し全体を色付けせず、判断の核になる
 *   語(ここでは「何を直すべきか」)に h-[3px] の下線を敷き、リビール時に origin-left の
 *   scale-x 0→1 で引く。下線は absolute なので語が折り返すと崩れる= whitespace-nowrap 必須。
 * - 和文見出しの改行は <br> で決める: 和文は語境界で折り返さず幅いっぱいまで貪欲に詰めるため、
 *   自然改行に任せると「を、」のような助詞が次行の頭に落ちる。各行を最も狭い環境(≒220px)でも
 *   収まる長さに割ってから <br> を入れる。text-wrap: balance は和文では効きが読めないので使わない。
 * - 小さな英語ラベルを既定にしない: 帯の頭は和文の短いラベル + 4px のアンバー角にする
 *   ("CONTACT" 等は別業種のサイトへそのまま移植でき、構図上の役割を持たない)。
 * - 矢印は「送り出して、入れ替える」: size-4 の overflow-hidden な箱に矢印を2つ重ね、
 *   hover で1つ目を translate-x で外へ送り、-translate-x-4 に待たせた2つ目を 0 へ戻す。
 *   opacity を触らないので下地のアンバーに濁りが出ない。
 * - 分割の罫線に「入場のとっかかり」を1つだけ置く: 罫の起点に w-10(SP)/ h-10(PC)の
 *   アンバー片を重ね、origin-left / origin-top で伸ばす。動かすのは transform と opacity だけ。
 *
 * 実案件への移植:
 * <section> をそのまま本文セクションの間か記事末に置く(デモシェルは同梱していない)。
 * ページ末の"締め"に使うなら cta-banner(BLK-01)、本文の途中に差し込むならこちら。
 */

export default function CtaSplitBand() {
  const rootRef = useRef<HTMLElement>(null);
  const [inView, setInView] = useState(false);

  // 画面に入ったら1度だけリビール(reduced-motion 時は motion-reduce: クラスで即時表示)
  useEffect(() => {
    const el = rootRef.current;
    if (!el) return;
    const io = new IntersectionObserver(
      (entries) => {
        if (entries.some((e) => e.isIntersecting)) {
          setInView(true);
          io.disconnect();
        }
      },
      { threshold: 0.2 },
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);

  // translate-y + opacity のスタッガー(transform / opacity のみ)
  const rise = (delay: number) => ({
    className: `transition-[opacity,transform] duration-700 ease-out motion-reduce:transition-none ${
      inView
        ? "translate-y-0 opacity-100"
        : "translate-y-2 opacity-0 motion-reduce:translate-y-0 motion-reduce:opacity-100"
    }`,
    style: { transitionDelay: inView ? `${delay}ms` : "0ms" },
  });

  const label = rise(0);
  const heading = rise(110);
  const lead = rise(220);
  const actions = rise(320);

  return (
    <section
      ref={rootRef}
      aria-labelledby="cta-split-band-heading"
      className="w-full max-w-4xl overflow-hidden rounded-2xl border border-gray-200 bg-white"
    >
      <div className="flex flex-col lg:flex-row lg:items-stretch">
        {/* 左: 見出しと短い説明。色も面も使わず余白で押す */}
        <div className="flex flex-col justify-center px-6 py-9 sm:px-9 sm:py-11 lg:flex-1 lg:px-10 lg:py-12">
          <p
            className={`flex items-center gap-2 text-[11px] font-bold tracking-[0.14em] text-gray-900 ${label.className}`}
            style={label.style}
          >
            <span
              aria-hidden="true"
              className="inline-block size-1 shrink-0 bg-amber-600"
            />
            サイト改善のご相談
          </p>

          {/* 和文は語境界で折り返さないため、行の切れ目は <br> で決める。
              1行が最も狭い環境(≒220px)でも収まる長さに割ってある */}
          <h2
            id="cta-split-band-heading"
            className={`mt-4 text-xl leading-[1.5] font-bold tracking-tight text-gray-900 sm:text-2xl ${heading.className}`}
            style={heading.style}
          >
            <span className="relative inline-block whitespace-nowrap">
              直す順番
              <span
                aria-hidden="true"
                className={`absolute -bottom-0.5 left-0 h-[3px] w-full origin-left bg-amber-600/70 transition-transform duration-700 ease-out motion-reduce:transition-none ${
                  inView ? "scale-x-100" : "scale-x-0 motion-reduce:scale-x-100"
                }`}
                style={{ transitionDelay: inView ? "430ms" : "0ms" }}
              />
            </span>
            だけ、
            <br />
            <span className={`${montserrat.className} tabular-nums`}>30</span>
            分で決めませんか。
          </h2>

          <p
            className={`mt-4 max-w-md text-[13px] leading-[1.9] text-gray-600 ${lead.className}`}
            style={lead.style}
          >
            制作のご依頼が前提でなくて構いません。現在のアクセス・問い合わせ導線・更新体制を伺い、
            先に手を付けるべき箇所をその場でお伝えします。
          </p>
        </div>

        {/* 右: 行動の場所。極薄アンバーはここだけに敷く */}
        <div className="relative flex shrink-0 flex-col justify-center border-t border-gray-200 bg-amber-50/60 px-6 py-8 sm:px-9 lg:w-[300px] lg:border-t-0 lg:border-l lg:px-8 lg:py-12">
          {/* 分割の罫線に重ねるアンバー片(SP=横 / PC=縦。入場で起点から伸びる) */}
          <span
            aria-hidden="true"
            className={`absolute -top-px left-6 h-px w-10 origin-left bg-amber-600 transition-transform duration-700 ease-out motion-reduce:transition-none sm:left-9 lg:hidden ${
              inView ? "scale-x-100" : "scale-x-0 motion-reduce:scale-x-100"
            }`}
          />
          <span
            aria-hidden="true"
            className={`absolute top-0 -left-px hidden h-10 w-px origin-top bg-amber-600 transition-transform duration-700 ease-out motion-reduce:transition-none lg:block ${
              inView ? "scale-y-100" : "scale-y-0 motion-reduce:scale-y-100"
            }`}
          />

          <div
            className={`flex flex-col gap-3 ${actions.className}`}
            style={actions.style}
          >
            {/* Primary: 矢印を送り出して入れ替える */}
            <a
              href="#"
              className="group flex items-center justify-between gap-3 rounded-lg bg-amber-600 px-5 py-3.5 text-sm font-bold text-white transition-transform duration-300 ease-out hover:-translate-y-0.5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-amber-600 motion-reduce:transition-none motion-reduce:hover:translate-y-0"
            >
              無料相談を予約する
              <span
                aria-hidden="true"
                className="relative block size-4 shrink-0 overflow-hidden"
              >
                <span className="absolute inset-0 flex items-center justify-center transition-transform duration-300 ease-out group-hover:translate-x-4 group-focus-visible:translate-x-4 motion-reduce:transition-none">
                  →
                </span>
                <span className="absolute inset-0 flex -translate-x-4 items-center justify-center transition-transform duration-300 ease-out group-hover:translate-x-0 group-focus-visible:translate-x-0 motion-reduce:transition-none">
                  →
                </span>
              </span>
            </a>

            {/* Secondary: 白地 + 罫線。主従が読めるよう font-weight まで落とす */}
            <a
              href="#"
              className="group flex items-center justify-between gap-3 rounded-lg border border-gray-300 bg-white px-5 py-3 text-sm font-semibold text-gray-800 transition-colors hover:border-gray-900 hover:text-gray-900 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-amber-600"
            >
              制作実績を見る
              <span
                aria-hidden="true"
                className="inline-block shrink-0 transition-transform duration-300 ease-out group-hover:translate-x-1 group-focus-visible:translate-x-1 motion-reduce:transition-none"
              >
                →
              </span>
            </a>
          </div>

          <p
            className={`mt-5 flex flex-col items-start gap-1 text-[11px] text-gray-500 sm:flex-row sm:flex-wrap sm:items-center sm:gap-x-2.5 ${actions.className}`}
            style={{ transitionDelay: inView ? "400ms" : "0ms" }}
          >
            <span>ご返信は1営業日以内</span>
            {/* 区切りの縦罫は横並びのときだけ。縦積みで出すと行末に線が余る */}
            <span
              aria-hidden="true"
              className="hidden h-2.5 w-px shrink-0 bg-gray-300 sm:block"
            />
            <span>
              平日{" "}
              <span className={`${montserrat.className} tabular-nums`}>
                10:00–19:00
              </span>
            </span>
          </p>
        </div>
      </div>
    </section>
  );
}

shadcn CLI でプロジェクトに追加

npx shadcn@latest add https://designs.first-ch.com/r/cta-split-band.json