Metadata
-
Date
-
Tagged
-
Older post
-
Newer post
CSS Position
Positioning things on the web is …
I’m bad at writing intros, let’s dive in.
Document flow
flow is the way we refer to the browser laying out elements when there are no changes made to those elements.
Every element has a natural size, and elements in flow affect the location of the elements around it.
Boxes in normal flow are either block or inline, but not both at the same time.
- Inline ones sit in the same direction as text.
- Block ones are stacked along the cross axis.
The display CSS property can set this.
p { display: block;}
span { display: inline;}There are 2 popular methods to take an element out of flow.
- absolute positioning, which we discuss later
- floating an element
Position
The default value for the CSS position property is static.
That’s why you almost never see it written in code, when a position is set explicitly, it’s usually with a different value.
The most important aspect is if the item gets taken out of flow or not.
Values for position that keep the element in the document flow:
staticrelativesticky
Values for position that remove the element from the document flow:
absolutefixed
Positioned elements can be offset by also defining a value for the top, right, bottom, and left properties with a distance.
Where that element is offset from is determined by the value you chose for position.
Relative
Relatively positioned elements remain in flow. They are offset relative to their original position.
That final offset position has no effect on other elements, they are laid out in the regular flow as if nothing happend.
If you played around with the interactive demo above, you might have noticed setting a bottom had no effect until you disabled top.
The top property takes priority.
bottom is ignored if CSS sees both properties are set.
The same thing happens with left and right.
If CSS sees both, left gets priority.
Absolute
An absolutely positioned element is removed from flow. Other elements are not affected by where the element is displayed on the page.
The absolute element is offset relative to the nearest positioned ancestor.
In other words: the closest element up the tree with a position set (that isn’t static).
If no top, right, bottom, or left offsets are set, the element is shown where it would be had it been in flow.
Because it was removed from the document flow, that means it will probably overlap the element after it though.
An absolutely positioned element is as small as it can be, based on its content.
Contrary to the relative demo, setting both left and right at the same time does work.
It will respect both unless a width is set.
In that case you’re asking the browser to satisfy two conflicting commands and it will ignore right again.
When both left and right are defined, and width constraints don’t prevent it, the element will stretch to satisfy both. If the element cannot stretch to satisfy both, the position of the element is overspecified. When this is the case, the left value has precedence when the container is left-to-right; the right value has precedence when the container is right-to-left.
So, position: absolute; is pretty cool, and unlike that space trek quote, I also deal in absolutes.
One two punch
It is a very popular practice to set position: relative; on the direct parent of an element with position: absolute;.
That way the provided offsets will be offsets from that parent, which is usually what you want.
The results might be identical if you didn’t do that, but it’s good to avoid unexpected results.
Tweaking
Setting a top, right, bottom, or left offset would lose the element’s original position.
If that position is not quite right, adding a margin is a useful tool.
It will affect the location of the absolutely positioned element but nothing else, as it is out of flow.
Centering
The method of placing an item with offsets makes it a bit awkward to exactly center things.
We don’t need to rely on magic numbers for those values however, a few techniques exist.
Margin
Setting the top and bottom to 0, with a margin-top of auto and a margin-bottom of auto will vertically center the absolutely positioned element.
The same logic can be applied to left, and right.
.absolute-center { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; width: 100px; /* has to be known for horizontal centering */ height: 100px; /* has to be known for vertical centering */}Transform
A solution that doesn’t need known dimensions leverages the transform property.
- Move the element’s top left edge to be in the exact center of the parent.
- Scoot the element over by half the size of that element with a
transform.
.absolute-center { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);}Both the margin and transform methods can be seen in this codepen.
Flexbox and grid
This surprised me (because I thought flexbox and grid would have no effect on items that are out of flow), but flexbox and grid can be used to place absolutely positioned elements!
Fixed
Fixed positioning is a specialized form of absolute positioning. The offsets are relative to the viewport, even when the page is scrolled.
Sticky
Elements with position: sticky are offset relative to nearest scrolling
ancestor.
That enables a bunch of neat applications
Sticky elements don’t always have to be offset from the top. Using multiple offsets works too.
The scrolling also doesn’t have to be vertical.
This CodePen has a horizontally scrolling parent with a sticky child that has a right set.
Conclusion
Positioning allows us to take elements out of the normal document flow.
Some values remove an item from flow entirely, others don’t.
Elements in flow take up space, they affect elements next to them.