make an element the same height as its child with css - javascript

I have this code and the child's height is changing but the parent's height remains the same. I want a CSS code to make the parent's height the same as the child
<div class = "parent">
<div class="child">
</div>
</div

Note: using your HTML
if you add the CSS
<style>
.parent, .child {
width: 120px; height: 100px;
}
</style>
<div class = "parent">
<div class="child">
</div>
</div
both child and parent would have the same width and height of: 120, by 100. Change these values to suite what you need.
if you add this additional CSS lines:
.parent { border: 1px solid red; }
.child { border: 1px solid blue }
this will draw your border - in different colours, so you can see easily what is happening - you can remove this after

Related

How to align a canvas and a div element side by side

I have a canvas and a div element which I want to split in the ratio 60% to 40%. So far any changes that I make to the display ensures that the div is displayed first and then the canvas.
And the Div element has buttons that have color changing properties for the canvas element.
<div id = "ModelArea1">
<div id = "Model1">
<canvas id ="scene1" style="width: 100%; height:100%;">
</canvas>
</div>
<div id ="SelectionArea1">
<button type ="button" class ="ButtonFormat" onclick =displayVariations()>Fabric Textures</button>
<div class = "FabricTectureOptions" style="display:none;">
<div class ="Fabric1">
</div>
<div class ="Fabric2">
</div>
</div>
<button type ="button" class ="ButtonFormat" onclick =displayVariations()>Leather Textures</button>
</div>
</div>
.Fabric1{
background-image: url("https://i.ibb.co/B2kPznR/Fabric-Upholstery-Moss-Plain-Weave001-AO-1-K.jpg");
height: 50px;
width: 50px;
border-radius: 10px;
display: inline-block;
}
.Fabric2{
background-image: url("https://i.ibb.co/kKZRpdm/Fabric-Upholstery-Moss-Plain-Weave001-COL-VAR3-1-K.jpg");
height: 50px;
width: 50px;
border-radius: 10px;
display: inline-block;
}
.ButtonFormat{
background-color: #eee;
color: #444;
cursor: pointer;
padding: 5px;
border-style: none outset outset none;
outline: none;
font-size: 12px;
}
.FabricTectureOptions{
padding: 0 18px;
overflow: hidden;
background-color: #f1f1f1;
border-radius: 10px;
}
#ModelArea1{
width:100%;
display:inline-flex;
}
#Model1{
width: 60%;
}
#SelectionArea1{
width: 40%;
}
What I am expecting is same height and width of the canvas and div but side by side.
| Canvas | Div |
| | |
| | |
Question 1: How do I get this alignment right?
Question 2: Can this be done only by wrapping the canvas into a div? Is there an alternative?
Here is a link to the codepen:
https://codepen.io/FarhaNaseem/pen/eYgKJZW
You can simply do this and it will work to an extent.
renderer.setSize(window.innerWidth * 0.6, window.innerHeight); // Set the width of the canvas initially to 60%;
But then you may have to update the canvasWidth when every time the window is resized. I have also created some new container via JS and appended the child elements into it.
// Canvas width dynamic resize
window.addEventListener("resize", () => {
let ratio = 0.6
let canvasWidth = window.innerWidth * ratio
renderer.setSize(canvasWidth, window.innerHeight) // You can also manipulate this height by multiplying with the ratio
camera.aspect = canvasWidth/ window.innerHeight
camera.updateProjectionMatrix() // Must be called after any change of parameters.
});
// Add elements to the DOM in a wrapper container
let ModelArea1 = document.querySelector("#ModelArea1")
let container = document.createElement("div")
container.classList.add("container")
document.body.append(container)
container.appendChild(renderer.domElement) // Append canvas to the container
container.appendChild(ModelArea1) // Append 40% area after canvas
This would give you a neater DOM generated:
<div class="container">
<canvas id="scene1" width="726" height="541">
</canvas>
<div id="ModelArea1">
<div id="Model1">
</div>
<div id="SelectionArea1">
<button type="button" class="ButtonFormat" onclick="displayVariations()">Fabric Textures</button>
<div class="FabricTectureOptions" style="display:none;">
<div class="Fabric1">
</div>
<div class="Fabric2">
</div>
</div>
<button type="button" class="ButtonFormat" onclick="displayVariations()">Leather Textures</button>
</div>
</div>
</div>
Finally you can turn the container to a flexbox element using display: flex
Output:
Codepen Demo: https://codepen.io/m4n0/pen/zYNeGVz

