LoginSignup
0
0

More than 1 year has passed since last update.

グラデーションカラー + SVG アイコン付きのボタンをじわっと変化させる

Last updated at Posted at 2023-03-27

デザイナーさんがグラデーションのついたボタンの色をマウスホバー時に変化させる(しかもSVGのアイコン付きなのでさらに面倒さが倍増)という案を出してきて、実装に苦労したので備忘録として残しておきます。

background: linear-gradient には transition が効かないので、じわっと変化させようとしても背景色だけ一瞬で切り替わってしまいます。
そこで before 疑似要素を重ねて opacity を変化させることで transition を実現しています(JavaScript は使いたくなかった)。

デモ

まずはデモ。
ソースコード見ればすぐに真似できると思います。

コード

JavaScript は使わず CSS のみで実現しています。

html

<div class="container">
  <button class="button">
    <div class="text">ボタン</div>
    <div class="icon">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path class="icon-path" d="M0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM294.6 135.1l99.9 107.1c3.5 3.8 5.5 8.7 5.5 13.8s-2 10.1-5.5 13.8L294.6 376.9c-4.2 4.5-10.1 7.1-16.3 7.1C266 384 256 374 256 361.7l0-57.7-96 0c-17.7 0-32-14.3-32-32l0-32c0-17.7 14.3-32 32-32l96 0 0-57.7c0-12.3 10-22.3 22.3-22.3c6.2 0 12.1 2.6 16.3 7.1z"/>
      </svg>
    </div>
  </button>
</div>

SCSS

$primary-color: #066435;
$light-color: #0bb660;
$text-color: #fff;
$transition-time: 1s;

.container {
  display: inline-block;
}

.text {
  position: relative;
}

.button {
  position: relative;
  width: 300px;
  color: $text-color;
  border: solid 1px $primary-color;
  height: 36px;
  border-radius: 18px;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all $transition-time;

  &::before {
    content: '';
    background: linear-gradient(90deg, $light-color, $primary-color);
    border-radius: 18px;
    position: absolute;
    width: 100%;
    height: 100%;
    transition: all $transition-time;
  }

  path {
    transition: all $transition-time;
    &.icon-path {
      fill: $text-color;
    }
  }

  &:hover {
    color: $primary-color;
    &::before {
      opacity: 0;
    }
    path.icon-path {
      fill: $primary-color;
    }
  }

  .icon {
    position: absolute;
    top: 8px;
    right: 9px;
    width: 18px;
    height: 18px;
  }
}

解説

まず hover したときの状態のスタイルを定義しておきます。
background-color は transparent なので省いています。

.button {
  border: solid 1px $primary-color;
}

次にその上に before 疑似要素をかぶせます。
これが hover していないときの表示なるので、ここにグラデーションの背景を設定します。

&::before {
  background: linear-gradient(90deg, $light-color, $main-color);
}

あとは hover 時に before 疑似要素を消すようにします。

&:hover {
  &::before {
    opacity: 0;
  }
}

ボタン内に配置した SVG の色も同時に変化させるために、path 要素の fill も CSS で設定します。
アイコンは配色がボタンと逆になるので、一見クラス名と色名が一致していないように見えますが、これで合っています。

path {
  &.icon-path {
    fill: $text-color;
  }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0