Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Suggestion: Equal Height Columns #1358

Closed
kretchy opened this issue Jan 6, 2013 · 18 comments
Closed

Feature Suggestion: Equal Height Columns #1358

kretchy opened this issue Jan 6, 2013 · 18 comments

Comments

@kretchy
Copy link

@kretchy kretchy commented Jan 6, 2013

.block-grid is a cool div-feature in Foundation. One thing that would be nice is to incorporate an option to design "rows" of "cells" with equal heights, discussed over here for instance: http://css-tricks.com/fluid-width-equal-height-columns/

@ghost
Copy link

@ghost ghost commented Jan 10, 2013

Would be very nice. My current workflow is giving those elements a min-height, which I then drop to 0px for small screens.

@ghost ghost assigned hatefulcrawdad Jan 11, 2013
@davilima6
Copy link

@davilima6 davilima6 commented Mar 17, 2013

+1

@brianlarson
Copy link

@brianlarson brianlarson commented Mar 28, 2013

Would love to see this too. Anyone know of the best workaround to do this with .panel? For instance, having a sidebar stretch below to match the main content height.

@rainwiz
Copy link

@rainwiz rainwiz commented May 15, 2013

+1

@hatefulcrawdad
Copy link

@hatefulcrawdad hatefulcrawdad commented May 15, 2013

Okay guys, we've been thinking about this for awhile. We hardly ever run into this as a main use-case for the grid in Foundation or for layouts we build. We definitely recognize that this is a useful feature and has its place on certain projects. We are going to say no on this for a core feature, but I didn't want to leave people hanging. Below is an example of what you can do to get that feature on your project.

Here's some example HTML of a grid snippet and a block-grid snippet. You'll notice a few data attributes, data-match-height and data-height-watch. These are used to scope the parent of the elements you want as the same height and to mark the children that will look to match heights.

<div class="row" data-match-height>
  <div data-height-watch class="small-3 columns" style="background: pink;">
    <p>Some text...</p>
  </div>
  <div data-height-watch class="small-6 columns" style="background: orange;">
    <p>Some text...</p>
    <img src="http://placehold.it/300x300">
  </div>
  <div data-height-watch class="small-3 columns" style="background: lightblue;">
    <p>Some text...</p>
  </div>
</div>

<br>

<div class="row" data-match-height>
  <div class="small-12">
    <ul class="small-block-grid-3">
      <li data-height-watch style="background: pink; height: 100px;">
        <p>Some text...</p>
      </li>
      <li data-height-watch style="background: orange; height: 120px;">
        <p>Some text...</p>
      </li>
      <li data-height-watch style="background: lightblue; height: 140px;">
        <p>Some text...</p>
      </li>
      <li data-height-watch style="background: purple; height: 150px;">
        <p>Some text...</p>
      </li>
      <li data-height-watch style="background: gray; height: 100px;">
        <p>Some text...</p>
      </li>
      <li data-height-watch style="background: pink; height: 200px;">
        <p>Some text...</p>
      </li>
    </ul>
  </div>
</div>

From here, I created a some JS that will do the magic:

$("[data-match-height]").each(function() {

  var parentRow = $(this),
      childrenCols = $(this).find("[data-height-watch]"),
      childHeights = childrenCols.map(function(){ return $(this).height(); }).get(),
      tallestChild = Math.max.apply(Math, childHeights);

  childrenCols.css('min-height', tallestChild);

});

You can include this JS in app.js under the JS links at the bottom of your pages.

In the case where you need a sidebar to be as tall as the main content area, just use a background image that repeats down the .row that holds both.

@fatlinesofcode
Copy link

@fatlinesofcode fatlinesofcode commented May 20, 2013

If you want to always have square thumbnails add a square transparent png and then add the real image as background-image.

<ul class="small-block-grid-4 large-block-grid-5">
  <li>
          <div style="background-image: url('myimage.jpg')">
          <img src="1x1.png"/>
          </div>
  </li>
</ul>

li{
    div{
      background: no-repeat top center;
      background-size: cover;
    }
    img{
      min-width: 100%;
    }
  }
@mhayes
Copy link
Contributor

@mhayes mhayes commented Jul 23, 2013

If someone is still looking for a way to accomplish equal-height panels, you can add the following JS snippet to your page:

$('.row[data-match-height]').each(function(){
  var self = $(this);
  self.find('.panel').height(self.height());
  $(window).on('resize', function(event) {
    var row_width = self.width();
    var panels = self.find('.panel');
    // Reset height of the panels
    panels.height('');
    var h = self.height();
    panels.each(function() {
      var panel = $(this);
      if ((row_width - panel.width()) > 40) {
        panel.height(h);
      }
    });
  });
});

To use it, just create a <div> container with a data-matching-height attribute, like so:

<div class="row" data-match-height>
  <div class="large-4 columns">
    <div class="panel">
      <h4>Panel 1</h4>
    </div>
  </div>
  <div class="large-4 columns">
    <div class="panel">
      <h4>Panel 1</h4>
    </div>
  </div>
  <div class="large-4 columns">
    <div class="panel">
      <h4>Panel 1</h4>
    </div>
  </div>
</div>

This will ensure that panels are equal height until they are viewed on a mobile device, at which point they will resort to their natural height. Hope that helps, happy coding!

@jaffe75
Copy link

@jaffe75 jaffe75 commented Aug 24, 2013

Would love to see this work for Tabs as well. Any thoughts?

@kalisurfer
Copy link

@kalisurfer kalisurfer commented Sep 3, 2013

After implementing the above feature, my panels get really really long (as in heights). Please note that the loop generates around 84 items.

Here is the code

