Get width of div with javascript [duplicate] - javascript

This question already has answers here:
How to find the width of a div using vanilla JavaScript?
(8 answers)
Closed 2 years ago.
Why document.getElementById("mydiv").style.width doesn't return the width of mydiv ? It returns an empty string. Some people suggested using offsetWidth, but it doesn't make sense to me why you can't get it from style.width.

The topic of DOM element dimensions is complicated.
You probably want one of :
offsetWidth
The HTMLElement.offsetWidth read-only property returns the layout
width of an element as an integer.
Typically, offsetWidth is a measurement in pixels of the element's CSS
width, including any borders, padding, and vertical scrollbars (if
rendered). It does not include the width of pseudo-elements such as
::before or ::after.
If the element is hidden (for example, by setting style.display on the
element or one of its ancestors to "none"), then 0 is returned.
clientWidth
The Element.clientWidth property is zero for inline elements and
elements with no CSS; otherwise, it's the inner width of an element in
pixels. It includes padding but excludes borders, margins, and
vertical scrollbars (if present).
When clientWidth is used on the root element (the <html> element), (or
on <body> if the document is in quirks mode), the viewport's width
(excluding any scrollbar) is returned. This is a special case of
clientWidth.
getBoundingClientRect
The Element.getBoundingClientRect() method returns the size of an
element and its position relative to the viewport.
The element's size is equal to its width/height + padding in the case
that the standard box model is being used, or width/height only if
box-sizing: border-box has been set on it.
jQuery hides some of this complexity behind a .width method.
const $ = document.querySelector.bind(document)
const d1 = $('#unstyled')
const d2 = $('#stylesheet')
const d3 = $('#inline')
const details = $('#details')
details.innerHTML = (`
<table>
<tr>
<td><h2>A</h2> offsetWidth: '${d1.offsetWidth}', clientWidth: '${d1.clientWidth}', getBoundingClientRect().width: '${d1.getBoundingClientRect().width}', style.width: '${d1.style.width}'
</td>
</tr>
<tr>
<td><h2>B</h2> offsetWidth: '${d2.offsetWidth}', clientWidth: '${d2.clientWidth}', getBoundingClientRect().width: '${d2.getBoundingClientRect().width}', style.width: '${d2.style.width}'
</td>
</tr>
<tr>
<td><h2>C</h2> offsetWidth: '${d3.offsetWidth}', clientWidth: '${d3.clientWidth}', getBoundingClientRect().width: '${d3.getBoundingClientRect().width}', style.width: '${d3.style.width}'
</td>
</tr>
</table>`)
* {
box-sizing: border-box;
font-family: sans-serif;
font-size: .9rem;
}
#stylesheet {
line-height: 50px;
width: 100px;
height: 50px;
text-align: center;
padding: 5px;
margin: 5px;
border: 5px solid red;
}
div {
display: inline-block;
box-shadow: 0 0 0px 1px silver inset;
}
table {
border: 0px;
}
td {
text-align: left;
padding: 0px;
}
<div id="unstyled">A</div>
<div id="stylesheet">B</div>
<div id="inline" style="width:100px;height:50px;text-align: center;line-height: 50px; padding: 5px; margin: 5px; border: 5px solid red;">C</div>
<section id="details"></section>

Related

height() returns a value that is lower than the actual height [duplicate]

