HTML and CSS project tutorial covering web development fundamentals. Learn to build interactive and responsive web pages.
position values works, with real code examples you can try yourself.The position property in CSS controls how an element is placed in the document. By default, every element follows the normal flow — block elements stack vertically, inline elements sit side by side. When you change the position value, you gain access to the top, right, bottom, and left offset properties that let you move the element around. There are five main values: static, relative, absolute, fixed, and sticky. Each one behaves differently, and choosing the right one depends on what you are trying to achieve. Understanding the differences is key to mastering CSS layouts.
Every HTML element starts with position: static. This is the default value, and it means the element follows the normal document flow. The top, right, bottom, and left properties have no effect on static elements. You might never write position: static explicitly, but it is important to understand that this is the baseline all other positioning values depart from. In practice, you will only set static explicitly when you want to override another positioning value that was applied by a CSS framework or a previous rule.
/* Static positioning — the default */
.element {
position: static;
/* top, left, etc. have NO effect */
}A relatively positioned element stays in the normal flow, but you can shift it using the offset properties. The element's original space is preserved, so surrounding elements do not reflow to fill the gap. This makes relative very useful for fine-tuning visual placement without disrupting the layout. For example, you can nudge an icon down by a few pixels or move a button slightly to the right. More importantly, position: relative creates a new containing block for absolutely positioned children.
.box {
position: relative;
top: 10px;
left: 20px;
/* Moved 10px down, 20px right from where it would normally be */
}An absolutely positioned element is removed entirely from the normal document flow. Other elements behave as if it does not exist. You then use top, right, bottom, and left to place it relative to its nearest positioned ancestor — the closest ancestor with a position value other than static. If no such ancestor exists, it positions itself relative to the <html> element (the initial containing block). This makes absolute positioning perfect for overlays, tooltips, dropdown menus, and custom badges on cards.
.parent {
position: relative;
}
.child {
position: absolute;
top: 0;
right: 0;
/* Sticks to the top-right corner of .parent */
}A fixed element is removed from the normal flow and positioned relative to the browser viewport. It stays in the same place even when the page scrolls. This is the go-to choice for sticky headers, floating action buttons, back-to-top links, and persistent cookie banners. Because fixed elements do not scroll with the rest of the page, be careful not to cover important content. You can use z-index to control which fixed elements appear on top. Fixed positioning is one of the easiest ways to create a persistent navigation bar.
nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
z-index: 1000;
}Sticky positioning is a hybrid of relative and fixed. The element behaves like relative within its parent container until the viewport reaches a defined scroll threshold, at which point it "sticks" and behaves like fixed. It stays stuck until its parent container scrolls out of view. This is perfect for section headers in long lists, table headers, and any UI element that should follow the user as they scroll through a specific section. Browser support for sticky is excellent across modern browsers.
.section-header {
position: sticky;
top: 0;
/* Stays at the top while scrolling through its container */
background: #f0f4ff;
padding: 0.5rem 1rem;
}When elements start overlapping — which they often do with absolute, fixed, and sticky — you need z-index to control which one sits on top. The z-index property accepts an integer value; higher numbers appear in front of lower numbers. However, z-index only works on positioned elements (anything other than static). Every time you set a position and z-index on an element, you create a new stacking context, which can affect how nested positioned elements layer. Keep your z-index values organized — using increments of 10 or 100 makes it easier to insert new layers later.
.modal-overlay {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgba(0,0,0,0.5);
z-index: 100;
}
.modal-content {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
z-index: 101;
}Let us combine everything into a practical example. A tooltip appears when you hover over a button. The button container is position: relative, and the tooltip is position: absolute so it hovers above the button. This pattern works for image captions, info icons, and navigation submenus. The key is that the relative parent gives the absolute child an anchor point to position against. Without the relative parent, the tooltip would fly off to the top-left corner of the page. This single pattern is used in virtually every UI framework today.
.tooltip-container {
position: relative;
display: inline-block;
}
.tooltip-text {
position: absolute;
bottom: 120%;
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 4px 8px;
border-radius: 4px;
white-space: nowrap;
opacity: 0;
transition: opacity 0.2s;
}
.tooltip-container:hover .tooltip-text {
opacity: 1;
}