【每周一专题】重学计算机系列(给自己明年计算机学习10周年的献礼)
【前端篇】第一篇:从前端文档流开始.
Writing-mode
The writing-mode CSS property sets :
- whether lines of text are laid out horizontally or vertically,
- as well as the direction in which blocks progress.
-
- When set for an entire document, it should be set on the root element (html element for HTML documents).
This property specifies the block flow direction, which is the direction in which block-level containers are stacked, and the direction in which inline-level content flows within a block container. Thus, it also determines the ordering of block-level content.
The writing-mode property is specified as one of the values listed below. The flow direction in horizontal scripts is also affected by the directionality of that script, either left-to-right (ltr, like English and most other languages) or right-to-left (rtl, like Hebrew or Arabic).
/* Keyword values */
/*
* For ltr scripts, content flows horizontally from left to right.
* For rtl scripts, content flows horizontally from right to left.
* The next horizontal line is positioned below the previous line.
*/
writing-mode: horizontal-tb;
/*
* For ltr scripts, content flows vertically from top to bottom, and the next vertical line is positioned to the left of the previous line.
* For rtl scripts, content flows vertically from bottom to top, and the next vertical line is positioned to the right of the previous line.
*/
writing-mode: vertical-rl;
/*
* For ltr scripts, content flows vertically from top to bottom, and the next vertical line is positioned to the left of the previous line.
* For rtl scripts, content flows vertically from bottom to top, and the next vertical line is positioned to the left of the previous line.
*/
writing-mode: vertical-lr;
/* (exprimental)
* For ltr scripts, content flows vertically from bottom to top.
* For rtl scripts, content flows vertically from top to bottom.
* All the glyphs, even those in vertical scripts, are set sideways toward the right.
*/
writing-mode: sideways-rl;
/* (exprimental)
* For ltr scripts, content flows vertically from top to bottom.
* For rtl scripts, content flows vertically from bottom to top.
* All the glyphs, even those in vertical scripts, are set sideways toward the left.
*/
writing-mode: sideways-lr;
/* Global values */
writing-mode: inherit;
writing-mode: initial;
writing-mode: revert;
writing-mode: revert-layer;
writing-mode: unset;
Example - Using multiple writing modes
<table>
<tr>
<th>Value</th>
<th>Vertical script</th>
<th>Horizontal (LTR) script</th>
<th>Horizontal (RTL) script</th>
<th>Mixed script</th>
</tr>
<tr>
<td>horizontal-tb</td>
<td class="example Text1"><span>我家没有电脑。</span></td>
<td class="example Text1"><span>Example text</span></td>
<td class="example Text1"><span>מלל ארוך לדוגמא</span></td>
<td class="example Text1"><span>1994年に至っては</span></td>
</tr>
<tr>
<td>vertical-lr</td>
<td class="example Text2"><span>我家没有电脑。</span></td>
<td class="example Text2"><span>Example text</span></td>
<td class="example Text2"><span>מלל ארוך לדוגמא</span></td>
<td class="example Text2"><span>1994年に至っては</span></td>
</tr>
<tr>
<td>vertical-rl</td>
<td class="example Text3"><span>我家没有电脑。</span></td>
<td class="example Text3"><span>Example text</span></td>
<td class="example Text3"><span>מלל ארוך לדוגמא</span></td>
<td class="example Text3"><span>1994年に至っては</span></td>
</tr>
<tr>
<td>sideways-lr</td>
<td class="example Text4"><span>我家没有电脑。</span></td>
<td class="example Text4"><span>Example text</span></td>
<td class="example Text4"><span>מלל ארוך לדוגמא</span></td>
<td class="example Text4"><span>1994年に至っては</span></td>
</tr>
<tr>
<td>sideways-rl</td>
<td class="example Text5"><span>我家没有电脑。</span></td>
<td class="example Text5"><span>Example text</span></td>
<td class="example Text5"><span>מלל ארוך לדוגמא</span></td>
<td class="example Text5"><span>1994年に至っては</span></td>
</tr>
</table>
.example.Text1 span, .example.Text1 {
writing-mode: horizontal-tb;
}
.example.Text2 span, .example.Text2 {
writing-mode: vertical-lr;
}
.example.Text3 span, .example.Text3 {
writing-mode: vertical-rl;
}
.example.Text4 span, .example.Text4 {
writing-mode: sideways-lr;
}
.example.Text5 span, .example.Text5 {
writing-mode: sideways-rl;
}
See also relative topics
inline-size
block-size
Normal Flow
Normal Flow, or Flow Layout, is the way that Block and Inline elements are displayed on a page before any changes are made to their layout, how they all work together and know about each other in your layout. out of flow means it works independently.
In normal flow:
- inline elements display in the inline direction, that is in the direction words are displayed in a sentence according to the Writing Mode of the document.
- Block elements display one after the other, as paragraphs do in the Writing Mode of that document.
In English therefore:
- inline elements display one after the other, starting on the left,
- block elements start at the top and move down the page.
How are elements laid out by default?
The process begins as the boxes of individual elements are laid out in such a way that any padding, border, or margin they happen to have is added to their content. This is what we call the box model.
By default, a block level element's content fills the available inline space of the parent element containing it and grows along the block dimension to accommodate its content. The size of Inline elements is just the size of their content. You can't set width or height on inline elements — they just sit inside the content of block level elements. If you want to control the size of an inline element in this manner, you need to set it to behave like a block level element (e.g., with display: block; or display: inline-block;, which mixes characteristics from both).
That explains how elements are structured individually, but how about the way they're structured when they interact with one another?
By default, block-level elements are laid out in the block flow direction, which is based on the parent's writing mode (initial: horizontal-tb). Each element will appear on a new line below the last one, with each one separated by whatever margin that's been specified. In English, for example, (or any other horizontal, top to bottom writing mode) block-level elements are laid out vertically.
Inline elements behave differently. They don't appear on new lines; instead, they all sit on the same line along with any adjacent (or wrapped) text content as long as there is space for them to do so inside the width of the parent block level element. If there isn't space, then the overflowing content will move down to a new line.
If two vertically adjacent elements both have a margin set on them and their margins touch, the larger of the two margins remains and the smaller one disappears. This is known as margin collapsing . Collapsing margins is only relevant in the vertical direction.
Example
<h1>Basic document flow</h1>
<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p>
<p>By default we span 100% of the width of our parent element, and we are as tall as our child content. Our total width and height is our content + padding + border width/height.</p>
<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p>
<p>Inline elements <span>like this one</span> and <span>this one</span> sit on the same line along with adjacent text nodes, if there is space on the same line. Overflowing inline elements will <span>wrap onto a new line if possible (like this one containing text)</span>, or just go on to a new line if not, much like this image will do: <img src="long.jpg" alt="snippet of cloth"></p>
body {
width: 500px;
margin: 0 auto;
}
p {
background: rgba(255,84,104,0.3);
border: 2px solid rgb(255,84,104);
padding: 10px;
margin: 10px;
}
span {
background: white;
border: 1px solid black;
}
The CSS box model
Everything in CSS has a box around it, and understanding these boxes is key to being able to create more complex layouts with CSS, or to align items with other items.
Block and inline boxes
In CSS we broadly have two types of boxes — block boxes and inline boxes. The type refers to how the box behaves in terms of page flow and in relation to other boxes on the page.
Boxes have an inner display type and an outer display type.
Outer display type
Block boxes
If a box has an outer display type of block, then:
- The box will break onto a new line.
- The width and height properties are respected.
- Padding, margin and border will cause other elements to be pushed away from the box.
- The box will extend in the inline direction to fill the space available in its container. In most cases, the box will become as wide as its container, filling up 100% of the space available.
Some HTML elements, such as <h1> and <p>, use block as their outer display type by default.
Inline boxes
If a box has an outer display type of inline, then:
- The box will not break onto a new line.
- The width and height properties will not apply.
- Vertical padding, margins, and borders will apply but will not cause other inline boxes to move away from the box.
- Horizontal padding, margins, and borders will apply and will cause other inline boxes to move away from the box.
Some HTML elements, such as <a>, <span>, <em> and <strong> use inline as their outer display type by default.
Inner display type
Boxes also have an inner display type, which dictates how elements inside that box are laid out.
Block and inline layout is the default way things behave on the web. By default and without any other instruction, the elements inside a box are also laid out in normal flow and behave as block or inline boxes.
You can change the inner display type for example by setting display: flex;. The element will still use the outer display type block but this changes the inner display type to flex. Any direct children of this box will become flex items and behave according to the Flexbox specification.
When you move on to learn about CSS Layout in more detail, you will encounter flex, and various other inner values that your boxes can have, for example grid.
What is the CSS box model?
The CSS box model as a whole applies to block boxes and defines how the different parts of a box — margin, border, padding, and content — work together to create a box that you can see on a page. Inline boxes use just some of the behavior defined in the box model.
- Content box: The area where your content is displayed; size it using properties like inline-size and block-size or width and height.
- Padding box: The padding sits around the content as white space; size it using padding and related properties.
- Border box: The border box wraps the content and any padding; size it using border and related properties.
- Margin box: The margin is the outermost layer, wrapping the content, padding, and border as whitespace between this box and other elements; size it using margin and related properties.
To add complexity, there is a standard and an alternate box model.
By default, browsers use the standard box model.
The standard box model
In the standard box model, if you give a box an inline-size and a block-size (or width and a height) attributes, this defines the inline-size and block-size (width and height in horizontal languages) of the content box. Any padding and border is then added to those dimensions to get the total size taken up by the box (see image below).
.box {
width: 350px;
height: 150px;
margin: 10px;
padding: 25px;
border: 5px solid black;
}
The actual space taken up by the box will be 410px wide (350 + 25 + 25 + 5 + 5) and 210px high (150 + 25 + 25 + 5 + 5).
Note: The margin is not counted towards the actual size of the box — sure, it affects the total space that the box will take up on the page, but only the space outside the box. The box's area stops at the border — it does not extend into the margin.
The alternative CSS box model
In the alternative box model, any width is the width of the visible box on the page. The content area width is that width minus the width for the padding and border (see image below). No need to add up the border and padding to get the real size of the box.
To turn on the alternative model for an element, set box-sizing: border-box on it:
.box {
box-sizing: border-box;
}
.box {
width: 350px;
inline-size: 350px;
height: 150px;
block-size: 150px;
margin: 10px;
padding: 25px;
border: 5px solid black;
}
Now, the actual space taken up by the box will be 350px in the inline direction and 150px in the block direction.
To use the alternative box model for all of your elements (which is a common choice among developers), set the box-sizing property on the element and set all other elements to inherit that value:
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
Note: An interesting bit of history — Internet Explorer used to default to the alternative box model, with no mechanism available to switch.
Use browser DevTools to view the box model
Margins, padding, and borders
Margin
The margin is an invisible space around your box. It pushes other elements away from the box. Margins can have positive or negative values. Setting a negative margin on one side of your box can cause it to overlap other things on the page. Whether you are using the standard or alternative box model, the margin is always added after the size of the visible box has been calculated.
We can control all margins of an element at once using the margin property, or each side individually using the equivalent longhand properties:
Margin Collapsing
Depending on whether two elements whose margins touch have positive or negative margins, the results will be different:
- Two positive margins will combine to become one margin. Its size will be equal to the largest individual margin.
- Two negative margins will collapse and the smallest (furthest from zero) value will be used.
- If one margin is negative, its value will be subtracted from the total.
In the example below, we have two paragraphs. The top paragraph has a margin-bottom of 50 pixels, the other has a margin-top of 30 pixels. The margins have collapsed together so the actual margin between the boxes is 50 pixels and not the total of the two margins.
You can test this by setting the margin-top of paragraph two to 0. The visible margin between the two paragraphs will not change — it retains the 50 pixels set in the margin-bottom of paragraph one. If you set it to -10px, you'll see that the overall margin becomes 40px — it subtracts from the 50px.
A number of rules dictate when margins do and do not collapse.
The main thing to remember is that margin collapsing is a thing that happens if you are creating vertical space with margins and don't get the space you expect.
Borders
The border is drawn between the margin and the padding of a box. If you are using the standard box model, the size of the border is added to the width and height of the box. If you are using the alternative box model then the size of the border makes the content box smaller as it takes up some of that available width and height.
For styling borders, there are a large number of properties — there are four borders, and each border has a style, width, and color that we might want to manipulate.
You can set the width, style, or color of all four borders at once using the border property.
To set the properties of each side individually, use:
To set the width, style, or color of all sides, use:
To set the width, style, or color of a single side, use one of the more granular longhand properties:
- border-top-width
- border-top-style
- border-top-color
- border-right-width
- border-right-style
- border-right-color
- border-bottom-width
- border-bottom-style
- border-bottom-color
- border-left-width
- border-left-style
- border-left-color
Padding
The padding sits between the border and the content area and is used to push the content away from the border. Unlike margins, you cannot have a negative padding. Any background applied to your element will display behind the padding.
The padding property controls the padding on all sides of an element. To control each side individually, use these longhand properties:
Properties for the box model and inline boxes
All of the above fully applies to block boxes. Some of the properties can apply to inline boxes too, such as those created by a element.
In the example below, we have a inside a paragraph. We have applied a width, height, margin, border, and padding to it. You can see that the width and height are ignored.
- The vertical margin, padding, and border are respected but don't change the relationship of other content to our inline box. The padding and border overlap other words in the paragraph.
- The horizontal padding, margins, and borders move other content away from the box.
Change box model to inline model with display: inline-block
display: inline-block is a special value of display, which provides a middle ground between inline and block. Use it if you do not want an item to break onto a new line, but do want it to respect width and height and avoid the overlapping seen above.
An element with display: inline-block does a subset of the block things we already know about:
- The width and height properties are respected.
- padding, margin, and border will cause other elements to be pushed away from the box.
It does not break onto a new line, and will only become larger than its content if you explicitly add width and height properties.
Block-level elements for detail
HTML (Hypertext Markup Language) elements historically were categorized as either "block-level" elements or "inline-level" elements.
Block-level element occupies the entire horizontal space of its parent element (container), and vertical space equal to the height of its contents, thereby creating a "block".
Browsers typically display the block-level element with a newline both before and after the element.
Note: A block-level element always starts on a new line and takes up the full width available (stretches out to the left and right as far as it can).
<p>This paragraph is a block-level element; its background has been colored to display the paragraph's parent element.</p>
p { background-color: #8ABB55; }
Inline elements for detail
Inline elements are those which only occupy the space bounded by the tags defining the element, instead of breaking the flow of the content.
Note: An inline element does not start on a new line and only takes up as much width as necessary.
<div>The following span is an <span class="highlight">inline element</span>;
its background has been colored to display both the beginning and end of
the inline element's influence.</div>
.highlight {
background-color:#ee3;
}
<div>The following paragraph is a <p class="highlight">block-level element;</p>
its background has been colored to display both the beginning and end of
the block-level element's influence.</div>
.highlight {
background-color:#ee3;
}
Notice:
Browsers typically display the block-level element with a newline both before and after the element.
Block-level vs. inline
There are a couple of key differences between block-level elements and inline elements:
- Content model
Generally, block-level elements may contain inline elements and (sometimes) other block-level elements. Inherent in this structural distinction is the idea that block elements create "larger" structures than inline elements.
- Default formatting
By default, block-level elements begin on new lines, but inline elements can start anywhere in a line.
Changing element levels
You can change the visual presentation of an element using the CSS display property. For example, by changing the value of display from "inline" to "block", you can tell the browser to render the inline element in a block box rather than an inline box, and vice versa.
However, doing this will not change the category and the content model of the element. For example, even if the display of the span element is changed to "block", it still would not allow to nest a div element inside it.
In flow and out of flow
The previous guide explained block and inline layout in normal flow. All elements that are in flow will be laid out using this method.
In flow Example
The following example contains a heading, paragraph, a list and a final paragraph which contains a strong element. The heading and paragraphs are block level, the strong element inline. The list is displayed using flexbox to arrange the items into a row, however it too is participating in block and inline layout - the container has an outside display type of block.
All of the elements bellow can be said to be in flow. Appearing on the page in the order that they are in the source.
.box > * {
border:1px solid green;
}
<div class="box">
<h1>A heading</h1>
<p>One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney.</p>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
<p>Their names were <strong>Stephen and Joseph Montgolfier</strong>, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery.</p>
</div>
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)
BFC
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.
Floated items
The float CSS property places an element on the left or right side of its container, allowing text and inline elements to wrap around it.
The element is removed from the normal flow of the page, though still remaining a part of the flow (in contrast to absolute positioning).
Examples
In this example, there is a div and then two paragraphs. A background color has been added to the paragraphs, and the div is floated left. The div is now out of flow.
As a float it is first laid out according to where it would be in normal flow, then taken out of flow and moved to the left as far as possible.
<div class="box">
<div class="float">I am a floated box!</div>
<p>One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery.</p>
<p>Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact.”</p>
</div>
p {
background-color: #ccc;
}
.float {
font-weight: bold;
width: 200px;
border: 2px dotted black;
padding: 10px;
}
p {
background-color: #ccc;
}
.float {
float: left;
font-weight: bold;
width: 200px;
border: 2px dotted black;
padding: 10px;
}
You can see the background color of the following paragraph running underneath, it is only the line boxes of that paragraph that have been shortened to cause the effect of wrapping content around the float. The box of our paragraph is still displaying according to the rules of normal flow. This is why, to make space around a floated item, you must add a margin to the item, in order to push the line boxes away from it. You cannot apply anything to the following in-flow content to achieve that.
p {
background-color: #ccc;
}
.float {
float: left;
font-weight: bold;
width: 200px;
border: 2px dotted black;
padding: 10px;
margin-right: 20px;
}
Syntax
/* Keyword values */
float: left;// The element must float on the LEFT side of its containing block.
float: right;// The element must float on the RIGHT side of its containing block.
float: none;// The element must not float.
float: inline-start;// The element must float on the start side of its containing block. That is the left side with ltr scripts, and the right side with rtl scripts.
float: inline-end;// The element must float on the end side of its containing block. That is the left side with ltr scripts, and the right side with rtl scripts.
/* Global values */
float: inherit;
float: initial;
float: revert;
float: revert-layer;
float: unset;
| Initial Value | none |
|---|---|
| Applies to | all elements, but has no effect if the value of display is none |
| Inherited | no |
| Computed Value | as specified |
| Animation Type | discrete |
A floating element is one where the computed value of float is not none.
As float implies the use of the block layout, it modifies the computed value of the display values, in some cases:
| Specified value | Computed value |
|---|---|
| inline | block |
| inline-block | block |
| inline-table | table |
| table-row | block |
| table-row-group | block |
| table-column | block |
| table-column-group | block |
| table-cell | block |
| table-caption | block |
| table-header-group | block |
| table-footer-group | block |
| inline-flex | flex |
| inline-grid | grid |
| other | unchanged |
How floated elements are positioned?
As mentioned above, when an element is floated, it is taken out of the normal flow of the document (though still remaining part of it). It is shifted to the left, or right, until it touches the edge of its containing box, or another floated element.
<section>
<div class="left">1</div>
<div class="left">2</div>
<div class="right">3</div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Morbi tristique sapien ac erat tincidunt, sit amet dignissim
lectus vulputate. Donec id iaculis velit. Aliquam vel
malesuada erat. Praesent non magna ac massa aliquet tincidunt
vel in massa. Phasellus feugiat est vel leo finibus congue.</p>
</section>
section {
box-sizing: border-box;
border: 1px solid blue;
width: 100%;
float: left;
}
div {
margin: 5px;
width: 50px;
height: 150px;
}
.left {
float: left;
background: pink;
}
.right {
float: right;
background: cyan;
}
In this example, there are three colored squares. Two are floated left, and one is floated right.
Note that the second "left" square is placed to the right of the first. Additional squares would continue to stack to the right, until they filled the containing box, after which they would wrap to the next line.
A floated element is at least as tall as its tallest nested floated children. We gave the parent width: 100% and floated it to ensure it is tall enough to encompass its floated children, and to make sure it takes up the width of the parent so we don't have to clear its adjacent sibling.
Clearing floats
Sometimes you may want to force an item to move below any floated elements. For instance, you may want paragraphs to remain adjacent to floats, but force headings to be on their own line.
The clear CSS property sets whether an element must be moved below (cleared) floating elements that precede it.
The clear property applies to floating and non-floating elements.
- When applied to non-floating blocks, it moves the border edge of the element down until it is below the margin edge of all relevant floats.
-
- The non-floated block's top margin collapses.
- Vertical margins between two floated elements on the other hand will not collapse.
- When applied to floating elements, the margin edge of the bottom element is moved below the margin edge of all relevant floats. This affects the position of later floats, since later floats cannot be positioned higher than earlier ones.
The floats that are relevant to be cleared are the earlier floats within the same block formatting context.
Note:
If an element contains only floated elements, its height collapses to nothing.
If you want it to always be able to resize, so that it contains floating elements inside it, you need to self-clear its children. This is called clearfix, and one way to do it is to add clear to a replaced ::after pseudo-element on it.
#container::after {
content: "";
display: block;
clear: both;
}
Syntax
/* Keyword values */
clear: none;// indicate that the element is not moved down to clear past floating elements.
clear: left;// indicate that the element is moved down to clear past left floats
clear: right;// indicate that the element is moved down to clear past right floats
clear: both;// indicate that the element is moved down to clear past both left and right floats
clear: inline-start;// indicate that the element is moved down to clear floats on start side of its containing block, that is the left floats on ltr scripts and the right floats on rtl scripts
clear: inline-end;// indicate that the element is moved down to clear floats on end side of its containing block, that is the right floats on ltr scripts and the left floats on rtl scripts
/* Global values */
clear: inherit;
clear: initial;
clear: revert;
clear: revert-layer;
clear: unset;
| Initial Value | none |
|---|---|
| Applies to | block-level elements |
| Inherited | no |
| Computed Value | as specified |
| Animation Type | discrete |
<div class="wrapper">
<p class="black">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus sit amet diam. Duis mattis varius dui. Suspendisse eget dolor.</p>
<p class="red">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
<p class="left">This paragraph clears left.</p>
</div>
.wrapper{
border:1px solid black;
padding:10px;
}
.left {
border: 1px solid black;
clear: left;
}
.black {
float: left;
margin: 0;
background-color: black;
color: #fff;
width: 20%;
}
.red {
float: left;
margin: 0;
background-color: pink;
width:20%;
}
p {
width: 50%;
}
<div class="wrapper">
<p class="black">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus sit amet diam. Duis mattis varius dui. Suspendisse eget dolor.</p>
<p class="red">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
<p class="right">This paragraph clears right.</p>
</div>
.wrapper{
border:1px solid black;
padding:10px;
}
.right {
border: 1px solid black;
clear: right;
}
.black {
float: right;
margin: 0;
background-color: black;
color: #fff;
width:20%;
}
.red {
float: right;
margin: 0;
background-color: pink;
width:20%;
}
p {
width: 50%;
}
<div class="wrapper">
<p class="black">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus sit amet diam. Duis mattis varius dui. Suspendisse eget dolor. Fusce pulvinar lacus ac dui.</p>
<p class="red">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus sit amet diam. Duis mattis varius dui. Suspendisse eget dolor.</p>
<p class="both">This paragraph clears both.</p>
</div>
.wrapper{
border:1px solid black;
padding:10px;
}
.both {
border: 1px solid black;
clear: both;
}
.black {
float: left;
margin: 0;
background-color: black;
color: #fff;
width:20%;
}
.red {
float: right;
margin: 0;
background-color: pink;
width:20%;
}
p {
width: 45%;
}
Absolute positioning
Giving an item position: absolute or position: fixed removes it from flow, and any space that it would have taken up is removed.
In the next example I have three paragraph elements, the second element has position absolute, with offset values of top: 30px and right: 30px. It has been removed from document flow.
<div class="box">
<p>One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney.</p>
<p class="abspos">Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery.</p>
<p>Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact.”</p>
</div>
p {
border: 2px solid green;
}
.abspos {
background-color: green;
color: #fff;
top: 30px;
right: 30px;
width: 400px;
}
p {
border: 2px solid green;
}
.abspos {
position: absolute;
background-color: green;
color: #fff;
top: 30px;
right: 30px;
width: 400px;
}
p {
border: 2px solid green;
}
.abspos {
position: absolute;
background-color: green;
color: #fff;
top: 0px;
right: 30px;
width: 400px;
}
p {
border: 2px solid green;
}
.abspos {
position: absolute;
background-color: green;
color: #fff;
top: 30px;
right: 0px;
width: 400px;
}
p {
border: 2px solid green;
}
.abspos {
position: absolute;
background-color: green;
color: #fff;
top: 0px;
right: 0px;
width: 400px;
}
p {
border: 2px solid green;
}
.abspos {
position: absolute;
background-color: green;
color: #fff;
width: 400px;
}
Using position: fixed also removes the item from flow, however the offsets are based on the viewport rather than the containing block.
When taking an item out of flow with positioning, you will need to manage the possibility of content overlapping. Out of flow essentially means that the other elements on your page no longer know that element exists so will not respond to it.
Relative positioning and flow
If you give an item relative positioning with position: relative, it remains in flow.
However, you are then able to use the offset values to push it around. The space that it would have been placed in normal flow is reserved.
However, as you can see in the example below.
<div class="box">
<p>One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney.</p>
<p class="relative">Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery.</p>
<p>Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact.”</p>
</div>
p {
border: 2px solid green;
}
.relative {
position: relative;
background-color: green;
color: #fff;
bottom: 50px;
left: 50px;
width: 400px;
}
p {
border: 2px solid green;
}
.relative {
position: relative;
background-color: green;
color: #fff;
bottom: 50px;
// left: 50px;
width: 400px;
}
Content overlapping
When you do anything to remove or shift an item from where it would be placed in normal flow, you can expect to need to do some managing of the content and the content around it to prevent overlaps.
Whether that involves clearing floats, or ensuring that an element with position: absolute does not sit on top of some other content.
For this reason methods which remove elements from being in-flow should be used with understanding of the effect that they have.
BFC for detail
A block formatting context (BFC) is a part of a visual CSS rendering of a web page. It's the region in which the layout of block boxes occurs and in which floats interact with other elements.
A block formatting context is created by at least one of the following:
- The root element of the document ().
- Floats (elements where float isn't none).
- Absolutely positioned elements (elements where position is absolute or fixed).
- Inline-blocks (elements with display: inline-block).
- Table cells (elements with display: table-cell, which is the default for HTML table cells).
- Table captions (elements with display: table-caption, which is the default for HTML table captions).
- Anonymous table cells implicitly created by the elements with display: table, table-row, table-row-group, table-header-group, table-footer-group (which is the default for HTML tables, table rows, table bodies, table headers, and table footers, respectively), or inline-table.
- Block elements where overflow has a value other than visible and clip.
- display: flow-root.
- Elements with contain: layout, content, or paint.
- Flex items (direct children of the element with display: flex or inline-flex) if they are neither flex nor grid nor table containers themselves.
- Grid items (direct children of the element with display: grid or inline-grid) if they are neither flex nor grid nor table containers themselves.
- Multicol containers (elements where column-count or column-width isn't auto, including elements with column-count: 1).
- column-span: all should always create a new formatting context, even when the column-span: all element isn't contained by a multicol container (Spec change, Chrome bug).
Formatting contexts affect layout, but typically, we create a new block formatting context for the positioning and clearing floats rather than changing the layout, because an element that establishes a new block formatting context will:
- contain internal floats.
- exclude external floats.
- suppress margin collapsing.
Note: A Flex/Grid container(display: flex/grid/inline-flex/inline-grid) establishes a new Flex/Grid formatting context, which is similar to block formatting context except layout. There's no floating children available inside a flex/grid container, but exclude external floats and suppress margin collapsing still works.
Contain internal floats
<section>
<div class="box">
<div class="float">I am a floated box!</div>
<p>I am content inside the container.</p>
</div>
</section>
<section>
<div class="box" style="overflow:auto">
<div class="float">I am a floated box!</div>
<p>I am content inside the <code>overflow:auto</code> container.</p>
</div>
</section>
<section>
<div class="box" style="display:flow-root">
<div class="float">I am a floated box!</div>
<p>I am content inside the <code>display:flow-root</code> container.</p>
</div>
</section>
section {
height:150px;
}
.box {
background-color: rgb(224, 206, 247);
border: 5px solid rebeccapurple;
}
.box[style] {
background-color: aliceblue;
border: 5px solid steelblue;
}
.float {
float: left;
width: 200px;
height: 100px;
background-color: rgba(255, 255, 255, .5);
border:1px solid black;
padding: 10px;
}
using float: left
In the 1st example above, we have a floated element inside a
using overflow: auto
Setting overflow: auto or set other values than the initial value of overflow: visible created a new BFC containing the float. Our
The problem with using overflow to create a new BFC is that the overflow property is meant for telling the browser how you want to deal with overflowing content:
- There are some occasions in which you will find you get unwanted scrollbars or clipped shadows when you use this property purely to create a BFC.
- In addition, it is potentially not readable for a future developer, as it might not be obvious why you used overflow for this purpose. If you use overflow, it is a good idea to comment the code to explain.
using display: flow-root
A newer value of display lets us create a new BFC without any other potentially problematic side-effects. Using display: flow-root on the containing block creates a new BFC .
With display: flow-root; on the
The value name of flow-root makes sense when you understand you are creating something that acts like the root element ( element in browser) in terms of how it creates a new context for the flow layout inside it.
Exclude external floats
<section>
<div class="float">Try to resize this outer float</div>
<div class="box"><p>Normal</p></div>
</section>
<section>
<div class="float">Try to resize this outer float</div>
<div class="box" style="display:flow-root">
<p>
<code>display:flow-root</code>
</p>
</div>
</section>
section {
height:150px;
}
.box {
background-color: rgb(224, 206, 247);
border: 5px solid rebeccapurple;
}
.box[style] {
background-color: aliceblue;
border: 5px solid steelblue;
}
.float {
float: left;
overflow: hidden; /* required by resize:both */
resize: both;
margin-right:25px;
width: 200px;
height: 100px;
background-color: rgba(255, 255, 255, .75);
border: 1px solid black;
padding: 10px;
}
In the example above, we are using display:flow-root and floats to implement double columns layout. We are able to do this because an element in the normal flow that establishes a new BFC does not overlap the margin box of any floats in the same block formatting context as the element itself.
Rather than inline-blocks with width:, in this case we don't have to specify the width of the right div.
Note that flexbox is a more efficient way to implement multi-column layout in modern CSS.
Margin collapsing
Creating a new BFC to avoid the margin collapsing between two neighbor div:
<div class="blue"></div>
<div class="red-outer">
<div class="red-inner">red inner</div>
</div>
.blue, .red-inner {
height: 50px;
margin: 10px 0;
}
.blue {
background: blue;
}
.red-outer {
overflow: hidden;
background: red;
}
Margin collapsing
The top and bottom margins of blocks are sometimes combined (collapsed) into a single margin whose size is the largest of the individual margins (or just one of them, if they are equal), a behavior known as margin collapsing.
Note that the margins of floating and absolutely positioned(absolute or fixed) elements never collapse.
Margin collapsing occurs in three basic cases:
- Adjacent siblings
-
- The margins of adjacent siblings are collapsed (except when the latter sibling needs to be cleared past floats).
- No content separating parent and descendants
-
- If there is :
-
-
- no border, padding, inline part, block formatting context created,
- or clearance to separate the margin-top of a block from the margin-top of one or more of its descendant blocks;
- or no border, padding, inline content, height, or min-height to separate the margin-bottom of a block from the margin-bottom of one or more of its descendant blocks,
-
-
- then those margins collapse.
- The collapsed margin ends up outside the parent.
- Empty blocks
-
- If there is no border, padding, inline content, height, or min-height to separate a block's margin-top from its margin-bottom, then its top and bottom margins collapse.
<p>The bottom margin of this paragraph is collapsed …</p>
<p>… with the top margin of this paragraph, yielding a margin of <code>1.2rem</code> in between.</p>
<div>This parent element contains two paragraphs!
<p>This paragraph has a <code>.4rem</code> margin between it and the text above.</p>
<p>My bottom margin collapses with my parent, yielding a bottom margin of <code>2rem</code>.</p>
</div>
<p>I am <code>2rem</code> below the element above.</p>
div {
margin: 2rem 0;
background: lavender;
}
p {
margin: .4rem 0 1.2rem 0;
background: yellow;
}
Some things to note:
- More complex margin collapsing (of more than two margins) occurs when the above cases are combined.
- These rules apply even to margins that are zero, so the margin of a descendant ends up outside its parent (according to the rules above) whether or not the parent's margin is zero.
- When negative margins are involved, the size of the collapsed margin is the sum of the largest positive margin and the smallest (most negative) negative margin.
- When all margins are negative, the size of the collapsed margin is the smallest (most negative) margin. This applies to both adjacent elements and nested elements.
- Collapsing margins is only relevant in the vertical direction.
Position
The position CSS property sets how an element is positioned in a document. The top, right, bottom, and left properties determine the final location of positioned elements.
/*
* The element is positioned according to the normal flow of the document.
* The top, right, bottom, left and z-index properties have no effect.
*
* This is the default value.
*/
position: static;
/*
* The element is positioned according to the normal flow of the document.
* then offset relative to itself based on the values of top, right, bottom, and left. The offset does not affect the position of any other elements.
* thus, the space given for the element in the page layout is the same as if position were static.
*
* This value creates a new stacking context when the value of z-index is not auto.
*
* Its effect on table-*-group, table-row, table-column, table-cell, and table-caption elements is undefined.
*/
position: relative;
/*
* The element is removed from the normal document flow, and no space is created for the element in the page layout.
* It is positioned relative to its closest positioned ancestor, if any; otherwise, it is placed relative to the initial containing block.
*
* Its final position is determined by the values of top, right, bottom, and left.
*
* This value creates a new stacking context when the value of z-index is not auto.
*
* The margins of absolutely positioned boxes do not collapse with other margins.
*/
position: absolute;
/*
* The element is removed from the normal document flow, and no space is created for the element in the page layout.
* It is positioned relative to the initial containing block established by the viewport, except when one of its ancestors has a transform, perspective, or filter property set to something other than none (see the CSS Transforms Spec), or the will-change property is set to transform, in which case that ancestor behaves as the containing block. (Note that there are browser inconsistencies with perspective and filter contributing to containing block formation.) Its final position is determined by the values of top, right, bottom, and left.
*
* This value always creates a new stacking context. In printed documents, the element is placed in the same position on every page.
*/
position: fixed;
/*
* The element is positioned according to the normal flow of the document,
* and then offset relative to its nearest scrolling ancestor and containing block (nearest block-level ancestor), including table-related elements, based on the values of top, right, bottom, and left. The offset does not affect the position of any other elements.
*
* This value always creates a new stacking context.
*
* Note that a sticky element "sticks" to its nearest ancestor that has a "scrolling mechanism" (created when overflow is hidden, scroll, auto, or overlay), even if that ancestor isn't the nearest actually scrolling ancestor.
*/
position: sticky;
/* Global values */
position: inherit;
position: initial;
position: revert;
position: revert-layer;
position: unset;
Types of positioning
- A positioned element is an element whose computed position value is either relative, absolute, fixed, or sticky. (In other words, it's anything except static.)
- A relatively positioned element is an element whose computed position value is relative.
- An absolutely positioned element is an element whose computed position value is absolute or fixed.
-
- The top, right, bottom, and left properties specify offsets from the edges of the element's containing block. (The containing block is the ancestor relative to which the element is positioned.)
- If the element has margins, they are added to the offset.
- The element establishes a new block formatting context (BFC) for its contents.
- A stickily positioned element is an element whose computed position value is sticky.
-
- It's treated as relatively positioned until its containing block crosses a specified threshold (such as setting top to value other than auto) within its flow root (or the container it scrolls within), at which point it is treated as "stuck" until meeting the opposite edge of its containing block.
Autofill the available verticle/horizontal space
Most of the time, absolutely positioned elements that have height and width set to auto are sized so as to fit their contents.
However, non-replaced, absolutely positioned elements can be made to fill the available vertical space by specifying both top and bottom and leaving height unspecified (that is, auto). They can likewise be made to fill the available horizontal space by specifying both left and right and leaving width as auto.\
Except for the case just described (of absolutely positioned elements filling the available space):
- If both top and bottom are specified (technically, not auto), top wins.
- If both left and right are specified, left wins when direction is ltr (English, horizontal Japanese, etc.) and right wins when direction is rtl (Persian, Arabic, Hebrew, etc.).
| Initial Value | static |
|---|---|
| Applies to | all elements |
| Inherited | no |
| Computed Value | as specified |
| Animation Type | discrete |
| Creates Stacking Context | yes |
Example
Relative positioning
Relatively positioned elements are offset a given amount from their normal position within the document, but without the offset affecting other elements.
<div class="box" id="one">One</div>
<div class="box" id="two">Two</div>
<div class="box" id="three">Three</div>
<div class="box" id="four">Four</div>
* {
box-sizing: border-box;
}
.box {
display: inline-block;
width: 100px;
height: 100px;
background: red;
color: white;
}
#two {
position: relative;
top: 20px;
left: 20px;
background: blue;
}
Absolute positioning
Elements that are relatively positioned remain in the normal flow of the document. In contrast, an element that is absolutely positioned is taken out of the flow; thus, other elements are positioned as if it did not exist.
The absolutely positioned element is positioned relative to its nearest positioned ancestor (i.e., the nearest ancestor that is not static). If a positioned ancestor doesn't exist, it is positioned relative to the ICB (initial containing block — see also the W3C definition), which is the containing block of the document's root element.
<h1>Absolute positioning</h1>
<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p>
<p class="positioned">By default we span 100% of the width of our parent element, and we are as tall as our child content. Our total width and height is our content + padding + border width/height.</p>
<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p>
<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="long.jpg"></p>
* {
box-sizing: border-box;
}
body {
width: 500px;
margin: 0 auto;
}
p {
background: aqua;
border: 3px solid blue;
padding: 10px;
margin: 10px;
}
span {
background: red;
border: 1px solid black;
}
.positioned {
position: absolute;
background: yellow;
top: 30px;
left: 30px;
}
Fixed positioning
Fixed positioning is similar to absolute positioning, with the exception that the element's containing block is the initial containing block established by the viewport, unless any ancestor has transform, perspective, or filter property set to something other than none (see CSS Transforms Spec), which then causes that ancestor to take the place of the elements containing block. Also, when the will-change property is set to transform, a new containing block is established.
This can be used to create a "floating" element that stays in the same position regardless of scrolling.
<div class="outer">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam congue tortor eget pulvinar lobortis.
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam ac dolor augue.
Pellentesque mi mi, laoreet et dolor sit amet, ultrices varius risus. Nam vitae iaculis elit.
Aliquam mollis interdum libero. Sed sodales placerat egestas. Vestibulum ut arcu aliquam purus viverra dictum vel sit amet mi.
Duis nisl mauris, aliquam sit amet luctus eget, dapibus in enim. Sed velit augue, pretium a sem aliquam, congue porttitor tortor.
Sed tempor nisl a lorem consequat, id maximus erat aliquet. Sed sagittis porta libero sed condimentum.
Aliquam finibus lectus nec ante congue rutrum. Curabitur quam quam, accumsan id ultrices ultrices, tempor et tellus.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam congue tortor eget pulvinar lobortis.
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam ac dolor augue.
Pellentesque mi mi, laoreet et dolor sit amet, ultrices varius risus. Nam vitae iaculis elit.
Aliquam mollis interdum libero. Sed sodales placerat egestas. Vestibulum ut arcu aliquam purus viverra dictum vel sit amet mi.
Duis nisl mauris, aliquam sit amet luctus eget, dapibus in enim. Sed velit augue, pretium a sem aliquam, congue porttitor tortor.
Sed tempor nisl a lorem consequat, id maximus erat aliquet. Sed sagittis porta libero sed condimentum.
Aliquam finibus lectus nec ante congue rutrum. Curabitur quam quam, accumsan id ultrices ultrices, tempor et tellus.
</p>
<div class="box" id="one">One</div>
</div>
* {
box-sizing: border-box;
}
.box {
width: 100px;
height: 100px;
background: red;
color: white;
}
#one {
position: fixed;
top: 80px;
left: 10px;
background: blue;
}
.outer {
width: 500px;
height: 300px;
overflow: scroll;
padding-left: 150px;
}
In the example below, box "One" is fixed at 80 pixels from the top of the page and 10 pixels from the left. Even after scrolling, it remains in the same place relative to the viewport.
Sticky positioning
Sticky positioning can be thought of as a hybrid of relative and fixed positioning when its nearest scrolling ancestor is the viewport.
A stickily positioned element is treated as relatively positioned until it crosses a specified threshold, at which point it is treated as fixed until it reaches the boundary of its parent.
#one {
position: sticky;
top: 10px;
}
The above CSS rule would position the element with id one relatively until the viewport was scrolled such that the element would be less than 10 pixels from the top. Beyond that threshold, the element would be fixed to 10 pixels from the top.
Classical example - sticky sub-headings of an alphabetized list
A common use for sticky positioning is for the headings in an alphabetized list. The "B" heading will appear just below the items that begin with "A" until they are scrolled offscreen. Rather than sliding offscreen with the rest of the content, the "B" heading will then remain fixed to the top of the viewport until all the "B" items have scrolled offscreen, at which point it will be covered up by the "C" heading, and so on.
You must specify a threshold with at least one of top, right, bottom, or left for sticky positioning to behave as expected. Otherwise, it will be indistinguishable from relative positioning.
<dl>
<div>
<dt>A</dt>
<dd>Andrew W.K.</dd>
<dd>Apparat</dd>
<dd>Arcade Fire</dd>
<dd>At The Drive-In</dd>
<dd>Aziz Ansari</dd>
</div>
<div>
<dt>C</dt>
<dd>Chromeo</dd>
<dd>Common</dd>
<dd>Converge</dd>
<dd>Crystal Castles</dd>
<dd>Cursive</dd>
</div>
<div>
<dt>E</dt>
<dd>Explosions In The Sky</dd>
</div>
<div>
<dt>T</dt>
<dd>Ted Leo & The Pharmacists</dd>
<dd>T-Pain</dd>
<dd>Thrice</dd>
<dd>TV On The Radio</dd>
<dd>Two Gallants</dd>
</div>
</dl>
* {
box-sizing: border-box;
}
dl > div {
background: #FFF;
padding: 24px 0 0 0;
}
dt {
background: #B8C1C8;
border-bottom: 1px solid #989EA4;
border-top: 1px solid #717D85;
color: #FFF;
font: bold 18px/21px Helvetica, Arial, sans-serif;
margin: 0;
padding: 2px 0 0 12px;
position: -webkit-sticky;
position: sticky;
top: -1px;
}
dd {
font: bold 20px/45px Helvetica, Arial, sans-serif;
margin: 0;
padding: 0 0 0 12px;
white-space: nowrap;
}
dd + dd {
border-top: 1px solid #CCC;
}
The stacking context
The stacking context is a three-dimensional conceptualization of HTML elements along an imaginary z-axis relative to the user, who is assumed to be facing the viewport or the webpage.
HTML elements occupy this space in priority order based on element attributes.
The rendering order of certain elements is influenced by their z-index value. This occurs because these elements have special properties which cause them to form a stacking context.
A stacking context is formed, anywhere in the document, by any element in the following scenarios:
- Root element of the document ().
- Element with a position value absolute or relative and z-index value other than auto.
- Element with a position value fixed or sticky (sticky for all mobile browsers, but not older desktop).
- Element that is a child of a flex container, with z-index value other than auto.
- Element that is a child of a grid container, with z-index value other than auto.
- Element with an opacity value less than 1 (See the specification for opacity).
- Element with a mix-blend-mode value other than normal.
- Element with any of the following properties with value other than none:
- Element with an isolation value isolate.
- Element with a will-change value specifying any property that would create a stacking context on non-initial value (see this post).
- Element with a contain value of layout, or paint, or a composite value that includes either of them (i.e. contain: strict, contain: content).
Importantly, the z-index values of its child stacking contexts only have meaning in this parent. Stacking contexts are treated atomically as a single unit in the parent stacking context.
In summary:
- Stacking contexts can be contained in other stacking contexts, and together create a hierarchy of stacking contexts.
- Each stacking context is completely independent of its siblings: only descendant elements are considered when stacking is processed.
- Each stacking context is self-contained: after the element's contents are stacked, the whole element is considered in the stacking order of the parent stacking context.
Note: The hierarchy of stacking contexts is a subset of the hierarchy of HTML elements because only certain elements create stacking contexts. We can say that elements that do not create their own stacking contexts are assimilated by the parent stacking context.
Example 1
In this example, every positioned element creates its own stacking context, because of their positioning and z-index values.
The hierarchy of stacking contexts is organized as follows:
- Root
-
- DIV #1
- DIV #2
- DIV #3
-
-
- DIV #4
- DIV #5
- DIV #6
-
It is important to note that DIV #4, DIV #5 and DIV #6 are children of DIV #3, so stacking of those elements is completely resolved within DIV#3. Once stacking and rendering within DIV #3 is completed, the whole DIV #3 element is passed for stacking in the root element with respect to its sibling's DIV.
Note:
- DIV #4 is rendered under DIV #1 because DIV #1's z-index (5) is valid within the stacking context of the root element, while DIV #4's z-index (6) is valid within the stacking context of DIV #3. So, DIV #4 is under DIV #1, because DIV #4 belongs to DIV #3, which has a lower z-index value.
- For the same reason DIV #2 (z-index 2) is rendered under DIV#5 (z-index 1) because DIV #5 belongs to DIV #3, which has an higher z-index value.
- DIV #3's z-index is 4, but this value is independent from z-index of DIV #4, DIV #5 and DIV #6, because it belongs to a different stacking context.
- An easy way to figure out the rendering order of stacked elements along the Z axis is to think of it as a "version number" of sorts, where child elements are minor version numbers underneath their parent's major version numbers.
-
- This way we can easily see how an element with a z-index of 1 (DIV #5) is stacked above an element with a z-index of 2 (DIV #2), and how an element with a z-index of 6 (DIV #4) is stacked below an element with a z-index of 5 (DIV #1). In our example (sorted according to the final rendering order):
- Root
-
-
- DIV #2 - z-index is 2
- DIV #3 - z-index is 4
-
-
-
-
- DIV #5 - z-index is 1, stacked under an element with a z-index of 4, which results in a rendering order of 4.1
- DIV #6 - z-index is 3, stacked under an element with a z-index of 4, which results in a rendering order of 4.3
- DIV #4 - z-index is 6, stacked under an element with a z-index of 4, which results in a rendering order of 4.6
-
-
-
-
- DIV #1 - z-index is 5
-
Example 2
<div id="div1">
<h1>Division Element #1</h1>
<code>position: relative;<br/>
z-index: 5;</code>
</div>
<div id="div2">
<h1>Division Element #2</h1>
<code>position: relative;<br/>
z-index: 2;</code>
</div>
<div id="div3">
<div id="div4">
<h1>Division Element #4</h1>
<code>position: relative;<br/>
z-index: 6;</code>
</div>
<h1>Division Element #3</h1>
<code>position: absolute;<br/>
z-index: 4;</code>
<div id="div5">
<h1>Division Element #5</h1>
<code>position: relative;<br/>
z-index: 1;</code>
</div>
<div id="div6">
<h1>Division Element #6</h1>
<code>position: absolute;<br/>
z-index: 3;</code>
</div>
</div>
* {
margin: 0;
}
html {
padding: 20px;
font: 12px/20px Arial, sans-serif;
}
div {
opacity: 0.7;
position: relative;
}
h1 {
font: inherit;
font-weight: bold;
}
#div1,
#div2 {
border: 1px dashed #696;
padding: 10px;
background-color: #cfc;
}
#div1 {
z-index: 5;
margin-bottom: 190px;
}
#div2 {
z-index: 2;
}
#div3 {
z-index: 4;
opacity: 1;
position: absolute;
top: 40px;
left: 180px;
width: 330px;
border: 1px dashed #900;
background-color: #fdd;
padding: 40px 20px 20px;
}
#div4,
#div5 {
border: 1px dashed #996;
background-color: #ffc;
}
#div4 {
z-index: 6;
margin-bottom: 15px;
padding: 25px 10px 5px;
}
#div5 {
z-index: 1;
margin-top: 15px;
padding: 5px 10px;
}
#div6 {
z-index: 3;
position: absolute;
top: 20px;
left: 180px;
width: 150px;
height: 125px;
border: 1px dashed #009;
padding-top: 125px;
background-color: #ddf;
text-align: center;
}
See also Other Interesting Topics
- Using z-index
- Stacking without the z-index property: The stacking rules that apply when z-index is not used.
- Stacking with floated blocks: How floating elements are handled with stacking.
- Using z-index: How to use z-index to change default stacking.
- Stacking context example 1: 2-level HTML hierarchy, z-index on the last level
- Stacking context example 2: 2-level HTML hierarchy, z-index on all levels
- Stacking context example 3: 3-level HTML hierarchy, z-index on the second level
Layout and the containing block
The size and position of an element are often impacted by its containing block.
Most often, the containing block is the content area of an element's nearest block-level ancestor, but this is not always the case.
When a user agent (such as your browser) lays out a document, it generates a box for every element. Each box is divided into four areas:
- Content area
- Padding area
- Border area
- Margin area
Many developers believe that the containing block of an element is always the content area of its parent, but that isn't necessarily true.
Let's investigate the factors that determine what an element's containing block is.