When Do Nested Child Elements Expand Their Parent Elment

When do nested child elements expand their parent elment?

The first thing that you should understand is the CSS Box Model. That will help you understand how properties of an element cause it to have the size and dimensions that it has. Another good resource is here.

To answer your main question in the most simple manner (and being very general):

  • Block level elements take up as much width as possible (obeying their CSS width rule). Their height is dependent on their content and the CSS height property.

    • Elements like div, p, and ul are all block.
    • These will generally cause your parent element to expand.
  • Inline level elements will continue to flow together in a line, filling up only as much width and height as necessary.

    • Elements like span, em, strong are all inline.
    • These will cause your parent element to expand only when there are enough of them on the same line to warrant another line.

There are many ways to tweak the display of elements with CSS.

Reach the parent element from the child

Add a click handler to the children:

$('i.child').click(function(){
$(this).parent().parent().hide()
})

When you click a child, it will cause its grandparent to hide (.nested_parent), which automatically hides its descendants (.nested_parent1 and .child).

Two nested divs are able to expand but not the parent

Use overflow to parent element, because your child divs floated:

<div style="overflow: hidden; background-color:#000; color:#FFFFFF; width:444px; height: auto;">

or use instead of

float:left; 

for childs

display: inline-block;

changing nested child div based on parent divs

I'm not quite sure why you define six different styles for .productOptionName when there are only three such divs in your example. I'm assuming your want to color those three divs all a different color without adding an id or extra class to them.

Right now you are trying to select the nth child that also has a class of .productOption with the .productOption:nth-child(n) selector. You only have one div with class .productOption which in this case is the first child (of the body) so only your first line of CSS will be executed:

