質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.04%

フロートの高さ揃えについて

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 5
  • VIEW 2,276

MrSung

score 13

Webデザインを主にやっていまして、JavaScriptに関してはまだまだ勉強不足な点が多く、進めていく中でわからない箇所が出てきましたので質問させてください。

現在、マルチカラムレイアウトを作っていまして、tableレイアウトやflexboxは使用できない制約下にあります。

使用するのはレガシーブラウザにも対応したfloatを使用したレイアウトになるのですが、ご存知の通り、floatでは中身の要素の高さがそのまま各boxの高さになってしまいますので、下図のようにレイアウトが崩れてしまいます。

高さが揃っていない状態

そこで、高さ揃えのプラグインなどを用いて調整するわけですが、こちらも制約があり、自作のスクリプトで高さ揃えをしないといけません。

HTMLの構成としては、fixedレイアウトでunorderd list直下にlistが並んでいる状態です。
nカラム構成なのかを取得して、各行ごとの高さを揃えるというスクリプトを、まず以下のように考えました。

$(function(){

  "use strict";

  // Get total number of lists
  var numberOfLists = $('li:last-of-type').index() + 1;
  //console.log('numberOfLists:', numberOfLists);

  // Get width of parent ul and li
  var widthOfParent = $('li').parent().width(), 
      widthOfLi = $('li').outerWidth();
  //console.log('widthOfLi:', widthOfLi);

  // Count how many lists are in one row
  var listsInRow = Math.floor(widthOfParent/widthOfLi);
  //console.log('listsInRow:', listsInRow);

  // Count how many lists are in one column
  var listsInColumn = Math.ceil(numberOfLists/listsInRow);
  //console.log('listsInColumn:', listsInColumn);


  var r = listsInRow, 
      c = listsInColumn;

  // Add the same class to lists in one row
  for (var i=1; i<=c; i++) {
    $('li:nth-of-type('+'-n'+(i*r)+')').addClass('equal_height--'+i);
    for (var j=1; j<=c; j++) {
      for (var k=1; k<c; k++) {
        $('.equal_height--'+j).removeClass('equal_height--'+(j+k));
      }
    }
  }  


  // Give each class the same height
  var biggestHeight_1 = 0, 
      biggestHeight_2 = 0, 
      biggestHeight_3 = 0;  

  $('.equal_height--1').each(function(){  
    if($(this).height() > biggestHeight_1){    
      biggestHeight_1 = $(this).height();  
    }  
  });  
  $('.equal_height--1').height(biggestHeight_1); 

  $('.equal_height--2').each(function(){  
    if($(this).height() > biggestHeight_2){    
      biggestHeight_2 = $(this).height();  
    }  
  });  
  $('.equal_height--2').height(biggestHeight_2); 

  $('.equal_height--3').each(function(){  
    if($(this).height() > biggestHeight_3){    
      biggestHeight_3 = $(this).height();  
    }  
  });  
  $('.equal_height--3').height(biggestHeight_3); 


  // Failed pattern 3
//   var biggestHeights = [], 
//       equal_heights = [];
//   for (var m=1; m<=c; m++) {
//     biggestHeights.push('biggestHeight_'+m);
//     equal_heights.push('.equal_height--'+m);
//   }
//   console.log(biggestHeights,equal_heights);

//   $.each($(equal_heights), function(){
//     for (var n=1; n<=c; n++) {
//       if($(this).height() > biggestHeights[n]){
//         biggestHeights[n] = $(this).height();
//       }
//       $(equal_heights).height(biggestHeights[n]);
//     }
//   });  


  // Failed pattern 2
//   var biggestHeight = 'biggestHeight_', 
//       arr = [], 
//       maxArr = []; 
//   for (var m=0; m<c; m++) {
//     arr = biggestHeight + String(m);
//     //console.log(arr);
//     $('.equal_height--'+(m+1)).height();
//   }


  // Failed pattern 1  
//   var biggestHeight = 0, 
//       arr = [], 
//       maxArr = [];
//   for (var m=1; m<=c; m++) {
//     for (var n=1; n<=r; n++) {
//       arr[m-1][m+n-2] = $('.equal_height--'+m+':nth-of-type('+n+')').height();
//       //$('.wrap').append('<p>'+arr[m-1][m+n-2]+'</p>');
//     }
//   }
//   $('.wrap').append('<p>'+arr[0]+'</p>');
//   for (var p=0; p<c; p++) {
//     maxArr[p] = Math.max(arr[p]);
//   }

//   for (var q=1; q<=c; q++) {
//     $('.equal_height--'+q).height(maxArr[q]);
//   } 


});

各行ごとに同じクラス名を割り当てて、その中で比較をし、一番高い高さを、同じ行の中の要素全てに適用するという設計で、下図のように上手く揃ってくれたのですが、

高さが揃っている状態

