I'm trying to equalise the heights of some content in a div. When I load the page, it looks like this:
I get this output in the console:
Content loop no.0
177
Content loop no.1
177
Content loop no.2
177
DONE
In the above output im logging the heights of each element when they loop. However, the second and third elements are 203px tall, not 177. When I resize my browser window, it corrects itself, and all works as expected. When I set breakpoints and step through the code, it works as expected. It only seems to happen when I refresh my browser???
I'm trying to only equalise the heights if the column is NOT full width.
Here is my code:
var c,
Cards = {
//Settings
settings: {
row: $('.row'),
card: $('.card')
},
//Initialising Function
init: function() {
c = this.settings;
this.resizeCard();
},
resize: function() {
c = this.settings;
this.resizeCard();
},
resizeCard: function() {
// Reset height
$('.card-content').css('height','');
// Iterate through each "Row" element
c.row.each(function(i) {
var rowWidth = c.row.width(),
columns = $(this).find('.grid-column'),
cards = $(this).find('.card'),
contentHeight = 0;
// If there's more than one card in this row...
if(cards.length > 1) {
// Iterate through each column, check the width
columns.each(function() {
if(rowWidth > $(this).outerWidth()) {// If the card is in a row of cards
$(this).find('.card').addClass('equal-height'); // Add the equal height class
}
});
}
// Iterate through each content div under "Equal Height" cards
$(this).find('.equal-height .card-content').each(function(i) {
console.log("Content loop no." + i)
if($(this).height() > contentHeight) {
contentHeight = $(this).height();
}
console.log(contentHeight)
})
// Set the final height of the content
if(contentHeight > 0) {
console.log("DONE");
$(this).find('.equal-height .card-content').css('height',contentHeight);
}
});
}
}
Related
I want to create a gallery grid slider responsive with equal height boxes.
Example
650px wide and above 3 columns and 2 rows.
550px wide and below 2 columns and 3 rows.
450px wide and below 1 column and 1 row.
I have been using this jQuery plugin https://github.com/liabru/jquery-match-height for now.
Can I use this with an other plugin slider or there's another alternative?
(function() {
/* matchHeight example */
$(function() {
// apply your matchHeight on DOM ready (they will be automatically re-applied on load or resize)
var byRow = $('.item-wrapper').hasClass('match-rows');
// apply matchHeight to each item container's items
$('.item-container').each(function() {
$(this).children('.item-query').matchHeight({
byRow: byRow
});
});
});
})();
https://jsfiddle.net/76cx7roy/
Here: I used bxslider.
But the problem is not responsive changing 2 columns and 3 rows to 1 column and 1 row. It only works when its load.
(function() {
/* matchHeight example */
$(function() {
// apply your matchHeight on DOM ready (they will be automatically re-applied on load or resize)
var byRow = $('.item-wrapper').hasClass('match-rows');
// apply matchHeight to each item container's items
$('.item-container').each(function() {
$(this).children('.item-query').matchHeight({
byRow: byRow
});
});
if($(window).width() > 450 && !$(".bx-s").length){
var divs = jQuery(".item-container .item-query");
for(var i = 0; i < divs.length; i+=6) {
divs.slice(i, i+6).wrapAll("<div class='bx-s'></div>");
}
}else{
$(".bx-s .item-query").unwrap();
}
$('.item-container').bxSlider({
nextSelector: '#item-nav-right',
prevSelector: '#item-nav-left',
pager: false,
nextText: 'next',
prevText: 'prev'
});
});
})();
https://jsfiddle.net/k55y6c9h/
I found this sweet jQuery snippet by CSS-Tricks' Chris Coyier that resets div elements heights that share the same top position on the page (are on the same row) to the tallest element.
The Problem
This solution almost works with fluid width layouts and resets height when top positions changes but it resets it to the original height of the current tallest element in the row when the page first loaded. This is an issue because the height of the tallest element might have changed since this page first loaded because of the use of relative units like ems or because of word wrapping with paragraphs.
Proposed Solution
The solution would be to have the row's elements' height being set to the tallest element's current height, not the original height. I have been unsuccessful in accomplishing this.
Here is the snippet where "li.half" is the elements being compared and resized.
jQuery(document).ready(function($) {
// these are (ruh-roh) globals. You could wrap in an
// immediately-Invoked Function Expression (IIFE) if you wanted to...
var currentTallest = 0,
currentRowStart = 0,
rowDivs = new Array();
function setConformingHeight(el, newHeight) {
// set the height to something new, but remember the original height in case things change
el.data("originalHeight", (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight")));
el.height(newHeight);
}
function getOriginalHeight(el) {
// if the height has changed, send the originalHeight
return (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight"));
}
function columnConform() {
// find the tallest DIV in the row, and set the heights of all of the DIVs to match it.
$('li.half').each(function() {
// "caching"
var $el = $(this);
var topPosition = $el.position().top;
if (currentRowStart != topPosition) {
// we just came to a new row. Set all the heights on the completed row
for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest);
// set the variables for the new row
rowDivs.length = 0; // empty the array
currentRowStart = topPosition;
currentTallest = getOriginalHeight($el);
rowDivs.push($el);
} else {
// another div on the current row. Add it to the list and check if it's taller
rowDivs.push($el);
currentTallest = (currentTallest < getOriginalHeight($el)) ? (getOriginalHeight($el)) : (currentTallest);
}
// do the last row
for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest);
});
}
$(window).resize(function(){
columnConform();
});
// Dom Ready
// You might also want to wait until window.onload if images are the things that
// are unequalizing the blocks
$(function() {
columnConform();
});
});
Please let me know if you can figure out how to make the setConformingHeight adjust on window resize.
Those solutions didn't work on window.resize() as elements height should be unlocked with $el.height('auto') before calculating new real height.
Here is my solution :
var currentRowTop = -100, currentHighest= 0;
$('.page-wrapper .cc').each(function() {
$el=$(this);
if($el.position().top!=currentRowTop){
equalizeHeight();
currentRowTop = $el.position().top;
$el.height('auto').addClass('same-height');
currentHighest=$el.height();
}else{
$el.height('auto').addClass('same-height');
currentHighest = ($el.height()>currentHighest) ? $el.height() : currentHighest ;
}
});
equalizeHeight();
function equalizeHeight(){
if($('.same-height').size()==0) return;
$('.same-height').height(currentHighest).removeClass('same-height');
}
I am modifying some code I found for paginating HTML content into a div. The code is from the jQuery rain site found on this page:
http://www.jqueryrain.com/?HtS47Rzc
The intent of this code is to take a large chunk of HTML, scan the top level child elements, and create a page object for each group of child elements that fit within a desired height (E.g. 400px). Once all the pages are built, each page is wrapped in a new div. The problem I'm having is that the calculated pages aren't close to the desired height once rendered to the page. So instead of each page having a nice block of text that neatly bumps into but does not exceed the bottom of the containing div, some pages have text falling far short of the desired page bottom and some exceed the page bottom. Actually they no longer exceed the page bottom since I added code that scans the pages array after each page has been wrapped with a div and sets the container div to the maximum div height found.
One thought I had is that the wrapping of the div was causing the variance so I explicitly added CSS rules to set the margins and padding to 0px. That had no effect. Can anyone tell me how to adjust the code so that the page height calculations work properly?
UPDATE: I'm showing the CSS for the div that holds a page and the DIV that contains it.
.example{
background:#FFF;
width:410px;
border:1px #000 solid;
margin:20px auto;
padding:15px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px
}
The page divs all have the class of "page":
#content .page {
position:absolute;
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
top:0px;
}
Here is my Javascript modified code. Note, the object being processed by the function is the main div that shows the paginated content:
(function ($) {
$.fn.extend({
MyPagination: function (options) {
var defaults = {
height: 400,
fadeSpeed: 400
};
var options = $.extend(defaults, options);
//Creating a reference to the object
var objContent = $(this);
// The array of pages we will build.
var fullPages = new Array();
// The array of elements for each page, used during pagination calculations.
var pageElements = new Array();
// The height for each page, reset after each page is built.
var height = 0;
var lastPage = 1;
var paginatePages;
// initialization function
init = function ()
{
// Build the array of pages by creating a new page when the sum of the child elements
// height values for each page exceeds the desired page height.
//
// NOTE: This is only an approximation. Haven't figured out why yet. When the
// operation is done there is large variance in the DIV height away from our desired
// height, many of them larger than our desired height.
objContent.children().each(function (i)
{
// Some browsers don't support clientHeight. In those cases, use offsetHeight.
var childHeight = this.clientHeight == 0 ? this.offsetHeight : this.clientHeight;
// If the height of all the children in the page elements array exceeds the desired
// page height, start a new page.
if (height + childHeight > options.height)
{
// Start a new page.
fullPages.push(pageElements);
// Reset the page elements array by initializing it to a new array.
pageElements = new Array();
// Reset the page height accumulatore. for the next page.
height = 0;
}
// Accumulate the child element's height into the height aggregator variable.
height += childHeight;
// Add the child element to the child elements array for the page currently being built.
pageElements.push(this);
});
if (height > 0) {
fullPages.push(pageElements);
}
// wrapping each full page
// $(fullPages).wrap("<div class='page'></div>");
// Wrapping each full page with a DIV. Give the DIV an ID that contains the page number.
$(fullPages).wrap(
function (ndx) {
return "<div class='page' name='pages' id='page_" + (ndx + 1) + "'></div>"
});
// Find the DIV with the maximum height.
var maxDivHeight = 0;
for (var ndx = 1; ndx <= fullPages.length; ndx++) {
var pageN = document.getElementById('page_' + ndx);
// Some browsers don't support clientHeight. In those cases, use offsetHeight.
var divHeight = pageN.clientHeight == 0 ? pageN.offsetHeight : pageN.clientHeight;
if (divHeight > maxDivHeight)
maxDivHeight = divHeight;
}
// Set the height of the content DIV to the maximum height we found plus a little padding.
objContent.height(maxDivHeight);
// hiding all wrapped pages
objContent.children().hide();
// making collection of pages for pagination
paginatePages = objContent.children();
// show first page
showPage(lastPage);
// draw controls
showPagination($(paginatePages).length);
};
// update counter function
updateCounter = function (i) {
$('#page_number').html(i);
};
// show page function
showPage = function (page) {
i = page - 1;
if (paginatePages[i]) {
// hiding old page, display new one
$(paginatePages[lastPage]).fadeOut(options.fadeSpeed);
lastPage = i;
$(paginatePages[lastPage]).fadeIn(options.fadeSpeed);
// and updating counter
updateCounter(page);
}
};
// perform initialization
init();
}
});
})(jQuery);
You can maybe use getBouningClientRect on your element. This will give you the position and size of that element:
var clientRect = element.getBoundingClientRect();
And now you can get the size and position:
var leftPos = clientRect.left;
var topPos = clientRect.top;
var width = clientRect.width;
var height = clientRect.height;
Hope this helps!
Here is a link to more information: https://developer.mozilla.org/en-US/docs/Web/API/element.getBoundingClientRect
I have two tables, side by side. What I am trying to do is have each row of each table that is in the same container have the same row height per row. I have gotten that far with this.
The way it works is you have an array thay grabs the row heights of each table and uses the largest height for each row. Thats fine except as its a single array that means if there are other containers on the page they will look at the same array. I tried writting a closure function but failed. any ideas?
$(document).ready(function() {
var heights = [];
computeTableHeights(true);
assignTableHeights();
var windowWidth = $(window).width();
$(window).resize(function() {
computeTableHeights(($(window).width() < windowWidth) && ($(window).width() != windowWidth));
windowWidth = $(window).width();
assignTableHeights();
})
function computeTableHeights(recordBiggestHeights) {
$("table").each(function() {
var rowIndex = 0;
var rows = $(this).find("tr");
$(rows).each(function() {
var rowHeight = $(this).css("height");
if (heights[rowIndex] === undefined) {
heights[rowIndex] = rowHeight;
} else {
var existingHeight = parseInt(heights[rowIndex]);
var currentHeight = parseInt(rowHeight);
if (shouldChangeHeight(recordBiggestHeights, existingHeight, currentHeight)) {
heights[rowIndex] = rowHeight;
}
}
rowIndex++;
});
});
}
function shouldChangeHeight(recordBiggestHeights, existingHeight, currentHeight) {
if (existingHeight == currentHeight) {
return false;
} else if (recordBiggestHeights) {
return existingHeight < currentHeight;
} else {
return existingHeight > currentHeight;
}
}
function assignTableHeights() {
$(".container table").each(function() {
var rowIndex = 0;
var rows = $(this).find("tr");
$(rows).each(function() {
var rowHeight = $(this).css("height");
if (heights[rowIndex]) {
var existingHeight = parseInt(rowHeight);
var targetHeight = parseInt(heights[rowIndex]);
if (existingHeight != targetHeight) {
$(this).css("height", heights[rowIndex]);
}
}
rowIndex++;
});
});
}
});
I think I understand what you're trying to do. If not, please elaborate a little on the requirements you're looking for, so I can revise this answer.
You want to treat the row heights of each container and its child tables separately. Correct me if I'm wrong
The code below loops through each container separately, before equalizing the heights of the table rows.
You are indeed right that storing all row heights for all tables in one array will not get you the results you need. You would need to create an array instance per container.
In your code you read out the css for the height of the row. Once you set the height in the css, this property will stay the same. I believe in your use-case you need the height of the row as the browser has calculated it (jquery offers methods for this purpose).
Therefore, on resizing, the css property should be cleared, before setting it again to the greatest calculated height.
function resizeHandler() {
// Treat each container separately
$(".container").each(function(i, container) {
// Stores the highest rowheight for all tables in this container, per row
var aRowHeights = [];
// Loop through the tables
$(container).find("table").each(function(indx, table) {
// Loop through the rows of current table (clear their css height value)
$(table).find("tr").css("height", "").each(function(i, tr) {
// If there is already a row height defined
if (aRowHeights[i])
// Replace value with height of current row if current row is higher.
aRowHeights[i] = Math.max(aRowHeights[i], $(tr).height());
else
// Else set it to the height of the current row
aRowHeights[i] = $(tr).height();
});
});
// Loop through the tables in this container separately again
$(container).find("table").each(function(i, table) {
// Set the height of each row to the stored greatest height.
$(table).find("tr").each(function(i, tr) {
$(tr).css("height", aRowHeights[i]);
});
});
});
}
$(document).ready(resizeHandler);
$(window).resize(resizeHandler);
I have this fiddle: http://jsfiddle.net/k5g87/
You can resize the result window in there.
Hey there, I have 20 divs floated left with different height. I use this script to resize them. It worked perfect when my website was designed using pixels.
When i have changed my website to % design (percentage design), the script stopped working that reliable, sometimes it does not resize.
can you take a look, see if there are any adjustments needed for liquid layouts?
maybe it's the way i call the script?
Ty very much
Here it is:
var currentTallest = 0;
var currentRowStart = 0;
var rowDivs = new Array();
function setConformingHeight(el, newHeight) {
// set the height to something new, but remember the original height in case things change
el.data("originalHeight", (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight")));
el.height(newHeight);
}
function getOriginalHeight(el) {
// if the height has changed, send the originalHeight
return (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight"));
}
function columnConform() {
// find the tallest DIV in the row, and set the heights of all of the DIVs to match it.
$('div.column').each(function(index) {
if(currentRowStart != $(this).position().top) {
// we just came to a new row. Set all the heights on the completed row
for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest);
// set the variables for the new row
rowDivs.length = 0; // empty the array
currentRowStart = $(this).position().top;
currentTallest = getOriginalHeight($(this));
rowDivs.push($(this));
} else {
// another div on the current row. Add it to the list and check if it's taller
rowDivs.push($(this));
currentTallest = (currentTallest < getOriginalHeight($(this))) ? (getOriginalHeight($(this))) : (currentTallest);
}
// do the last row
for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest);
});
}
$(window).resize(function() {
columnConform();
});
$(document).ready(function() {
columnConform();
});
Well if you change it to fluid layout (% design) then you are going to have to add a window resize listener, basically when the resize event is done or while it's running you need to recall the script so it can recalculate with new dimensions, you did not need to doo that with pixels because it was a fixed size and once assigned will not change no matter how many times you resize the actual screen.
If you use styles like this:
<style>
.parent{
background:#F00;height:300px
}
.parent div{
float:left;height:100%;width:33.33%;
}
</style>
<div class="parent">
<div style="background:#FED"></div>
<div style="background:#EDF"></div>
<div style="background:#DFE"></div>
</div>
You just have to set the height of the parent div, and the width of the children div