Css : Justify child divs with variable width

how to justify child divs with variable width inside parent div with fixed width.I want to justify child divs not only on single line but inside the whole parent container. Parent and Child elements are dynamically generated.
<div class="parent">
<div class="child">1.2345</div>
<div class="child">1:223345</div>
<div class="child">1:23421225</div>
<div class="child">1:2345</div>
<div class="child">1:235</div>
<div class="child">1:2345</div>
.
.
.
30 Child elements
</div>
CSS
.parent{
width:450px;
text-align:justify;
}
.child{
float: left;
margin: 2px;
}
output is something like this
UPDATED
Now i have set width to each child divs depending on its text length.
.parent{
width:250px;
text-align:justify;
border: 1px solid #ddd;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.child{
margin: 2px;
}
<div class="parent">
<div class="child">1.2345</div>
<div class="child">1:2345</div>
<div class="child">1:2345</div>
<div class="child">1:2345</div>
<div class="child">1:2345</div>
<div class="child">1:2345</div>
. . . 30 Child elements
</div>
demo add 30 +
Once all of your child divs have been added to the DOM, you could get the element with the greatest width and then set the width of each of the other divs.
var childDivs = [].slice.call(document.querySelectorAll("div.child"));
var maxWidth = Math.max.apply(null, childDivs.map(function(ele){
return ele.offsetWidth;
}));
for(var i = 0; i < childDivs.length; i++){
childDivs[i].style.width = maxWidth + "px";
}
CSS Flex box can do the job but you must ensure browser compatibility.
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Also, there are a few concepts to understand before using flexbox. In the end, it can solve many CSS layout problems.
Ohterwise, you may need to use javascript to dynamically resize your elements.

Setting a length (height or width) for one element minus the variable length of another, i.e. calc(x - y), where y is unknown

