Is there an easy way to get the height of a parent div which has a hidden child div inside? If not, what could be the hard way to achieve such a result?
PS: I know that this topic might be repetitive, but the other topics I have found were all with negative scored best answers.
var getHeight = $(".parent").height();
console.log(getHeight);
.parent{
position:absolute;
top:0;
left:0;
}
.visibleChild{
position:relative;
height:20px;
background-color:red;
}
.hiddenChild{
display:none;
height:20px;
background-color:green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<div class="visibleChild">
This div is visible.
</div>
<div class="hiddenChild">
This div is hidden.
</div>
</div>
You can certainly get the height of the parent when a child element is not displayed, but it sounds like you want to get the height of the parent when all of the children's heights are accounted. In this case, you can make the child(s) hidden but displayed, grab the height, and revert:
/* parentSelector: selector we wish to know its height
* childSelector: children to display when measuring parent
*/
function getHeight(parentSelector, childSelector) {
var parent = $(parentSelector);
var children = parent.children(childSelector);
var styleState = [];
//set state
children.each(function (i) {
let c = $(this);
styleState[i] = c.css(['display', 'visibility']);
c.css({ display: '', visibility: 'hidden' });
});
var height = parent.css('height');
//revert state
children.each(function (i) {
let { display, visibility } = styleState[i];
$(this).css({ display, visibility });
});
return height;
}
$('#test > div').hide();
console.log(getHeight('#test', 'div'));
#test { background: brown; padding: 1em }
#test > div { height: 50px; background: yellow; margin: 1em 0 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">
<span>span</span>
<div>div</div>
<div>div</div>
</div>
I hope this helps!
Related
I am loading html page inside a div with jquery. It does work fine.
var loginBtn = $("#loginBtn");
var loginPage = $("#login");
var submitBtn = $("#submitBtn");
var submitPage = $("#submit");
var checkBtn = $("#checkBtn");
var checkPage = $("#check");
loginPage.load( "login.html" );
submitPage.load( "submitPoints.html" );
checkPage.load( "checkPoints.html" );
body {
margin: 0 !important;
padding: 0 !important;
background-color: white;
}
#mainFrame {
width: 100%;
height: 300px;
background-color:cadetblue;
padding-top: 0;
margin-top: 0px;
position: relative;
}
<div id="mainFrame">
<div id="login"></div>
<div id="check"></div>
<div id="submit"></div>
</div>
My issue is that if the loaded html has no content, the margin between the parent document body (white) and the top of the loaded html (green) is none (that's what I want, it's ok).
However as soon as I add content to the loaded html, a gap is generated at the top of the page :\
I thought it was all about setting some line-height prop in the css but it seems helpless.
Any ideas what I am doing wrong ?
What you are seeing is the top margin of the first piece of content overflowing its container (also known more commonly as margin collapsing):
body {
background:yellow;
}
#container {
background:green;
height:300px;
}
<div id="container">
<h1>I have a top margin of 1em by default that is overflowing into the body.</h1>
</div>
If you give your container element a padding of that same amount, the margin space of the body won't be used and the element will be pushed down in the green area.
body {
background:yellow;
}
#container {
background:green;
height:300px;
padding:1em;
}
<div id="container">
<h1>I have a top margin of 1em by default that is now contained within my parent.</h1>
</div>
Or, you could set the top margin of the first piece of content to zero:
body {
background:yellow;
}
#container {
background:green;
height:300px;
}
#container > h1:first-child { margin-top:0; }
<div id="container">
<h1>My top margin has been set to zero.</h1>
</div>
Finally, you could set the overflow of the content area to auto but (although this seems to be the popular answer), I don't prefer this approach as you run the risk of unintended fitting of the content as the content changes and/or the container size changes. You give up a bit of sizing control:
body {
background:yellow;
}
#container {
background:green;
height:300px;
overflow:auto;
}
<div id="container">
<h1>The content area has had its overflow set to auto.</h1>
</div>
When you load new content it gets rendered in the document and those new elements might have properties. In this case, most probably the Login has a margin value. Another option is that it has a class or some selector that is being picked up by a CSS file which appends the margin to it.
Easiet way would be to right-click on the Login element, choose inspect, and analyze the style of the element with web-dev / style.
If you want to keep the margin on the inner content, you should set an overflow. Look what happens when we remove the overflow: auto line from .content > div (try clicking the box after running the code sample below).
This is because of margin collapsing. The margin on the inner content is combined with the margin on the outer element and applied on the outer element, i.e. two margins of the two elements are collapsed into a single margin.
document.querySelector('.content').addEventListener('click', (e) => {
e.target.classList.toggle('overflow');
});
html,
body {
margin: 0;
padding: 0;
}
.outer {
width: 200px;
background: red;
}
.content > div {
width: 100%;
height: 300px;
background: cadetblue;
cursor: pointer;
}
.content > div.overflow {
overflow: auto;
}
.test {
margin: 10px;
display: block;
}
<div class="outer">
<div class="content">
<div><span class="test">Test</span></div>
</div>
</div>
Here is my goal:
When the user hovers a div of class "item" another div of class "menu" should appear overlaying the "item" div.
The position of the "menu" div should be relative to the "item" div.
When the user unhovers the item "div" the menu div should disappear.
When the user mouses over the "menu" div the "menu" div the "menu" div should not disappear so that user can click a button in it.
I am looking for a JavaScript and CSS solution. If you can help but you can only post a JQuery solution I will still appreciate it but I will have to translate it to straight JavaScript.
So far I have tried:
To make the "hover" div an absolutely positioned child of the document.body. This works for positioning, but hovering the "hover" div unhovers the "item" div and I don't know how to figure out that the new hovered div is the "hover" div.
To make the "hover" div a absolutely or fixed positioned child of the "item" div. This places the "hover" div underneath the "item" div and style.top seems to have no effect on the "hover" div".
To make the "hover" div a relatively positioned child of the "item" div. This places the "hover" div within the "item" div and increases the size of the "hover" div, which I don't want.
Thank you for your help with this!
Here is a JSFiddle that is a starting point for a solution https://jsfiddle.net/ypn5f1ng/
HTML
<div id=content>
content
<div class=item>item 1</div>
<div class=item>item 2</div>
more content
</div>
CSS
body { background:green; }
#content { z-index:100; width:500px; position:absolute; left:0px; right:0px; margin-left:auto; margin-right:auto; background:white; margin-top:10px; background:lightblue; padding:5px; }
div.item { background:pink; margin:5px}
div.hover { background:yellow; height:15px; width:100px; z-index:101; position:fixed }
JavaScript
function getElem(event) {
if (!event) {
event = window.event;
}
var elem = null;
if (event.target) {
elem = event.target;
} else if (event.srcElement) {
elem = event.srcElement;
}
if (elem && elem.nodeType == 3) {
elem = elem.parentNode;
}
return elem;
}
var hoverDiv = null;
function onItemMouseOver(event) {
var elem = getElem(event);
if (!hoverDiv) {
hoverDiv = document.createElement('DIV');
hoverDiv.className = "hover";
document.body.appendChild(hoverDiv);
//elem.appendChild(hoverDiv);
hoverDiv.style.right=100;
hoverDiv.style.top=-100;
}
}
function onItemMouseOut(event) {
if(hoverDiv) {
hoverDiv.parentNode.removeChild(hoverDiv);
hoverDiv = null;
}
}
var items = document.getElementsByClassName("item");
for(var i = 0; i < items.length; ++i) {
var item = items[i];
item.onmouseover = onItemMouseOver;
item.onmouseout = onItemMouseOut;
}
fiddle
HTML
<div class='a'>
<div class="b">
asfdwa
</div>
</div>
CSS
.a {
position: relative;
width: 300px;
height: 300px;
background: lightgray;
}
.b {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 80px;
background: pink;
opacity: 0;
transition: .2s opacity ease-in-out;
}
.b a {
display: block;
margin: 1rem;
}
.a:hover .b {
opacity: 1;
}
The best approach is to use CSS only if possible (no JS).
In this situation, I would recommend to put the div you would like to display on hover into the div that is the trigger.
<div class="parent">
<div class="child">
...
</div>
...
</div>
Than the CSS would look like this:
div.child {
display: none;
}
div.parent:hover div.child {
display: block;
}
With this technique you can position the child even to get outside the parent and it will not disappear if you get out of the parent if you are still on the child since the child is technically (not visually) in the parent. You just need to make sure that the parent at least touches the displayed child since the child will disappear if you travel over the gap between them with your cursor (the cursor won't be on the parent nor on the child)
I am trying to make a vertical list to the left of the content associated with that list item (vertical tabs). I am using jQuery to find the height of the largest "tab content", and make the ul equal that height, because there is a 1px border on the right side of the ul and I want it to line up with he content. However, the taller the height of the content gets, the more deficient the height of the ul is.
Here is a photo:
(the 1px right border of the ul should be the same height of the content)
And here is the jsfiddle showing what's going on:
http://jsfiddle.net/jM4F5/
jQuery(document).ready(function($) {
var tallest = $('#tatab-container ul').height(); // Minimum height is default ul height
$('#tamain-container p').each(function() {
var thisHeight = $(this).height();
if(thisHeight > tallest) {
tallest = thisHeight; // Modify to height of tallest paragraph
}
});
$('#tatab-container ul').css('height', tallest); // Update ul height
});
When I use an alert to see what jQuery has, it returns the same height for the ul as well as the paragraph, but if so, why is the ul shorter?
You are trying to use the <ul> structurally when that is really what your container <div>'s are for. Try something like this: JSFIDDLE
jQuery(document).ready(function($) {
var tatabcont = $('#tatab-container');
var tamaincont = $('#tamain-container');
var tallest = tatabcont.height();
if (tamaincont.height() > tallest) { tallest = tamaincont.height(); }
tatabcont.height(tallest + "px");
tamaincont.height(tallest + "px");
});
* { box-sizing: border-box; }
#tatab-container {
width: 30%;
float: left;
overflow: hidden;
border-right: 1px solid #666;
}
#tamain-container {
width: 65%;
float: left;
margin-left: 5%;
}
#tatab-container ul {
width: 100%;
padding-left: 0;
}
#tatab-container ul li {
padding: 5px;
border-bottom: 1px solid #666;
list-style-type: none;
}
Revision: updated jQuery with .resize() : UPDATED JSFIDDLE
jQuery(document).ready(function($) {
$(window).resize(function(){ equalHeight(); });
equalHeight();
});
function equalHeight() {
var tatabcont = $('#tatab-container');
var tamaincont = $('#tamain-container');
tatabcont.css("height","auto"); // reset container height to natural
tamaincont.css("height","auto"); // reset container height to natural
var tallest = tatabcont.height();
if (tamaincont.height() > tallest) { tallest = tamaincont.height(); }
tatabcont.height(tallest + "px");
tamaincont.height(tallest + "px");
}
This is occurring because when you adjust the height of the <ul>, you push the <p> content down further again. You need to set a specific width on the <p> element, so the math calculating in .height() is correct.
Some small CSS like:
#tamain-container {
float: right;
width: 60%;
}
http://jsfiddle.net/jM4F5/3/
could you try with this code, you will adjust the height of shorter to taller one.
jQuery(function($) {
var tallest = $('#tamain-container p').height();
var short = $('#tatab-container ul').height();
if(tallest > short){
$('#tatab-container ul').css('height',tallest);
}
if(tallest < short){
$('#tamain-container p').css('height',short);
}
});
#tamain-container {float:left;width:55%;}
http://jsfiddle.net/jM4F5/19/
I would use css display:table to acheieve this. Something like this
<div style='display:table;border-collapse:collapse;'>
<div style='display:table-row'>
<div style='display:table-cell;border-right:1px solid#000;'>// UL Navigation</div>
<div style='display:table-cell'>//All Tabs content</div>
</div>
The table cells will always be of the same height and so will the border.
I am trying to dynamically give child A tags an even width based on the number of tags contained in a list. (eg. if 4 A's they will all be 25% width, 3 tags they will be 33%).
I have tried counting the number of children inside the div and dividing 100 by the var number with no success
jQuery
var numChildren = $("div a").size()
$('a').css({ width : 100/numChildren });
CSS
a { width: /*DYNAMIC*/ (all even) }
div {width: 100%; }
HTML
<div>
<a></a>
<a></a>
<a></a>
<a></a>
</div>
You can do it CSS-only, without counting the number of elements:
HTML:
<div class="wrapper">
<a></a>
<a></a>
<a></a>
</div>
CSS:
.wrapper {
display: table;
width: 100%;
height: 50px;
margin: 10px 0;
}
.wrapper > a {
display: table-cell;
border: 1px solid #000;
}
Demo
With your current code, if there are four elements, you are setting this:
width: 25;
I think you want this:
$('a').css({ width : 100/numChildren + '%' });
Try changing the jquery to:
var numChildren = $("div a").length;
$('a').css({ 'width', 100/numChildren + '%' });
HTML
<div>
<a>Test Me</a>
<a>Test Me</a>
<a>Test Me</a>
<a>Test Me</a>
</div>
JAVASCRIPT
var numChildren = $("div a").length;
$('a').css({ width : 100/numChildren+'%' });
alert(100/numChildren);
CSS
div
{
width:300px;
}
a
{
position:relative;
float:left;
background-color:#EEE;
}
JSFIDDLE LINK
I don't think you need to set width in percentage. As you are ultimately going to use javascript to evenly distribute width
HTML:
<div>
<a>One</a>
<a>Two</a>
<a>Three</a>
<a>Four</a>
</div>
Javascript:
var parent = $("div");
var anchors = parent.find('a');
anchors.css({ width : parent.width() / anchors.length });
CSS:
div > a {
background: red;
display: inline-block;
}
Demo
You can use this code :
jsFiddle here
HTML
<div id="content">
<a></a>
<a></a>
<a></a>
<a></a>
</div>
CSS
#content{
width:100px;
height:20px;
background:#888;
}
a{
height:20px;
background:red;
display:block;
float:left;
}
jQuery
$(document).ready(function(){
var numberChild = $("#content a").length;
$("#content a").css("width",(100/numberChild)+"%");
});
Oriol's answer is the correct one, if you don't need to support IE7 and below.
If you need support for these browsers, you can calculate the relative width as others already explained.
But if you know that you will never have more than n children, you can also do:
// assuming that will never have more than 4 children
$('div:has(a)').addClass('one');
$('div:has(a+a)').addClass('two');
$('div:has(a+a+a)').addClass('three');
$('div:has(a+a+a+a)').addClass('four');
and the css
div a { width: 100%; }
div.two a { width: 50%; }
div.three a { width: 33.3%; }
div.four a { width: 25%; }
demo
I want to control the automatic height change of the container when I add something that changes the lenght of the content. Right now, if I apply a innerHTML change on the content, the height is changed accordingly. I want to apply a transition to that height change. How can I do that? ( I can also use jQuery )
Record the height before changing the content, change the content, record the height after, set the height to the former height, and animate to the latter height. When the animation has completed, set the height to be automatic again. You can do this using height and animate.
Try it on JSFiddle.
var texts = [
"This is just some sample text that's being used to demonstrate animating the height when content changes.",
"Shorter."
];
var div = $('div').click(changeContent);
function changeContent() {
var oldHeight = div.height();
texts.push(div.text());
div.text(texts.shift());
var newHeight = div.height();
div.height(oldHeight);
div.animate({height: newHeight}, 'fast', function() {
div.height('auto');
});
}
div {
width: 150px;
background: lightgray;
overflow-y: hidden;
}
<div>This is some example content.</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="containter" style="overflow:hidden">
<div>
Content.....
</div>
</div>
//add something...
$('#container').animate({height:$('#container').content().outerHeight()});
or:
$('#container').animate({height:$('#container').children().first().outerHeight()});
and when adding append to the div inside the containter:
$('#container').children().first().append(somethingNew);
Based on icktoofay's answer.
I make the button disabled while changing the height and add a fading effect. This solution is useful for updating of the products filter and so on.
Also I check the box-sizing property. If it's box-sizing then I get newHeight by .outerHeigth() instead of .height() to prevent the height fluctuation when new content has the same height. You can check this situation, for example by setting the random variable to value 5. The reason is that
.height() will always return the content height, regardless of the value of the CSS box-sizing property.
CodePen
$('#button').click(function() {
var $button = $(this),
buttonOriginalText = $button.html();
$button.prop('disabled', true).html('Updating...');
$('#content').animate({
opacity: 0
}, 'fast', function() {
var newHeight,
$content = $(this),
oldHeight = $content.height();
$content.html(getRandomContent());
newHeight = ('border-box' === $content.css('box-sizing') ? $content.outerHeight() : $content.height());
$content.height(oldHeight).animate({
height: newHeight,
opacity: 1
}, 'slow', function() {
$content.height('auto');
$button.prop('disabled', false).html(buttonOriginalText);
});
});
});
function getRandomContent() {
var random = 1 + Math.round(Math.random() * 11), // 1..12
paragraph = '<p>Paragraph</p>';
return paragraph.repeat(random);
}
* {
box-sizing: border-box; /* comment out to test "content-box" */
font: 16px Helvetica, 'sans-serif';
}
.content {
counter-reset: content;
padding: 6px 18px;
}
.content p {
counter-increment: content;
}
.content p:after {
content: ' ' counter(content) '.';
}
.content-box {
border: 2px solid red;
margin-top: 24px;
max-width: 220px;
}
<button id="button" class="button">Update the content</button>
<div class="content-box">
<div id="content" class="content">Animatie the automatic height when content is resized.</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>