CSS Display, Positioning and Related Concepts
One of the hardest things for me to understand in CSS is positioning: how to position an item the way I want it on the page.
Over the years I've found out that there are multiple concepts associated with positioning:
- Display
- Box Model
- Containing Block
- Parent element
- Position
- z-index
You can also work with perspective
in CSS but that is not part of positioning so it will not be covered in this post
Display #
The display CSS property defines an element is treated as a block or inline element and the layout used for its children, such as flow layout, grid or flex.
The traditional syntax is a single keyword. Modern browsers also support a two-keyword syntax that defines inner and outer display attributes.
The first attribute is either block
or inline
. This describes how the element plays in the page layout alongside other elements.
The second attribute describes the behavior of the element's children.
Until the level 3 specification was released we use a single value for display, like so:
.demo {
display: grid;
}
With the level 3 specification, the equivalent declaration is:
.demo {
display: block grid;
}
The single-value versions are still supported but may create unexpected results. If the browser sees:
.demo {
display: grid;
}
It will interpret it as:
.demo {
display: block grid;
}
This may not be what you were expecting so it pays to code defensively and include both the one-value and the two-value versions of the display property.
There are a few values for the display property that deserve special consideration:
- flow
- The element lays out its contents using flow layout (block-and-inline layout).
- If its outer display type is
inline
orrun-in
, and it is participating in a block or inline formatting context, the block generates an inline box. Otherwise, it generates a block container box. - Depending on the value of other properties (such as position, float, or overflow) and whether the block itself participates in a block or inline formatting context, it either establishes a new block formatting context (BFC) for its contents or integrates its contents into its parent formatting context.
- flow-root
- The element generates a block element box that establishes a new block formatting context, defining where the formatting root lies.
- inline-block
- The element generates a block element box that will be flowed with surrounding content as if it were a single inline box (behaving much like a replaced element would).
- It is equivalent to an inline flow-root.
- For more details on the
display
property check MDN's display and Digging Into The Display Property: The Two Values Of Display for more information.
Box model #
All content it a web page is in a box. The Box Model describes how these boxes surrounding the content behave and how it interacts with other content on the page.
There are multiple boxes around the content. They are:
- Content box
- The area where your content is displayed
- Size it using properties like
inline-size
andblock-size
orwidth
andheight
. - 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.
Position #
The position
CSS property controls how an element is positioned in a document.
The top
, right
, bottom
, and left
properties determine the final location of positioned elements. The exact effect of these properties will depend on the value of the position property.
The possible values are:
- static
- 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.
- relative
- The element is positioned according to the normal flow of the document, and then offset relative to itself based on the top, right, bottom, and left values. The offset does not affect the position of any other elements.
- This value creates a new stacking context when the value of
z-index
is not auto. - absolute
- The element is removed from the normal document flow, and no space is created for the element in the page layout.
- The element 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.
- fixed
- The element is removed from the normal document flow, and no space is created for the element in the page layout.
- The element is positioned relative to the initial containing block established by the viewport, unless one of its ancestors has a
transform
,perspective
, orfilter
property set to any value except none, or thewill-change
property is set totransform
, in which case that ancestor behaves as the containing block. - The final position is determined by the values of top, right, bottom, and left.
- This value always creates a new stacking context.
- sticky
- 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
, andleft
. - The offset does not affect the position of any other elements.
display: sticky
always creates a new stacking context. A sticky element "sticks" to its nearest ancestor that has a "scrolling mechanism" (created when overflow ishidden
,scroll
,auto
, oroverlay
), even if that ancestor isn't the nearest actually scrolling ancestor.
Containing block #
The size and position of an element are often impacted by its containing block. It is worth exploring what makes the containing block as this will impact the position of an element on the page.
The default containing block is the content area of the element itself. Identifying the actual containing block is hard since it'll depend on the value of the position
property.
- If the position property is
static
,relative
, orsticky
, the containing block is the content box of the nearest ancestor that is either ablock
container (such as aninline-block
,block
, orlist-item
element) or establishes a formatting context (such as atable
,flex
, orgrid
container) - If the position is
absolute
, the containing block is formed by the padding box of the nearest ancestor element with a position value other thanstatic
- If the position is
fixed
, the containing block is established by the viewport (for continuous media like the browser viewport) or the page area (for paged media) - If the position is
absolute
orfixed
, the containing block may also be formed by the edge of the padding box of the nearest ancestor element that has one of the following:- A transform or perspective value other than
none
- A will-change value of
transform
orperspective
- A contain value of
paint
(e.g.contain: paint;
) - A backdrop-filter other than
none
(e.g.backdrop-filter: blur(10px);
)
- A transform or perspective value other than
Parent Element #
A related element to containing block is the parent element is the container directly above and connected to an element in the document tree.
Sometimes the parent element is the same as the containing block, but that's not always the case since the location of the containing block depends on the position attribute of the element.
z-index #
The z-index
CSS property sets the z-order of a positioned element and its children.
What has helped me reason through z-index is to think of the content in the page being in layers. The z-index
property controls how the layers interact with the higher positive values being "closer" to the user.
Something to note:
Larger elements with higher z-index values cover those smaller elements with a lower z-index.