BLOG

CSS背景のbackground-repeatで画像が見切れた時の対応方

Written by EVOWORX

INDEX

こんにちは、コーダーのJackieです。

今回はCSS background-repeatとjQuery(JavaScript)を使用して、枠線を作る方法について話したいと思います。

はじめに

CSSのbackgroundプロパティは背景色だけではなく、

  • 値でlinear-gradientでグラデーション色を入れる
  • 背景画像のプロパティbackground-image<body><table>だけではなく、<p><div><span>などブロックもインラインの要素にも背景画像を指定できる

など柔軟に画像を配置できます。

また、CSSプロパティのborderで表せないデザインを背景画像(background-repeat)を繰り返させて再現することもできます。

例えばこのような点線を作りたいとします。

一見、border: dottedで簡単に作れそうに見えますが、この点線のデザインを確認したところ、点のwidth: 4pxheight: 4px、点と点の間隔は15pxになっています。

borderでこれを作るときはborder: 4px dotted black;のように指定できますが、下記のコードペン通り、点と点の間を指定することができず、border-width4pxから変えると枠線の幅も点の間隔が一緒に大きくなるので、カスタマイズ性が限られています。

4px以下になると点が丸い形が表現できなくなり、四角い形に見えてしまいます。

今回作りたい点線はborderで再現が難しいので、background-imagebackground-repeatを使ってみましょう。

background-repeatの使い方

borderの代わりにbackground-repeatで枠線を作る場合は、まずは繰り返させる「点」の画像を用意しないといけません。

上記の点線から、一つの点(画像のdashedの線に囲っているエリア)を書き出し、このようにリピートさせます。

.box {
  width: 370px;
  background: url(https://www.evoworx.co.jp/wp3/wp-content/uploads/2021/12/dotted_single.png);
  background-repeat: repeat-x;
}

今回はwidth: 370pxに設定しましたが、コードペンで見ると点が切れてしまっています。

一旦background-repeatの仕様を振り返りましょう。

background-repeat: repeat

画像は描画領域全体を覆うのに必要な回数だけ、繰り返し描画されます。最後の背景画像が領域に収まりきらない場合は切り取られます。

MDN Web Docs

通常のrepeatは、最後入りきれない画像が切れて、領域を全部埋めるようになります。また、repeat-xでは横方向で、repeat-yは縦の方向で繰り返すようになります。

しかしデザイン上、枠線の画像が切れてしまうことは望ましくありません。

その時は他にspaceroundという値もあります。

background-repeat: space

画像は指定された方向に切り抜きなし敷き詰められる回数だけ繰り返されます。最初の画像と最後の画像は領域の両端にそれぞれ接触するように描画され、余白が画像同士の間に均一に分配されます。

MDN Web Docs

background-repeat: round

利用できる空間が広がるにつれ、繰り返し描画された画像は、画像をもう1つ追加するだけの余裕 (残りの空間 ≧ 画像の幅の半分) ができるまで、 (隙間を空けずに) 伸長されます。次の画像が追加されると、描画されたすべての画像が収まるように縮小されます。

MDN Web Docs

下記のデモでbackground-repeatのrepeat, space, round、それぞれの挙動を確認できます。リサイズしてみてください。

上記のとおり、background-repeat: roundの場合は画像が縮んだり伸びたりし、background-repeat: spaceの場合は画像と画像の間に間隔ができます。どっちも最初と最後の背景画像が描画エリアの端にくっ付け、最初と最後の画像の間にいい感じに調整してくれます。一行のCSSで実行でき、caniuseにより主なブラウザ対応もしているので安心です。

しかし、CSSでspaceかroundを使ってしまうと画像と画像の間の余白が伸びたり、または画像自体が伸び縮んでしまうことがあり、デザイン通りの再現が難しい場合もあります。

CSSだけで解決できない場合のjQueryの解決

CSSだけで目指しているデザインの比率・間隔を保ち再現できない場合は、JavaScriptやjQueryを使用して作ることができます。

上記の点線の例にこちらのjQueryを追加します。

background-repeatの値はrepeat-xのままです。

$(window).on('load', function() {
    var $div = $('.box');
    $div.css('width', "372" );
    var w = 16;
    var remainder = $div.width() % w;
 
    // あまりを削ってコンテナを小さくする
    var newWidth = $div.width() - remainder ; 
 
    $div.css('width', newWidth);
  });

簡単に言うと、背景画像が入るために描画領域を変えます。

解説

1. background-repeatが入る要素・コンテナを取得し、画像の幅(もしくは高さ)等を指定します。

// 背景画像に入っている要素・コンテナ
var $div = $('.box'); 

デフォルトの幅の値を与えます。今回は372pxにしました。そして書き出した一つの「点」の画像の幅も使いやすいように変数のwとして設定します。

// 初期ロード時の要素の幅を設定する
$div.css('width', "372" );
 
// 背景画像の幅
var w = 16

2. 剰余演算子 (%) で余りを計算します

 var remainder = $div.width() % w; // 余りを計算する

3. 次で、描画領域(要素の幅)を変更しますが、2択があります:

  • コンテナの幅から、計算した余りを削り、コンテナを小さくします。結果的に最後に見切れた背景画像が削られます。
var newWidth = $div.width() - remainder
  • もう一つ背景画像が入れるようにコンテナを大きくします。背景画像の幅からあまりをひくと、追加分が割ります。
var newWidth = $div.width() + (w-remainder); 

どちらかを選んで使ってください。

(どちらにするかはデザインに応じて選ぶといいです。)

5. 最後にコンテナの新しい幅を反映します。

$div.css('width', newWidth);

コードペンのデモで試してみてください。

まとめ

今回はbackground-repeatの値、repeat、space、とroundを使って枠線を作ってみました。個人的にはspaceとroundがあんまり使ったことがないですが、CSSのみで画像が見切れないので便利だと思いました。そしてCSSだけでデザインの再現が難しい場合はjQueryを使用した方法も解説しました。

以上、いくつかのbackground-repeatの使い所を紹介しましたが、今後も便利なCSSを発見して使いこなせたらなと思います。

参考