GODRICH

css ボタン デザイン 9選 — キャンディグラデ・押し込み・ローディング

css ボタン デザインとは、ボタンの色・形、マウスを乗せたときと押したときの反応までを、コード数行で決める作業です。どこかのランディングページで見たキャンディのようなグラデーションボタンや、指でぐっと押せる立体ボタンを自分のサイトにそのまま移したいとき、この9種類は1ファイル貼るだけで済みます。

自動再生 · タイルを押すとその項目へ · すべて1つのzip

9個は人気順ではなく、ボタンが実際の画面でたどる順に並べてあります。まず目を引くキャンディグラデーション(01)・光の帯(02)・もちもちブロブ(03)。次にホバーに反応する枠の描画(04)・矢印スライド(05)・デュオトーンワイプ(06)。そしてクリックの瞬間のリングリップル(07)・3D押し込み(08)を経て、押したあとの待ち時間を示すピルローダー(09)で終わります。

01キャンディグラデーションボタン

ボタンの3倍の幅があるキャンディ色の布を下に敷き、それを毎回ちょうど1周期ぶん左へ押し出します。動くのはtranslateXひとつだけなのでレイアウト計算はなく、周期がきっちり240pxなので、ストライプのつなぎ目は見えません。ランディングページの最初の画面の登録ボタンに合います。

repeating-linear-gradienttranslateX(-240px) 한 주기overflow: hidden
.btn__bg {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 720px;
  background: repeating-linear-gradient(to right,
    $color 0 58px, $candy-b 64px 118px, $candy-c 124px 178px, $color 184px 240px);
}
.stage.is-demo .btn__bg { animation: gradient-flow $duration $easing infinite; }
@keyframes gradient-flow {
  0%   { transform: translateX(0); }
  100% { transform: translateX(-240px); }
}

02光の帯スイープボタン

暗いボタンの上を、斜めに傾けた白い光の帯が一度横切り、ガラスに光が差すようなハイライトを残します。帯は::afterの疑似要素で、skewX(-20deg)で斜めに寝かせてtranslateXだけで動かすので、ボタンの幅が変わってもそのまま動きます。もう一度目を引きたい決済・購入ボタンにぴったりです。

translateX(±150%)skewX(-20deg)overflow: hidden
.btn::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0; left: -60%;
  width: 60%;
  background: linear-gradient(115deg,
    transparent 0%, rgba(255, 255, 255, .85) 50%, transparent 100%);
  transform: skewX(-20deg) translateX(-10%);
}
@keyframes sweep {
  0%, 10% { transform: skewX(-20deg) translateX(-10%); }
  55%     { transform: skewX(-20deg) translateX(310%); }
  100%    { transform: skewX(-20deg) translateX(310%); }
}

03もちもちブロブボタン

ラベルの裏に隠れていたミント色の丸が左右に膨らみ、ボタンの輪郭がゼリーのように伸びたり縮んだりします。丸はボタンと同じ色なので境界がひとつに溶け、膨らみはscaleひとつで表します。子ども向けショップのカート追加ボタンによく合います。

::before·::after scaleborder-radius: 50%$ease-pop
.btn::before, .btn::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 56px; height: 56px;
  border-radius: 50%;
  background: $color;
  transform: translateY(-50%) scale(.3);
}
.stage.is-demo .btn::before { animation: blob-l $duration $easing infinite; }
@keyframes blob-l {
  0%, 12% { transform: translateY(-50%) scale(.3); }
  40%     { transform: translateY(-50%) scale(1.3) translateX(-8px); }
  100%    { transform: translateY(-50%) scale(.3); }
}

04枠が描かれるボタン

ボタンの周りを手描きのように1ストロークずつ描き込みます。SVGの四角にpathLength="100"属性を付けると、実際の長さが何ピクセルでも100目盛りの定規で数えられるので、stroke-dashoffsetを100から0へ減らすだけで描画が完成します。描き終わったあと淡い絵の具が満ちるまでが1周期です。

stroke-dashoffsetpathLength=100vector-effect: non-scaling-stroke
.btn__rect {
  fill: none;
  stroke: $color;
  stroke-width: 3;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}
.stage.is-demo .btn__rect { animation: draw $duration $easing infinite; }
@keyframes draw {
  0%, 12% { stroke-dashoffset: 100; }
  55%     { stroke-dashoffset: 0; }
  100%    { stroke-dashoffset: 100; }
}

05矢印スライドボタン

ラベルだけのマスと、ラベルに矢印が付いたマスの2つを並べ、まとめて半マスぶん押し出します。マウスを乗せると文字が左へ押し出され、矢印が右から定位置へ滑り込みます。トラックの幅を200%に固定してあるので、どんな文字の長さでもずれません。次の内容へ連れて行く「続きを読む」に向いています。

격층 translateXoverflow: hidden$ease-spring
.btn__track { display: flex; width: 200%; height: 100%; }
.btn__cell  { flex: 0 0 50%; display: flex; align-items: center; }
.stage.is-demo .btn__track { animation: slide-in $duration $easing infinite; }
@keyframes slide-in {
  0%, 18%  { transform: translateX(0); }
  55%, 72% { transform: translateX(-50%); }
  88%      { transform: translateX(-4%); }
  100%     { transform: translateX(0); }
}

06デュオトーンワイプボタン

ボタンをクリームとピーチの2色に分け、下の色が左からscaleXで広がり、絵の具がにじむように全面が入れ替わります。文字も背景色に合わせて2枚重ねてopacityで交代するので、色が移る瞬間も読めたままです。料金プランカードの「はじめる」に合います。

