これまでに何度か「斜めの背景」や「丸みを帯びたアーチ状の背景」を使ったサイトを作ることがありました。その度に実装方法を悩んでいましたが、最近ではSVGを使うのが1番良いのでは?と思うようになってきました。
今回はその方法についてをメモしておきます。
斜め背景を作る方法はいくつかあります。
translate:rotate()
を使って長方形を回転させて配置するtranslate:skew()
を使って長方形を歪ませる1番簡単なのが1つ目の「斜めに切り出した画像を使う」方法で、2、3と少し実装の難易度が高くなります。ただし難易度が高くなってキレイに表示されるかというと、そうでもなく結局は端がギザギザになる現象と戦うことは必至です。
2、3のCSSの場合は画像に比べると色の変更や角度などの調整がしやすいことや、画像を置かないため読み込みに使われるリソースが減らせると言った利点はあります。
でもギザギザ。
やっぱりビットマップデータで斜めにするのはかなり強引な気がします。
そこで使えるのがベクターデータの「SVG」です。
前置きが長くなってしまったので、全部の方法で一度斜め背景を使ったデモページを作ってみることにします。
どうでしょうか?
ちょっとわかりにくいかもしれませんが、SVGの方が鮮明ではないですか?
SVGは「.svg」という拡張子で画像として扱うのではなく、htmlのソース内に直接書きます。こうすることでSVGの要素にもCSSを使うことができるので、色変更も簡単になりますし、外部ファイルの読み込みを減らすこともできます。
あとデモ作ってみて思いましたが、CSSのtransform:skew()
とSVGは設置が簡単ですが、PNGはPhotoshop開いて画像作って設置してがめんどくさい割にギザギザ、transform:rotate()
は角度とか幅合わしたりの計算がすごいめんどくさいのでかなり目分量で合わすことになってややこしいし不具合出そう。
ただ見た目に関してはCSSでも許容範囲かもしれません。スマホで拡大すると若干ジャギってるかなってくらいでした。
一応、デモで使った実際のコードを書いておきます。
<div class="demo">
<div class="demo-item">
<div class="demo-item__inner png">
<img
class="top"
src="diagonal-bg-top.png">
<p class="demo-title">PNG</p>
<img
class="bottom"
src="diagonal-bg-bottom.png"
>
</div>
<!-- /.demo-item__inner -->
</div>
<!-- /.demo-item -->
</div>
<!-- /.demo -->
.demo{
background:$blue;
&-item{
padding:30px 0;
background:#fff;
/* メディアクエリ判定のMixinでレスポンシブ対応 */
@include min-screen(768px){
padding:150px 0;
}
&__inner{
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height:60vh;
background:url(bg-1.jpg) no-repeat center center;
background-size: cover;
@include min-screen(768px){
height:100vh;
}
&.png{
.top{
position: absolute;
top:0;
right:0;
z-index: 10;
width: 100%;
}
.bottom{
position: absolute;
bottom:0;
left:0;
z-index: 10;
width: 100%;
}
}
}
}
}
単純に用意したPNG画像を上下に配置しているだけです。
<div class="demo">
<div class="demo-item">
<div class="demo-item__inner rotate">
<p class="demo-title">transform:rotate()</p>
</div>
<!-- /.demo-item__inner -->
</div>
<!-- /.demo-item -->
</div>
<!-- /.demo -->
.demo-item__inner
に繋げて追記
&.rotate{
overflow: hidden;
&::before,
&::after{
content:"";
position: absolute;
display: block;
width: 120%;
height:200px;
background:#fff;
transform:rotate(-4deg);
}
&::before{
top:-139px;
right:0;
z-index: 10;
}
&::after{
left:0;
bottom:-139px;
z-index: 10;
}
}
before
・after
擬似要素を使って長方形を作り、それを回転させて配置しています。ただ回転させるだけでなく、ちょっと大きくして位置をずらす必要があるので調整がかなりめんどいです。。。。数学よわよわなのでずらす位置の計算方法があるのかは謎。笑
<div class="demo">
<div class="demo-item">
<div class="demo-item__inner skew">
<p class="demo-title">transform:skew()</p>
</div>
<!-- /.demo-item__inner -->
</div>
<!-- /.demo-item -->
</div>
<!-- /.demo -->
.demo-item__inner
に繋げて追記
&.skew{
overflow: hidden;
&::before,
&::after{
content:"";
position: absolute;
display: block;
width: 100%;
height:100px;
background:#fff;
transform:skewY(-4deg);
}
&::before{
top:-50px;
right:0;
z-index: 10;
}
&::after{
left:0;
bottom:-50px;
z-index: 10;
}
}
before
・after
擬似要素を使って長方形を作り、transform:skewY()
でY方向だけ歪みを入れることで斜めの形を作っています。こちらもずれた分だけ上下の位置調整が必要ですが、先ほどのtransform:rotate()
よりは比較的調整が簡単。
<div class="demo">
<div class="demo-item">
<div class="demo-item__inner svg">
<div class="svg-box top">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1440 100" preserveAspectRatio="none">
<path d="M0,0 v100 l1440,-100 Z" fill="#ffffff" />
</svg>
</div>
<!-- /.svg-box -->
<p class="demo-title">SVG</p>
<div class="svg-box bottom">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1440 100" preserveAspectRatio="none">
<path d="M0,100 l1440,0 v-100 Z" fill="#ffffff" />
</svg>
</div>
<!-- /.svg-box -->
</div>
<!-- /.demo-item__inner -->
</div>
<!-- /.demo-item -->
</div>
<!-- /.demo -->
.demo-item__inner
に繋げて追記
&.svg{
.svg-box{
position: absolute;
height:0;
padding-top: calc(100 / 1440 * 100%);
z-index: 10;
width: 100%;
}
.top{
top:0;
right:0;
}
.bottom{
bottom:0;
left:0;
}
svg{
position: absolute;
top: 0;
left: 0;
display: block;
width: 100%;
height: 100%;
}
}
PNGの時と同じく上下にSVGを配置します。ただインラインSVG(HTMLに直接埋め込んだSVG)は少し癖があるので注意。インラインSVGの場合は親要素(.svg-box
)を作り、そこにposition:absolute;
で絶対配置するようにします。SVGの親要素にはheight:0;
としてpadding-top
で高さを付けます。ここの場合はcalc(100 / 1440 * 100%)
として横幅1440pxの時に高さ100pxになるように計算させています。こうすることでIEでもSVGをレスポンシブ対応できます。SVGはPath要素の機能を使って対角線を通るパスを引いてあげるだけでOKです。SVGの書き方について参考にしたサイトは下の注意点の後に掲載しています。
SVGはイラレやフォトショで書き出した際にそのまま読み込むと、アスペクト比を保とうとして画像が横幅100%まで広がってくれません。
そのため、レスポンシブ対応するためには<svg>
要素に以下の属性を追記する必要があります。
preserveAspectRatio="none"
この記述があるとアスペクト比を無視して思った通りの幅に広がってくれます。svgはベクターデータなので、pngなどのビットマップデータと違って画像がどんなに伸びたり縮んだりしようが引き伸ばされて画像が粗くなることはありません。そのためこういう背景などに使う時は画面サイズに合わせて伸びてくれた方が便利なんですよね。
先ほど使った斜め背景にも追記しています。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1440 100" preserveAspectRatio="none">
<path d="M0,100 l1440,0 v-100 Z" fill="#ffffff" />
</svg>
ということで、画面サイズに合わせて可変させたいSVGにはpreserveAspectRatio="none"
を追記しましょう!
ちなみに今回はイラレを使わず普通にSVGのPath機能を使って描画しました。
Pathの書き方についての参考サイトは古い記事ですが下記です。「画面全体に斜め線を引く」の部分で簡単なPathの書き方についてわかりやすく書いてあります。
SVGで画面全体に斜め線や曲線を引く
https://www.webopixel.net/javascript/1024.html
これはもう典型的に画像でしか作れない形状ですね。(CSSマスターの方は作れるかもしれません)PNGとSVGバージョンを作りました。
このSVGにもpreserveAspectRatio="none"
を追記して、CSSで画像のサイズを調整しています。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1440 435" width="1440px" height="435px" preserveAspectRatio="none">
<path fill-rule="evenodd" fill="#ccc" d="M-0.000,434.875 L-0.000,253.000 L-0.000,248.000 C-0.000,204.260 -0.000,31.932 -0.000,0.000 C449.375,242.487 990.625,242.487 1440.000,0.000 C1440.000,31.932 1440.000,204.260 1440.000,248.000 L1440.000,253.000 L1440.000,434.875 L-0.000,434.875 Z"/>
</svg>
このSVGはPhotoshopで長方形をワープさせたものを別の長方形と結合させて作りました。イラレでも同じことができると思います。SVGにめちゃ強の人はPath要素にそのまま書いてもできるかも。笑
SVGを使うとクロスブラウザ対応ができ、キレイに表示できるだけでなくIE11でも見れるのでかなり使えるテクニックだと思います。
今回はSVGで斜めやアーチ状などの変わった形状もレスポンシブでキレイに表示できる方法をメモしました。
最近のデザイントレンドで「アイソメトリックイラスト」などを使うような案件だとSVGを使った曲線の背景との組み合わせを要求されることもあると思います。受託制作だと「ギザギザになってるよ」とか普通に突っ込まれそうなので対処法として覚えておいても良いかなと思います。