This question already has answers here:
What is difference between width, innerWidth and outerWidth, height, innerHeight and outerHeight in jQuery
(6 answers)
Closed 1 year ago.
I have the following markup:
<div class="accordion__feature accordion__feature--1">
<span class="accordion__label display--1">Dashboard</span>
</div>
Upon inspecting .accordion__feature--1, it has a height of 62px. But when running a console.log, it gives me the value of -32.
I have read this similar question, which mentions a min-height being set. However, I do not have any min-height's being set, so unsure what's happening?
Demo:
$(document).ready(function() {
var height = $('.accordion__feature--1').height();
console.log(height);
});
.accordion__feature {
border: 1px solid;
padding: 15px 0px;
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="accordion__feature accordion__feature--1">
<span class="accordion__label">Dashboard</span>
</div>
In the above demo, the actual height is 50px, but it's logging out 18. Even if it's a padding issue, that should only be a difference of 30px?
Change height() to outerHeight()
var height = $('.accordion__feature--1').outerHeight();
$(document).ready(function() {
var height = $('.accordion__feature--1').outerHeight();
console.log(height);
});
.accordion__feature {
border: 1px solid;
padding: 15px 0px;
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="accordion__feature accordion__feature--1">
<span class="accordion__label">Dashboard</span>
</div>

Setting `element.style.height` not working as expected if `element.style.box-sizing` is `border-box`

I am having an understanding problem with the following code:
let myDiv1 = document.getElementById("myDiv1");
alert("Click me to make 'Hello' vanish");
myDiv1.style.height = "0px";
let myDiv2 = document.getElementById("myDiv2");
alert("Click me to make 'World' vanish");
myDiv2.style.height = "0";
.myClass1 {
box-sizing: border-box;
overflow: hidden;
padding-top: 2em;
padding-bottom: 2em;
background-color: yellow;
}
.myClass2 {
box-sizing: content-box;
overflow: hidden;
padding-top: 2em;
padding-bottom: 2em;
background-color: orange;
}
<body>
<div id="myDiv1" class="myClass1">
Hello
</div>
<div id="myDiv2" class="myClass2">
World
</div>
</body>
I understand the behavior of the second (orange) div: It has box-sizing: content-box;, so its height does not include the padding or the borders. Hence, when its height is set to 0, it shrinks basically by the height of the text "World", but the padding is left as-is. Since the padding exceeds the original text height, the text is still visible in the padding. Only that part of padding which is now outside the div (due to the reduced height) becomes invisible (due to overflow: hidden;).
I do not understand the behavior of the first (yellow) div, though. It has box-sizing: border-box;, so its height does include the padding and the borders. Hence, when its height is set to 0, it should shrink to "real" zero height, meaning that the text, the padding and the borders then should be outside the div and thus should be invisible (due to overflow: hidden;).
Can anybody explain why this is not the case and why the first div behaves just like the second div?
P.S. Tested in Firefox and Chrome, both up-to-date (production channel) at the time of writing this.
border-box tells the browser to account for any border and padding in the values you specify for an element's width and height. If you set an element's width to 100 pixels, that 100 pixels will include any border or padding you added, and the content box will shrink to absorb that extra width. This typically makes it much easier to size elements. ref
Here is an example to better ilustrate your issue:
.box {
display: inline-block;
padding-top: 2em;
padding-bottom: 2em;
border: 2px solid blue;
background: linear-gradient(red, red) content-box, orange;
height: 100px;
animation:move 5s linear infinite alternate;
}
#keyframes move{
to {
height:0;
}
}
<div class="box">
World
</div>
<div class="box" style=" box-sizing: border-box;">
World
</div>
The first example is the trivial one where we decrease the height (red area) until 0 and the animation never stop.
In the second case the height include the padding and border so before reaching 0 the content area is already 0 that's why the animation seems to stop because we cannot decrease more than 0 and the border/padding already consumed all the space.
It's logical that when height is equal to 0 both are the same since in the first one we tell the browser that the content area should be 0 (we don't care about padding/border) and in the second case we told the browser to account for the padding/border into the height we specified so we have less room for the content area and since we cannot have less than 0 then its 0.
In other words, you aren't setting the total height that will be split between the content area, padding and border but you are setting a height and the browser is shrinking it as much as possible to include the border and padding.
Related for more examples and details: box-sizing: border-box with no declared height/width

Dynamically increase and decrease an input text box size depending on another selector width