I know we can use calc when lengths are defined:
flex-basis: calc(33.33% - 60px);
left: calc(50% - 25px);
height: calc(100em/5);
But what if a length is variable?
height: calc(100% - <<header with variable height>>);
OR
width: calc(100% - 50px - <<box with variable width>>);
Is there a standard way to do this in CSS?
I know the overall task is possible with flexbox and tables, but I'm wondering if CSS offers a simpler method. Flexbox, tables and simple Javascript are acceptable alternatives.
height demo
width demo
You can use CSS tables:
.wrapper {
display: table;
width: 100%;
margin: 15px 0;
}
.horizontal.wrapper > div {
display: table-cell;
white-space: nowrap; /* Prevent line wrapping */
border: 1px solid;
}
.left { width: 100px } /* Minimum width of 100px */
.center { width: 0; } /* Width given by contents */
.vertical.wrapper { height: 200px; }
.vertical.wrapper > div {
display: table-row;
}
.vertical.wrapper > div > span {
display: table-cell;
border: 1px solid;
}
.top { height: 100px; } /* Minimum heigth of 100px */
.middle { height: 0; } /* Height given by content */
.bottom { height: 100%; } /* As tall as possible */
<div class="horizontal wrapper">
<div class="left">100px wide</div>
<div class="center">Auto width, given by contents</div>
<div class="right">Remaining space</div>
</div>
<div class="vertical wrapper">
<div class="top"><span>100px tall</span></div>
<div class="middle"><span>Auto height, given by contents</span></div>
<div class="bottom"><span>Remaining space</span></div>
</div>
The horizontal case can also be achieved with floats:
#wrapper, .right { overflow: hidden; } /* Establish BFC */
#wrapper > div { border: 1px solid; }
.left, .middle { float: left; }
.left { width: 100px }
<div id="wrapper">
<div class="left">100px</div>
<div class="middle">Auto width, given by contents</div>
<div class="right">Remaining space</div>
</div>
Flexbox can do that.
Support is IE10 and up.
JSfiddle Demo
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
#container {
height: 100%;
display: flex;
flex-direction: column;
}
#top {
background-color: lightgreen;
}
#bottom {
background-color: lightblue;
flex: 1;
}
<div id="container">
<div id="top">green box variable height</div>
<div id="bottom">blue box no longer overflows browser window</div>
</div>
I'm looking for something simple and portable. In the same way a CSS
property can be easily applied across documents, I'm looking for
something similar in terms of ease-of-application for this function.
... isolated fix is preferred.
Horizontal:
This can be achieved using CSS only. As you do not prefer a flex layout solution, the next best bet would be a table layout.
A simple CSS snippet which you could drop into your project (and be done with) would look like this:
div.flexh {
display: table; box-sizing: border-box; padding: 0; margin: 0;
}
div.flexh > div {
display: table-cell; width: auto;
box-sizing: border-box; vertical-align: middle;
}
div.flexh > div:first-child {
/* Override your custom styling below */
min-width: 75px; width: 75px; max-width: 75px;
}
div.flexh > div:last-child { width: 100%; }
You can then add your site-specific styling to this base CSS as per site requirements. Like, nowrap etc.
Two apparent advantages of this solution are:
You do not need to change your markup and also do not need to decorate all children with classes. Just apply the class flexh to your parent div and that would be it.
Minimal Markup Required:
<div class="flexh">
<div>...</div>
<div>...</div>
<div>...</div>
</div>
You are not limited to just three columns. You could have as many columns as need be. The first one will have fixed width, the last one will be flexible, and all the columns in-between would get content-based widths.
Demo Fiddle: http://jsfiddle.net/abhitalks/qqq4mq23/
Demo Snippet:
div.flexh {
display: table; box-sizing: border-box; padding: 0; margin: 0;
/* Override your custom styling below */
width: 80%; border: 2px solid black;
border-right: 2px dashed black;
font-size: 1em;
}
div.flexh > div {
display: table-cell; width: auto;
box-sizing: border-box; vertical-align: middle;
/* Override your custom styling below */
background-color: lightgreen; border: 1px solid #ddd;
padding: 15px 5px;
}
div.flexh > div:first-child {
/* Override your custom styling below */
min-width: 75px; width: 75px; max-width: 75px;
background-color: orange;
}
div.flexh > div:last-child {
width: 100%;
/* Override your custom styling below */
background: skyblue;
}
<div class="flexh">
<div>75px Fixed Width</div>
<div>Variable Content Width</div>
<div>Flexible Remaining Width</div>
</div>
<hr/>
<div class="flexh">
<div>75px Fixed Width</div>
<div><img src='//placehold.it/128x48/66c' /></div>
<div>Flexible Remaining Width</div>
</div>
<hr/>
<div class="flexh">
<div>75px Fixed Width</div>
<div>Variable TextWidth</div>
<div>
<img src='//placehold.it/128x48/66c' />
<p>Variable ContentWidth</p>
</div>
<div>Flexible Remaining Width</div>
</div>
Vertical:
This is a bit tricky to achieve without flex layout. A table layout would not work here mainly because, the table-row would not keep a fixed height as required by your use-case. The height on a table-row or table-cell is only an indicative of the minimum height required. If the space is constrained, or the content exceeds the available space, then the cell or row will increase its height depending on the content.
As per the specs here: http://www.w3.org/TR/CSS21/tables.html#height-layout
The height of a 'table-row' element's box is calculated once the user
agent has all the cells in the row available: it is the maximum of the
row's computed 'height', the computed 'height' of each cell in the
row, and the minimum height (MIN) required by the cells...
...the height of a cell box is the minimum height required by the
content
This effect can be seen here: http://jsfiddle.net/abhitalks/6eropud3/
(Resize the window pane and you will see that the first row will increase in height as the content cannot be fit into the specified height, hence defeating the purpose)
Therefore, you can restrict the height indirectly either using inner markup like a div element, or let go of the table-layout and calculate the height for the flexible one. In your use-case, you prefer not to change the markup, hence I am not proposing an inner markup.
The best-bet here would be to use the time-tested model of plain block-level divs with the height of the flexible one to be calculated. As you have already discovered that it is not possible with CSS, you will need a small JavaScript snippet to do that for you.
A simple JavaScript snippet (no jQuery) which you could wrap in a window.load and drop into your project (and be done with) would look like this:
var flexv = document.querySelectorAll('div.flexv');
/* iterate the instances on your page */
[].forEach.call(flexv, function(div) {
var children = [].slice.call(div.children), // get all children
flexChild = children.splice(-1, 1), // get the last child
usedHeight = 0, totalHeight = div.offsetHeight;
children.forEach(function(elem) {
usedHeight += elem.offsetHeight; // aggregate the height
});
/* assign the calculated height on the last child */
flexChild[0].style.height = (totalHeight - usedHeight) + 'px';
});
The CSS snippet is more or less like the horizontal one, sans table layout, which also you could just drop into your project and just add the additional site-specific styling. Minimal markup required remains the same.
Demo Fiddle 2: http://jsfiddle.net/abhitalks/Ltcuxdwf/
Demo Snippet:
document.addEventListener("load", flexit);
function flexit(e) {
var flexv = document.querySelectorAll('div.flexv');
[].forEach.call(flexv, function(div) {
var children = [].slice.call(div.children),
flexChild = children.splice(-1, 1),
usedHeight = 0, totalHeight = div.offsetHeight;
children.forEach(function(elem) {
usedHeight += elem.offsetHeight;
});
flexChild[0].style.height = (totalHeight - usedHeight) + 'px';
});
}
div.flexv {
display: inline-table; box-sizing: border-box; padding: 0; margin: 0;
overflow: hidden;
/* Override your custom styling below */
height: 320px; width: 20%; border: 1px solid black; font-size: 1em;
margin: 8px;
}
div.flexv > div {
display: block; height: auto; box-sizing: border-box;
overflow: hidden;
/* Override your custom styling below */
background-color: lightgreen; border: 1px solid #ddd;
padding: 5px 15px;
}
div.flexv > div:first-child {
/* Override your custom styling below */
min-height: 36px; height: 36px; max-height: 36px;
background-color: orange;
}
div.flexv > div:last-child {
height: 100%;
/* Override your custom styling below */
background: skyblue;
}
<div class="flexv">
<div>36px Fixed Height</div>
<div>Variable Content Height</div>
<div>Flexible Remaining Height</div>
</div>
<div class="flexv">
<div>36px Fixed Height</div>
<div><img src='//placehold.it/64x72/66c' /></div>
<div>Flexible Remaining Height</div>
</div>
<div class="flexv">
<div>36px Fixed Height</div>
<div>Variable Text Height</div>
<div>
<img src='//placehold.it/72x48/66c' />
<p>Variable Content Height</p>
</div>
<div>Flexible Remaining Height</div>
</div>
Note: As pointed out by #LGSon, the display: inline-table used for the demo does not play well with Firefox. This is only for a demo and should be replaced by either block or inline-block as per your use-case.
Updated
As I commented earlier, and besides flex, this is also solvable using display: table and here is a fiddle demo I made showing that.
If a fixed top also were required for the vertical demo, here is an update of my original display:table version: fiddle demo
Sometimes I haven't been able (or didn't want) to use either flex nor tables, and I have, on and off, looked into making use of css calc() and css attr().
Both come short though, as calc() can only use +-*/ and attr() can only return a string value, which can't be computed by calc().
My suggestion, using plain javascript, is based on that these 2 methods, at some point, might be extended so we can make better use of them.
This is how I would like see them work;
width: calc(100% - attr(this.style.left))
but as they don't, and I can't add it to my css either as it wouldn't validate properly (might even break the parsing, who knows) I added a variant as an attribute on the element instead, with some quirks to make it easier to compute.
And in this case (the 2 demos) it looks like this:
//height
<div id="bottom" data-calcattr="top,height,calc(100% - toppx)">...</div>
//width
<div class="box right" data-calcattr="left,width,calc(100% - leftpx)">...</div>
Together with below script, which by no means is fully developed/tested on all property combinations, it does adjust the div's size.
In short, when runned, it take the attribute, split it into an array, take the first item value as from which property to read, the second to which property to set and the third to which the read value gets inserted/replaced and assigned to the property to be set (hmmm, still working on a better way to express this, but hopefully the script is clear enough with whats going on).
Here is a fiddle showing both the height and width demo, integrated, making use of the same script.
function calcattr() {
var els = document.querySelectorAll('[data-calcattr]');
for (i = 0; i < els.length; i++) {
var what = els[i].getAttribute('data-calcattr');
if (what) {
what = what.split(',');
var rect = els[i].getBoundingClientRect();
var parentrect = els[i].parentNode.getBoundingClientRect();
var brd = window.getComputedStyle(els[i].parentNode,null).getPropertyValue('border-' + what[0] + '-width');
what[2] = what[2].replace(what[0],parseInt(rect[what[0]]-parentrect[what[0]]) - parseInt(brd));
els[i].setAttribute("style", what[1] + ":" + what[2]);
}
}
}
IN CSS
Although I've never tried it, I believe that this would work:
.top {
height:13px;
}
.main {
height:calc(100% - var(height));
}
http://www.creativebloq.com/netmag/why-you-need-use-css-variables-91412904
IN SASS
$top_height: 50px
.main {
height: calc(100% - $top_height)
}
Sass Variable in CSS calc() function
In both cases on container css you should put:
#container {
overflow: hidden;
}
But, it will hide the information that overflows the container. I think that is the point, since you put white-space: nowrap; it means that you don't want to change the height, so you have to hide the text that can't fits the container.

