CSS: Position sticky vs fixed, why is width handled differently [duplicate] - html

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

Related

Bottom margin not working when placing a photo [duplicate]

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.

Do fixed and absolutely positioned elements not take the full width of their container like block elements? If yes then why?

From this post I came to know that absolutely positioned elements do not behave as block level elements.
"Because absolutely positioned elements do not behave as block level elements and do not flow after each other like normal adoes."
From the discussion in comments it seems that absolutely positioned elements are still block-level elements. The only difference is that they do not take the full width of their parent container. I figured out that the same is true for fixed positioned elements too. I tried the following code. In this code two boxes are shown. One is statically positioned and second is absolutely positioned. It can be seen that statically positioned box takes the full width of it's parent container(viewport). But the absolutely positioned box doesn't take the full width of it's parent container(viewport).
<!DOCTYPE html>
<html>
<style>
.abslnowidth {
position: absolute;
display: block;
border: 1px dotted black;
padding: 10px;
background-color: gray;
}
.staticyeswidth {
position: static;
background-color: bisque;
padding: 15px;
border: 1px dotted black;
}
.abslnowidth:hover, .staticyeswidth:hover {
color:red; background-color: yellow;
}
body {
text-align:center;
border: 2px solid darkgreen;
}
</style>
<body style="">
<p>Two boxes are shown below, viz, the gray and bisque colored boxes. The gray colored box is absolutely poistioned and the bisque colored box is statically positioned <br></p>
<div class="abslnowidth">
Absolutely positioned
</div>
<div class="staticyeswidth">
Statically positioned
</div>
</body>
</html>
Note that the the fixed positioned box behaves similar to absolutely positioned box in that that it also doesn't take the full width of it's parent container.
Much to my surprise, I noticed the fixed/absolutely position element doesn't behave like block-level elements even if I explicitly set display: block; It kind of behaves like inline or inline-block elements, as inline or inline-block elements do not take the full width of their parent container.
Precise Question:
Are absolutely/fixed positioned elements still block-level elements?
Do fixed and absolutely positioned elements not take the full width of their container like block elements are supposed to take? If yes then why? If it is defined this way for some specific purpose then what is that purpose. Please note that I'm not asking for unilateral opinion. I mean if someone really knows why this feature exists and what would be the practical downsides, had it been not this way. Or in other words,
Would there be technical downsides to the web-design if the absolutely/fixed positioned boxes were made to take the full width of their container. My guess is that absolutely/fixed positioned block are supposed to be adjusted. E.g. see this code used to make tool-tip. The black tooltip section should not take the whole width of "Hover over me" box because then we'd have to manually set the width of tool tip box. So I think that's a good reason to define absolutely/fixed positioned boxes to not take the width of their container.
Please provide some good reference e.g. w3 official documentation if possible.
This question could have different possible answers depending on what kind of block behavior you're expecting or referring to.
As per your comment above, the following answer refers to the width behaviour of such element.
Normally, block-level elements per default take up the full available width of their container element. However, when you set position: fixed or absolute the element isn't displayed in the same sense as with the rest of the elements.
As per MDN:
A block-level element occupies the entire space of its parent element (container), thereby creating a "block."
As such, the meaning of the container for a block-level element makes alters when refering to absolute or fixed positioned elements. It makes more sense to rather call it the parent.
Since there is no container element to inherit its width, you're seeing it behave more like an inline-block-type element.
Here's what the W3C says for calculating the width of an absolutely positioned, non-replaced element:
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.
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;
This is true. You have not defined any values for width, left nor right nor do they inherit such values. As such they take the default auto. The direction property is indeed ltr as well, so we continue on to rule number three as suggested, which says:
width and right are auto and left is not auto, then the width is shrink-to-fit . Then solve for right.
The shrink-to-fit width rule applies, and goes as follows:
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, calculate the available width: this is found by solving for width after setting left (in case 1) or right (in case 3) to 0.
Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).

How to compute width & height of an element?

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

Height: 100% VS Height:auto [duplicate]

This question already has answers here:
difference between css height : 100% vs height : auto
(4 answers)
Closed 8 years ago.
I am trying to understand the following
Height: auto; What does this do?
Height: 100%; What does this do?
What is the difference betweem 1 and 2 ? Any examples to explain the difference ?
Thanks in advance!
height: auto; means, the height of the element will increase according to the content it holds, if you assign fixed height, the content overflows, so when you don't know that that your element will contain how much, you set it to auto, so the height will auto increase.
When you set height: 100%; so it will take entire vertical space of the container element, so say for example, when the container element is 200px in height, and you use height: 100%; on the child element, it will be height: 100%; of the container element = 200px.
By default, the element's height is always set to auto unless and until you specify the height using px % or any other unit.
Demo (height: auto;) Keep adding content and your element will expand vertically.
Demo 2 (height: 100%;), this will behave just like you are setting some fixed height to your element, if the content increases, it will overflow. This method only comes handy where you want your child element to take 100% vertical space of the parent container.
height:100%: implies the element is going to have the 100% height of its parent container.
height:auto: means, the element will have flexible height i.e. its height will depend upon the height of children elements of it
Click here for difference with code
reference:http://www.w3.org/TR/CSS2/visudet.html#the-height-property
Content height: the 'height' property
<percentage>
Specifies a percentage height. The percentage is calculated with
respect to the height of the generated box's containing block. If the
height of the containing block is not specified explicitly (i.e., it
depends on content height), and this element is not absolutely
positioned, the value computes to 'auto'. A percentage height on the
root element is relative to the initial containing block. Note: For
absolutely positioned elements whose containing block is based on a
block-level element, the percentage is calculated with respect to the
height of the padding box of that element. This is a change from CSS1,
where the percentage was always calculated with respect to the content
box of the parent element.
auto
The height depends on the values of other properties. See the prose
below.
Note that the height of the containing block of an absolutely positioned element is independent of the size of the element itself,
and thus a percentage height on such an element can always be
resolved. However, it may be that the height is not known until
elements that come later in the document have been processed.
Negative values for 'height' are illegal.
For example, the following rule sets the content height of paragraphs to 100 pixels:
p { height: 100px }
Paragraphs of which the height of the contents exceeds 100 pixels will
overflow according to the 'overflow' property.

How height: auto works in HTML and CSS?

In CSS and HTML how does height: auto work? What do browsers consider while calculating height of the element, for which height is set to auto?
You can split two cases:
div and other containers: the height is the one the browser will use if you don't specify anything, trying to contain the element contents. (read Mathijs's answer for more details)
images and other block elements with intrinsic dimensions (width and height): if you specify the width, then "height: auto" will scale proportionally.
So, in other words, is useless unless you need to reset the browser behaviour or keep proportions to some objects.
Here's an excerpt on this copied from the W3C CSS2 spec
If it only has inline-level children, the height is the distance
between the top of the topmost line box and the bottom of the
bottommost line box.
If it has block-level children, the height is the distance between the
top margin-edge of the topmost block-level child box and the bottom
margin-edge of the bottommost block-level child box.
Absolutely positioned children are ignored, and relatively positioned
boxes are considered without their offset. Note that the child box may
be an anonymous block box.
In addition, if the element has any floating descendants whose bottom
margin edge is below the element's bottom content edge, then the
height is increased to include those edges. Only floats that
participate in this block formatting context are taken into account,
e.g., floats inside absolutely positioned descendants or other floats
are not.