フロントの人の雑多メモ

縦横比の異なる画像を、高さを等しく横に並べるJS

縦横比の異なる画像を、高さを等しく横に並べるJS

ギャラリーページなどで使える、アスペクト比のバラバラな画像たちを高さを揃えて横並びに配置できるJavaScriptコードのご紹介。

ちなみに、メインビジュアルは実家で飼ってたうさぎです。

目次

サンプル

高さが等しくなるようにJSで配置しています。これ1つ1つ画像です。

(検証で見てみてね)

5カラムなどにも対応。

CSSはFlexboxでもfloatでもどちらでも良くて、上記はFlex、下記はfloatを使用。

また、このレイアウトを実際に使ってるページがこちら

さかもとこのみOFFICIAL HOMEPAGE

HTML

親要素を.galleryheight、子要素を.colとし、その中にimgタグを入れます。

<ul class="galleryheight">
	<li class="col"><img src="img/img_240_480.png"></li>
	<li class="col"><img src="img/img_680_240.png"></li>
	<li class="col"><img src="img/img_360_360.png"></li>
	<li class="col"><img src="img/img_800_120.png"></li>
	<li class="col"><img src="img/img_680_240.png"></li>
	<li class="col"><img src="img/img_240_480.png"></li>
	<li class="col"><img src="img/img_360_360.png"></li>
	<li class="col"><img src="img/img_240_480.png"></li>
	<li class="col"><img src="img/img_360_360.png"></li>
</ul>

CSS

ごくごく普通のFlexレイアウトです。

というか、ごくごく普通のカラムレイアウトを作成してください

たぶん何カラムでも大丈夫です。

.galleryheight {
	display: flex;
	flex-wrap: wrap;
	margin: 0 0 -2%;
	padding: 0;
	list-style: none;
}
.galleryheight .col {
	width: 32%;
	margin: 0 2% 2% 0;
}
.galleryheight .col:nth-child(3n) {
	margin-right: 0;
}
.galleryheight .col img {
	width: 100%;
}

JS

JSはjQueryバージョンとネイティブJavaScriptバージョンを紹介していきます。

画像が1000枚くらいになると、0.1~0.05秒程度の差が生まれました。

jQueryとJavaScriptの処理速度比較デモ

jQueryバージョン

$(function(){
	//親要素の幅
	let parentWidth = $(".galleryheight").width();
	//子要素
	let elm = $(".galleryheight .col");
	//小要素の数だけwhile文 (forではうまく作れず)
	let elmLen = elm.length;
	let i = 0;
	while(i < elmLen){
		//初めの(左端の)offset (四捨五入)
		let offset = Math.round(elm.eq(i).offset().top);
		//計算用
		let colWidth = 0;
		let imgWidth = 0;
		//その行の配列
		let arr=[];
		//左端と同じoffsetが続く間while文
		while(i < elmLen && offset == Math.round(elm.eq(i).offset().top)){
			//該当の子要素
			let target = elm.eq(i);
			let targetWidth = target.width();
			let targetImg = target.find("img");
			//imgの幅
			let width = targetImg.width();
			//幅が0の場合はスルー
			if(width > 0){
				let height = targetImg.height();
				//試しに高さを1にしてみたときの幅 (以降 テスト幅)
				let testWidth = width / height;
				//配列に追加
				arr.push([target, testWidth]);
				//子要素の幅を加算
				colWidth += targetWidth;
				//テスト幅を加算
				imgWidth += testWidth;
			}

			++i;
		}

		//その行の数(カラム数)だけfor文
		let arrLen = arr.length;
		for(var j = 0; j < arrLen; j++){
			//該当要素のテスト幅 ÷ テスト幅の合計 × 100%で割合を出せるが
			//子要素の幅の合計 ÷ 親要素の幅の合計を掛け、少数第二位で切り捨てにし調整
			let newWidth = Math.floor((arr[j][1] / imgWidth * 100 * colWidth / parentWidth) * 100) / 100;
			//セット
			arr[j][0].css("width", newWidth + "%");
		}
	}
});

JavaScriptバージョン

//親要素の幅
let parentWidth = document.querySelector(".galleryheight").clientWidth;
//子要素
let elm = document.querySelectorAll(".galleryheight .col");

//offset取得用
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;

//小要素の数だけwhile文
let elmLen = elm.length;
let i = 0;
while(i < elmLen){
	//初めの(左端の)offset (四捨五入)
	let offset = Math.round(elm[i].getBoundingClientRect().top + scrollTop);
	//計算用
	let colWidth = 0;
	let imgWidth = 0;
	//その行の配列
	let arr=[];
	//左端と同じoffsetが続く間while文
	while(i < elmLen && offset == Math.round(elm[i].getBoundingClientRect().top + scrollTop)){
		//該当の子要素
		let target = elm[i];
		let targetWidth = target.clientWidth;
		let targetImg = target.getElementsByTagName("img")[0];
		//imgの幅
		let width = targetImg.clientWidth;
		//幅が0の場合はスルー
		if(width > 0){
			let height = targetImg.clientHeight;
			//試しに高さを1にしてみたときの幅 (以降 テスト幅)
			let testWidth = width / height;
			//配列に追加
			arr.push([target, testWidth]);
			//子要素の幅を加算
			colWidth += targetWidth;
			//テスト幅を加算
			imgWidth += testWidth;
		}

		++i;
	}

	//その行の数(カラム数)だけfor文
	let arrLen = arr.length;
	for(var j = 0; j < arrLen; j++){
		//該当要素のテスト幅 ÷ テスト幅の合計 × 100%で割合を出せるが
		//子要素の幅の合計 ÷ 親要素の幅の合計を掛け、少数第二位で切り捨てにし調整
		let newWidth = Math.floor((arr[j][1] / imgWidth * 100 * colWidth / parentWidth) * 100) / 100;
		//セット
		arr[j][0].style.width = newWidth + "%";
	}
}

参考になれば幸いです。

カスタマイズなどもできますので、お気軽にコメントください。

コメント

内容を確認の上、個人情報などは省いて掲載させていただきます。

お名前・メールアドレスも入力する

メールで返信がほしい場合に入力してください。

頂いた個人情報は開示しません。返信のためだけに利用いたします。

直接送信されます。確認の上、「送信」してください。

お役に立てましたら応援をお待ちしております!
頂いた応援は子育てに活用させていただきます。

OFUSEで応援を送る


または以下のボタンからなにか買って応援 (PR)

Amazon

楽天市場

Yahoo!ショッピング

Amazonのアソシエイトとして「けん」は適格販売により収入を得ています。

シェア

Twitterでシェア Facebookでシェア LINEでシェア はてなブックマークでシェア

お役に立てましたら応援をお待ちしております!
頂いた応援は子育てに活用させていただきます。

OFUSEで応援を送る