I have an input text box which has some padding to it. I also have a wrapper class selector which is used next to that input text box. I am trying to remove set padding from the input text box and make that space dynamic so that the element size would (especially width) increase and decrease depending on the screen size (i.e. Mobile or Large view as large screen) without effecting the wrapper.
The text box looks like the following. a, c, d, e are buttons which appear dynamically. So the space for b here should expand if the there is only one button on the right and decrease if there are all the buttons on the right.
|____|________________________ |_____|_____|_____|
a b c d e
so the css class selectors that I have includes b and another one includes all the c, d, e (wrapper).
I assume this can't only be done through CSS. Any suggestion?
CSS:
.input {
position: relative;
width: 100%;
max-width: var(--grid-main-max-width);
padding: 1.188rem 2.9rem 1.188rem 4.5rem;
margin: 0;
font-size: 16px;
border: 1px solid var(--color-gray);
border-radius: 0.375rem;
outline: 0;
}
.wrapper {
position: absolute;
top: 0;
right: 1.5rem;
bottom: 0;
display: flex;
justify-content: center;
}
HTML
<div>
<input class="input">
<div class= "wrapper">
<button>c</button>
<button>d</button>
<button>e</button>
</div>
</div>
The solution only needed to count the width of the input text box and the wrapper and assign the difference as a padding to the right of the input text box. The following little change was added to an onInput event.
document.getElemendById("inputTextBox").style.paddingRight = document.getElemendById("searchFieldWrapper").clientWidth;
And also needed to use Media Queries for #media (--large-viewport) / #media (--medium-viewport) to assign different padding for the input. as #Scott Marcus mentioned in a comment.
Lets say you have div child blocks for those child elements or you can specify some class.
div:first-child:nth-last-child(1){
width: 100%;
}
div:first-child:nth-last-child(2),
div:first-child:nth-last-child(2) ~ div{
width: 50%;
}
div:first-child:nth-last-child(3),
div:first-child:nth-last-child(3) ~ div{
width: 33.3%;
}
div:first-child:nth-last-child(4),
div:first-child:nth-last-child(4) ~ div{
width: 25%;
}
//and so on
Source refer to here
Also if you want to modify other elements you can use
div:first-child:nth-last-child(2) > .someClass{
style:goesHere
}
(UPDATE: I figured out you used a wrapper element, and that a is'nt a label but a button. But this answer is easily adaptable to your question.)
You can use the calc function provided by CSS. Given this piece of HTML (I joined all the elements to remove side effects of the blank characters; we can fix it in an other way but I wanted to keep the answer simple):
<html>
<head>
</head>
<body>
<article id="demo">
<label>a</label><input type="text" placeholder="b" /><button>c</button><button>d</button><button>e</button>
</article>
</body>
</html>
This piece of CSS allow the input text element to fill the available space.
article#demo {
/* the width (80vw) includes border and padding */
width: 80vw;
}
article#demo label {
/* to make label resizable */
display: inline-block;
width: 30px;
}
article#demo button {
width: 20px;
margin: 0;
padding: 0;
background-color: #f0f0ff;
box-sizing: border-box;
/* see above */
}
article#demo input[type="text"] {
box-sizing: border-box;
/* text input width = 100% minus other items */
width: calc(100% - 30px - 3 * 20px);
}
You can set the width of article#demo using any unit (em, ex, etc.) it should work.
In your final design, use box-sizing:border-box to set the whole element, including borders and padding, within the CSS width. Otherwise, you'll have to adjust the calc parameter.
If you put left or right margins, count them too.
If you use font-dependent units (em, etc.), the same font-family and other font-related CSS entries have to be set - implicitly or not - for all the concerned elements.
Working fiddle with a little interactive test here.

How to guarantee an element will have a particular height