Why the container div height was not updated?

I'm adding elements into a container div whose height is 'auto' initially. I expect its height will be updated as the children elements appended. But, actually not. Could someone help me? I just want the container div height gets updated according to the children's height.
I used chrome debuging tool, the height of container div is less than height of children divs. Children divs are float:left.
If you're adding floated children to a div you need to have overflow:auto; on the parent.
You can also use another element to clear the float clear:both will do this.
This is because floated elements are taken out of the document flow.
Here's an example that shows you a few techniques you can use : http://jsfiddle.net/Tn5c3/
The CSS
#a, #b {
padding: 10px;
margin:10xp
}
#a {
background: #aa0000;
}
#b {
background: #00aa00;
overflow: auto;
}
p {
background: #0000aa;
padding: 5px;
}
.clear {
clear:both;
height: 50px;
}
The JS
$('#bb').click(function() {
addChild($('#b'));
});
$('#ba').click(function() {
addChild($('#a'));
});
function addChild(parent) {
var child = $('<p>floated para</p>').css({
'float': 'left'
});
parent.append(child);
}
The HTML
<button id='ba'>Add to A</button>
<button id='bb'>Add to B</button>
<div id='a'></div>
<div class='clear'></div>
<div id='b'></div>

jQuery - watch for element height change

I have a element, which is absolute positioned and has a fixed height.
This element has a lot of child elements, which could change their contents, and in consequence their height.
The problem is that the container element doesn't auto expand to fit its children (because of it's fixed height and absolute position).
How can I can resize the main container to match its children height?
Assuming you can change the css, this can be done fairly simply in css. Instead of setting height simply set min-height and your element should expand thusly.
min-height
Optionally if you did want to/need to do it in jQuery something like the following would work:
html:
<div id='container'>
<div class='child'>Content</div>
<div class='child'>Content</div>
<div class='child'>Content</div>
<div class='child'>Content</div>
</div>
CSS:
.child{
height: 40px;
background-color: red;
}
#container{
height: 120px;
background-color: gray;
padding: 5px;
}
javascript:
var childHeight = 0
$('.child').each( function() {
childHeight = childHeight + $(this).height();
})
$('#container').height(childHeight);
Working example:
http://jsfiddle.net/EcZZL/1/

Categories

Resources