If you have a div that sits at the 'bottom' like so:
<div id="box" style="position: absolute;width: 10px;height: 10px;bottom: 0px;"></div>
and then if you were to change the position using 'top'...
$('#box').css({'top':'0px'});
what happens to the 'bottom' css command and what decides who (top or bottom) wins?
Should I cancel bottom somehow at the same time as setting top?
Ideas:
$('#box').css({'top':'0px','bottom','none'});
$('#box').css({'top':'0px','bottom',''});
It never occurred to me before
The interactions between width, height, and box offsets in a variety of scenarios in CSS are all detailed in section 10 of the spec.
Since your element is absolutely positioned, refer to section 10.6.4, which says:
For absolutely positioned elements, the used values of the vertical dimensions must satisfy this constraint:
'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block
If all three of 'top', 'height', and 'bottom' are auto, set 'top' to the static position and apply rule number three below.
If none of the three are 'auto': If both 'margin-top' and 'margin-bottom' are 'auto', solve the equation under the extra constraint that the two margins get equal values. If one of 'margin-top' or 'margin-bottom' is 'auto', solve the equation for that value. If the values are over-constrained, ignore the value for 'bottom' and solve for that value.
In your case, because the values are over-constrained once you set a value for top, top wins.
Note that setting none won't work because it's not a valid value for bottom, and setting the empty string reverts it to its default value which for most if not all elements is auto, which does not result in over-constrained values.
Top "wins" when all three of top, bottom and height are present - MDN:
...the top property overrides the bottom property, so if top is not auto, the computed value of bottom is the negative of the computed value of top.
Related
actually I saw many questions like this but I can't found normal answer of this question because that I open this question again.
When we have block element(display: block) this element contain full width of parent component if element itself root element this element width take 100%.
But when we look block element(display:block) but position absolute elements there are work like inline-block elements(work like block element but width not full of parent component) even parent element position relative.
Can anyone explain me why position absolute and fixed elements width not work like display: block elements.
https://jsfiddle.net/epbkmzh3/28/
<div class="container">
<div style="background: red;"> 1 </div>
</div>
<div class="container" style="position: relative;">
<div style="position: absolute; background: red;"> 1 </div>
</div>
It's because absolute and fixed positioning removes the element from document flow.
And since those elements are removed from document flow, there is no reference for what width they should be, so they only take as much space as their content.
They are still "block" elements if they are inherently block elements (div, p, etc.), unless the display property is changed via CSS. Edit for clarity: The browser will still compute as display: block even if the display property is changed via CSS.
Here is some documentation on document flow:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flow_Layout/In_Flow_and_Out_of_Flow
The important part:
Taking an item out of flow
All elements are in-flow apart from:
floated items
items with position: absolute (including position: fixed which acts in the same way)
the root element (html)
Out of flow items create a new Block Formatting Context (BFC) and therefore everything inside them can be seen as a mini layout, separate from the rest of the page. The root element therefore is out of flow, as the container for everything in our document, and establishes the Block Formatting Context for the document.
Here is the Specification detailing how you can find the width/height of any element: https://www.w3.org/TR/CSS21/visudet.html
From there you can read for absolute element that:
The constraint that determines the used values for these elements is:
'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = width of containing block
Then
If all three of 'left', 'width', and 'right' are 'auto': First set any 'auto' values for 'margin-left' and 'margin-right' to 0. Then, if the 'direction' property of the element establishing the static-position containing block is 'ltr' set 'left' to the static position and apply rule number three below; otherwise, set 'right' to the static position and apply rule number one below.
And the rule number three:
'width' and 'right' are 'auto' and 'left' is not 'auto', then the width is shrink-to-fit . Then solve for 'right'
The rule number one is also similar
And if you continue reading you will find how to calculate the shrink-to-fit width. You will also notice that the same shrink-to-fit algorithm apply to float and inline-block element
Also note that fixed element is a particular case of absolute so the same rule applies. The only difference is the containing block
Fixed positioning is a subcategory of absolute positioning. The only difference is that for a fixed positioned box, the containing block is established by the viewport. ref
You can also see that block elements follow almost the same constraint (without left/right) but the rules are different:
The following constraints must hold among the used values of the other properties:
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
Then
If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.
This will make width = width of containing block
An important difference between inline-block element is that absolute element will not take the width of their content like we may think. This happen in most of the case due to the constraint explained above but check the below example:
.container {
clear:left;
margin:5px;
}
<div class="container" style="float:left;position:relative;">
<div style="display:inline-block; background: red;"> 1 1 1 1 1 1 </div>
</div>
<div class="container" style="float:left;position:relative;">
<div style="position: absolute; background: red;"> 1 1 1 1 1 1 </div>
</div>
Note how the absolute element will wrap to the smallest size possible unline the inline-block. This is due to the fact that the containing block is also a shrink-to-fit container.
Related: Why everything word-wrap inside an absolute element nested inside a float or inline-block element
CSS 2.2 Spec for 10.3.7 Absolutely positioned, non-replaced elements says:
If all three of 'left', 'width', and 'right' are 'auto': First set any 'auto' values for 'margin-left' and 'margin-right' to 0. Then, if the 'direction' property of the element establishing the static-position containing block is 'ltr' set 'left' to the static position and apply rule number three below; otherwise, set 'right' to the static position and apply rule number one below.
If none of the three is 'auto': If both 'margin-left' and 'margin-right' are 'auto', solve the equation under the extra constraint that the two margins get equal values, unless this would make them negative, in which case when direction of the containing block is 'ltr' ('rtl'), set 'margin-left' ('margin-right') to zero and solve for 'margin-right' ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto', solve the equation for that value. If the values are over-constrained, ignore the value for 'left' (in case the 'direction' property of the containing block is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve for that value.
I was playing with these rules. In one case I set left, right and width, not an auto value, but I am not getting how right value is affecting the layout. To me it seems it has no effect, like the used value of right is set to 0 (0 is my guess as browser devtool shows the value as 5px). Can anyone explain if my guess is correct or not? If not then how it is applying in the layout, because I am not able to justify it from the documentations of the spec above.
.parent {
width: 200px;
height: 200px;
background: #ffe;
position: relative;
border: 1px solid #999;
}
.child {
background: #ee2;
position: absolute;
left: 5px;
width: 100px;
padding: 5px;
right: 5px;
}
<div class="parent">
<div class="child">
I am positioned
</div>
</div>
the display is like:
Stickers has MDN's version. The relevant portion of the text from your citation itself is in the last sentence, which corroborates with MDN's interpretation (MDN simply uses different terminology that may be more accessible to web developers):
If the values are over-constrained, ignore the value for 'left' (in case the 'direction' property of the containing block is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve for that value.
The term "over-constrained" is defined in section 10.3.3 however:
If all of the above have a computed value other than 'auto', the values are said to be "over-constrained" and one of the used values will have to be different from its computed value.
The MDN article explains it clearly:
When both left and right are defined, the position of the element is overspecified. When this is the case, the left value has precedence when the container is left-to-right (thus, the computed value of right is set to -left); the right value has precedence when the container is right-to-left (thus, the computed value of left is set to -right).
I am reading the book Head First HTML and CSS and there it is written that a requirement for any floating element is that it must have a width. I tried floating right a div element without specifying width on it, and the float property works(it moves the div furthest right as possible) as supposed. Does this mean that there is an error in the book, or it is something that i am missing ?
Yes, you can have floated elements with no width values declared in the cascade. Then, through a defaulting process, the specified value will be the initial value.
For width, the initial value is auto.
CSS explains what should happen when a floated non-replaced element has width: auto:
If width is computed as auto, the used value is the
"shrink-to-fit" width.
Calculation of the shrink-to-fit width is similar to calculating the
width of a table cell using the automatic table layout algorithm.
Roughly: calculate the preferred width by formatting the content
without breaking lines other than where explicit line breaks occur,
and also calculate the preferred minimum width, e.g., by trying all
possible line breaks. CSS 2.1 does not define the exact algorithm.
Thirdly, find the available width: in this case, this is the width of
the containing block minus the used values of margin-left,
border-left-width, padding-left, padding-right,
border-right-width, margin-right, and the widths of any relevant
scroll bars.
Then the shrink-to-fit width is:
min(max(preferred minimum width, available width), preferred width)
The "shrink-to-fit" algorithm is now called fit-content measure.
float:right is simple stacking of elements, left to right until a line width is filled, then top to bottom. Like writing an English newspaper page.
float:left is used for things like a sidebar, it would take up the whole page, unless its width is constrained. This is why the width must be specified.
My understanding is,
Width of an element = (left border width + left padding width + content width + right padding width + right border width)
Height of an element = (top border height + top padding height + content height + bottom padding height + bottom border height)
Below is the diagram for the same.
width of an element = (10+10+140+10+10) = 180
height of an element = (10+10+150+10+10) = 190
margin is not included in the size of an element.
content & padding are only included in the click region.
Is the above formula correct on computing width and height of an html element?
It sounds like what you are describing is the offsetWidth and offsetHeight of an element, which returns the "layout width and height" of the element, i.e. the final width after all calculations.
MDN defines offsetWidth the following way:
The HTMLElement.offsetWidth read-only property returns the layout width of an element. Typically, an element's offsetWidth is a measurement which includes the element borders, the element horizontal padding, the element vertical scrollbar (if present, if rendered) and the element CSS width.
So to answer your question, the final layout width of an element is typically the sum of the element's borders, horizontal padding, vertical scrollbar width, and content width.
The final layout height (offsetHeight) would be similar.
The way CSS calculates height and width is not as simple and straightforward as it may seem.
The most direct answer to your question...
How to compute width & height of an element?
...is: It depends on the type of box being used.
According to the CSS Visual Formatting Model:
10.3 Calculating widths and margins
The values of an element's width, margin-left, margin-right,
left and right properties as used for layout depend on the type of
box generated and on each other... The following situations need to be
distinguished:
inline, non-replaced elements
inline, replaced elements
block-level, non-replaced elements in normal flow
block-level, replaced elements in normal flow
floating, non-replaced elements
floating, replaced elements
absolutely positioned, non-replaced elements
absolutely positioned, replaced elements
inline-block, non-replaced elements in normal flow
inline-block, replaced elements in normal flow
10.6 Calculating heights and margins
For calculating the values of top, margin-top, height, margin-bottom, and bottom a distinction must be made between various kinds of boxes:
same list as above
I was actually hoping to create a simple reference guide here by listing the variables that make up the width and height for at least a few of the box types. So I started with block-level and found that calculating the width, in general terms, was easy enough:
containing block width = margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right
However, when I got to height, I found this:
10.6.3 Block-level non-replaced elements in normal flow when overflow computes to visible
This section also applies to block-level non-replaced elements in
normal flow when overflow does not compute to visible but has been
propagated to the viewport.
If margin-top, or margin-bottom are auto, their used value is 0.
If height is auto, the height depends on whether the element has
any block-level children and whether it has padding or borders:
The element's height is the distance from its top content edge to the
first applicable of the following:
the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin does not collapse
with the element's bottom margin
the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
zero, otherwise
Only children in the normal flow are taken into account (i.e.,
floating boxes and absolutely positioned boxes are ignored, and
relatively positioned boxes are considered without their offset). Note
that the child box may be an anonymous block box.
There are many factors to consider when calculating height.
TL;DR
For an accurate and specific reading of the calculations used to determine the width or height of an HTML element, refer to the CSS Visual Formatting Model. To learn the exact height or width of an element refer to the computed values tab in developer tools.
The width CSS property specifies the width of the content area of an element. The content area is inside the padding, border, and margin of the element.
https://developer.mozilla.org/en-US/docs/Web/CSS/width
This page explains the box model in more detail: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model
I sometimes find it convenient to give the size of an element in terms of the bottom, top, left and right properties, rather than using width and height. This is, for example, the accepted answer here:
CSS 100% height with padding/margin
However, for some reason this doesn't work with an svg element. I've tried the following example with the latest stable Firefox and Chrome. The svg element inexplicably wants to take a size of 300x150:
Fiddle
Why?
While it's not mentioned directly in the spec (at least in my knowledge)<svg> is considered as a replaced element (unlike <div> which is a non-replaced block level element).
For absolutely positioned replaced elements, if the values of top/bottom are over-constrained, once you set a value for top, bottom would be ignored. This is true for left/right properties as well.
10.3 Calculating widths and margins / 10.3.8 Absolutely positioned, replaced elements
If at this point the values are over-constrained, ignore the value for either 'left' (in case the 'direction' property of the containing
block is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve
for that value.
10.6 Calculating heights and margins / 10.6.5 Absolutely positioned, replaced elements
If at this point the values are over-constrained, ignore the value for
'bottom' and solve for that value.
Hence the absolutely positioned <svg> element would be position with the respect to top and left offsets.