Say that I have this element on my page:
<div style="height: 1em;"> </div>
I want to use JavaScript to measure the height of the div to figure out how many px are equivalent to 1em for that element.
So if I did:
document.querySelector('div').getBoundingClientRect()
Then I might get 16.
But what if users can inject arbitrary styles onto this webpage? What if they do something like:
div { border: 1px solid black; }
Then I would get 18, because of the unexpected border applied to all div elements.
To avoid this, I could add a laundry list of styles to the div to remove potential "unexpected styles:"
<div style="border: 0; margin: 0; padding: 0; height: 1em;"> </div>
But is that list of styles comprehensive? If not, what other styles do I need? Or is there a better way to make this calculation?
Set the font-style: 1em !important; on the element, and get the font size in px using Window#getComputedStyle:
var fontSize = window.getComputedStyle(div).fontSize;
console.log(fontSize);
<div id="div" style="font-size: 1em;"></div>
My previous not bullet proof answer:
This fails if the user uses borders and/or paddings which height is greater than 16.
You can use box-sizing: border-box on the element. With this box sizing, the borders and the paddings don't increase the dimensions of the element. The content area is the original width/height minus any paddings and borders.
console.log(div.getBoundingClientRect().height);
div {
padding: 3px;
border: 2px solid black;
}
<div id="div" style="height: 1em; box-sizing: border-box;">

Auto resize child divs so they equally share width of parent

Let's say I have a parent div with a fixed width of 320px and I want to be able to (or I want my users to be able to) add any amount of child divs to the parent and have them all adjust automatically to share the width of the parent.
I don't want the parent width to change, nor do I want to do this with any sort of scrolling overflow - I just need for the divs inside to fit the width of the parent equally.
For example,
If there is only one child then the width is 100%, if there are two then their width is 50% each etc
How would I go about doing this?
I've approached this many different ways with css, but can't seem to figure it out. I'm assuming this has to be done with some sort of javascript, but I don't know enough to pull it off.
But, If it can be done with just css, that would be great.
Thanks in advance.
(Don't know if you'll need to know this, but the child divs will have no text. They're just blank with background-color and fixed height)
Example code:
CSS
.box {
margin: 10px;
background: white;
border-radius: 6px;
border: 1px solid darken(white, 12%);
-webkit-box-shadow: 0px 1px 4px rgba(50, 50, 50, 0.07);
-moz-box-shadow: 0px 1px 4px rgba(50, 50, 50, 0.07);
box-shadow: 0px 1px 4px rgba(50, 50, 50, 0.07);
float: left;
}
.line {
height: 6px;
opacity: 0.4;
-moz-opacity: 0.4;
filter:alpha(opacity=4);
margin-bottom: -1px;
float: left;
}
HTML
...
<div class="box">
<div class="line"> </div>
</div>
...
#will be able to add any amount of .lines
Use display: table (and table-layout: fixed with fixed width for container if you need equal-width columns) for container and display: table-cell for child elements.
Hope this helps!
<html>
<body>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script tye="text/javascript">
function resizeChildren( $div ){
var $children = $div.children(".child"); // Change .line to the appropriate class of the children
var $count = $children.length; // Determine how may children
var $width = $div.width(); // Get width of parent
var $cellwidth = Math.floor( $width / $count ); // Calculate appropriate child width
$children.width( $cellwidth ); // Apply width
}
function addChild( $div, $html ){
$( $html ).prependTo ( $div ); // Add a new child
resizeChildren ( $div ); // Call the resize function
}
$(document).ready( function(){
$("#add").click( function(){ // When <a id="add" is clicked...
addChild( $(".parent"), '<div class="child">Random...</div>' );
return false;
});
});
</script>
<style type="text/css">
.parent {
width: 500px;
border: 1px solid #000;
}
.child {
float: left;
}
</style>
<div class="parent" style="width: 500px;">
<div class="child">Random...</div>
<br clear="all" /></div>
Add DIV
</body>
</html>
Some browsers require also rule font-size:0px to show DIV which height is below 1em, otherwise their height will be 1em.
EDIT
There has came more info while I was writing my answer. If that table lay-out is working, answer to the last comment is above. I removed the part of my answer considering positioning, because I missunderstood your question also.

Categories