What is CSS position: static?
position: static is the default positioning mode for almost every element on the page.
A static element participates in the normal document flow: it goes where the layout system (block, inline,
flex, grid, etc.) places it.
The most important “meaning” to remember:
Static elements ignore top, right, bottom, and
left.
Those offset properties only affect elements that are position: relative, absolute,
fixed, or sticky.
.card {
position: static;
}
.card {
position: static;
top: 40px;
left: 40px;
}
.card {
position: relative;
top: 40px;
left: 40px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.stack {
display: grid;
gap: 12px;
max-width: 720px;
}
.card {
border: 3px solid #111;
border-radius: 14px;
background: #fff;
padding: 14px;
}
.label {
display: inline-block;
font-weight: 700;
padding: 4px 10px;
border: 2px solid #111;
border-radius: 999px;
}
.muted {
opacity: 0.8;
}
.cardClick the snippets. Notice how
topandleftdo nothing while the element isstatic, but work immediately once it becomesrelative.Neighbor .cardI am just here to show the layout flow.
Normal flow and position: static
“Normal flow” is how the browser naturally lays out elements:
-
Block elements (like
div,p) stack vertically by default. -
Inline elements (like
span,em) sit inside a line of text. - Flex and grid containers place their children according to their own layout rules.
If an element is static, it stays inside this normal flow. That means it affects the layout around it and is affected by it.
.flow {
display: block;
}
.flow {
display: flex;
gap: 10px;
}
.flow {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.flow {
border: 3px solid #111;
border-radius: 14px;
background: #fff;
padding: 12px;
max-width: 780px;
}
.item {
border: 2px dashed #111;
border-radius: 12px;
padding: 12px;
background: #f6f6f6;
}
.item strong {
font-weight: 800;
}
Item A
Static childItem B
Static childItem C
Static childItem D
Static child
Notice: we never had to set position: static here.
The children are static automatically, and the container’s layout mode (block, flex, grid) decides where they go.
Learn more about flex in the CSS Flexbox Interactive Tutorial, and about grid in the CSS Grid Interactive Tutorial.
Why top, bottom, left, and
right “don’t work” on static elements
This is the classic “CSS position static not working” moment. It’s not broken. It’s doing exactly what static means.
-
If the element is
position: static, offsets are ignored. -
If you want to nudge it without leaving the flow, use
position: relative. -
If you want it to be taken out of the flow and placed precisely, use
position: absolute(orfixed).
.badge {
position: static;
bottom: 0;
right: 0;
}
.badge {
position: relative;
bottom: 0;
right: 0;
}
.badge {
position: relative;
bottom: 18px;
right: 18px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.card {
max-width: 720px;
border: 3px solid #111;
border-radius: 16px;
padding: 18px;
background: #fff;
}
.badge {
display: inline-block;
padding: 8px 12px;
border: 2px solid #111;
border-radius: 999px;
font-weight: 800;
background: #f6f6f6;
}
.muted {
opacity: 0.8;
}
We are trying to push the badge toward the bottom-right using
Badgebottomandright. Withstatic, that does nothing.
Also important: margin and transform still work on static elements.
So if you just need spacing, use margins.
If you need a visual shift without affecting layout, transform: translate() is another option.
CSS position: static vs position: relative
These two are close cousins, but they behave differently in one key way:
-
static: normal flow, offsets ignored. -
relative: still in normal flow, but offsets apply (it can be nudged).
Another way to say it:
relative is “static, but allowed to move.”
.pop {
position: static;
top: 16px;
left: 16px;
}
.pop {
position: relative;
top: 16px;
left: 16px;
}
.pop {
position: relative;
top: -12px;
left: 0;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.row {
max-width: 780px;
border: 3px solid #111;
border-radius: 16px;
padding: 12px;
background: #fff;
display: grid;
gap: 10px;
}
.box {
border: 2px dashed #111;
border-radius: 12px;
padding: 12px;
background: #f6f6f6;
}
.pop {
border-style: solid;
background: #fff;
}
.muted {
opacity: 0.8;
}
Pop boxSwitch between static and relative to see the offset behavior.
Neighbor boxNotice: with
relative, the pop box moves visually, but this neighbor still acts as if the pop box is in its original spot.
That last point is crucial for beginners:
relative does not “pull things up” around it.
It keeps its original space in the layout, then moves visually.
Learn more about position: relative; in the CSS Position Relative Interactive Tutorial.
CSS position: static vs position: absolute
absolute is where positioning gets spicy:
-
static: stays in the normal flow, affects layout. -
absolute: removed from normal flow, does not take up space, and can be placed using offsets.
Absolute positioning is usually based on the nearest ancestor that is not static (often a parent with
position: relative).
If no such ancestor exists, the browser uses the initial containing block (roughly the viewport/page).
.pin {
position: static;
}
.pin {
position: absolute;
top: 12px;
right: 12px;
}
.frame {
position: relative;
}
.pin {
position: absolute;
top: 12px;
right: 12px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.frame {
max-width: 360px;
border: 3px solid #111;
border-radius: 16px;
padding: 18px;
background: #fff;
}
.content {
border: 2px dashed #111;
border-radius: 12px;
padding: 14px;
background: #f6f6f6;
}
.pin {
display: inline-block;
padding: 8px 12px;
border: 2px solid #111;
border-radius: 999px;
font-weight: 800;
background: #fff;
}
.muted {
opacity: 0.8;
}
The badge tries to "pin" to the top-right. First it is
Pinned?static(no pinning), thenabsolute(it moves), then we make the parentrelativeso the pin is relative to this box.
If you ever see an absolutely positioned element “teleport” somewhere unexpected, the first question is: “Which ancestor is it positioned against?” If all ancestors are static, it won’t be relative to the parent you expected.
Learn more about position: absolute; in the CSS Position Absolute Interactive Tutorial.
CSS position: static vs position: sticky
sticky starts out behaving like a normal-flow element (like static),
but then it “sticks” when you scroll past a threshold.
Two common beginner gotchas:
-
Sticky needs at least one offset, usually
top(orbottom). - Sticky sticks within its scroll container (often the nearest ancestor with scrolling).
.header {
position: static;
}
.header {
position: sticky;
top: 0;
}
.scroller {
height: 220px;
overflow: auto;
}
.header {
position: sticky;
top: 0;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.scroller {
max-width: 780px;
border: 3px solid #111;
border-radius: 16px;
background: #fff;
}
.header {
border-bottom: 3px solid #111;
background: #f6f6f6;
padding: 12px 14px;
font-weight: 900;
}
.list {
padding: 14px;
display: grid;
gap: 10px;
}
.row {
border: 2px dashed #111;
border-radius: 12px;
padding: 12px;
background: #fff;
}
.muted {
opacity: 0.8;
}
Sticky header (scroll inside this box)Row 1Row 2Row 3Row 4Row 5Row 6Row 7Row 8
If you switch to sticky and it “does nothing,” check:
Is there a top (or bottom) value?
Without it, there’s no sticking threshold.
Learn more about position: sticky; in the CSS Position Sticky Interactive Tutorial.
CSS position: static vs position: fixed
fixed is the “stick it to the viewport” positioning mode.
It removes the element from normal flow (like absolute), but instead of positioning relative to a parent,
it positions relative to the viewport (your browser window).
-
static: stays in normal flow, takes up space, offsets ignored. -
fixed: removed from flow, does not take up space, offsets work, and it stays put when you scroll.
The most common real-world example is a “chat” button or a cookie banner that stays visible while scrolling.
.floater {
position: static;
bottom: 16px;
right: 16px;
}
.floater {
position: fixed;
bottom: 16px;
right: 16px;
}
.floater {
position: fixed;
top: 16px;
right: 16px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.viewport-demo {
max-width: 780px;
border: 3px solid #111;
border-radius: 16px;
background: #fff;
padding: 14px;
height: 260px;
overflow: auto;
position: relative;
}
.filler {
border: 2px dashed #111;
border-radius: 12px;
background: #f6f6f6;
padding: 12px;
display: grid;
gap: 10px;
min-height: 620px;
}
.filler p {
margin: 0;
}
.floater {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 12px;
border: 3px solid #111;
border-radius: 999px;
background: #fff;
font-weight: 900;
}
.dot {
width: 10px;
height: 10px;
border-radius: 999px;
border: 2px solid #111;
background: #f6f6f6;
}
.muted {
opacity: 0.8;
}
Common fixed gotchas (and why they matter when you expected static)
-
Layout jump: because fixed elements are removed from flow, they don’t reserve space.
If you turn a header into
position: fixed, content may slide under it unless you add padding/margin to compensate. - Mobile browser behavior: some mobile browsers treat the “viewport” differently as the address bar shows/hides, which can make fixed UI feel a bit jumpy. Test on real devices.
- Use fixed for overlays, not layout: if your goal is “put the footer at the bottom of a card,” that’s not fixed. That’s a layout job (flex/grid).
A quick rule of thumb: Static is for normal layout. Fixed is for UI that must stay on screen while scrolling.
Learn more about position: fixed; in the CSS Position Fixed Interactive Tutorial.
CSS position: static and z-index
This is a sneaky one. Beginners often try:
z-index: 9999;
and nothing happens.
In most common cases, z-index only works on positioned elements
(elements whose position is not static), or on certain layout contexts like flex/grid
items.
So if your element is plain static in normal flow, z-index often won’t change stacking.
.a {
z-index: 10;
}
.a {
position: relative;
z-index: 10;
}
.b {
position: relative;
z-index: 20;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.stage {
max-width: 780px;
border: 3px solid #111;
border-radius: 16px;
background: #fff;
padding: 14px;
display: grid;
gap: 10px;
}
.pile {
position: relative;
height: 160px;
border: 2px dashed #111;
border-radius: 14px;
background: #f6f6f6;
}
.card {
width: 220px;
height: 110px;
border: 3px solid #111;
border-radius: 14px;
padding: 10px;
background: #fff;
position: absolute;
top: 22px;
left: 22px;
}
.a {
transform: translate(0, 0);
}
.b {
transform: translate(70px, 34px);
}
.title {
font-weight: 900;
}
.muted {
opacity: 0.8;
}
These boxes overlap. Try changing which one is on top using
z-index. First we applyz-indexwithout positioning (often useless), then we position it and it starts to behave.AI want to be on topBMe too
Quick practical tip:
if you’re trying to “bring something forward,” adding
position: relative
is often the smallest change that makes z-index behave.
Learn more about z-index and stacking in the CSS Z-Index Interactive Tutorial.
“CSS position static bottom” explained
People often search for “position static bottom” because they want an element to sit at the bottom of something.
The key idea:
bottom does not apply to static elements.
To place something at the bottom, you usually want one of these approaches:
- Layout approach: use flex or grid to push content to the bottom (recommended).
-
Positioning approach: make the parent positioned, then use
position: absoluteon the child.
.panel {
display: flex;
flex-direction: column;
}
.footer {
margin-top: auto;
}
.panel {
position: relative;
}
.footer {
position: absolute;
left: 14px;
right: 14px;
bottom: 14px;
}
.panel {
position: relative;
}
.footer {
position: static;
bottom: 14px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.panel {
max-width: 780px;
border: 3px solid #111;
border-radius: 16px;
background: #fff;
padding: 14px;
height: 310px;
}
.body {
border: 2px dashed #111;
border-radius: 12px;
padding: 12px;
background: #f6f6f6;
}
.footer {
border: 3px solid #111;
border-radius: 12px;
padding: 10px 12px;
background: #fff;
font-weight: 800;
}
.muted {
opacity: 0.8;
}
Panel contentWe want the footer to sit at the bottom of this panel. Try the flex method, then the absolute method, then the "static + bottom" method (which fails).
If the element is part of the layout (like a footer inside a card), flex/grid is usually the cleanest choice. Absolute positioning is great for overlays, badges, and “pin to corner” UI.
“CSS position static relative” clarified
This phrase usually means one of two things:
-
“Is
staticrelative to its parent?” (Answer: it’s placed by normal flow inside the parent.) -
“How do I make it relative?” (Answer: change it to
position: relative.)
A static element’s placement depends on layout rules (block, flex, grid).
But it is not “relative positioning.”
If you need offsets, you need relative (or another positioned value).
.container {
display: grid;
gap: 10px;
}
.box {
position: static;
}
.container {
display: grid;
gap: 10px;
}
.box {
position: relative;
top: 16px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.container {
max-width: 780px;
border: 3px solid #111;
border-radius: 16px;
padding: 14px;
background: #fff;
}
.box {
border: 2px dashed #111;
border-radius: 12px;
padding: 12px;
background: #f6f6f6;
}
.box strong {
font-weight: 900;
}
.muted {
opacity: 0.8;
}
Box AStatic: placed by the grid flow.
Box BThis one will get pushed visually when .box becomes relative and moves.
CSS position: static example gallery
Here are a few quick “static in real life” examples. Most of your page is static most of the time, and that’s a good thing.
.nav a {
display: inline-block;
padding: 10px 12px;
}
.article p {
margin: 0 0 12px 0;
}
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.demo {
max-width: 980px;
display: grid;
gap: 14px;
}
.nav {
border: 3px solid #111;
border-radius: 16px;
background: #fff;
padding: 10px;
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.nav a {
border: 2px solid #111;
border-radius: 999px;
text-decoration: none;
color: #111;
background: #f6f6f6;
font-weight: 700;
}
.article {
border: 3px solid #111;
border-radius: 16px;
background: #fff;
padding: 14px;
}
.cards {
border: 3px solid #111;
border-radius: 16px;
background: #fff;
padding: 14px;
}
.card {
border: 2px dashed #111;
border-radius: 12px;
padding: 12px;
background: #f6f6f6;
min-height: 84px;
}
.muted {
opacity: 0.8;
}
@media (max-width: 740px) {
.cards {
grid-template-columns: 1fr;
}
}
Article content
Static paragraphs follow normal flow. This is the browser being helpful.
Spacing is managed with margins and layout, not with
topandleft. Card 1
StaticCard 2
StaticCard 3
Static
Debugging: “static not working” checklist
If you tried to move something and it won’t budge, run through this list:
-
Is it still
position: static? If yes, offsets are ignored. - Are you actually trying to do layout? If you’re aligning items, use flex/grid first.
-
Are you trying to overlay / pin?
Use
position: absoluteon the overlay and make the parent or the target ancestorposition: relative. -
Is
z-indexnot working? Addposition: relative(or confirm it’s a flex/grid item) and watch for stacking contexts. -
Is sticky not sticking?
Add
topand check the scroll container.
.help {
position: static;
top: 30px;
z-index: 999;
}
.help {
position: relative;
top: 30px;
z-index: 999;
}
.shell {
position: relative;
}
.help {
position: absolute;
top: 14px;
right: 14px;
}
*,
::before,
::after {
box-sizing: border-box;
}
.wrap {
padding: 18px;
font-family: system-ui, Arial, sans-serif;
}
.shell {
max-width: 780px;
border: 3px solid #111;
border-radius: 16px;
background: #fff;
padding: 14px;
}
.block {
border: 2px dashed #111;
border-radius: 12px;
padding: 14px;
background: #f6f6f6;
min-height: 140px;
}
.help {
display: inline-block;
padding: 8px 12px;
border: 2px solid #111;
border-radius: 999px;
background: #fff;
font-weight: 900;
}
.muted {
opacity: 0.8;
}
This playground shows the common path: static offsets do nothing, relative offsets work, and absolute is for pinning inside a parent.
?
Key takeaways
-
position: staticis the default: normal flow, no offset positioning. -
Offsets (
top,right,bottom,left) do nothing on static elements. -
Use
position: relativeto nudge something while keeping its layout space. -
Use
position: absoluteto overlay or pin, usually inside a parent set toposition: relative. -
If
z-index“doesn’t work,” ensure the element is positioned (or verify its stacking context).
Conclusion
Understanding position: static is crucial because it forms the baseline for all other positioning
schemes. Remember, static elements follow the normal flow and ignore offsets, making them predictable and reliable.
