ボタンのborderにhoverを使ったらずれて表示された話

はじめに

「オンマウス時のみ枠線が表示されるボタン」を作る機会があり(さらにボタンの背景をグラデーションで設定)、実装してみるとオンマウス時にborderの幅だけボタンがずれて表示されてしまいました。

現象の再現

特に何も対策しないと、下のボタンのようにマウスオーバー時に少しずれます。

ボタンをマウスオーバーして下さい

その時の解決策を以下にまとめています。

目次

背景が単色なら同じ色のborderを設定する

まずは、参考までに背景が単色の場合の設定です。

当初、box-sizing:border-box;を使えばできるんじゃないか、と思っていたのですが、横幅のずれはなくなりましたが、高さがずれました。

そこで考えたのが、オフマウス時に背景色と同じ色のborderを設定して、オンマウス時に別の色を設定する方法です。

背景が単色ならこれが簡単だと思います。

HTML

HTMLは以下すべて共通です。

  1. <a href="#" class="test">Button</a>

CSS

  1. .test {
  2.  display: block;
  3.  width: 180px;
  4.  line-height: 50px;
  5.  background: #000;
  6.  color: #fff;
  7.  text-decoration: none;
  8.  text-align: center;
  9.  border: 4px solid #000;
  10. }
  11. .test:hover {
  12.  border: 4px solid #ff0000;
  13. }

できあがったもの

ボタンをマウスオーバーして下さい

背景がグラデーションの場合の設定

背景色がグラデーションでマウスオーバー時のみ枠線を表示させたい場合、オフマウス時でもborderが表示されるため、上記の方法では上手くいきません。

現象の再現

枠線をグラデーションにする方法もあるのですが、手順が若干面倒です。

私は上記のようなボタンを作成する場合、高さはline-heightで調整しているのですが、その場合、オンマウス時のborderの値に合わせてline-heightを調整すれば、ズレがなくなります。

CSS

  1. .test {
  2.  display: block;
  3.  width: 180px;
  4.  line-height:50px;
  5.  background-image: linear-gradient( to right, #000 , #666);
  6.  color: #fff;
  7.  text-decoration: none;
  8.  text-align: center;
  9. }
  10. .test:hover {
  11.  border: 4px solid #ff0000;
  12.  line-height:42px;
  13.  box-sizing:border-box;
  14. }

上記CSSでは、オンマウス時のborderを4pxで設定しているので、line-heightを4px×2の8px分引いて設定すればOKです。

できあがったもの

ボタンをマウスオーバーして下さい

幅・高さにpaddingを使う場合の設定

上記の例では行の高さ調整にline-heightを使用しているのですが、行幅・高さをpaddingで設定する場合は以下のようにpaddingとhover時のborderの値を調整します。

(今回は、ボタンの幅もwidthではなくpaddingで設定しています)

CSS

  1. .test {
  2.  display: inline-block;
  3.  padding: 20px 40px;
  4.  background-image: linear-gradient( to right, #000 , #666);
  5.  color: #fff;
  6.  text-decoration: none;
  7.  text-align: center;
  8. }
  9. .test:hover {
  10.  border: 4px solid #ff0000;
  11.  padding: 16px 36px;
  12. }

今回は、オンマウス時のpaddingは2倍した値を引かず、1倍の値を縦横それぞれのpaddingから引いています。

できあがったもの

ボタンをマウスオーバーして下さい