scaleX 레이어 와이프transform-origin: leftcolor 전환
.btn__wash {
  position: absolute;
  inset: 0;
  background: $color;
  transform: scaleX(0);
  transform-origin: left;
}
@keyframes wash {
  0%, 12%  { transform: scaleX(0); }
  48%, 70% { transform: scaleX(1); }
  100%     { transform: scaleX(0); }
}
.stage.is-demo .btn__t-on-dark { animation: swap-in $duration $easing infinite; }

07リングリップルボタン

押した瞬間、波ではなく鐘の音のように枠線のリングが外へ広がります。::afterに3pxの枠線の円を重ね、scaleで大きくしながらopacityで消していくだけなので、色を変えればどんなアイコンボタンにも乗せられます。同じ瞬間ハートがぐっと膨らんで弾むので、いいね・ブックマークのトグルに合います。

::after 링 확산scale + opacity:active 트리거
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 3px solid $color;
  opacity: 0;
}
@keyframes ring {
  0%  { transform: scale(1);   opacity: .9; }
  34% { transform: scale(1.8); opacity: 0; }
  50% { transform: scale(1);   opacity: .9; }
  84% { transform: scale(1.8); opacity: 0; }
}

083D押し込みボタン

ボタンの下に8pxの硬い影を敷いて物理的なキーのように見せ、押した瞬間その厚みぶんtranslateYで沈み込み、影が消えます。離すとき小さく跳ね返るまでをループに入れ、実使用では:activeに2行書くだけです。ゲームのスタートや子ども向けアプリの大きなボタンに合います。

translateY 눌림box-shadow 두께:active 트리거
$depth: 8px;
.btn {
  box-shadow: 0 $depth 0 darken($color, 22%),
              0 #{$depth + 6px} #{$sp-3} rgba(23, 20, 26, .22);
}
.btn:active { transform: translateY($depth); }
@keyframes press {
  0%, 20%  { transform: translateY(0); }
  35%, 55% { transform: translateY($depth); }
  70%      { transform: translateY(-3px); }
  85%,100% { transform: translateY(0); }
}

09ピルローダーボタン

ファイルを送る瞬間、ラベルがゆっくり消え、ボタンが濃い紺にロックされ、ピルの中の短いバーが左から右へ2回滑ります。バーはtranslateXだけで動き、待ち時間が終わればラベルが戻ります。実使用では送信中にis-busyクラスを付けるだけです。

라벨 opacity 스왑translateX 로더 막대$dur-loop 주기
.btn__bar {
  position: absolute;
  top: 0; bottom: 0;
  width: 60px;
  border-radius: $r-pill;
  background: $subject-cream;
  transform: translateX(-60px);
}
@keyframes bar-run {
  0%   { transform: translateX(-60px); }
  100% { transform: translateX(168px); }
}
@keyframes busy-bg {
  0%, 15%  { background: $color; }
  25%, 85% { background: $busy; }
  95%,100% { background: $color; }
}

どこで壊れるか — 柔らかいパステルは機械に見えない

01番は最初、今と逆の作りでした。背景グラデーションそのものの位置をbackground-positionで動かし、色もにじむパステルの組み合わせです。目には明らかに流れているのに、レンダリングされたフレームを機械で測ると強度0.0・動いたフレーム0枚でした。フレーム間でグラデーションが進む距離は10pxで、その間の色の変化が測定のしきい値を下回り、どのピクセルも変わっていないと数えられたのです。境目がはっきりしたストライプに描き直し、層ごとtranslateXで動かしてようやく測定を通しました。02番の光の帯の移動距離を帯の幅の数倍にしたのも同じ理由です。9個のフォルダの圧縮パスワードは3vxxw8yhで、そのまま入力しないと開きません。グラデーションの周期(240px)と移動距離が正確に一致しなければループがつながらないことも、この項目で直接確かめました — 4pxずれただけで1周ごとに模様がずれます。

アクセシビリティ

9個すべてprefers-reduced-motion: reduceanimation: noneに落ち、止まった後もそれが何なのか分かる静止画をそれぞれ決めてあります。01はストライプが見える位置で止まり、04は枠が描き終わった完成状態で止まり、05はラベルと矢印が一緒に見えるマスで止まります。09のバーは中央に停まり、色と形だけで「ロード中」を伝えます。すべてのボタンはキーボード操作時に:focus-visibleの枠を出します。設定の切り替え方はMDNのprefers-reduced-motionのページにあります。

FAQ

JavaScriptが分からなくても使えますか?

はい、この9個はすべてCSS(SCSS)だけで動き、JavaScriptは1行もありません。09も実使用ではボタンにis-busyクラスを付け外しするだけで済みます。最初の一歩のリップルやホバーはCSSボタンアニメーション9種の記事にあります。

色を自分のブランド色に変えるにはどこを直しますか?

各項目のSCSS先頭の$color1つが基本色です。01番は$colorのほかに補助色が2つ、08番は濃い縁の色がdarken($color, 22%)で自動的に付いてきます。06番は下に敷く色が$colorなので、上の色を変えるときは背景の行も一緒に直します。

zipの中には何が入っていますか?

9項目それぞれのindex.htmlstyle.scss・コンパイル済みのstyle.css、そしてReactプロジェクトにそのまま置ける.tsx.module.scssの組です。duration・easing・colorがpropsとして抜けているので、値を変えればそのまま変種として使えます。他のボタン素材はサイト内検索から探せます。

解凍パスワードを入力してください

パスワードはこの記事の本文の中にあります。読み進めると出てきます。