最後の各クラスごとに高さ揃えをするというコード(// Give each class the same heightの下)を上手くまとめることができません。

全体的な設計やコードの書き方も含めて、ご教授いただけると幸いです。

ご参考までに、HTMLとCSSは下記のような感じです。

<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
    <div class="wrap">
       <ul>
          <li>Lorem ipsum dolor sit amet, no vel aliquid singulis, vix ex paulo choro. Facilisis concludaturque per eu, ad eius dolorem deleniti sed, quas detraxit et vel. At novum platonem sit.</li>
          <li>Lorem ipsum dolor sit amet, no vel aliquid singulis, vix ex paulo choro. Facilisis concludaturque per eu, ad eius dolorem deleniti sed, quas detraxit et vel. At novum platonem sit. Qui eros timeam percipit te, possit mnesarchum ne mel. Et est iisque legendos,</li>
          <li>Doctus phaedrum id est, pro lorem intellegam ut. Dicat deleniti instructior mel ei. Debet oratio tacimates vim ea, te pri rebum choro, scaevola volutpat omittantur ne nec. Natum eirmod facilisis mel in, porro appetere disputationi eu pri.</li>
          <li>Minim ridens duo in, ut his nibh albucius definitionem, id vis essent mollis interesset. Probo graece te cum.</li>
          <li>No sit semper maiorum, nibh nominati ei vim. Pro unum liber conceptam ut. No invidunt perfecto indoctum pri, ex falli mundi duo, esse fugit ea est. Mel ei ipsum aeterno bonorum, solum illud honestatis te nam, viderer intellegat et mea.</li>
          <li>Cu iuvaret volumus detracto eos, altera accusam eos ei, te falli suscipit comprehensam eam. Has ea graeci consequat, ex assum ponderum consetetur ius, electram iudicabit definitionem mea in.</li>
          <li>Id quo porro alterum. Ne mea purto case. Quod nonumes corpora et sed, te quod fugit pri. Cu sea quis purto decore, ad iusto tation sed, iriure menandri honestatis te usu.</li>
          <li>Vocent evertitur te has, exerci impetus ullamcorper ut sit. Has nulla mazim at, est harum molestie ei, vim et corpora deleniti consequuntur. Elit atqui nostrum ad nam, ad sententiae adipiscing eum. Electram petentium laboramus his ut, malis inani voluptaria id est. Cu iuvaret volumus detracto eos, altera accusam eos ei, te falli suscipit comprehensam eam. Has ea graeci consequat, ex assum ponderum consetetur ius, electram iudicabit definitionem mea in.</li>
          <li>Doctus phaedrum id est, pro lorem intellegam ut. Dicat deleniti instructior mel ei. Debet oratio tacimates vim ea, te pri rebum choro, scaevola volutpat omittantur ne nec. Natum eirmod facilisis mel in, porro appetere disputationi eu pri.</li>
          <li>Minim ridens duo in, ut his nibh albucius definitionem, id vis essent mollis interesset. Probo graece te cum.</li>
          <li>No sit semper maiorum, nibh nominati ei vim. Pro unum liber conceptam ut. No invidunt perfecto indoctum pri, ex falli mundi duo, esse fugit ea est. Mel ei ipsum aeterno bonorum, solum illud honestatis te nam, viderer intellegat et mea. Id quo porro alterum. Ne mea purto case. Quod nonumes corpora et sed, te quod fugit pri. Cu sea quis purto decore, ad iusto tation sed, iriure menandri honestatis te usu.</li>
          <li>Cu iuvaret volumus detracto eos, altera accusam eos ei, te falli suscipit comprehensam eam. Has ea graeci consequat, ex assum ponderum consetetur ius, electram iudicabit definitionem mea in.</li>
      </ul>


    </div>
</body>
</html>
@import url(https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css);

$col-4: 960px;
$col-3: 725px;
$col-2: 530px;
$padding-wrap: 20px;

$width-li: 215px;
$padding-li: 10px;

html {
  box-sizing: border-box;
}
*, *::before, *::after {
  box-sizing: inherit;
}

body {
  background-color: lightgray;
}

.wrap {
  width: $col-4;
  padding: $padding-wrap;
  margin: 20px auto;
  background-color: #fff;
  box-shadow: 0 0 1px #ccc;
}

ul {
  overflow: hidden;
  list-style: none;
  & li {
    width: $width-li;
    padding: $padding-li;
    margin-bottom: 20px;
    float: left;
    color: #fff;
    &:not(:nth-of-type(4n)) {
      margin-right: 20px;
    }  // 3col: 3n, 2col: 2n
    &:nth-of-type(8n+1) {
      background-color: tomato;
    }
    &:nth-of-type(8n+2) {
      background-color: orange;
    }
    &:nth-of-type(8n+3) {
      background-color: desaturate(yellow, 30%);
    }
    &:nth-of-type(8n+4) {
      background-color: lighten(green, 10%);
    }
    &:nth-of-type(8n+5) {
      background-color: blue;
    }
    &:nth-of-type(8n+6) {
      background-color: navy;
    }
    &:nth-of-type(8n+7) {
      background-color: purple;
    }
    &:nth-of-type(8n) {
      background-color: gray;
    }
  }
}

どうぞよろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

コメントがないと意味不明なソースになってしまいました。。。

var ulObj = $("div.wrap ul");
var liList = ulObj.children("li");
var liCount = liList.length;
var liWidth = liList.outerWidth();
var colCount = Math.floor(ulObj.outerWidth() / liWidth);

var counter = 0;
var greatestHeight = 0;
liList.each(function(index, value) {
    counter++;
    var height = $(value).outerHeight();
    greatestHeight = height > greatestHeight ? height : greatestHeight;

    if (counter == colCount || index == liCount - 1) {
        liList.slice(index - (counter - 1), index + 1).css("height", Math.round(greatestHeight));
        counter = 0;
        greatestHeight = 0;
    }
});

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/17 14:50

    おっしゃる通り、コメントがなくて意味不明ですが(笑)、
    こちらのやり方で、あっさりと解決してしまいました。。

    勉強になります。
    ありがとうございました。

    キャンセル

+1

for や .each() で繰り返し処理を作るだけで解決しそうですが、

for (var i = 1, l = 3, biggestHeight = 0, elements; i < l; ++i) {
  elements = jQuery('.equal_height--' + i);
  elements.each(function () {
    var height = jQuery(this).height();

    if (height > biggestHeight) {
      biggestHeight = height;
    }
  });
  elements.height(biggestHeight);
}

後々の事を考慮して汎用関数を作っておくとすっきりと思われます。

function setSameHeightByElements (elements1 /* [,elements2, ...] */) {
  for (var i = 0, l = arguments.length, biggestHeight = 0, elements; i < l; ++i) {
    elements = arguments[i];

    if (!(elements in jQuery)) {
      throw new Error(elements + ' is not a jQuery object');
    }

    for (var j = 0, m = elements.length; j < m; ++j) {
      var height = jQuery(elements[j]).height();

      if (height > biggestHeight) {
        biggestHeight = height;
      }
    }

    elements.height(biggestHeight);
  }
}

setSameHeightByElements(jQuery('.equal_height--1'), jQuery('.equal_height--2'), jQuery('.equal_height--3'));

Re: MrSung さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/17 14:48

    ご丁寧なご回答ありがとうございます!

    上段のJSで試してみたのですが、なぜか2段目以降が、全て同じ高さになってしまいました。。

    書き方、ご参考にさせてください。

    キャンセル

+1

mapを利用して段階的にやってみました。
クラスを付ける部分もmapで書き直してみましたが、高さをそろえるための全体の手順としては不要でした。

var setEqualHeight = function(){
  var $li = $('li');

  var numberOfLists = $li.length;
  //console.log('numberOfLists:', numberOfLists);

  // Get width of parent ul and li
  var widthOfParent = $li.parent().width(), 
      widthOfLi = $li.outerWidth();
  //console.log('widthOfLi:', widthOfLi);

  // Count how many lists are in one row
  var listsInRow = Math.floor(widthOfParent/widthOfLi);
  console.log('listsInRow:', listsInRow);

  // Count how many lists are in one column
  var listsInColumn = Math.ceil(numberOfLists/listsInRow);
  console.log('listsInColumn:', listsInColumn);

  // Add the same class to lists in one row
  $.map($li, function(item, index){
    var $item = $(item),
        num = Math.floor(index / listsInRow) + 1,
        className = 'equal_height--' + num;

    $item.addClass(className);
  });

  // 各要素の高さを集めた配列を作成
  var heightArray = [];

  $.map($li, function(item, index){
    var $item = $(item),
        height = $item.height(),
        num = Math.floor(index / listsInRow);

    heightArray[num] = heightArray[num] || [];
    heightArray[num].push(height);
  });

  console.log(heightArray);
  // n行目の要素の高さが heightArray[n-1]に配列としてまとめられた二重配列ができる。
  // [[128,192,192,80],[176,144,128,352],[192,80,304,144]]

  // 上記二重配列を元にして、最大の高さだけを抽出した配列を作成
  var maxHeightArray = $.map(heightArray, function(item, index){
    var maxHeight = Math.max.apply(null, item); // 配列の中から最大値を抽出
    return maxHeight;
  });

  console.log(maxHeightArray); // [192,352,304]

  // 上記結果を各行に適用
  $.map($li, function(item, index){
    var $item = $(item),
        num = Math.floor(index / listsInRow),
        maxHeight = maxHeightArray[num]; // 最大の高さを上記配列から取り出す

    $item.height(maxHeight);
  });
}

setEqualHeight();

最後の適用をfor文でやるとこんな感じでした。

// 上記結果を各行に適用
 var $content = $li;

 for(var i = 0; i < listsInColumn ;i++){
  var $target = $content.slice(0, listsInRow), // 1行目から順に4つずつ抽出
      maxHeight = maxHeightArray[i];

  $target.height(maxHeight);
  $content = $content.slice(listsInRow); // 高さを適用した行を除外して、ループの最初に戻る
 }

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる