How can you get the dimensions of the content area of a DOM element?
Strangely couldn't find a question/answer to this. Many questions about measuring DOM elements as a whole, but none about the content area itself.
Example:
div {
width: 100px;
height: 200px;
padding: 10px;
border: 5px;
margin: 15px;
box-sizing: border-box;
}
Now somethings get you various parts of the box model, but nothing seems to give you the content:
const elem = document.querySelector('div');
elem.offsetWidth; // content + padding + border
elem.clientWidth; // content + padding
window.getComputedStyle(elem); // Returns an object with width padding and border as strings like "15px".
window.getBoundingClientRect(); // Gives width and height of total box-model excluding margin if sizing is border-box.
You'll need to subtract the computed paddings from the client width and height:
const elem = document.getElementById('elem');
const computedStyles = window.getComputedStyle(elem)
const extraWidthOffset = +computedStyles.getPropertyValue("padding-left").slice(0, -2) + +computedStyles.getPropertyValue("padding-right").slice(0, -2)
const extraHeightOffset = +computedStyles.getPropertyValue("padding-top").slice(0, -2) + +computedStyles.getPropertyValue("padding-bottom").slice(0, -2)
const contentWidth = elem.clientWidth - extraWidthOffset
const contentHeight = elem.clientWidth - extraHeightOffset
console.log(contentWidth, contentHeight)
#elem {
width: 100px;
height: 200px;
padding: 10px;
border: 5px;
margin: 15px;
box-sizing: border-box;
}
<div id="elem">
<p>Content</p>
</div>
Related
I wanted a vertical dragBar for resizing two divs. I have created an example for the same but I am facing an issue.
Actual : As and when I resize the the upper div and move the slider down, the area of parent div increases and hence a scroll bar is given.
Expected: When Resizing, if the slider is moved down, it should only show the data contained in the upper div and when slider is moved up, it should show the content of lower div and should not increase the over all length of the parent div.
var handler = document.querySelector('.handler');
var wrapper = handler.closest('.wrapper');
var boxA = wrapper.querySelector('.box1');
var boxB = wrapper.querySelector('.box2');
var isHandlerDragging = false;
document.addEventListener('mousedown', function(e) {
// If mousedown event is fired from .handler, toggle flag to true
if (e.target === handler) {
isHandlerDragging = true;
}
});
document.addEventListener('mousemove', function(e) {
// Don't do anything if dragging flag is false
if (!isHandlerDragging) {
return false;
}
// Get offset
var containerOffsetTop= wrapper.offsetTop;
var containerOffsetBottom= wrapper.offsetBottom;
// Get x-coordinate of pointer relative to container
var pointerRelativeXpos = e.clientY - containerOffsetTop;
var pointerRelativeXpos2 = e.clientY - e.offsetTop + e.offsetHeight;
var boxAminWidth = 30;
boxA.style.height = (Math.max(boxAminWidth, pointerRelativeXpos - 2)) + 'px';
boxA.style.flexGrow = 0;
boxB.style.height = (Math.max(boxAminWidth, pointerRelativeXpos2 - 8)) + 'px';
boxB.style.flexGrow = 0;
});
document.addEventListener('mouseup', function(e) {
// Turn off dragging flag when user mouse is up
isHandlerDragging = false;
});
body {
margin: 40px;
}
.wrapper {
background-color: #fff;
color: #444;
/* Use flexbox */
}
.box1, .box2 {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
margin-top:2%;
/* Use box-sizing so that element's outerwidth will match width property */
box-sizing: border-box;
/* Allow box to grow and shrink, and ensure they are all equally sized */
}
.handler {
width: 20px;
height:7px;
padding: 0;
cursor: ns-resize;
}
.handler::before {
content: '';
display: block;
width: 100px;
height: 100%;
background: red;
margin: 0 auto;
}
<div class="wrapper">
<div class="box1">A</div>
<div class="handler"></div>
<div class="box2">B</div>
</div>
Hope I was clear in explaining the issue I am facing in my project. Any help is appreciated.
It looks like your on the right track. You just need to make the wrapper a flexbox with the flex direction column and assign it a height. Also box 2 needs to have a flex of 1 so it can grow and shrink as needed. Finally I needed to remove the code that set the flex grow to 0 in the JavaScript. Here is the result.
var handler = document.querySelector('.handler');
var wrapper = handler.closest('.wrapper');
var boxA = wrapper.querySelector('.box1');
var boxB = wrapper.querySelector('.box2');
var isHandlerDragging = false;
document.addEventListener('mousedown', function(e) {
// If mousedown event is fired from .handler, toggle flag to true
if (e.target === handler) {
isHandlerDragging = true;
}
});
document.addEventListener('mousemove', function(e) {
// Don't do anything if dragging flag is false
if (!isHandlerDragging) {
return false;
}
e.preventDefault();
// Get offset
var containerOffsetTop= wrapper.offsetTop;
var containerOffsetBottom= wrapper.offsetBottom;
// Get x-coordinate of pointer relative to container
var pointerRelativeXpos = e.clientY - containerOffsetTop;
var pointerRelativeXpos2 = e.clientY - e.offsetTop + e.offsetHeight;
var boxAminWidth = 30;
boxA.style.height = (Math.max(boxAminWidth, pointerRelativeXpos - 2)) + 'px';
boxB.style.height = (Math.max(boxAminWidth, pointerRelativeXpos2 - 8)) + 'px';
});
document.addEventListener('mouseup', function(e) {
// Turn off dragging flag when user mouse is up
isHandlerDragging = false;
});
body {
margin: 40px;
}
.wrapper {
background-color: #fff;
color: #444;
/* Use flexbox */
display: flex;
flex-direction: column;
height: 200px;
}
.box1, .box2 {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
margin-top:2%;
/* Use box-sizing so that element's outerwidth will match width property */
box-sizing: border-box;
/* Allow box to grow and shrink, and ensure they are all equally sized */
}
.box2 {
flex: 1;
}
.handler {
width: 20px;
height:7px;
padding: 0;
cursor: ns-resize;
}
.handler::before {
content: '';
display: block;
width: 100px;
height: 100%;
background: red;
margin: 0 auto;
}
<div class="wrapper">
<div class="box1">A</div>
<div class="handler"></div>
<div class="box2">B</div>
</div>
Im trying to get a div called touch-container to hold a canvas with 3 div's on top. I'm sizing them using javascript as well.
The problem is that each of the 3 div's have a margin which takes up the rest of the space in the container even though i specifically state 0 margin.
Here is a jsFiddle, if you inspect, you can see the margin Jsfiddle
HTML:
<div id = "touch-container">
<div id = "touch-left" class = "touch-control"></div>
<div id = "touch-middle" class = "touch-control"></div>
<div id = "touch-right" class = "touch-control"></div>
<canvas id = "canvas" width = "960" height = "560"></canvas>
</div>
CSS:
body {
margin: 0;
}
#touch-container{
width: 964px;
height: 560px;
display: inline-block;
margin: 0;
}
.touch-control{
position: relative;
margin: 0;
}
#touch-left{
background-color: red;
}
#touch-middle{
background-color: green;
}
#touch-right{
background-color: blue;
}
JS:
var leftTouch = document.getElementById('touch-left');
var upTouch = document.getElementById('touch-middle');
var rightTouch = document.getElementById('touch-right');
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext("2d");
var width = (canvas.width > canvas.height ? canvas.width : canvas.height);
var height = (canvas.height > canvas.width ? canvas.width : canvas.height);
leftTouch.style.width = (width/ 4) + 'px';
leftTouch.style.height = height + 'px';
upTouch.style.width = (width/ 2) + 'px';
upTouch.style.height = height + 'px';
rightTouch.style.width = (width/ 4) + 'px';
rightTouch.style.height = height + 'px';
ctx.fillRect(0,0,canvas.width, canvas.height);
I've colored them in so it should be a black square on the bottom, then from left to right, a red, green and blue square that takes up 25%, 50% 25% of the container respectively so you wont even be able to see the black canvas.
You didn't add any float in your elements(squares) so the squares don't know how they should be located, You most use float:left; to force squares to be in a same line and display:inline-block; wont works in your case (it just works for text only):
Jsfiddle
css:
#touch-container{
width: 964px;
height: 560px;
display: block;/* new update */
margin: 0;
}
#touch-left{
background-color: red;
float:left;/* new update from here to below */
display:block;
}
#touch-middle{
background-color: green;
float:left;/* new update from here to below */
display:block;
}
#touch-right{
background-color: blue;
float:left;/* new update from here to below */
display:block;
}
Margin refers to the spacing between block and inline-block level elements. Since divs are block elements, they stack on top of each other, and margin: 0 removes any space between them.
If you are looking to place the divs on top of the canvas element, you can achieve that with absolute positioning.
.touch-control {
position: absolute;
top: 0;
}
Then you can use your javascript to set the 'left' property of each div to where you want it, or positioning them individually with the css.
Having a simple html code
<div id="header">
<div id="headerBox">
<div id="headerText">
</div>
</div>
</div>
with css styles
div#header {
display: block;
overflow: hidden;
margin: 0;
padding: 0;
width: 100%;
}
div#headerBox {
padding: 1em;
text-align: center;
white-space: nowrap;
border-bottom: 10px double gray;
}
div#headerText {
background: red;
display: inline-block;
}
and jQuery (2.x edge)
function resize(win) {
var size;
var w = $('#headerBox').width();
$('#headerText').html('');
$('#headerBox').css('font-size', 1 + 'px');
$('#headerText').html(
"width of <span style=\"font-size:2em;\">headerBox</span> element is " + w + "px");
while ($('#headerText').width() <= w) {
size = parseInt($('#headerBox').css('font-size').replace(/\D+$/, ''), 10);
$('#headerBox').css('font-size', (size + 1) + 'px');
}
$('#headerBox').css('font-size', size + 'px');
}
$(window).resize(function(e){
resize(this)
});
resize(window);
all together accessible via this fiddle,
I experience incorrect jQuery element width calculation. When you access the above fiddle, you see that headerText element is too wide. There should be same right padding as is on left side, text should be centered. Once you resize the Result window (in the fiddle), text is adjusted as supposed to.
Question is WHY there is incorrect calculation on the very first time?
It seems that var w = $('#headerBox').width(); is incorrect calculated. WHY?
Found the problem:
Due to padding: 1em; for headerBox, width of this element changes with change of font-size.
So in while loop I need to work with up-to-date information, not the one I stored at the beginning.
Therefore
var w = $('#headerBox').width();
...
while ($('#headerText').width() <= w) {
...
}
needs to be changed to
while ($('#headerText').width() <= $('#headerBox').width()) {
...
}
JQuery .width doesn't include the padding of #headerbox. Use .outerWidth to get correct width.
var w = $('#headerBox').outerWidth();
I have a web page that accepts three inputs.
I am dynamically creating a triangle from these three inputs (by setting border-widths).
I want the triangle to fit inside the div on the page. For example, if the inputs were 500, 500, 300 I want to reduce these to fit inside the div on the page while retaining the aspect ratio of the inputs.
HTML:
<div id="triangle"></div>
CSS:
#triangle {
max-width: 200px;
width: 0;
height: 0;
margin: 0 auto;
}
jQuery:
$("#triangle").css({
"border-left": length1 + "px solid transparent",
"border-right": length2 + "px solid transparent",
"border-bottom": length3 + "px solid #2383ea"
});
Here is one way of doing it.
Start with the following HTML, two nested block elements:
<div id="triangle"><div class="inner"></div></div>
and some basic CSS:
body {
margin: 0;
}
#triangle {
border: 1px dotted gray;
max-width: 400px;
margin: 0 auto;
}
#triangle .inner {
width: 0;
height: 0;
}
and now use the following jQuery/JavaScript:
var length1 = 1500;
var length2 = 1500;
var length3 = 1500;
var maxWidth = parseInt($("#triangle").css("max-width"));
var baseWidth = Math.min($("#triangle").width(),maxWidth);
var scale = baseWidth/(length1+length2);
$("#triangle .inner").css({
"border-left": length1*scale + "px solid red",
"border-right": length2*scale + "px solid green",
"border-bottom": length3*scale+ "px solid #2383ea"
});
You can see a demo at: http://jsfiddle.net/audetwebdesign/WVcvj/
Programming Notes
You will enter the length1, length2 and length3 from a form or something.
By default, #triangle will take on the width of the parent container, so use that width if it is smaller than the maximum width (you can get the value using the .css function). The parseInt() function will strip out the px label that comes with the value.
The base of the triangle has a width of length1+length2, so calculate the ratio of the available width to the specified width.
You then normalize the three border widths and you are done!
i'm having the following piece of code:
<head>
<style>
#mainDiv {
background-color: grey;
position: absolute;
}
#one {
height: 150px;
width: 70px;
bottom: 300px;
right: 500px;
background-color: green;
position: absolute;
}
#two {
height: 200px;
width: 200px;
margin-top: 50px;
margin-bottom: 20px;
margin-left: 90px;
margin-right: 5px;
background-color: blue;
position: absolute;
}
</style>
</head>
<body>
<div id="mainDiv">
<div id="one"></div>
<div id="two"></div>
</div>
</body>
i want to resize #mainDiv so it will include its children and will consider all positioning and margin attributes (basically #mainDiv's grey area will surround children and visually show the positioning and margins spaces).
i know it can't be done dynamically using CSS. how can i implement such using pure JavaScript without the use of JQuery?
note: there's no restriction on children's position attribute it can be any of them but "fixed".
code need to support all major browsers + IE8 + mobile (android 2.3 + 4, iphone).
thanks!
Use position relative for second div so the mainDiv greay area will surround your children element
#mainDiv {
background-color: grey;
position: absolute;
}
#one {
height: 150px;
width: 100px;
bottom: 300px;
right: 500px;
background-color: yellow;
}
#two {
height: 200px;
width: 200px;
margin-top: 50px;
margin-bottom: 20px;
margin-left: 90px;
margin-right: 5px;
background-color: blue;
position: relative;
}
I did something maybe complicated that you can find here: http://jsfiddle.net/YMmHz/1/
Basically I get all possible values:
var widthOne, widthTwo, heightOne, heightTwo;
var leftOne, leftTwo, rightOne, rightTwo, topOne, topTwo, botOne, botTwo;
var marginLeftOne, marginLeftTwo, marginRightOne, marginRightTwo, marginTopOne, marginTopTwo, marginBotOne, marginBotTwo;
var paddingLeftOne, paddingLeftTwo, paddingRightOne, paddingRightTwo, paddingTopOne, paddingTopTwo, paddingBotOne, paddingBotTwo;
var maxWidthOne, maxWidthTwo, maxHeightOne, maxHeightTwo;
With different tests:
widthOne = $('#one').width();
widthTwo = $('#two').width();
(parseInt($('#one').css('left')))? leftOne = parseInt($('#one').css('left')):leftOne = 0;
(parseInt($('#two').css('left')))? leftTwo = parseInt($('#two').css('left')):leftTwo = 0;
And then define the size of the #mainDiv like this:
(maxWidthOne>=maxWidthTwo)? $('#main_div').width(maxWidthOne):$('#main_div').width(maxWidthTwo);
(maxHeightOne>=maxHeightTwo)? $('#main_div').height(maxHeightOne):$('#main_div').height(maxHeightTwo);
In your case it's not possible because of some logical reasons.
How is it possible to find a right position for id one when the
parent has no size and therefor no usable right position.
If you are using left instead of right for id one the situation
becomes better.
all the best
try this one
<script>
window.onload = function() {
var elems, max_top, max_right;
elems = mainDiv.getElementsByTagName( 'div' );
for( i = 0; i < elems.length; i++ ) {
elem = elems[ i ].offsetLeft + elems[ i ].offsetWidth + elems[ i ].style.marginLeft;
max_right = ( max_right > elem ) ? max_right : elem;
elem = elems[ i ].offsetTop + elems[ i ].offsetHeight + elems[ i ].style.marginBottom;
max_top = ( max_top > elem ) ? max_top : elem;
}
console.log( 't: ' + max_top + ', r: ' + max_right );
mainDiv.style.height = max_top;
mainDiv.style.width = max_right;
}
</script>
The code is having some problem with getting the margins.
I found a good page which solves the problem.
http://www.quirksmode.org/dom/getstyles.html