.productOption:nth-child(1) > form > .productOptionDetails > .productOptionName { color:#049b5c;} 

This line of CSS will select the .productOption div, then the form inside of it. Then all the divs with class .productOptionDetails, and then all divs inside of those with class .productOptionName, coloring them #049b5c.

If you want to color all three divs with class .productOptionName in your example a different color, try the below example. This selects the div with class .productOption, then the form inside of it. Then uses the nth-child() selector to select child one, three and five that also have a class of .productOptionDetails, and selects the .productOptionName inside of those.

.productOption > form > .productOptionDetails:nth-child(1) > .productOptionName { color:red;}
.productOption > form > .productOptionDetails:nth-child(3) > .productOptionName { color:blue;}
.productOption > form > .productOptionDetails:nth-child(5) > .productOptionName { color:green;}
<div class="productOption">
<form action="#" method="post">
<div class="productOptionDetails">
<input type="hidden" name="id" value="1">
<input type="hidden" name="add" value="Add">
<input type="hidden" name="productTitle" value="2 Hours">
<input type="hidden" name="productPrice" value="220">
<input type="hidden" name="productSize" value="">
<input type="hidden" name="productWeight" value="">
<div class="productOptionName">2 Hours</div>
<div class="productOptionSize">1</div>
<div class="productOptionCode">2hr</div>
<div class="productOptionPrice">$220.00</div>
</div>
<div class="productOptionOrder">
<div class="productOptionQty">
<input id="qtyfield" type="text" name="qty" value="1">
</div>
<div class="addtocart">
<button class="productD_order" type="submit" value="Order Online">Add To  <img src="himages/cart-icon.png" alt="Sample Image"></button>
</div>
</div>
<div class="productOptionDetails">
<input type="hidden" name="id" value="1">
<input type="hidden" name="add" value="Add">
<input type="hidden" name="productTitle" value="2 Hours">
<input type="hidden" name="productPrice" value="220">
<input type="hidden" name="productSize" value="">
<input type="hidden" name="productWeight" value="">
<div class="productOptionName">2 Hours</div>
<div class="productOptionSize">1</div>
<div class="productOptionCode">2hr</div>
<div class="productOptionPrice">$220.00</div>
</div>
<div class="productOptionOrder">
<div class="productOptionQty">
<input id="qtyfield" type="text" name="qty" value="1">
</div>
<div class="addtocart">
<button class="productD_order" type="submit" value="Order Online">Add To  <img src="himages/cart-icon.png" alt="Sample Image"></button>
</div>
</div>
<div class="productOptionDetails">
<input type="hidden" name="id" value="1">
<input type="hidden" name="add" value="Add">
<input type="hidden" name="productTitle" value="2 Hours">
<input type="hidden" name="productPrice" value="220">
<input type="hidden" name="productSize" value="">
<input type="hidden" name="productWeight" value="">
<div class="productOptionName">2 Hours</div>
<div class="productOptionSize">1</div>
<div class="productOptionCode">2hr</div>
<div class="productOptionPrice">$220.00</div>
</div>
<div class="productOptionOrder">
<div class="productOptionQty">
<input id="qtyfield" type="text" name="qty" value="1">
</div>
<div class="addtocart">
<button class="productD_order" type="submit" value="Order Online">Add To  <img src="himages/cart-icon.png" alt="Sample Image"></button>
</div>
</div>
</form>
</div>

extend parent and children nested selectors in less

The issue with parentChildProperty not being applied to the ul element can be fixed by also extending .parent-class .child-class in the ul styles

This will not resolve all the issues. It will still leave many unnecessary selectors in the generated CSS, but it will generate the required CSS to allow the page to display correctly.

Updated less:

.parent-class{
parentProperty: value;
.child-class { parentChildProperty: value; }
}

.child-class {
childProperty:value;
& > li{ childLiProperty:value; }
}

nav{
&:extend(.parent-class all);
ul{
&:extend(.child-class all);
&:extend(.parent-class .child-class);
}
}

Flexbox / Expanding height due to nested element

Update
As I already said in the comment. You cannot change the height of the elements independently they are all in a parent-child-relationship.

You should consider using less markup and maybe use a different approach to achieve the same. If it is about the styling you could make .value growing with the .slider-val-text and use an independent absolute element to draw over the .slider-val-text (you just have to add enough padding and draw over it at the top there for this greenish box background).

However, you can set a fixed height to the .value container. Try height: 168px. The problem with that is, that it will not change depending on the text you put in in .slider-val-text.

You could use javascript and set the height of the .value container based on the height of the .slider-val-text once the DOM has finished loading.

document.addEventListener("DOMContentLoaded", function() {
const childHeight = document.querySelector('.slider-val-text').offsetHeight;
const parent = document.querySelector('.value');
let verticalPadding = parseInt(window.getComputedStyle(parent, null).getPropertyValue('padding-top'));
verticalPadding += parseInt(window.getComputedStyle(parent, null).getPropertyValue('padding-bottom'));
parent.style.height = childHeight + verticalPadding + 'px';
});
.menu-item-list {
position: absolute;
top: 2em;
left: 1em;
right: 40%;
}

.menu-item-list li {
display: flex;
}

.menu-item-list .control-slider .value {
box-sizing: border-box;
/* ADDED */
padding: 0 1em 0 0;
}

.menu-item-list .control-slider .slider-view {
width: 100%;
padding: 0;
display: flex;
}

.menu-item-list .control-slider .slider-view .slider-val-line-parent {
padding: 0;
text-align: right;
display: flex;
flex-flow: column wrap;
/*position: absolute; REMOVED */
left: 0;
}

.menu-item-list .control-slider .slider-view .slider-val-line-parent .slider-val-text {
flex: 1;
/* width: calc(100% + 16px); REMOVED */
/*right: 7px;
position: relative;
top: 36px; REMOVED */
padding-top: 36px;
padding-right: 0px;
padding-left: 0px;
font-size: 14px;
justify-content: right;
}

.menu-item-list .control-slider .slider-box {
height: 1.5em;
padding: 0.1em 0.25em;
width: 50%;
position: relative;
background-color: purple;
opacity: 50%;
}

.menu-item-list .control-slider .slider-box .safe-slider {
background-color: green;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
position: relative;
}

.menu-item-list .control-slider .slider-box .safe-slider .slider-val-line-parent {
border-style: dashed;
border-color: black;
display: flex;
}

.menu-item-list .menu-item {
background-color: orange;
}

.menu-item-list .menu-item .label {
width: 57%;
background-color: yellow;
opacity: 50%;
}

.menu-item-list .menu-item .value {
width: 43%;
}

.menu-item-list .menu-item.active.control-slider {
display: flex;
flex-direction: column;
}

.menu-item-list .menu-item.active.control-slider .label {
width: 100%;
margin: 0;
}

.menu-item-list .menu-item.active.control-slider .value {
width: 100%;
padding: 1em 1em 1.5em;
}
<ol class="menu-item-list">
<li id="menu-item-las-powr" class="menu-item control-slider active">
<div class="label">Label</div>
<div class="value">
<div class="slider-view">
<div class="slider-box">
<div class="safe-slider">
<div class="slider-val-line-parent">
<div class="slider-val-text">
BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO
BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO
</div>
</div>
</div>
</div>
</div>
</div>
</li>
</ol>

Prevent nested elements from triggering an event for parent element

Solution 1: Compare target with currentTarget:

$("#parentEle").click( function(e) {
if(e.target == e.currentTarget) {
alert('parent ele clicked');
} else {
//you could exclude this else block to have it do nothing within this listener
alert('child ele clicked');
}
});

Fiddle

e.target will be the element that started the event.

e.currentTarget will be where it currently is (bubbling up) which will be parentEle in this click event as that's what this is listening for.

If they are the same, you know the click was directly on the parent.


Solution 2: Stop the propagation before the event hits the parentEle:

The other option is to prevent the event from bubbling up in the first place if there is a click on a child element. That can be done like this:

$("#parentEle").click( function(e) {
alert('parent ele clicked');
});
$("#parentEle").children().click( function(e) {
//this prevent the event from bubbling to any event higher than the direct children
e.stopPropagation();
});

Fiddle


The main difference between the two is that the first solution will just ignore the event in this listener and allow it to keep bubbling up. This may be necessary if you have a parent of this parentEle that needs to get the event.

The second solution stops any click events from bubbling past parentEle's direct children. So if there was a click event on a parent of parentEle, they would never see these events either.



Related Topics



Leave a reply



Submit