If I have div A and div B, is there a way to say A.width = b.width = MAX(a.width, b.width) ? That is, whichever has the largest inner content would dictate how large both are.
The actual problem I'm trying to solve is with columns - left, middle, and right. I want the left and right to be the same fixed width (but this could vary depending on their content).
It is not possible to use CSS to achieve this. However, if there is a way to do it with a JS-based solution. Here I am using jQuery. Let's say you have two divs, with classes a and b respectively.
$(function() {
function equalizeSize($ele) {
if($ele.length > 1) {
// Let CSS automatically calculate natural width first
$ele.css({ width: 'auto' });
// And then we fetch the newly calculated widths
var maxWidth = Math.max.apply(Math, $ele.map(function(){ return $(this).outerWidth(); }).get());
$ele.css({ width: maxWidth });
}
}
// Run when DOM is ready
equalizeSize($('.a, .b'));
// Run again when viewport has been resized, which **may** affect your div width.
// This is optional, but good to have
// ps: You might want to look into throttling the resize function
$(window).resize(equalizeSize($('.a, .b')));
});
See proof-of-concept fiddle here: http://jsfiddle.net/teddyrised/N4MMg/
The advantages of this simple function:
Allows you to dictate what elements you want to equalize widths with.
Uses the .map() function to construct an array, which we then use Math.max.apply to get the maximum value in the array
Forces automatic calculation of width when the function first fires (especially when resizing the viewport)
Allows you to call to recalculate the size again, using the handler equalizeSize() when you change the content in the divs... you can call the function again, say, after an AJAX call that appends content to either element.
It is not very clear what you want from the description. but I can rewrite your code this way.
var properWidth = Math.max($("#a").width(), $("#b").width());
$("#a").css("width", properWidth + "px");
$("#b").css("width", properWidth + "px");
I am not sure if it is this kind of solution you want.
I'm not sure there is a way to do it like that. But why not make a default function to set the size:
function changeSize(w, h)
{
A.setAttribute('style', 'width:'+w+'; height:'+h);
b.setAttribute('style', 'width:'+w+'; height:'+h);
}
Working fiddle: http://jsfiddle.net/kychan/ER2zZ/
This question already has answers here:
Get the real width and height of an image with JavaScript? (in Safari/Chrome)
(30 answers)
Closed 9 years ago.
I am scaling images to fit within a div and I want to center them with letterboxes by using positions, but when I try to get the width of the element with .width() immediately after setting the height, .width() returns 0.
For example:
$(image).css("height", "100%");
console.log($(image).width());
This echoes 0 to the console, but if I call $(image).width() from the console sometime later, the correct value is given. How can I get the width of the <img> element immediately after I change it's height?
Edit:
So my code goes something like this:
$(window).load(function(){
cSCMH();
});
function cSCMH()
{
//Some other code
for(var i = 0; i < $("sc mh im img").length; i++)
{
var image = $("sc mh im img")[i];
//More code
$(image).css("height", "100%");
console.log($(image).width());
}
}
The console still receives 0
Edit 2:
Okay so I think I know what the root of the problem is. The images don't appear to load into the page until they are made visible on the screen (I have them in a tab div where the display is set to none onload).
Is there any way to force the images to load even though they are not visible?
I have confirmed this is the issue. The images are not loaded until the div's display is set to block. How can I make the images load in onpageload instead?
Try using the image's load event
function cSCMH() {
$("sc mh im img").load(function () {
var $img = $(this);
$img.css("height", "100%");
console.log($img.width());
}).filter(function () {
return this.complete;
}).trigger('load');
}
Since height() does not provide callback function, You can use animate() here:
$(image).animate({"height": '100%'}, function() {
console.log($(image).width());
})
Also, to make sure all the images are loaded properly, you can wrap your code inside $(window).load(function() { ... });
$(window).load(function() {
$(image).animate({"height": '100%'}, function() {
console.log($(image).width());
})
});
You need to wait for dom change.
$(image).css("height", "100%");
setTimeout(function() {
console.log($(image).width());
}, 0);
setting height in percentage wouldn't set it when you haven't set it's parent's div fixed height. So you can also try by using height 100% to your body like this:
html,body{height: 100%;}
I have I div or some other element which I load content into with:
$('#my_div').load('ajax.php',function(){
//Do random stuff.
}
However the height of the div will then change, causing the page to jump up and down, looking ugly.
Is there a way for it to animate the height when the new content is loaded or changed? I know one can do this with FluidMoveBehavior in C#.
How can I achieve the same effect with Javascript/jQuery?
Here's some Fiddle
When you want to create a height or width animation with jQuery you have to set a number indicating the desired size. I assume that you use height: auto in this case so you have to find a little workarround.
Get the height:
var autoHeight = $("#content").height("auto").height();
Animate to autoHeight:
$("#content").animate({height: autoHeight}, 1000);
And together:
var currentHeight = $("#content").height();
var autoHeight = $("#content").height("auto").height();
$("#content").height(currentHeight);
$("#content").animate({height: autoHeight}, 1000);
Stolen from here
What I do is the opposite. I animate the page to scroll to the top if not already BEFORE I call the load.
So that the top of any new dynamic content is always in view.
I know this isn't the answer you were looking for, but I've found it works best.
You could hide #my_div before the load(), and then slideDown() in the complete function:
$('#my_div').hide().load('ajax.php', function() {
$(this).slideDown();
});
Or, create a temporary element, hide it, append it, use its height to animate #my_div once the load is complete, and then remove it.
$('<span/>').hide().appendTo('body').load('ajax.php', function(text) {
$('#my_div').animate({ height: $(this).height() }, '800').html(text);
$(this).remove();
});
I have a console setup on a tool I've created. The console can be minimized when clicked and maximized when clicked again.
The issue however is that once I maximize it, it simply minimizes when it is complete. What are my options?
$('#consolebutton').mouseup(function() {
if ($('#footconsole').height(200)) {
$('#footconsole').animate({
height: 14
}, 100)
} else if ($('#footconsole').height(14)) {
$('#footconsole').animate({
height: 200
}, 100);
}
});
(I do realize that checking the height of the div, is actually setting the height of the div and that is the problem.)
http://jsfiddle.net/VaDBW/3/
Try this...
$('#consolebutton').mouseup(function() {
var $footconsole = $('#footconsole');
if ($footconsole.height() == 200) {
$footconsole.animate({
height: 14
}, 100)
} else {
$footconsole.animate({
height: 200
}, 100);
}
});
It does a comparison against height (rather than set it), and I also set a variable to the value of $("#footconsole"), rather than keep searching for it.
Call the height() method without parameters. Without parameters, it returns the current height. When passing a parameter, it is setting the height.
if($('#footconsole').height() == 14) for example. Though in my opinion you're better off saving a status flag in data versus checking height
if($('#footconsole').data('collapsed'))
{
$('#footconsole').data('collapsed', false);
/* do expand code */
} else {
$('#footconsole').data('collapsed', true);
/* do collapse code */
}
You can also use a class to define the settings and, if you need to do more than just toggle the class, you can check with hasClass to make further adjustments. Lots of options. But going off of raw height seems a bit strange.
I would use toggleClass() inside of a click(function(){...}); and then you dont need the if statements and you can put the height differences in the CSS.
I need to get height of an element that is within a div that is hidden. Right now I show the div, get the height, and hide the parent div. This seems a bit silly. Is there a better way?
I'm using jQuery 1.4.2:
$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
You could do something like this, a bit hacky though, forget position if it's already absolute:
var previousCss = $("#myDiv").attr("style");
$("#myDiv").css({
position: 'absolute', // Optional if #myDiv is already absolute
visibility: 'hidden',
display: 'block'
});
optionHeight = $("#myDiv").height();
$("#myDiv").attr("style", previousCss ? previousCss : "");
I ran into the same problem with getting hidden element width, so I wrote this plugin call jQuery Actual to fix it. Instead of using
$('#some-element').height();
use
$('#some-element').actual('height');
will give you the right value for hidden element or element has a hidden parent.
Full documentation please see here. There is also a demo include in the page.
Hope this help :)
You are confuising two CSS styles, the display style and the visibility style.
If the element is hidden by setting the visibility css style, then you should be able to get the height regardless of whether or not the element is visible or not as the element still takes space on the page.
If the element is hidden by changing the display css style to "none", then the element doesn't take space on the page, and you will have to give it a display style which will cause the element to render in some space, at which point, you can get the height.
I've actually resorted to a bit of trickery to deal with this at times. I developed a jQuery scrollbar widget where I encountered the problem that I don't know ahead of time if the scrollable content is a part of a hidden piece of markup or not. Here's what I did:
// try to grab the height of the elem
if (this.element.height() > 0) {
var scroller_height = this.element.height();
var scroller_width = this.element.width();
// if height is zero, then we're dealing with a hidden element
} else {
var copied_elem = this.element.clone()
.attr("id", false)
.css({visibility:"hidden", display:"block",
position:"absolute"});
$("body").append(copied_elem);
var scroller_height = copied_elem.height();
var scroller_width = copied_elem.width();
copied_elem.remove();
}
This works for the most part, but there's an obvious problem that can potentially come up. If the content you are cloning is styled with CSS that includes references to parent markup in their rules, the cloned content will not contain the appropriate styling, and will likely have slightly different measurements. To get around this, you can make sure that the markup you are cloning has CSS rules applied to it that do not include references to parent markup.
Also, this didn't come up for me with my scroller widget, but to get the appropriate height of the cloned element, you'll need to set the width to the same width of the parent element. In my case, a CSS width was always applied to the actual element, so I didn't have to worry about this, however, if the element doesn't have a width applied to it, you may need to do some kind of recursive traversal of the element's DOM ancestry to find the appropriate parent element's width.
Building further on user Nick's answer and user hitautodestruct's plugin on JSBin, I've created a similar jQuery plugin which retrieves both width and height and returns an object containing these values.
It can be found here:
http://jsbin.com/ikogez/3/
Update
I've completely redesigned this tiny little plugin as it turned out that the previous version (mentioned above) wasn't really usable in real life environments where a lot of DOM manipulation was happening.
This is working perfectly:
/**
* getSize plugin
* This plugin can be used to get the width and height from hidden elements in the DOM.
* It can be used on a jQuery element and will retun an object containing the width
* and height of that element.
*
* Discussed at StackOverflow:
* http://stackoverflow.com/a/8839261/1146033
*
* #author Robin van Baalen <robin#neverwoods.com>
* #version 1.1
*
* CHANGELOG
* 1.0 - Initial release
* 1.1 - Completely revamped internal logic to be compatible with javascript-intense environments
*
* #return {object} The returned object is a native javascript object
* (not jQuery, and therefore not chainable!!) that
* contains the width and height of the given element.
*/
$.fn.getSize = function() {
var $wrap = $("<div />").appendTo($("body"));
$wrap.css({
"position": "absolute !important",
"visibility": "hidden !important",
"display": "block !important"
});
$clone = $(this).clone().appendTo($wrap);
sizes = {
"width": $clone.width(),
"height": $clone.height()
};
$wrap.remove();
return sizes;
};
Building further on Nick's answer:
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").css({'position':'static','visibility':'visible', 'display':'none'});
I found it's better to do this:
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").removeAttr('style');
Setting CSS attributes will insert them inline, which will overwrite any other attributes you have in your CSS file. By removing the style attribute on the HTML element, everything is back to normal and still hidden, since it was hidden in the first place.
You could also position the hidden div off the screen with a negative margin rather than using display:none, much like a the text indent image replacement technique.
eg.
position:absolute;
left: -2000px;
top: 0;
This way the height() is still available.
I try to find working function for hidden element but I realize that CSS is much complex than everyone think. There are a lot of new layout techniques in CSS3 that might not work for all previous answers like flexible box, grid, column or even element inside complex parent element.
flexibox example
I think the only sustainable & simple solution is real-time rendering. At that time, browser should give you that correct element size.
Sadly, JavaScript does not provide any direct event to notify when element is showed or hidden. However, I create some function based on DOM Attribute Modified API that will execute callback function when visibility of element is changed.
$('[selector]').onVisibleChanged(function(e, isVisible)
{
var realWidth = $('[selector]').width();
var realHeight = $('[selector]').height();
// render or adjust something
});
For more information, Please visit at my project GitHub.
https://github.com/Soul-Master/visible.event.js
demo: http://jsbin.com/ETiGIre/7
Following Nick Craver's solution, setting the element's visibility allows it to get accurate dimensions. I've used this solution very very often. However, having to reset the styles manually, I've come to find this cumbersome, given that modifying the element's initial positioning/display in my css through development, I often forget to update the related javascript code. The following code doesn't reset the styles per say, but removes the inline styles added by javascript:
$("#myDiv")
.css({
position: 'absolute',
visibility: 'hidden',
display: 'block'
});
optionHeight = $("#myDiv").height();
optionWidth = $("#myDiv").width();
$("#myDiv").attr('style', '');
The only assumption here is that there can't be other inline styles or else they will be removed aswell. The benefit here, however, is that the element's styles are returned to what they were in the css stylesheet. As a consequence, you can write this up as a function where an element is passed through, and a height or width is returned.
Another issue I've found of setting the styles inline via js is that when dealing with transitions through css3, you become forced to adapt your style rules' weights to be stronger than an inline style, which can be frustrating sometimes.
By definition, an element only has height if it's visible.
Just curious: why do you need the height of a hidden element?
One alternative is to effectively hide an element by putting it behind (using z-index) an overlay of some kind).
In my circumstance I also had a hidden element stopping me from getting the height value, but it wasn't the element itself but rather one of it's parents... so I just put in a check for one of my plugins to see if it's hidden, else find the closest hidden element. Here's an example:
var $content = $('.content'),
contentHeight = $content.height(),
contentWidth = $content.width(),
$closestHidden,
styleAttrValue,
limit = 20; //failsafe
if (!contentHeight) {
$closestHidden = $content;
//if the main element itself isn't hidden then roll through the parents
if ($closestHidden.css('display') !== 'none') {
while ($closestHidden.css('display') !== 'none' && $closestHidden.size() && limit) {
$closestHidden = $closestHidden.parent().closest(':hidden');
limit--;
}
}
styleAttrValue = $closestHidden.attr('style');
$closestHidden.css({
position: 'absolute',
visibility: 'hidden',
display: 'block'
});
contentHeight = $content.height();
contentWidth = $content.width();
if (styleAttrValue) {
$closestHidden.attr('style',styleAttrValue);
} else {
$closestHidden.removeAttr('style');
}
}
In fact, this is an amalgamation of Nick, Gregory and Eyelidlessness's responses to give you the use of Gregory's improved method, but utilises both methods in case there is supposed to be something in the style attribute that you want to put back, and looks for a parent element.
My only gripe with my solution is that the loop through the parents isn't entirely efficient.
One workaround is to create a parent div outside the element you want to get the height of, apply a height of '0' and hide any overflow. Next, take the height of the child element and remove the overflow property of the parent.
var height = $("#child").height();
// Do something here
$("#parent").append(height).removeClass("overflow-y-hidden");
.overflow-y-hidden {
height: 0px;
overflow-y: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent" class="overflow-y-hidden">
<div id="child">
This is some content I would like to get the height of!
</div>
</div>
Here's a script I wrote to handle all of jQuery's dimension methods for hidden elements, even descendants of hidden parents. Note that, of course, there's a performance hit using this.
// Correctly calculate dimensions of hidden elements
(function($) {
var originals = {},
keys = [
'width',
'height',
'innerWidth',
'innerHeight',
'outerWidth',
'outerHeight',
'offset',
'scrollTop',
'scrollLeft'
],
isVisible = function(el) {
el = $(el);
el.data('hidden', []);
var visible = true,
parents = el.parents(),
hiddenData = el.data('hidden');
if(!el.is(':visible')) {
visible = false;
hiddenData[hiddenData.length] = el;
}
parents.each(function(i, parent) {
parent = $(parent);
if(!parent.is(':visible')) {
visible = false;
hiddenData[hiddenData.length] = parent;
}
});
return visible;
};
$.each(keys, function(i, dimension) {
originals[dimension] = $.fn[dimension];
$.fn[dimension] = function(size) {
var el = $(this[0]);
if(
(
size !== undefined &&
!(
(dimension == 'outerHeight' ||
dimension == 'outerWidth') &&
(size === true || size === false)
)
) ||
isVisible(el)
) {
return originals[dimension].call(this, size);
}
var hiddenData = el.data('hidden'),
topHidden = hiddenData[hiddenData.length - 1],
topHiddenClone = topHidden.clone(true),
topHiddenDescendants = topHidden.find('*').andSelf(),
topHiddenCloneDescendants = topHiddenClone.find('*').andSelf(),
elIndex = topHiddenDescendants.index(el[0]),
clone = topHiddenCloneDescendants[elIndex],
ret;
$.each(hiddenData, function(i, hidden) {
var index = topHiddenDescendants.index(hidden);
$(topHiddenCloneDescendants[index]).show();
});
topHidden.before(topHiddenClone);
if(dimension == 'outerHeight' || dimension == 'outerWidth') {
ret = $(clone)[dimension](size ? true : false);
} else {
ret = $(clone)[dimension]();
}
topHiddenClone.remove();
return ret;
};
});
})(jQuery);
If you've already displayed the element on the page previously, you can simply take the height directly from the DOM element (reachable in jQuery with .get(0)), since it is set even when the element is hidden:
$('.hidden-element').get(0).height;
same for the width:
$('.hidden-element').get(0).width;
(thanks to Skeets O'Reilly for correction)