<% for (var i=0; i < data.length; i++){ %>
  <% if (i==0) { %>
    <div class="large-6 small-12 columns">
  <% } else { %>
    <div class="large-3 small-6 columns">
  <% } %>



      <a href="/details/<%= data[i]._id %>"><img src="<%= data[i].get('thumbUrl') %>" /></a>
      <div class="panel">
        <div class="row">
          <div class="small-2 columns gametitle"><h5><%= i+1 %></h5></div>
          <div class="small-10 columns gametitle"><h6><%= data[i].title %></h6></div>
        </div>
         <div class="row">
          <div class="large-12 columns gametitle"><%= data[i].get('trendIndex') %></div>
        </div>
      </div> 
    </div>
  <% } %>
</div>
@jmarston4
Copy link

@jmarston4 jmarston4 commented Sep 5, 2013

@hatefulcrawdad - can you share why you don't see this is a main use case? It seems having for portfolio type situations (image in one half of a row, text description in the other) would arise quite a bit. I am not sure I agree a JS solution is "right" for those who still need to support (dummies) with JS turned off. Dummies or not, in some corporate spaces we have to support them or lose 5-10% of customers.

@KarlEyeWeb
Copy link

@KarlEyeWeb KarlEyeWeb commented Nov 1, 2013

@hatefulcrawdad in case anyone else has this issue with the Javascript provided.

If you want to get the height of a div which just contains an image you'll need to wrap the function inside of a $(window).load() as this will then only trigger once the whole page has loaded, including images. Whereas $(document).ready() only checks that the DOM elements have been created before triggering, therefore giving inaccurate results.

If you want to include padding too you can change $(this).height(); to $(this).outerHeight();

This is what I use for more accurate results:

    $(window).load(function() {
        $("[data-match-height]").each(function() {
            var parentRow = $(this),
                childrenCols = $(this).find("[data-height-watch]"),
                childHeights = childrenCols.map(function(){ return $(this).outerHeight(); }).get(),
                tallestChild = Math.max.apply(Math, childHeights);
            childrenCols.css('min-height', tallestChild);
        });
    });
@gormus
Copy link
Contributor

@gormus gormus commented Nov 15, 2013

@KarlEyeWeb, may I suggest a little tweak to your code. Here is how I changed to make it work with nested grids.

I only changed the childrenCols selector to find immediate children:

$(window).load(function() {
  $("[data-match-height]").each(function() {
    var parentRow = $(this),
      childrenCols = $("> [data-height-watch]", this),
      childHeights = childrenCols.map(function(){ return $(this).outerHeight(); }).get(),
      tallestChild = Math.max.apply(Math, childHeights);
    childrenCols.css('min-height', tallestChild);
  });
});
@gormus
Copy link
Contributor

@gormus gormus commented Nov 15, 2013

If you'd like to have vertical lines between each column, except the one displayed on the edge, here is my "work-in-progress" solution.

[data-height-watch] {
  border-left: 1px solid gray;
}
[data-match-height] > [data-height-watch][data-height-watch-novrule] {
  border-left: 0 none;
}

@media only screen and (max-width:1023px) {
  [data-height-watch] {
    min-height: 1px !important;
    border-left: 0 none !important;
  }
}

I add [data-height-watch-novrule] attribute to the columns where I don't want any vertical lines:

<div class="row" data-match-height>
  <div class="medium-12 large-9 large-push-3 columns" data-height-watch>
    Main column on the right
  </div>
  <div class="large-3 large-pull-9 columns" data-height-watch data-height-watch-novrule>
    Sidebar column on the left
  </div>
</div>
@shadysamir
Copy link

@shadysamir shadysamir commented Dec 29, 2013

The code above by @hatefulcrawdad is what I needed. Except that it doesnt count for box-sizing model used by foundation (and all modern frameworks). While JQuery height will return the actual height regardless of margins and padding this is not what we need in this case. This is why the value from css("height") is what we need to set as min-height. My code below applies equal heights to ALL block grids, something I think should be done by foundation as default. If you wish to customize that, change the selectors.

TODO: Disable script if large only is used and screen is small.

$("ul[class *= 'block-grid']").each(function() {
  var parentRow = $(this);
  childrenCols = $(this).find("li");
  childHeights = childrenCols.map(function() {
    return $(this).height();
  }).get();
  childCssHeights = childrenCols.map(function() {
    return $(this).css('height');
  }).get();
  tallestChild = Math.max.apply(Math, childHeights);
  cssIndex = childHeights.indexOf(tallestChild);
  childrenCols.css('min-height', childCssHeights[cssIndex]);
});
@rafibomb
Copy link
Member

@rafibomb rafibomb commented Jan 17, 2014

This will be part of 5.1. We'll close this in favor of #3950

@snappercridge
Copy link

@snappercridge snappercridge commented Feb 5, 2014

I'm hoping the issue in 5.1 will address a substantial need in this function to not just measure the height of all the element, but also depending on their row. In other words what if the second row of content block's tallest element is different from row to row. This addition should include that adjustment as outlined here: http://css-tricks.com/examples/EqualHeightsInRows/

@joshbedo
Copy link

@joshbedo joshbedo commented Jun 26, 2014

If you guys want a non-hacky/non javascript solution you can use pseudo selectors like shown here
https://webdesign.tutsplus.com/tutorials/quick-tip-solving-the-equal-height-column-conundrum--cms-20403

All the JavaScript solutions i've seen for this are entirely overkill and you should not listen to the window resize event to calculate your layout.

@brianlarson
Copy link

@brianlarson brianlarson commented Jun 30, 2014

I believe we're all set now with Foundation's new Equalizer component: http://foundation.zurb.com/docs/components/equalizer.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet