{"componentChunkName":"component---src-templates-post-jsx","path":"/blog/offset-parent-and-stacking-context-positioning-elements-in-all-three-dimensions/","result":{"data":{"mdx":{"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nconst _frontmatter = {\n  \"title\": \"Offset parent and stacking context: positioning elements in all three dimensions\",\n  \"cover\": \"/blogs/offset/cover.svg\",\n  \"date\": \"2023-07-06\",\n  \"updated\": \"2023-08-16\",\n  \"type\": [\"tutorial\"]\n};\nconst layoutProps = {\n  _frontmatter\n};\nconst MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  let {\n    components\n  } = _ref,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, `They are fundamental CSS concepts you use every single day whether you know it or not: the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `offset parent`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `stacking context`), `. In this article we'll explore how you can use them to position elements in all three dimensions, and how to debug them.`), mdx(\"h2\", {\n    \"id\": \"prefer-video\"\n  }, `Prefer video?`), mdx(\"p\", null, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://kevinpowell.co/\"\n  }), `Kevin Powell`), ` and I recorded a video on the offset parent and stacking context as well so if you prefer video, you can find all the info here:`), mdx(\"div\", {\n    \"className\": \"gatsby-resp-iframe-wrapper\",\n    \"style\": {\n      \"paddingBottom\": \"56.25%\",\n      \"position\": \"relative\",\n      \"height\": \"0\",\n      \"overflow\": \"hidden\"\n    }\n  }, ` `, mdx(\"div\", _extends({\n    parentName: \"div\"\n  }, {\n    \"style\": {\n      \"position\": \"relative\",\n      \"width\": \"100%\",\n      \"paddingTop\": \"56.25%\"\n    }\n  }), ` `, mdx(\"iframe\", _extends({\n    parentName: \"div\"\n  }, {\n    \"src\": \"https://www.youtube.com/embed/GS6b9p6edfk\",\n    \"title\": \"YouTube video player\",\n    \"frameBorder\": \"0\",\n    \"allow\": \"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\",\n    \"allowFullScreen\": true,\n    \"style\": {\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\",\n      \"width\": \"100%\",\n      \"height\": \"100%\"\n    }\n  })), ` `), ` `), mdx(\"h2\", {\n    \"id\": \"offset-parent\"\n  }, `Offset parent`), mdx(\"p\", null, `When you position your element with absolute positioning along the X and Y axis, what is it positioned relative to? The answer is the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `offset parent`), `. Whenever you position an element with top, right, bottom and left, the browser looks at this 'offset parent' to determine where to place the element.`), mdx(\"p\", null, `The offset parent of an element is the nearest ancestor with a position other than `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `static`), `, or the body if none of the ancestor have positioning. This means that if you position an element with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: absolute`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `top: 0`), `, it will be positioned at the top of the offset parent. So when you're laying out a page, knowing the offset parent of an element is crucial to understanding where it will be positioned.`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `Something that could trip you up here is that we're talking about placing an element `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `relative`), ` to another element, but using `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `position: absolute`), ` to do so. When an element has an absolute position, it get's taken out of the document flow (it no longer pushed other elements down) but it's placement is still `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `relative`), ` to the offset parent.`)), mdx(\"h3\", {\n    \"id\": \"an-example\"\n  }, `An example`), mdx(\"p\", null, `Let's look at an example. Here we have the HTML and CSS for a block quote and we want to put a quote mark behind it for styling.`), mdx(\"p\", null, `As you can see, the quote is in the top left of the `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `page`), ` instead of the top left of the block quote, and that's because the blockquote itself doesn't have an offset. That means the offset parent of the quote mark is the body.`), mdx(OffsetExample, {\n    mdxType: \"OffsetExample\"\n  }), mdx(\"p\", null, `Click the button above to set `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: relative`), ` on the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<blockquote>`), ` (or edit the CSS directly!) Now without changing the styling of the span with the quote mark, it moved from the top left of the page to the top left of the blockquote. and that's because we made the blockquote an offset parent.`), mdx(\"h3\", {\n    \"id\": \"how-to-find-the-offset-parent\"\n  }, `How to find the offset parent`), mdx(\"p\", null, `For a given element, how do you find the offset parent? You could open the element inspector and go through all ancestors to see which one has a position other than `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `static`), ` set, but browsers also have a built-in way to find the offset parent: the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `offsetParent`), ` property on the element in JavaScript. This property returns the offset parent of an element, or null if there is none.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"js\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-js\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), `const`), ` offsetParent `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), `=`), ` element`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `.`), `offsetParent`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`)))), mdx(\"p\", null, `But selecting an element, switching over to the console tab and typing that in each time is also a bit cumbersome.`), mdx(\"p\", null, `There's a much easier way to find the offset parent: the `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"/docs/elements-panel/#debug\"\n  }), `'debug' tab`), ` in the Polypane Elements panel. This tab shows you the offset parent of the currently selected element, you can hover it to highlight it in the page and by clicking it the elements panel immediately jumps to it so you can edit it, in sync across all the panes in your tab.`), mdx(\"img\", {\n    alt: \"Element debug panel with an arrow pointing to the offset parent\",\n    src: offsetpanel1,\n    className: \"imgshadow\",\n    style: {\n      margin: '1rem auto 1rem',\n      display: 'block',\n      maxWidth: '100%'\n    }\n  }), mdx(\"p\", null, `Now that you know about the offset parent and how to quickly find it, debugging positioning issues becomes a lot easier as you'll always know what an element is positioned relative to. But there's more to positioning than just the offset parent. Let's look at the other dimension: the z-axis.`), mdx(\"h2\", {\n    \"id\": \"stacking-context\"\n  }, `Stacking context`), mdx(\"p\", null, `Where offset parents tell you how an element is positioned in the x and y direction, the stacking context tells you how it gets positioned in the third dimension: how close it is towards the front of the screen.`), mdx(\"p\", null, `You'll have encountered stacking context before when you used `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` to position elements on top of each other and two elements not responding to `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` the way you think they should. That's because they were in different stacking contexts: regardless of how high or low your z-index is, it's only relative to other elements in the same stacking context.`), mdx(\"h3\", {\n    \"id\": \"what-is-a-stacking-context\"\n  }, `What is a stacking context?`), mdx(\"p\", null, `When you create a new stacking context, all the elements inside that stacking context will be positioned on the z-axis relative to each other, initially in source order (they have an implied value of 0, or auto). This is helpful because it means that you can position elements on top of each other without having to worry about other elements on the page, and lets you \"group\" elements together. The element that you create the stacking context on is called the stacking context parent.`), mdx(\"p\", null, `In other words, stacking only happens within the context. There's no way to break out of it. In fact, you could look at z-indexes the same as `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://polypane.app/css-specificity-calculator/\"\n  }), `CSS specificity`), `: No matter how high your z-index is, any stacking context with a higher z-index will always be on top of the stacking context with a lower z-index and all elements inside it.`), mdx(\"p\", null, `Suppose you have this DOM tree:`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Stacking context 1: `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index: 1`), mdx(\"ul\", {\n    parentName: \"li\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Element 1: `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index: 10`)))), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Stacking context 2: `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index: 2`), mdx(\"ul\", {\n    parentName: \"li\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Element 2: `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index: 5`))))), mdx(\"p\", null, `Then despite Element 1 having a higher z-index than Element 2, it's still below it, because the z-indexes behave like specificity. The 'real' z-index of Element 1 is (1,10) while that of Element 2 is (2,5). Because the z-index of stacking context 2 is higher, it and Element 2 are still on top.`), mdx(\"h3\", {\n    \"id\": \"creating-a-stacking-context\"\n  }, `Creating a stacking context`), mdx(\"p\", null, `Unlike offset parents, the default context is not the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `body`), `, but the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `html`), ` element. Also unlike offset parents, which only get set with a `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position`), ` other than `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `static`), `, there are many different properties that can each create a new stacking context:`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position`), ` of `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `fixed`), ` or `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `sticky`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` other than `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `auto`), ` (with a `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position`), ` other than `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `static`), ` or when in a flex or grid layout)`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `opacity`), ` less than 1`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mix-blend-mode`), ` other than normal`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `filter`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `backdrop-filter`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `transform`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `perspective`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `clip-path`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mask`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mask-image`), ` or `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mask-box-image`), ` other than none`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `isolation`), ` set to `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `isolate`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `container-type`), ` set to `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `size`), ` or `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `inline-size`), ` (so any container element)`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `will-change`), ` property set to `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mix-blend-mode`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `filter`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `transform`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `perspective`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `clip-path`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mask`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mask-image`), ` or `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mask-box-image`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `contain`), ` set to `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `layout`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `paint`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `strict`), ` or `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `content`))), mdx(\"p\", null, `That's quite a list! But it's not as bad as it looks. Most of these properties are not used very often, and the ones that are used often are `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position`), `, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `opacity`), `. So if you're having trouble with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` not working, check if the elements are in the same stacking context.`), mdx(\"p\", null, `If you want to be more explicit in creating a stacking context, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `isolation: isolate`), ` is the most explicit one. It also isolates other things, like `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `mix-blend-mode`), `, which means it doesn't interact with elements outside of the stacking context, but that's not likely a change that will affect your design.`), mdx(\"h3\", {\n    \"id\": \"an-example-1\"\n  }, `An example`), mdx(\"p\", null, `Lets look at an example. We're building on the previous example. If you look at the previous example you can see that the quote sits on top of the text, obscuring it.`), mdx(\"p\", null, `We want to move it behind the blockquote and we can do this by setting a negative `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` on the blockquote (step 1). When we do that however, we can see that it disappears, because it's now behind the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `div.parent`), ` element as well.`), mdx(\"p\", null, `The stacking context of the blockquote is the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `html`), ` element, so a negative z-index will place it at the beginning of that stacking context, which is behind the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `div.parent`), ` element.`), mdx(StackingExample, {\n    mdxType: \"StackingExample\"\n  }), mdx(\"p\", null, `To keep the quote behind the text but in front of the background, we can add `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `isolation: isolate`), ` to `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `.parent`), ` (step 2).`), mdx(\"p\", null, `This will make `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `.parent`), ` a new stacking context, so `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index: -1`), ` will only place the quote behind all elements `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `within`), ` that stacking context or in our case, only behind the text.`), mdx(\"h3\", {\n    \"id\": \"how-to-find-the-stacking-context-parent\"\n  }, `How to find the stacking context parent`), mdx(\"p\", null, `Unfortunately, there is no `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `element.stackingContextParent`), ` property in JavaScript, so you can't find the stacking context parent with JavaScript as easily as you can find the offset parent. You'll have to check parent elements for each of the properties listed above to see if an element is in a specific stacking context.`), mdx(\"p\", null, `Instead of that, the `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"/docs/elements-panel/#debug\"\n  }), `'debug' tab`), ` in the Polypane Elements panel shows you two bits of information:`), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, `If the current element creates a new stacking context`), mdx(\"li\", {\n    parentName: \"ol\"\n  }, `What stacking context the current element is in`)), mdx(\"img\", {\n    alt: \"Element debug panel with an arrow pointing to the stacking context parent\",\n    src: offsetpanel2,\n    className: \"imgshadow\",\n    style: {\n      margin: '1rem auto 1rem',\n      display: 'block',\n      maxWidth: '100%'\n    }\n  }), mdx(\"p\", null, `Like the offset parent you can hover the stacking context parent to highlight it in the page and by clicking it the elements panel immediately jumps to it so you can edit it, in sync across all the panes in your tab.`), mdx(\"h2\", {\n    \"id\": \"conclusion\"\n  }, `Conclusion`), mdx(\"p\", null, `Offset parents and stacking context are two important concepts in CSS positioning. They can be a bit confusing at first, but once you understand them they can help you debug positioning issues (in all three dimensions much faster. The Elements panel in Polypane makes it easy to find them both so you can immediately inspect and fix the issues as you work.`), mdx(\"h2\", {\n    \"id\": \"want-more\"\n  }, `Want more?`), mdx(\"p\", null, `If you want to learn even more, check out our full guide on `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://polypane.app/blog/understanding-the-fundamentals-of-css-layout/\"\n  }), `Understanding the fundamentals of CSS Layout`), `. It also covers offsetParent and stacking context, but goes much deeper into other layout concepts like block and inline, normal flow, flex and grid.`));\n}\n;\nMDXContent.isMDXComponent = true;","timeToRead":6,"tableOfContents":{"items":[{"url":"#prefer-video","title":"Prefer video?"},{"url":"#offset-parent","title":"Offset parent","items":[{"url":"#an-example","title":"An example"},{"url":"#how-to-find-the-offset-parent","title":"How to find the offset parent"}]},{"url":"#stacking-context","title":"Stacking context","items":[{"url":"#what-is-a-stacking-context","title":"What is a stacking context?"},{"url":"#creating-a-stacking-context","title":"Creating a stacking context"},{"url":"#an-example-1","title":"An example"},{"url":"#how-to-find-the-stacking-context-parent","title":"How to find the stacking context parent"}]},{"url":"#conclusion","title":"Conclusion"},{"url":"#want-more","title":"Want more?"}]},"excerpt":"They are fundamental CSS concepts you use every single day whether you know it or not: the  offset parent  and  stacking context . In this article we'll explore…","frontmatter":{"title":"Offset parent and stacking context: positioning elements in all three dimensions","cover":"/blogs/offset/cover.svg","date":"2023-07-06","updated":"2023-08-16"},"fields":{"slug":"/blog/offset-parent-and-stacking-context-positioning-elements-in-all-three-dimensions/","date":"2023-07-05T22:00:00.000Z","ogFileName":"offset-parent-and-stacking-context-positioning-elements-in-all-three-dimensions"}}},"pageContext":{"slug":"/blog/offset-parent-and-stacking-context-positioning-elements-in-all-three-dimensions/"}},"staticQueryHashes":["4164364741","425175329"]}