object-fit:contain; – 余白部分をフィルターで埋める

画像のサイズがすべて同じサイズで統一されているのであればCSS設計も楽なのですが、実際は横長/縦長と色々なサイズがあるのでobject-fit: contain;で画像サイズを維持し要素内に上手く収まるように設定しても、様々な画像サイズがあるので、画像のサイズによって親要素のコンテンツボックスのサイズに影響を受けて拡大縮小されてしまいます。

そこで余白に対し画像を複製させてその上にフィルターをかけて埋めるといった方法をこの記事で紹介します。イメージとしてはこちらの画像のような感じに仕上げます。

https://unsplash.com/photos/8Q50o-omNRI

作り方

簡単にですが、作りやすいように上の画像の作成イメージをお伝えしておきます。

  1. 余白部分用の背景画像を用意してプロパティfilter: blur;でぼかす。
  2. 背面のぼかし画像の上にメイン画像を配置
  3. メイン画像の上にテキスト要素を配置
  4. 一番上の層にaタグ要素を配置。

サンプルコード

下記のコードをそのまま流用すればサンプル画像のようにしようできます。手順を知りたい場合は下の作成手順をご覧ください。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
	padding:100px;
}
.center{
	margin:0 auto;
}

article.pickup_contents{
	position:relative;
	overflow:hidden;
	width:650px;
	height:400px;
}
.contents_filter > img{
	vertical-align:top;
	width:100%;
	height: 95%;
	margin: 1.5% 0;
	object-fit: contain;
	position: absolute;
	top: 0;
	left: 0;
	z-index:60;
}
.contents_filter > a{
	display:block;
}
.contents_filter > a::before{
	position:absolute;
	top:0;
	left:0;
	content:"";
	display:block;
	width:100%;
	height:100%;
	z-index:90;
}
.contents_filter > a::after{
	position:absolute;
	top:0;
	left:0;
	content:"";
	display:block;
	width:100%;
	height:100%;
	z-index:70;
	transition:.3s;
	background:linear-gradient(rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 1)100%);
}
.contents_filter > a:hover::after{
	opacity:.8;
}
.contents_back_img{
	width:100%;
	height:100%;
}
.contents_back_img > img{
	width:100%;
	height:100%;
	object-fit: cover;
	z-index:50;
	filter: blur(8px);
}
article.pickup_contents > h2{
	position:absolute;
	bottom:20px;
	left:0;
	color:#fff;
	width: 90%;
	margin: 0 5%;
	font-size:20px;
	z-index:85;
}
article.pickup_contents span.top_pickup_tag{
	font-size:15px;
	color:#f0f0f0;
	background:#e30b0b;
	padding:2px 4px;
	margin-right:10px;
}
</style>
</head>
<body>
<article class="pickup_contents center">
	<div class="contents_filter">
		<!-- <a href=""></a> -->
		<img src="./img.jpeg" alt="">
	</div>
	<div class="contents_back_img">
		<img src="./img.jpeg" alt="">
	</div>
	<h2><span class="top_pickup_tag">Pick up</span> Bibliothèque François Mitterrand, Paris, France</h2>
</article>
</body>
</html>

作成手順

余白部分のぼかし画像を作成する

この部分はメイン画像に対してobject-fit:contain;で余白が出た部分を補う箇所になります。コードはこちらになります。

<style>
article.pickup_contents{
	position:relative;
	overflow:hidden;
	width:650px;
	height:400px;
}
.contents_back_img{
	width:100%;
	height:100%;
}
.contents_back_img > img{
	width:100%;
	height:100%;
	object-fit: cover;
	z-index:50;
	filter: blur(8px);
}
</style>
</head>
<body>
<article class="pickup_contents center">
	<div class="contents_back_img">
		<img src="./img.jpeg" alt="">
	</div>
</article>
</body>
</html>

.pickup_contentsでメイン要素のサイズを決め、その中に背面用のぼかし画像を作っています。

背面用の画像はどのみちぼかすのでアスペクト比はお好みで構いません。width:100%; height:100%;だけでもいいですし、object-fitを使って親要素に対して拡大縮小させても構いません。あとは、filterを使用してぼかします。

ただ、filterを使用するとぼかし部分がはみ出てしまいますので、見栄え的に悪いのでoverflow:hidden;で隠します。

背面のぼかし画像の上にメイン画像を配置

先程のコードに下記のコードを追加します。

<style>
article.pickup_contents{
	position:relative;
	overflow:hidden;
	width:650px;
	height:400px;
}
.contents_back_img{
	width:100%;
	height:100%;
}
.contents_back_img > img{
	width:100%;
	height:100%;
	object-fit: cover;
	z-index:50;
	filter: blur(8px);
}
.contents_filter > img{
	vertical-align:top;
	width:100%;
	height: 95%;
	margin: 1.5% 0;
	object-fit: contain;
	position: absolute;
	top: 0;
	left: 0;
	z-index:60;
}
</style>
</head>
<body>
<article class="pickup_contents center">
	<div class="contents_filter">
		<img src="./img.jpeg" alt="">
	</div>
	<div class="contents_back_img">
		<img src="./img.jpeg" alt="">
	</div>
</article>
</body>
</html>

メインの画像を中央配置させるようにすれば大丈夫です。

テキストを入れリンクを加える

最後にテキストを加えてリンクで全面を囲むようにします。

画像の上にテキストを置くとどうしても画像の色によっては見づらくなってしまうので、<a>タグに対して::before, ::afterの擬似要素を作成しています。

::beforeにはアンカーリンク機能。::afterにはテキストの背景に透過させた背景色を設定しています。

そうする事でどの画像の背景色でもテキストが見えやすくなります。

<style>
article.pickup_contents{
	position:relative;
	overflow:hidden;
	width:650px;
	height:400px;
}
.contents_filter > img{
	vertical-align:top;
	width:100%;
	height: 95%;
	margin: 1.5% 0;
	object-fit: contain;
	position: absolute;
	top: 0;
	left: 0;
	z-index:60;
}
.contents_filter > a{
	display:block;
}
.contents_filter > a::before{
	position:absolute;
	top:0;
	left:0;
	content:"";
	display:block;
	width:100%;
	height:100%;
	z-index:90;
}
.contents_filter > a::after{
	position:absolute;
	top:0;
	left:0;
	content:"";
	display:block;
	width:100%;
	height:100%;
	z-index:70;
	transition:.3s;
	background:linear-gradient(rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 1)100%);
}
.contents_filter > a:hover::after{
	opacity:.8;
}
.contents_back_img{
	width:100%;
	height:100%;
}
.contents_back_img > img{
	width:100%;
	height:100%;
	object-fit: cover;
	z-index:50;
	filter: blur(8px);
}
article.pickup_contents > h2{
	position:absolute;
	bottom:20px;
	left:0;
	color:#fff;
	width: 90%;
	margin: 0 5%;
	font-size:20px;
	z-index:85;
}
article.pickup_contents span.top_pickup_tag{
	font-size:15px;
	color:#f0f0f0;
	background:#e30b0b;
	padding:2px 4px;
	margin-right:10px;
}
</style>
</head>
<body>
<article class="pickup_contents center">
	<div class="contents_filter">
		<!-- <a href=""></a> -->
		<img src="./img.jpeg" alt="">
	</div>
	<div class="contents_back_img">
		<img src="./img.jpeg" alt="">
	</div>
	<h2><span class="top_pickup_tag">Pick up</span> Bibliothèque François Mitterrand, Paris, France</h2>
</article>
</body>