{"componentChunkName":"component---src-templates-post-jsx","path":"/blog/understanding-the-fundamentals-of-css-layout/","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\": \"Understanding the fundamentals of CSS Layout\",\n  \"cover\": \"/blogs/complete/web_development__isometric.svg\",\n  \"date\": \"2026-01-22\",\n  \"type\": [\"reference\", \"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, `When developers say that CSS is hard, they're usually talking about CSS layout. What often gets omitted though is that developers are assumed to understand and effectively use CSS without being taught how it works in the first place.`), mdx(\"p\", null, `I think this is because the syntax of CSS is simple, especially compared to JavaScript and even to HTML.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `select-thing-here`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `guess-a-property`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` give-it-a-value`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token comment\"\n  }), `/* ...and repeat */`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"p\", null, `It leads to the impression that all you need to write CSS is to understand the syntax and have a reference for the properties and values.`), mdx(\"p\", null, `That, of course, is not true.`), mdx(\"p\", null, `Imagine if you were assumed to learn JS by just looking at its syntax. How would you ever learn what `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `this`), ` refers to, or how closures work, or how prototypal inheritance works? It would make no sense!`), mdx(\"p\", null, `CSS is no less deserving of understanding its underlying concepts, so let's build that foundation.`), mdx(\"h2\", {\n    \"id\": \"prefer-video\"\n  }, `Prefer video?`), mdx(\"p\", null, `This article is a written version of a talk by Kilian Valkhof, Polypane's creator. You can watch the video 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(\"iframe\", _extends({\n    parentName: \"div\"\n  }, {\n    \"src\": \"https://www.youtube.com/embed/Al4yGtRYyew\",\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(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, `Interested in having this talk at your conference or meetup? `, mdx(\"a\", _extends({\n    parentName: \"em\"\n  }, {\n    \"href\": \"https://kilianvalkhof.com/speaking/\"\n  }), `Get in touch!`))), mdx(\"h2\", {\n    \"id\": \"galls-law\"\n  }, `Gall's law`), mdx(\"p\", null, `When you look at CSS as a whole, it's a complex system that is hard to understand. But it's also a system that works.`), mdx(\"p\", null, `We have a programming principle that covers that:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `All complex systems that work, evolved from simple systems that worked.`)), mdx(\"p\", null, `This is known as Gall's law, and it applies to CSS layout as well. At its core, CSS layout is built on a few fundamental concepts that work together to create the complex layouts we see on the web today.`), mdx(\"p\", null, `CSS Layout started out with a single layout algorithm called `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `normal flow`), `.`), mdx(\"p\", null, `Normal flow has a few basic rules, which all subsequent layout algorithms built upon. Indeed, that's the first lesson:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `CSS has `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `multiple`), ` layout algorithms.`)), mdx(\"p\", null, `Specific properties in CSS let you opt into different layout algorithms, each with their own rules and behaviors.`), mdx(\"p\", null, `Once you understand the foundation of normal flow, you can start to understand how other layout algorithms like positioning, Flexbox, and Grid build upon it.`), mdx(\"p\", null, `In other words, this article will help you go from this:`), mdx(\"img\", {\n    \"src\": \"/blogs/csslayout/cssbad.gif\",\n    \"alt\": \"\",\n    \"className\": \"imgshadow\"\n  }), mdx(\"p\", null, `…`, `to this:`), mdx(\"img\", {\n    \"src\": \"/blogs/csslayout/cssgood.gif\",\n    \"alt\": \"\",\n    \"className\": \"imgshadow\"\n  }), mdx(\"p\", null, `Are you ready?`), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"width\": \"200px\",\n      \"height\": \"200px\",\n      \"margin\": \"2rem auto\"\n    }\n  }), mdx(\"h2\", {\n    \"id\": \"everything-is-a-box\"\n  }, `Everything is a box`), mdx(\"p\", null, `The most fundamental concept in CSS is that `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `everything is a box`), `. Every element creates a rectangular box, and the x and y position of the box, along with it's width and height create the combined layout on the page.`), mdx(\"p\", null, `CSS is:`), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, `A bunch of boxes,`), mdx(\"li\", {\n    parentName: \"ol\"\n  }, `placed on the screen,`), mdx(\"li\", {\n    parentName: \"ol\"\n  }, `according to layout algorithms.`)), mdx(\"p\", null, `This might seem like an obvious statement, but it's important to understand: before screens became ubiquitous, the idea of a \"live\" layout algorithm wasn't really needed. Boxes didn't interact with each other. They were put in a place and then just ...stayed there.`), mdx(\"p\", null, `Print pages are `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `laid out`), ` of course, and have been for centuries, but that didn't really happen in real time by a system of rules, an algorithm.`), mdx(\"p\", null, `So, CSS is a bunch of boxes. The initial layout algorithm that places them on the screen is:`), mdx(\"h2\", {\n    \"id\": \"normal-flow\"\n  }, `Normal flow`), mdx(\"p\", null, `Normal flow is the default layout algorithm in CSS. It's what you get when you don't explicitly opt into any other layout algorithm.`), mdx(\"p\", null, `It comes from when the web was made for document sharing, and \"normal flow\" refers to the way text flows across a page: `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `from left to right, from top to bottom`), ` (for western languages).`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token comment\"\n  }), `/* Normal flow is the default - no CSS needed! */`)))), mdx(\"p\", null, `From left to right is the `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `inline`), ` direction, from top to bottom is the `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `block`), ` direction. So text\ncharacters will be inline, side by side, and wrap to the next line. Paragraphs and headings are block, and they stack vertically.`), mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"border\": \"5px solid dodgerblue\",\n      \"width\": \"200px\",\n      \"height\": \"180px\",\n      \"paddingLeft\": \"0.5rem\"\n    }\n  }, mdx(\"p\", {\n    style: {\n      \"fontSize\": \"2rem\"\n    }\n  }, \"Inline \\u2192\"), mdx(\"p\", {\n    style: {\n      \"fontSize\": \"2rem\",\n      \"transformOrigin\": \"0 0\",\n      \"transform\": \"rotate(90deg)\",\n      \"position\": \"absolute\",\n      \"left\": \"-5%\",\n      \"top\": \"0\",\n      \"whiteSpace\": \"nowrap\"\n    }\n  }, \"Block \\u2192\")), mdx(\"p\", null, `Browsers ship with a default stylesheet that dictates which elements are block and which are inline: `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<p>`), ` is block, but `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<em>`), ` is inline.`), mdx(\"p\", null, `So that's why, if you write semantic HTML, the browser already makes your page look like a document.`), mdx(\"h3\", {\n    \"id\": \"non-western-languages\"\n  }, `Non-western languages`), mdx(\"p\", null, `Not all languages are written left to right, top to bottom. Some languages are written right to left (like Arabic and Hebrew), and some are written top to bottom (like traditional Chinese and Japanese).`), mdx(\"p\", null, `This is why CSS has a `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `writing-mode`), ` property that lets you change the inline and block directions to fit the language you're using.`), mdx(\"p\", null, `Along with that writing mode, many of the explicit directional and sizing properties, like \"left\" or \"height\" now have logical equivalents. Instead of `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `left`), `, which for western languages is the start of inline text, the property name is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `inset-inline-start`), `. Instead of `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `height`), `, which is the size in the block direction, the property name is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `block-size`), `.`), mdx(\"p\", null, `Writing CSS with these logical properties makes them more portable. For this article though, we'll stick to the physical properties like `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `left`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `width`), ` for simplicity.`), mdx(\"h3\", {\n    \"id\": \"formatting-context-and-anonymous-boxes\"\n  }, `Formatting context and anonymous boxes`), mdx(\"p\", null, `Block and inline tell you how a given element lays out in comparison to the elements around it. This state of being block or inline is called the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `formatting context`), `, and each element has a formatting context.`), mdx(\"p\", null, `But not everything is an element. Consider this HTML:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"html\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `p`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `This is `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `em`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `emphasized`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `em`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `p`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`))))), mdx(\"p\", null, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<p>`), ` is a block element and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<em>`), ` is inline.`), mdx(\"p\", null, `But what about the words \"This is\"? How does that work?`), mdx(\"p\", null, `Earlier I wrote that in CSS, everything is a box, and that's also how normal flow solves this. The browser creates something called an `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `anonymous box`), ` around that text. In this case because `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<em>`), ` is an inline box, the anonymous box will also be inline: it will be an `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `anonymous inline box`), `.`), mdx(\"div\", {\n    className: \"gatsby-highlight\"\n  }, mdx(\"pre\", {\n    className: \"language-html\"\n  }, \"<p>\", mdx(\"span\", {\n    style: {\n      \"border\": \"2px solid hotpink\"\n    }\n  }, \"This is \"), \"<em>emphasized</em></p>\")), mdx(\"p\", null, `With that, the browsers now has two inline boxes, and it knows what do to with that. It can lay them out next to each other.`), mdx(\"p\", null, `If the code was this though:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"html\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  This is\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `p`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `a new paragraph`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `p`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`))))), mdx(\"p\", null, `Both the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<div>`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<p>`), ` are block-level, so the anonymous box generated for \"This is\" will be an `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `anonymous `, mdx(\"strong\", {\n    parentName: \"em\"\n  }, `block`), ` box`), `, and the browser can lay out the two boxes on top of each other:`), mdx(\"div\", {\n    className: \"gatsby-highlight\"\n  }, mdx(\"pre\", {\n    className: \"language-html\"\n  }, \"<div>\", mdx(\"br\", null), mdx(\"div\", {\n    style: {\n      \"border\": \"2px solid hotpink\"\n    }\n  }, \"\\xA0\\xA0This is\"), mdx(\"div\", {\n    style: {}\n  }, \"\\xA0\\xA0<p>a new paragraph</p>\"), \"</div>\")), mdx(\"h3\", {\n    \"id\": \"whitespace-and-anonymous-boxes\"\n  }, `Whitespace and anonymous boxes`), mdx(\"p\", null, `This anonymous box generation is why some things you might expect to work don't. Take this example.`), mdx(AnonymousBoxExample, {\n    mdxType: \"AnonymousBoxExample\"\n  }), mdx(\"p\", null, `Both divs are 50% wide, but they don't sit on the same line. Even though 50% + 50% is 100%.`), mdx(\"p\", null, `This is caused by an anonymous inline box created by the newline, the whitespace, between the two divs. That inline box takes up space (the width of a single space character) to the right of the first div, and so the second div no longer fits on the same line:`), mdx(\"div\", {\n    className: \"anomymous-example\"\n  }, mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"hotpink\"\n    }\n  }, \"First\"), mdx(\"div\", {\n    className: \"anonymousbox\"\n  }, \"\\xA0\"), mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"dodgerblue\"\n    }\n  }, \"Second\")), mdx(\"p\", null, `It would be great if we can select that anonymous box and hide it but unfortunately that's not something we can do with CSS.`), mdx(\"p\", null, `We can only target named boxes.`), mdx(\"h4\", {\n    \"id\": \"solving-the-whitespace-issue\"\n  }, `Solving the whitespace issue`), mdx(\"p\", null, `We can solve this whitespace problem in several ways:`), mdx(\"h5\", {\n    \"id\": \"remove-the-whitespace\"\n  }, `Remove the whitespace`), mdx(\"p\", null, `Remove the character space between the two `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `div`), `s, and the anonymous box is never created (...until you run `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `prettier`), ` on your code).`), mdx(\"div\", {\n    className: \"gatsby-highlight\"\n  }, mdx(\"pre\", {\n    className: \"language-html\"\n  }, \"<div>\", mdx(\"br\", null), \"\\xA0\\xA0<div class=\\\"half\\\">\", mdx(\"br\", null), \"\\xA0\\xA0</div><div class=\\\"half\\\">\", mdx(\"br\", null), \"\\xA0\\xA0</div>\", mdx(\"br\", null), \"</div>\")), mdx(\"div\", {\n    className: \"anomymous-example\"\n  }, mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"hotpink\"\n    }\n  }, \"First\"), mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"dodgerblue\"\n    }\n  }, \"Second\")), mdx(\"h5\", {\n    \"id\": \"disable-wrapping\"\n  }, `Disable wrapping`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.container`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `white-space`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` nowrap`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    className: \"anomymous-example\",\n    style: {\n      \"whiteSpace\": \"nowrap\",\n      \"border\": \"2px solid black\"\n    }\n  }, mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"hotpink\"\n    }\n  }, \"First\"), mdx(\"span\", null, \"\\xA0\"), mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"dodgerblue\"\n    }\n  }, \"Second\")), mdx(\"p\", null, `When you disable wrapping, you force both `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `div`), `s on the same line regardless of the width of the container. Notice that there is still that space between the two `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `div`), `s, they don't sit flush against each other and that the second `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `div`), ` overflows the container.`), mdx(\"p\", null, `Since the total width is still 50% + the width of a space character + 50%, the second `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `div`), ` overflows the container.`), mdx(\"h5\", {\n    \"id\": \"set-the-font-size-to-0\"\n  }, `Set the font-size to 0`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.container`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `font-size`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.container > div`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `font-size`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 16px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token comment\"\n  }), `/* Reset for children */`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    className: \"anomymous-example\",\n    style: {\n      \"fontSize\": \"0\"\n    }\n  }, mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"hotpink\",\n      \"fontSize\": \"16px\"\n    }\n  }, \"First\"), mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"dodgerblue\",\n      \"fontSize\": \"16px\"\n    }\n  }, \"Second\")), mdx(\"p\", null, `If you set the font-size of the parent to 0, the anonymous box will still be created, but it won't have any width since the width of a space at font-size 0 is 0.`), mdx(\"p\", null, `If your child elements have text in them, you will need to reset the font size in them or your text won't show up either.`), mdx(\"h5\", {\n    \"id\": \"white-space-collapse-discard-in-the-future\"\n  }, `White-space-collapse: discard (in the future!)`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.container`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `white-space-collapse`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` discard`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"whiteSpaceCollapse\": \"discard\"\n    }\n  }, mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"hotpink\"\n    }\n  }, \"First\"), ' ', mdx(\"div\", {\n    className: \"half\",\n    style: {\n      \"background\": \"dodgerblue\"\n    }\n  }, \"Second\")), mdx(\"p\", null, `To show you how much CSS is still being worked on, white-space-collapse\nis part of the newest CSS specification, text level 4.`), mdx(\"p\", null, `The value we mention above, 'discard', isn't even supported in any browser as of January 2026. So this is a feature for the future and doesn't work yet.`), mdx(\"p\", null, `Even normal flow, which has been around since `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `literally the beginning of CSS`), `, is\nstill being worked on!`), mdx(\"h3\", {\n    \"id\": \"the-box-model\"\n  }, `The box model`), mdx(\"p\", null, `We're not done talking about boxes interact by a long shot, but for the next few concepts we need to understand how boxes themselves are built up. For that we need to talk about the box model.`), mdx(\"p\", null, `You have probably seen a version of this diagram before. A box in CSS actually\nconsists of a few distinct areas.`), mdx(\"p\", null, `The center area is where you content is, the text or child elements. This content is pushed inwards by the padding. The edge of a box is called the border, and outside of the border is the margin which pushes a box away from other boxes.`), mdx(\"div\", {\n    className: \"boxmodel\"\n  }, \"margin\", mdx(\"div\", null, \"border\", mdx(\"div\", null, \"padding\", mdx(\"div\", null, \"content\")))), mdx(\"p\", null, `For stupid browser reasons there are two models when it comes to determining the size of a box when you\ngive it a width: `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `content-box`), ` and `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `border-box`), `.`), mdx(\"p\", null, `One of those is the default in browsers, and the other one\nmakes sense.`), mdx(\"h4\", {\n    \"id\": \"content-box\"\n  }, `Content-box`), mdx(\"p\", null, `The default is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `content-box`), `. In that model, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `width`), ` is applied to the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `content-box`), `, and padding and borders are added to it for the final rendered width.`), mdx(\"div\", {\n    className: \"boxmodel\"\n  }, \"margin\", mdx(\"div\", null, \"border\", mdx(\"div\", null, \"padding\", mdx(\"div\", {\n    style: {\n      \"border\": \"2px solid red\"\n    }\n  }, \"content\")))), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-text\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-text\"\n  }), `Actual width = width + padding + border`))), mdx(\"p\", null, `This is confusing because when you set `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `width: 200px`), `, the actual rendered width might be 250px after padding and borders.`), mdx(\"h4\", {\n    \"id\": \"border-box\"\n  }, `Border-box`), mdx(\"p\", null, `To improve this situation, most modern CSS resets include the following CSS`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `*`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `box-sizing`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` border-box`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"p\", null, `With `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `border-box`), `, the width you set is applied to the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `border-box`), ` of the element, so it `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `includes`), ` the border and padding layers. The space for the content is width minus padding minus border.`), mdx(\"div\", {\n    className: \"boxmodel\"\n  }, \"margin\", mdx(\"div\", {\n    style: {\n      \"border\": \"2px solid red\"\n    }\n  }, \"border\", mdx(\"div\", null, \"padding\", mdx(\"div\", null, \"content\")))), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-text\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-text\"\n  }), `Actual width = width`))), mdx(\"p\", null, `This means that when you see `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `width: 200px`), ` in your CSS, you know the element is actually 200px wide regardless of the padding and border. It's much easier to work with.`), mdx(\"p\", null, `Try editing the values in the example below to see how `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `content-box`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `border-box`), ` differ. Notice that both boxes have the same width value (200px), but the content-box is physically larger because padding and borders are added outside the content width.`), mdx(BoxModelExample, {\n    mdxType: \"BoxModelExample\"\n  }), mdx(\"p\", null, `With this understanding of the box model, we can go back to talking about how boxes interact.`), mdx(\"h3\", {\n    \"id\": \"how-inline-boxes-work\"\n  }, `How inline boxes work`), mdx(\"p\", null, `Everything in CSS is a box, but \"box\" isn't always what you expect.`), mdx(\"p\", null, `A block box makes sense: the element is a rectangle, and the border sits on all edges.`), mdx(\"div\", {\n    className: \"box\",\n    \"aria-hidden\": \"true\",\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"border\": \"5px solid dodgerblue\",\n      \"display\": \"block\",\n      \"width\": \"50%\",\n      \"color\": \"transparent\",\n      \"lineHeight\": \"4\",\n      \"fontSize\": \"20px\"\n    }\n  }, \"gr gerg dg dsgf d gzrg gr drg xesrg es\"), mdx(\"p\", null, `But inline elements can wrap to the next line without becoming a block element, and so the box around an inline element is split up and looks, well, kind of broken:`), mdx(\"div\", {\n    className: \"fragment\",\n    style: {\n      \"textAlign\": \"center\",\n      \"width\": \"50%\",\n      \"margin\": \"1rem auto\",\n      \"lineHeight\": \"4\"\n    }\n  }, mdx(\"span\", {\n    className: \"box\",\n    style: {\n      \"color\": \"transparent\",\n      \"padding\": \"10px\",\n      \"border\": \"5px solid dodgerblue\",\n      \"textAlign\": \"center\"\n    },\n    \"aria-hidden\": \"true\"\n  }, \"gr gerg dg dsgf d gzrg gr drg xesrg es gr gerg dg dsgf d gzrg gr drg xesrg es gr gerg dg dsgf d gzrg gr drg xesrg es r gerg dg dsgf d gzrg gr drg xesrg es\")), mdx(\"p\", null, `The top and bottom borders are drawn for each line the element spans, while the inline borders and padding (left and right) are only drawn at the very start and very end.`), mdx(\"p\", null, `That looks really broken, doesn't it? Browsers render an inline element as one, long, single line (it's inline after all), and then they slice that up into different line segments where it wraps. Thinking about it in that way makes it a bit easier to visualize what is happening and why it's happening. The box is sliced up into different parts.`), mdx(\"h4\", {\n    \"id\": \"decorations\"\n  }, `Decorations`), mdx(\"p\", null, `If you have \"decorations\" (which is what borders and padding are called) on an inline element, you probably expect those to be applied to each line segment.`), mdx(\"p\", null, `Luckily, we can tell browsers how to treat each broken-up line with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `box-decoration-break`), `. The default value is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `slice`), `, which is quite literally slicing up the box into different parts.`), mdx(\"p\", null, `But you can also tell the browser to treat each line as its own box with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `clone`), `. Each line becomes its own box with borders and padding on all sides.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `span`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `box-decoration-break`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` clone`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    className: \"fragment\",\n    style: {\n      \"textAlign\": \"center\",\n      \"width\": \"50%\",\n      \"margin\": \"1rem auto\",\n      \"lineHeight\": \"4\"\n    }\n  }, mdx(\"span\", {\n    className: \"box\",\n    style: {\n      \"color\": \"transparent\",\n      \"padding\": \"10px\",\n      \"border\": \"5px solid dodgerblue\",\n      \"boxDecorationBreak\": \"clone\",\n      \"textAlign\": \"center\"\n    },\n    \"aria-hidden\": \"true\"\n  }, \"gr gerg dg dsgf d gzrg gr drg xesrg es gr gerg dg dsgf d gzrg gr drg xesrg es gr gerg dg dsgf d gzrg gr drg xesrg es r gerg dg dsgf d gzrg gr drg xesrg es\")), mdx(\"h4\", {\n    \"id\": \"placement-of-inline-elements\"\n  }, `Placement of inline elements`), mdx(\"p\", null, `Some things like vertical margins, explicit widths and height don't apply to inline elements. This is because when an element is \"in line\", it's placement on the page is determined by the line it's in. So we know text is \"in line\", but what's a line?`), mdx(\"h3\", {\n    \"id\": \"lines-and-baselines\"\n  }, `Lines and baselines`), mdx(\"p\", null, `Browsers started out as a way to lay out lines of text. The inline text inside a box is laid out in a number of `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `lines`), `, and these lines are laid out based on the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `line-height`), `:`), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"margin\": \"2rem 0\",\n      \"textAlign\": \"left\",\n      \"position\": \"relative\",\n      \"fontSize\": \"5rem\",\n      \"fontWeight\": \"bold\",\n      \"lineHeight\": \"1.5\",\n      \"overflow\": \"hidden\"\n    }\n  }, \"What are lines in browsers?\", mdx(\"div\", {\n    className: \"fragment\",\n    style: {\n      \"background\": \"dodgerblue\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"50%\"\n    }\n  })), mdx(\"p\", null, `Within each of these lines there is a `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `baseline`), `. The baseline is determined by the font you use, and it's the bottom of your text characters (except for descenders, which go below the baseline).`), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"margin\": \"2rem 0\",\n      \"textAlign\": \"left\",\n      \"position\": \"relative\",\n      \"fontSize\": \"5rem\",\n      \"fontWeight\": \"bold\",\n      \"lineHeight\": \"1.5\",\n      \"overflow\": \"hidden\"\n    }\n  }, \"What are lines in browsers?\", mdx(\"div\", {\n    style: {\n      \"background\": \"grey\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"50%\",\n      \"opacity\": \"0.5\"\n    }\n  }), mdx(\"div\", {\n    className: \"fragment\"\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"dodgerblue\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"37%\"\n    }\n  }), mdx(\"div\", {\n    style: {\n      \"background\": \"dodgerblue\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"87%\"\n    }\n  }))), mdx(\"p\", null, `What you should understand here is that:`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Inline elements are laid out in lines`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Each line has a baseline`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `The baseline is determined by the font`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `All inline elements align with the baseline `, mdx(\"em\", {\n    parentName: \"li\"\n  }, `by default`), `.`)), mdx(\"p\", null, `IF you want your text to be in a different place (vertically) in the line, you can change the vertical alignment of an inline element with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `vertical-align`), `.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `span`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `vertical-align`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` baseline`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token comment\"\n  }), `/* default */`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `vertical-align`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` top`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `vertical-align`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` middle`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `vertical-align`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` bottom`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `vertical-align`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` text-top`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `vertical-align`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` text-bottom`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"p\", null, `The `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `top`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `bottom`), ` values are determined by the line height you set on the element:`), mdx(\"div\", {\n    style: {\n      \"overflow\": \"auto\",\n      \"display\": \"block\",\n      \"lineHeight\": \"2\",\n      \"border\": \"5px solid dodgerblue\",\n      \"margin\": \"2rem\",\n      \"textAlign\": \"center\",\n      \"position\": \"relative\",\n      \"fontSize\": \"4rem\",\n      \"fontWeight\": \"bold\"\n    }\n  }, mdx(\"span\", {\n    style: {\n      \"verticalAlign\": \"top\",\n      \"fontSize\": \"0.8em\",\n      \"lineHeight\": \"1\"\n    }\n  }, \"top\"), \"Baseline\", mdx(\"span\", {\n    style: {\n      \"verticalAlign\": \"bottom\",\n      \"fontSize\": \"0.8em\",\n      \"lineHeight\": \"1\"\n    }\n  }, \"bottom\"), mdx(\"div\", {\n    style: {\n      \"background\": \"dodgerblue\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"68%\"\n    }\n  })), mdx(\"p\", null, `The `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `text-top`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `text-bottom`), ` are determined by the font. Text-top will align the x-height with the top of ascenders (the parts of letters like b, d, f, h that extend above the x-height), and text-bottom will align the bottom of normal letters with the bottom of descenders.`), mdx(\"div\", {\n    style: {\n      \"display\": \"block\",\n      \"lineHeight\": \"2\",\n      \"border\": \"5px solid dodgerblue\",\n      \"margin\": \"2rem\",\n      \"textAlign\": \"center\",\n      \"position\": \"relative\",\n      \"fontSize\": \"4rem\",\n      \"fontWeight\": \"bold\",\n      \"overflow\": \"hidden\"\n    }\n  }, mdx(\"span\", {\n    style: {\n      \"verticalAlign\": \"text-top\",\n      \"fontSize\": \"0.8em\",\n      \"lineHeight\": \"1\"\n    }\n  }, \"text-top\"), \"Baseline\", mdx(\"span\", {\n    style: {\n      \"verticalAlign\": \"text-bottom\",\n      \"fontSize\": \"0.8em\",\n      \"lineHeight\": \"1\"\n    }\n  }, \"text-bottom\"), mdx(\"div\", {\n    style: {\n      \"background\": \"dodgerblue\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"68%\"\n    }\n  })), mdx(\"p\", null, `Lastly, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `middle`), ` is weird.`), mdx(\"p\", null, `It's calculated from a combination of the font metrics and the line-height, and that causes it to not always mean the exact middle of the line:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `middle = baseline + (x-height / 2)`)), mdx(\"p\", null, `In the example below, you can see that the word \"middle\" is actually closer to the bottom of the line than to the top.`), mdx(\"div\", {\n    style: {\n      \"display\": \"block\",\n      \"lineHeight\": \"2\",\n      \"border\": \"5px solid dodgerblue\",\n      \"margin\": \"2rem\",\n      \"textAlign\": \"center\",\n      \"position\": \"relative\",\n      \"fontSize\": \"5rem\",\n      \"fontWeight\": \"bold\",\n      \"overflow\": \"hidden\"\n    }\n  }, \"Baseline \", mdx(\"span\", {\n    style: {\n      \"verticalAlign\": \"middle\"\n    }\n  }, \"middle\"), mdx(\"div\", {\n    style: {\n      \"background\": \"grey\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"66%\"\n    }\n  }), mdx(\"div\", {\n    style: {\n      \"background\": \"dodgerblue\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"33%\"\n    }\n  }), mdx(\"div\", {\n    style: {\n      \"background\": \"dodgerblue\",\n      \"height\": \"1px\",\n      \"width\": \"100%\",\n      \"position\": \"absolute\",\n      \"right\": \"0\",\n      \"left\": \"0\",\n      \"top\": \"70%\"\n    }\n  })), mdx(\"p\", null, `I'd like to apologize for that on behalf of CSS.`), mdx(\"p\", null, `For practical purposes, just know it exists but might not behave exactly as you expect.`), mdx(\"p\", null, `From the explanation above, what you need to remember is that, by default, `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `all`), ` inline elements sit on the baseline.`), mdx(\"h4\", {\n    \"id\": \"inline-elements-sit-on-the-baseline\"\n  }, `Inline elements sit on the baseline`), mdx(\"p\", null, `With that knowledge, does the following situation already make sense?`), mdx(\"div\", {\n    style: {\n      \"display\": \"block\",\n      \"border\": \"5px solid dodgerblue\",\n      \"position\": \"relative\",\n      \"margin\": \"2rem 0\",\n      \"textAlign\": \"center\"\n    }\n  }, mdx(\"img\", {\n    src: \"/blogs/csslayout/kitten.jpg\",\n    style: {\n      \"width\": \"200px\",\n      \"padding\": \"0\",\n      \"margin\": \"0\",\n      \"display\": \"inline\"\n    }\n  })), mdx(\"p\", null, `If you now find this obvious, then good job! The inline image is sitting on the baseline, and that's why there is 'unexpected' whitespace below it.`), mdx(\"p\", null, `In the past, you might have fixed that by setting `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: block`), ` on the image, but this has other layout effects too:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `img`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `display`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` block`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"display\": \"block\",\n      \"border\": \"5px solid dodgerblue\",\n      \"position\": \"relative\",\n      \"margin\": \"2rem 0\",\n      \"textAlign\": \"center\"\n    }\n  }, mdx(\"img\", {\n    src: \"/blogs/csslayout/kitten.jpg\",\n    style: {\n      \"width\": \"200px\",\n      \"padding\": \"0\",\n      \"margin\": \"0\",\n      \"display\": \"block\"\n    }\n  })), mdx(\"p\", null, `The whitespace is gone, but the image now also no longer sits inline with any text, nor does it follow the text align.`), mdx(\"p\", null, `Another way you could have fixed this is by setting `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `line-height: 0`), ` on the parent:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `div`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `line-height`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"display\": \"block\",\n      \"border\": \"5px solid dodgerblue\",\n      \"position\": \"relative\",\n      \"margin\": \"2rem 0\",\n      \"textAlign\": \"center\",\n      \"lineHeight\": \"0\"\n    }\n  }, mdx(\"img\", {\n    src: \"/blogs/csslayout/kitten.jpg\",\n    style: {\n      \"width\": \"200px\",\n      \"padding\": \"0\",\n      \"margin\": \"0\",\n      \"display\": \"inline\"\n    }\n  })), mdx(\"p\", null, `If the line-height is 0, then the space below the baseline is also 0, so the whitespace is gone. If you have other text in the parent, that text will also be affected and could even start overlapping.`), mdx(\"h5\", {\n    \"id\": \"fixing-images\"\n  }, `'Fixing' images`), mdx(\"p\", null, `The easiest 'fix' in this case it to simply `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `move the image off the baseline`), `, for example by aligning it to the top or bottom of the line instead:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `img`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `vertical-align`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` top`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token comment\"\n  }), `/* or bottom */`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"display\": \"block\",\n      \"border\": \"5px solid dodgerblue\",\n      \"position\": \"relative\",\n      \"margin\": \"2rem 0\",\n      \"textAlign\": \"center\"\n    }\n  }, mdx(\"img\", {\n    src: \"/blogs/csslayout/kitten.jpg\",\n    style: {\n      \"width\": \"200px\",\n      \"padding\": \"0\",\n      \"margin\": \"0\",\n      \"display\": \"inline\",\n      \"verticalAlign\": \"top\"\n    }\n  })), mdx(\"p\", null, `The bottom of the image no longer sits on the baseline, so there is no longer whitespace reserved below it!`), mdx(\"p\", null, `Now that we have discussed inline behaviour and understand how layout happens `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `inside`), ` boxes when they're in normal flow, lets move outside the box and see how the space between boxes works.`), mdx(\"h3\", {\n    \"id\": \"margin-behavior\"\n  }, `Margin behavior`), mdx(\"p\", null, `Margins are outside of an element and you can use them to push boxes away from each other.`), mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"border\": \"5px solid dodgerblue\",\n      \"width\": \"200px\",\n      \"height\": \"180px\",\n      \"outline\": \"1rem solid #ff05\"\n    }\n  }), mdx(\"div\", {\n    style: {\n      \"textAlign\": \"center\",\n      \"margin\": \"1rem 0\"\n    }\n  }, mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"borderLeft\": \"1rem solid #ff05\",\n      \"borderRight\": \"1rem solid #ff05\",\n      \"display\": \"inline\",\n      \"color\": \"transparent\",\n      \"lineHeight\": \"1\",\n      \"fontSize\": \"3.5rem\",\n      \"outline\": \"5px solid dodgerblue\",\n      \"outlineOffset\": \"calc( -1rem - 5px)\",\n      \"overflowY\": \"clip\"\n    }\n  }, \"gr gerg dg dsgf d gz\")), mdx(\"p\", null, `For block elements, this happens in all directions. For inline elements, as we previously mentioned, it's the line they sit on that determines their placement. Adding margin to inline elemens will only apply in the inline direction (left and right).`), mdx(\"h4\", {\n    \"id\": \"margin-collapse\"\n  }, `Margin collapse`), mdx(\"p\", null, `When there are two block elements with margins stacked vertically and there are no other box parts (like border or padding) between them, the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `larger margin of the two is picked`), ` and they 'collapse' into each other.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.hotpink`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-bottom`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 1rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.dodgerblue`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 2rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"width\": \"50%\",\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    className: \"\",\n    style: {\n      \"left\": \"-20px\",\n      \"height\": \"50px\",\n      \"position\": \"relative\",\n      \"background\": \"hotpink\",\n      \"marginBottom\": \"1rem\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"top\": \"100%\",\n      \"height\": \"1rem\"\n    }\n  })), mdx(\"div\", {\n    className: \"\",\n    style: {\n      \"height\": \"50px\",\n      \"background\": \"dodgerblue\",\n      \"marginTop\": \"2rem\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"bottom\": \"100%\",\n      \"height\": \"2rem\"\n    }\n  }))), mdx(\"p\", null, `We've made the margins semi-transparent here so you can see how they actually overlap, or 'collapse', rather than add up.`), mdx(\"p\", null, `This happens when any two elements in the same `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `formatting context`), ` (remember that one?) have margins that interact.`), mdx(\"h4\", {\n    \"id\": \"margin-collapse-between-parents-and-children\"\n  }, `Margin collapse between parents and children`), mdx(\"p\", null, `Elements and their children also share a formatting context, and that is why you also get margin collapse between parents and children.`), mdx(\"p\", null, `You might add a margin to the first element inside a parent with the idea of pushing that element down from the top of the parent element, but due to margin collapse that margin is applied `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `outside of the parent`), `, rather than pushing down the first element.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.parent`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 1rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"width\": \"50%\",\n      \"margin\": \"4rem auto 1rem\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"bottom\": \"100%\",\n      \"height\": \"1rem\"\n    }\n  }), mdx(\"div\", {\n    style: {\n      \"fontSize\": \"20px\",\n      \"margin\": \"0\",\n      \"position\": \"relative\",\n      \"textAlign\": \"center\"\n    }\n  }, \"Hello there\", mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"bottom\": \"100%\",\n      \"height\": \"3rem\"\n    }\n  })))), mdx(\"p\", null, `You'll frequently want to prevent this, and while there is no explicit `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `margin-collapse: none`), ` property, You can instead prevent margin collapse or create a new formatting context.`), mdx(\"p\", null, `Firstly, adding a padding or a border, no matter how small, to the parent element will prevent margin collapse since the margins are no longer adjacent.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.parent`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 1rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `padding-top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 1px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.child`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 3rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"width\": \"50%\",\n      \"margin\": \"4rem auto 1rem\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"position\": \"relative\",\n      \"paddingTop\": \"1px\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"bottom\": \"100%\",\n      \"height\": \"1rem\"\n    }\n  }), mdx(\"div\", {\n    style: {\n      \"fontSize\": \"20px\",\n      \"marginTop\": \"3rem\",\n      \"position\": \"relative\",\n      \"textAlign\": \"center\"\n    }\n  }, \"Hello there\", mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"bottom\": \"100%\",\n      \"height\": \"3rem\"\n    }\n  })))), mdx(\"p\", null, `And while this works, you can see that 1px of padding is affecting the layout. This might matter, or it might not.`), mdx(\"p\", null, `another way is to use `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `overflow: auto`), ` (or `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `hidden`), `) on the parent element. This creates a new formatting context `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `inside`), ` the element, and now the element and the child element are in different formatting contexts, which prevents margin collapse.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.parent`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `overflow`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.child`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 3rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"width\": \"50%\",\n      \"margin\": \"4rem auto 1rem\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"height\": \"1rem\"\n    }\n  }), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"position\": \"relative\",\n      \"overflow\": \"auto\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"fontSize\": \"20px\",\n      \"marginTop\": \"3rem\",\n      \"position\": \"relative\",\n      \"textAlign\": \"center\"\n    }\n  }, \"Hello there\", mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"bottom\": \"100%\",\n      \"height\": \"3rem\"\n    }\n  })))), mdx(\"p\", null, `Overflow auto will prevent other elements from being shown outside of the parent element, and when you have restrictions on the width or height of the element, it will show a scrollbar when the content overflows.`), mdx(\"p\", null, `The explicit option is to define the parent as a new formatting context, which you can do with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: flow-root`), `.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.parent`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `display`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` flow-root`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.child`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 3rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"width\": \"50%\",\n      \"margin\": \"4rem auto 1rem\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"height\": \"1rem\"\n    }\n  }), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"position\": \"relative\",\n      \"display\": \"flow-root\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"fontSize\": \"20px\",\n      \"marginTop\": \"3rem\",\n      \"position\": \"relative\",\n      \"textAlign\": \"center\"\n    }\n  }, \"Hello there\", mdx(\"div\", {\n    style: {\n      \"background\": \"olive\",\n      \"opacity\": \"0.2\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"bottom\": \"100%\",\n      \"height\": \"3rem\"\n    }\n  })))), mdx(\"p\", null, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `flow-root`), ` is a bit of a magical property that creates a new block formatting context without affecting other layout aspects of the element. It's a great way to prevent margin collapse without side effects.`), mdx(\"h4\", {\n    \"id\": \"negative-margins\"\n  }, `Negative margins`), mdx(\"p\", null, `Margins can also be negative. When you use negative margins you're not adding space between element, but you're changing the position of the element itself in a way that no longer interacts with the elements around it.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.top`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-bottom`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 1rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.overlap`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` -2rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"width\": \"50%\",\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    className: \"\",\n    style: {\n      \"left\": \"-20px\",\n      \"height\": \"50px\",\n      \"position\": \"relative\",\n      \"background\": \"hotpink\",\n      \"marginBottom\": \"1rem\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"yellow\",\n      \"opacity\": \"0.33\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"top\": \"100%\",\n      \"height\": \"1rem\"\n    }\n  })), mdx(\"div\", {\n    className: \"\",\n    style: {\n      \"height\": \"50px\",\n      \"background\": \"dodgerblue\",\n      \"marginTop\": \"-2rem\",\n      \"position\": \"relative\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"yellow\",\n      \"opacity\": \"0.33\",\n      \"position\": \"absolute\",\n      \"width\": \"100%\",\n      \"top\": \"0%\",\n      \"height\": \"2rem\"\n    }\n  }))), mdx(\"p\", null, `The way they get calculated is by taking the margin value, which can also be collapsed, see how the two margins overlap, then subtracting the negative value and starting the new element there.`), mdx(\"p\", null, `Negative margins exist, but you're better off ignoring them and using positioning instead for overlapping layouts. (More on positioning later.)`), mdx(\"h4\", {\n    \"id\": \"centering-block-elements-with-margin-auto\"\n  }, `Centering block elements with margin: auto`), mdx(\"p\", null, `You can use margins to center elements horizontally by setting the left and right margins to `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `auto`), `:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.block`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `width`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 200px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-right`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"background\": \"color-mix(in srgb, yellow, transparent 80%)\"\n    }\n  }, mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"width\": \"200px\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"background\": \"dodgerblue\",\n      \"height\": \"100px\"\n    }\n  })), mdx(\"p\", null, `This element gets centered because the layout for horizontal margins uses a `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `constraint-based layout`), ` when either width or margin is set to auto.`), mdx(\"p\", null, `A constraint-based layout means that there is a formula that gets solved to determine the layout. The rule is:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `total width = margin-left + border-left + padding-left + width + padding-right + border-right + margin-right`)), mdx(\"p\", null, `Because borders and paddings are fixed values we can leave them out and instead simplify it to this:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `available space to fill out = margin-left + width + margin-right`)), mdx(\"p\", null, `Let's see what happens when we plug in different values for the width and margins into this formula.`), mdx(\"h5\", {\n    \"id\": \"case-1-everything-is-set-to-auto\"\n  }, `Case 1: everything is set to auto`), mdx(\"p\", null, `When all three values are set to `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `auto`), `, the width takes up all available space, and both margins are set to 0.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.block`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-right`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `width`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"background\": \"color-mix(in srgb, yellow, transparent 80%)\"\n    }\n  }, mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"width\": \"auto\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"background\": \"dodgerblue\",\n      \"height\": \"100px\"\n    }\n  })), mdx(\"p\", null, `This is because the \"preferred width\" of a block element is 100%. So the equation becomes:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `total width = 0 + 100% + 0`)), mdx(\"h5\", {\n    \"id\": \"case-2-the-width-is-auto\"\n  }, `Case 2: the width is auto`), mdx(\"p\", null, `If you have values for both margins but aren't defining with, then the width takes up all remaining space between the two margins.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.block`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 2rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-right`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 2rem`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `width`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"background\": \"color-mix(in srgb, yellow, transparent 80%)\"\n    }\n  }, mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"width\": \"auto\",\n      \"marginLeft\": \"2rem\",\n      \"marginRight\": \"2rem\",\n      \"background\": \"dodgerblue\",\n      \"height\": \"100px\"\n    }\n  })), mdx(\"p\", null, `This is because the preferred width is still 100%, and the constraint then makes this formula:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `total width = 2rem + (100% - 4rem) + 2rem`)), mdx(\"h5\", {\n    \"id\": \"case-3-the-width-is-fixed\"\n  }, `Case 3: the width is fixed`), mdx(\"p\", null, `When the width is fixed and both margins are set to `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `auto`), `, the remaining space is divided equally between the two margins.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.block`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `width`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 50%`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-right`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"background\": \"color-mix(in srgb, yellow, transparent 80%)\"\n    }\n  }, mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"width\": \"50%\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"background\": \"dodgerblue\",\n      \"height\": \"100px\"\n    }\n  })), mdx(\"p\", null, `This is because the equation becomes:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `total width = 25% + 50% + 25%`)), mdx(\"h5\", {\n    \"id\": \"case-4-width-and-one-of-the-margins-are-fixed\"\n  }, `Case 4: width and one of the margins are fixed`), mdx(\"p\", null, `When the width is fixed and one of the margins is also set to a fixed value, the other margin is set to the remaining space.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.block`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `width`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 200px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-right`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 50px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin-left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` auto`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"background\": \"color-mix(in srgb, yellow, transparent 80%)\"\n    }\n  }, mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"width\": \"200px\",\n      \"marginRight\": \"50px\",\n      \"marginLeft\": \"auto\",\n      \"background\": \"dodgerblue\",\n      \"height\": \"100px\"\n    }\n  })), mdx(\"p\", null, `The equation becomes:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `total width = (100% - 250px) + 200px + 50px`)), mdx(\"p\", null, `The browser calculates the remaining space as `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `100% - 250px`), ` and adds it to the left margin, and so even though block elements normally start at the left edge of their container, this one is pushed to the right even though it doesn't have a specific value for `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `margin-left`), `.`), mdx(\"h3\", {\n    \"id\": \"inline-block-the-hybrid\"\n  }, `Inline-block: The hybrid`), mdx(\"p\", null, `There's one last trick normal flow has: `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: inline-block`), `.`), mdx(\"p\", null, `Given all the time we spent figuring out the differences between inline and block elements and how their specific behavior differs, what even is inline-block?`), mdx(\"p\", null, `Inline-block tells the browser that an element behaves as `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `inline for the formatting context around it`), `, but is &`, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `rendered as a block box`), `, creating its own formatting context.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.tag`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `display`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` inline-block`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `padding`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 5px 10px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 5px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `background`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` dodgerblue`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `width`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 250px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"background\": \"color-mix(in srgb, yellow, transparent 80%)\",\n      \"textAlign\": \"center\"\n    }\n  }, \"text text text\", mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"display\": \"inline-block\",\n      \"padding\": \"5px 10px\",\n      \"margin\": \"5px\",\n      \"background\": \"dodgerblue\",\n      \"width\": \"250px\"\n    }\n  }, ' ', \"We have a bunch of text that wraps across lines.\"), \"More text text text\"), mdx(\"p\", null, `You can see that the element sits inline with the rest of the text and you can even see that the text is placed on the same `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `baseline`), `, but the element itself behaves as a block element, since it has a width, padding on all sides and the content inside of it wraps to multiple `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `lines`), `.`), mdx(\"p\", null, `The CSS specification calls this behavior \"shrink-to-fit\". Before Flexbox, this was a great way to render things like a list of tags or navigation items:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.nav-item`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `display`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` inline-block`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `padding`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 5px 10px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 5px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `background`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` dodgerblue`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"margin\": \"1rem auto\",\n      \"position\": \"relative\",\n      \"background\": \"color-mix(in srgb, yellow, transparent 80%)\",\n      \"textAlign\": \"center\"\n    }\n  }, mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"display\": \"inline-block\",\n      \"padding\": \"5px 10px\",\n      \"margin\": \"5px\",\n      \"background\": \"dodgerblue\"\n    }\n  }, \"Home\"), mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"display\": \"inline-block\",\n      \"padding\": \"5px 10px\",\n      \"margin\": \"5px\",\n      \"background\": \"dodgerblue\"\n    }\n  }, \"About\"), mdx(\"div\", {\n    className: \"box\",\n    style: {\n      \"display\": \"inline-block\",\n      \"padding\": \"5px 10px\",\n      \"margin\": \"5px\",\n      \"background\": \"dodgerblue\"\n    }\n  }, \"Contact\")), mdx(\"h4\", {\n    \"id\": \"display-values-outer-and-inner\"\n  }, `Display values: outer and inner`), mdx(\"p\", null, `The `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display`), ` property can have two parts: an outer and an inner value. `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `inline-block`), ` as a value is from before this was introduced, but in \"modern\" CSS it's equivalent to:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `display`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` inline flow-root`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`)))), mdx(\"p\", null, `The outer value is how the element behaves in relation to other elements, so inline, and the inner value is how the element behaves in relation to its own content. We want that to have a block formatting context. You don't set that with \"block\", but with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `flow-root`), `. Think of it as \"a new 'normal flow' starting point\".`), mdx(\"p\", null, `When you set a single item, that item is either for the inner or outer value depending on the value: some are inherently outer values, and some are inherently inner values. For example `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: grid`), ` creates a grid for the content, and the outer value is inferred to be `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `block`), `, making it the same as `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: block grid`), `. `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: inline`), ` on the other hand is inherently an outer value, so the inner value is inferred to be `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `flow`), `, making it the same as `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: inline flow`), `.`), mdx(\"p\", null, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `flow-root`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `flow`), ` are the two new keywords here and they are `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `roughly`), ` equivalent to `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `block`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `inline`), `, but only for the inner value.`), mdx(\"h3\", {\n    \"id\": \"thats-normal-flow\"\n  }, `That's Normal Flow`), mdx(\"p\", null, `CSS's simplest layout algorithm! Would you have expected that there was so much behind something that you can essentially describe as \"text goes from left to right, top to bottom\"?`), mdx(\"p\", null, `The good news is that all other layout algorithms build upon these concepts. In fact, unless you explicitly take an element \"out of flow\", elements are still considered \"in flow\" regardless of what other layout algorithm you use, and the normal flow algorithm is used in addition to it.`), mdx(\"h4\", {\n    \"id\": \"key-takeaways-for-normal-flow\"\n  }, `Key takeaways for normal flow`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Block elements stack vertically (↓)`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Inline elements flow horizontally (→)`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Everything is a box`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Anonymous boxes get created for text outside of elements`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Margins collapse vertically`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `All inline elements sit on the baseline`)), mdx(\"h2\", {\n    \"id\": \"other-layout-algorithms\"\n  }, `Other layout algorithms`), mdx(\"p\", null, `To get any other layout algorithm, you need to opt into them. There are three main layout algorithms in CSS:`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Positioning`), ` (relative, absolute, fixed, sticky)`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Flexbox`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Grid`))), mdx(\"p\", null, `There's a few more, like table layout, floats and multi-column, but the first two are hacks that we haven't needed in well over a decade, and multi-column is too niche for this already long article (and indeed, might soon be replaced by the masonry-style grid layout algorithm).`), mdx(\"h2\", {\n    \"id\": \"a-small-detour-sizes-in-percentages\"\n  }, `A small detour: sizes in percentages`), mdx(\"p\", null, `Before we dive into the other layout algorithms, we need to talk about percentages. When you use a percentage value for a size or a margin, padding etc, what is that percentage based on?`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `div`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `width`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 50%`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `height`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 25%`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `margin`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 10% 5%`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `padding`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 5% 2.5%`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"p\", null, `Well, for `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `width`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `height`), ` (and their min and max and logical equivalents), percentages are based on the size of the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `containing block`), `. So 50% width is 50 percent of the width of the containing block, and 25% height is 25% of the height of the containing block.`), mdx(\"h3\", {\n    \"id\": \"hold-up-containing-block\"\n  }, `Hold up, containing block?`), mdx(\"p\", null, `So we have offset parents, stacking contexts and now also \"containing block\".`), mdx(\"p\", null, `The containing block is the box that contains the element. For most elements, this is the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `content-box`), ` (remember the box model) of the first parent element that is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: block`), `.`), mdx(\"p\", null, `For `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: absolute`), ` elements, it's the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `padding-box`), ` of the closest stacking context, and for `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: fixed`), ` elements, it's the viewport.`), mdx(\"p\", null, `Those last two are exceptions but in practical use those exceptions actually result in elements sizing in ways you would expect.`), mdx(\"h3\", {\n    \"id\": \"percentages-for-margin-and-padding\"\n  }, `Percentages for margin and padding`), mdx(\"p\", null, `For margins and paddings, percentages are always based on the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `width`), ` of the containing block, even for `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `margin-top`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `padding-bottom`), `.`), mdx(\"p\", null, `That's a bit confusing, but it's because of how the rest of CSS works. Most elements have a vertical size that changes based on their content: the more lines of text you add to a paragraph, the taller it gets.`), mdx(\"p\", null, `If you were able to add a padding-top based on a percentage of the height, then that would increase the absolute height of the element, which in turn would increase the padding-top's absolute value, which would then update the height of the element and so on: it would create an infinite loop.`), mdx(\"p\", null, `Instead, having percentages for vertical margins and paddings based on the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `width`), ` of the containing block gives you a predictable value that doesn't change when it causes the height of an element to increase.`), mdx(\"h2\", {\n    \"id\": \"positioning-schemes\"\n  }, `Positioning schemes`), mdx(\"p\", null, `With positioning, we can tell the browser how to place an element either in relation to its calculated flow position, or explicitly take it out of normal flow. It's also where the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `third dimension`), ` is introduced with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), `. That concept doesn't exist in normal flow, and adding z-index to an element without a position does nothing.`), mdx(\"p\", null, `Elements by default have `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: static`), `, which means no explicit positioning. To activate the positioning layout algorithm, pick a different value:`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `static`), ` (the default)`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `relative`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `absolute`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `fixed`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `sticky`))), mdx(\"p\", null, `Each of these are their own little layout algorithm, so let's go through them one by one.`), mdx(\"h3\", {\n    \"id\": \"position-relative\"\n  }, `Position: relative`), mdx(\"p\", null, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `relative`), ` is the basic value that lets you opt in to positioning layout. A relatively positioned element has a box placed in the same spot as normal flow, but you can move the element away from that box using `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `top`), `, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `left`), `, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `bottom`), `, and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `right`), `, which are called `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `inset properties`), `. There's also a `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `inset`), ` shorthand property that lets you set all four inset properties at once.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.box`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `position`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` relative`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 40px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 40px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"lineHeight\": \"1\",\n      \"textAlign\": \"center\",\n      \"fontSize\": \"2rem\",\n      \"margin\": \"1rem 0 2rem\"\n    }\n  }, \"text text text\", mdx(\"div\", {\n    style: {\n      \"background\": \"#0002\",\n      \"width\": \"100px\",\n      \"height\": \"100px\",\n      \"margin\": \"0 auto\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"background\": \"dodgerblue\",\n      \"width\": \"100px\",\n      \"height\": \"100px\",\n      \"position\": \"relative\",\n      \"top\": \"40px\",\n      \"left\": \"40px\"\n    }\n  })), \"text text text\"), mdx(\"p\", null, `Notice that the original box is the one that takes up space and pushes the text away, but the element itself is elsewhere. The original box is used for the rest of the layout.`), mdx(\"p\", null, `This pushing away of the element from it's original box is something you'll rarely want, or need. What you mainly use `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: relative`), ` for is to `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `make an element an offset parent`), ` for absolutely positioned children. Before we get into what an offset parent is, let's explain `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: absolute`), `.`), mdx(\"h3\", {\n    \"id\": \"position-absolute\"\n  }, `Position: absolute`), mdx(\"p\", null, `Where elements with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: relative`), ` are still in normal flow, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: absolute`), ` elements are not. This means they do not interact with other elements: they don't take up space and don't push other elements out of the way.`), mdx(\"p\", null, `Inset properties don't move them away from their initial box like `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `relative`), `, they instead position the element in relation to the offset parent.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.box`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `position`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` absolute`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 40px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `right`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 40px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"lineHeight\": \"1\",\n      \"textAlign\": \"center\",\n      \"alignContent\": \"center\",\n      \"fontSize\": \"2rem\",\n      \"margin\": \"1rem 0 2rem\",\n      \"position\": \"relative\",\n      \"height\": \"200px\"\n    }\n  }, mdx(\"p\", null, \"text text text\"), mdx(\"div\", {\n    style: {\n      \"background\": \"dodgerblue\",\n      \"width\": \"100px\",\n      \"height\": \"100px\",\n      \"position\": \"absolute\",\n      \"top\": \"40px\",\n      \"right\": \"40px\"\n    }\n  }), mdx(\"p\", null, \"text text text\")), mdx(\"h4\", {\n    \"id\": \"the-offset-parent\"\n  }, `The offset parent`), mdx(\"p\", null, `The offset parent is the first element in the list of ancestors that is itself also positioned (any position value other than `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `static`), `). By default, the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `body`), ` is the only offset parent. So `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: absolute; top: 0;`), ` will place an element at the top of the page.`), mdx(\"p\", null, `If you add positioning to any parent element, it becomes an offset parent, and now `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `top: 0`), ` no longer means the top of the body element, but of that parent element.`), mdx(\"p\", null, `Any element that is positioned will become an offset parent, so you can have many offset parents inside of other offset parents. You're always positioning against the nearest offset parent up the DOM tree.`), mdx(\"h5\", {\n    \"id\": \"finding-the-offset-parent\"\n  }, `Finding the offset parent`), mdx(\"p\", null, `Layout issues where your absolutely positioned element isn't where you expect it are almost always because what you think the offset parent is is different from what the browser thinks.`), mdx(\"p\", null, `To find the offset parent in Chrome, Safari, Firefox etc`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Find the element in the element inspector`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Switch to the console panel`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Type `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `$0.offsetParent`), ` and hit enter`)), mdx(\"p\", null, `In `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"/\"\n  }), `Polypane`), `, you can see the offset parent directly in the element inspector's debug panel.`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Find the element in the `, mdx(\"a\", _extends({\n    parentName: \"li\"\n  }, {\n    \"href\": \"/docs/elements-panel/\"\n  }), `element inspector`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Switch to the debug tab`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `See Offset parent under \"contexts\"`)), 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, `Learn more about that in our dedicated article on `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"/blog/offset-parent-and-stacking-context-positioning-elements-in-all-three-dimensions/#offset-parent\"\n  }), `Offset parent and stacking context`), ` (more on that second one later).`), mdx(\"h3\", {\n    \"id\": \"position-fixed\"\n  }, `Position: fixed`), mdx(\"p\", null, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: fixed`), ` is a lot like `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `absolute`), `. Elements are taken out of the normal flow, but in this scheme, the offsetParent is always the viewport, and inset properties are used to position from the edge of it.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.header`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `position`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` fixed`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `right`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"p\", null, `That means that while absolutely positioned elements scroll along with the rest of the page, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `fixed`), ` elements will always stay in view.`), mdx(\"h3\", {\n    \"id\": \"position-sticky\"\n  }, `Position: sticky`), mdx(\"p\", null, `The last scheme is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: sticky`), `. It was added to CSS much later than the other ones, and it's for elements that you like to keep in view for some part of the time, but still want to scroll along with their offset parent.`), mdx(\"p\", null, `With `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position:sticky`), `, the element will be placed the same way as `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: relative`), `, but the top/left/bottom/right values don't move the element. Instead they determine where an element gets stuck relative to the scrolling context, which is usually the viewport.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.sticky-header`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `position`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` sticky`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 50%`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"height\": \"20vh\",\n      \"textAlign\": \"center\",\n      \"border\": \"5px solid hotpink\"\n    }\n  }, mdx(\"div\", {\n    className: \"sticky-header\",\n    style: {\n      \"position\": \"sticky\",\n      \"top\": \"50%\",\n      \"background\": \"dodgerblue\",\n      \"width\": \"250px\",\n      \"height\": \"50px\",\n      \"margin\": \"0 auto\"\n    }\n  }, \"Scroll down to see me stick\")), mdx(\"p\", null, `As an element scrolls it will behave like a relatively positioned element, until it hits that inset value where it gets stuck.`), mdx(\"p\", null, `Then it will stay stuck, until the offset parent's bottom catches up with it, at which point the element will get unstuck and continue scrolling with it's offset parent.`), mdx(\"p\", null, `A tricky thing here is that it will only get stuck if the browser determines it `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `can`), ` get stuck. To learn more about debugging sticky positioning, check out our article: `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"/blog/getting-stuck-all-the-ways-position-sticky-can-fail/#main\"\n  }), `Getting stuck: all the ways position sticky can fail`)), mdx(\"h2\", {\n    \"id\": \"overview-of-positioning-schemes\"\n  }, `Overview of positioning schemes`), mdx(\"p\", null, `So to compare the different positioning schemes, here's a quick overview:`), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Position`), mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `In Flow?`), mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Offset Parent`))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `static`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Yes`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Not applicable`)), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `relative`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Yes`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Nearest positioned`)), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `absolute`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `No`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Nearest positioned`)), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `fixed`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `No`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Viewport`)), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `sticky`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Yes`, `*`), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), `Scrollport`)))), mdx(\"p\", null, `*`, ` until it gets stuck, then it becomes like fixed.`), mdx(\"div\", {\n    className: \"threed\"\n  }), mdx(\"h2\", {\n    \"id\": \"the-stacking-context\"\n  }, `The stacking context`), mdx(\"p\", null, `Remember how I said that with positioning, we introduce the third dimension? Well we haven't talked about that yet.`), mdx(\"p\", null, `While the offset parent tells you how an element is positioned in the x and y directions, the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `stacking context`), ` tells you how it's positioned in the third dimension, the z-axis. Or in other words, how close it is to the \"front of the screen\". And like offset parents, you have stacking contexts inside stacking contexts.`), mdx(\"p\", null, `The default stacking context is not the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `body`), ` element, but the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `html`), ` element. So all elements are stacked in relation to the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `html`), ` element by default.`), mdx(\"h3\", {\n    \"id\": \"default-stacking-order\"\n  }, `Default stacking order`), mdx(\"p\", null, `Elements by default have a stacking order that's the same as source order and`, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` lets you reorder them.`), mdx(\"div\", {\n    className: \"code-and-demo\"\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `div::before`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `background`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` hotpink`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `z-index`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 1`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `div::after`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `background`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` rebeccapurple`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `z-index`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` -1`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    className: \"threed threed2\"\n  })), mdx(\"div\", {\n    className: \"code-and-demo\"\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token comment\"\n  }), `/* Flip them around: */`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `div::before`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `z-index`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` -1`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `div::after`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `z-index`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 1`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    className: \"threed threed2 threed3\"\n  })), mdx(\"h3\", {\n    \"id\": \"reordering-happens-inside-the-stacking-context\"\n  }, `Reordering happens inside the stacking context`), mdx(\"p\", null, `In the example below, the purple element has a `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` of 99, which is (much) higher than the blue element's `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` of just 2. So you'd expect the purple element to be in front of the blue one. However, because the purple element is inside of the pink element with a `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), ` of 1, it's stuck inside the stacking context of the pink element.`), mdx(\"div\", {\n    className: \"code-and-demo\"\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.first`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `background`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` hotpink`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `z-index`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 1`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.inner`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `background`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` rebeccapurple`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `z-index`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 99`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.second`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `background`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` dodgerblue`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `z-index`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 2`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    className: \"stack\"\n  }, mdx(\"div\", {\n    className: \"stack1\"\n  }, \"1\", mdx(\"div\", {\n    className: \"inner\"\n  }, \" 99 \")), mdx(\"div\", {\n    className: \"stack2\"\n  }, \"2 \"))), mdx(\"p\", null, `So instead of 99 being more than 2, you should actually think of it as (1,99) which `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `is`), ` less than 2. No matter how high your z-index is, it will never win from elements in a stacking context with a higher z-index than the stacking context you're currently in.`), mdx(\"h3\", {\n    \"id\": \"creating-a-stacking-context\"\n  }, `Creating a stacking context`), mdx(\"p\", null, `There's just a `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `few`), ` CSS properties that can create a 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 isolate`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `container-type`), ` set to size or 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, `…`, ` This makes `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `offsetParent`), ` sound easy right? It's quite a lot if you list them all out. Most of these properties aren't used very often though.`), mdx(\"h4\", {\n    \"id\": \"the-most-common-ones-are\"\n  }, `The most common ones are:`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `opacity`)), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `transform`))), mdx(\"h4\", {\n    \"id\": \"explicit-stacking-context\"\n  }, `Explicit stacking context`), mdx(\"p\", null, `Out of the entire list, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `isolation: isolate`), ` is the most explicit way of indicating in your CSS that you're creating a new stacking context:`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.container`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `isolation`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` isolate`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"h3\", {\n    \"id\": \"a-practical-stacking-context-example\"\n  }, `A practical stacking context example`), mdx(\"p\", null, `Here's a practical example, a simple block quote design with a decorative quote mark. After positioning the quote mark correctly in the X and Y axis we can now see that the quote mark is in front of the text. Because the text itself isn't an element (it's an anonymous box), we can't bring it forward using `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), `.`), mdx(\"div\", {\n    className: \"code-and-demo\"\n  }, mdx(\"div\", {\n    style: {\n      \"flex\": \"1 1 auto\"\n    }\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `blockquote`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token comment\"\n  }), `/* offset parent */`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `position`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` relative`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `blockquote span`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `position`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` absolute`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"html\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `blockquote`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `span`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token entity named-entity\",\n    \"title\": \"“\"\n  }), `&ldquo;`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `span`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  Lorem ipsum dolor sit...\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `blockquote`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)))))), mdx(\"div\", {\n    style: {\n      \"position\": \"relative\",\n      \"alignContent\": \"center\",\n      \"flex\": \"1 1 auto\"\n    }\n  }, mdx(\"div\", {\n    className: \"quote\"\n  }, mdx(\"blockquote\", null, mdx(\"span\", null, \"\\u201C\"), \"Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora tenetur molestias consequatur, quidem nam ipsum minima aliquid recusandae delectus enim.\")))), mdx(\"p\", null, `Instead, we need to bring the quote backwards with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index: -1`), `:`), mdx(\"div\", {\n    className: \"code-and-demo\"\n  }, mdx(\"div\", {\n    style: {\n      \"flex\": \"1 1 auto\"\n    }\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `blockquote span`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `position`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` absolute`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `left`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 0`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `z-index`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` -1`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`))))), mdx(\"div\", {\n    style: {\n      \"position\": \"relative\",\n      \"alignContent\": \"center\",\n      \"flex\": \"1 1 auto\"\n    }\n  }, mdx(\"div\", {\n    className: \"quote\"\n  }, mdx(\"blockquote\", null, mdx(\"span\", {\n    style: {\n      \"zIndex\": \"-1\"\n    }\n  }, \"\\u201C\"), \"Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora tenetur molestias consequatur, quidem nam ipsum minima aliquid recusandae delectus enim.\")))), mdx(\"p\", null, `When you do that however, the quote mark disappears behind the background of the blockquote. That's because the current stacking context is still the HTML element. So we need to make the parent element the stacking context.`), mdx(\"div\", {\n    className: \"code-and-demo\"\n  }, mdx(\"div\", {\n    style: {\n      \"flex\": \"1 1 auto\"\n    }\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `blockquote`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `isolation`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` isolate`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`))))), mdx(\"div\", {\n    style: {\n      \"position\": \"relative\",\n      \"alignContent\": \"center\",\n      \"flex\": \"1 1 auto\"\n    }\n  }, mdx(\"div\", {\n    className: \"quote\"\n  }, mdx(\"blockquote\", {\n    style: {\n      \"isolation\": \"isolate\"\n    }\n  }, mdx(\"span\", {\n    style: {\n      \"zIndex\": \"-1\"\n    }\n  }, \"\\u201C\"), \"Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora tenetur molestias consequatur, quidem nam ipsum minima aliquid recusandae delectus enim.\")))), mdx(\"p\", null, `The blockquote is now a new stacking context, and the quote mark can no longer go behind the background. Instead, it sits at the beginning of the stacking context inside the blockquote: behind the text but in front of the background.`), mdx(\"h3\", {\n    \"id\": \"finding-the-stacking-context\"\n  }, `Finding the stacking context`), mdx(\"p\", null, `Finding the stacking context of an element is not as easy as finding the offset parent. Unlike `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `element.offsetParent`), `, there is no `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `element.stackingContext`), ` property.`), mdx(\"p\", null, `That's why we built a debug panel into Polypane that not only shows you the offset parent, but also the stacking context of the selected element, along with whether the element itself creates a stacking context. It's very neat, and you can learn more about it in our article on `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"/blog/offset-parent-and-stacking-context-positioning-elements-in-all-three-dimensions/#stacking-context\"\n  }), `Offset parent and stacking context`), `.`), 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(\"h4\", {\n    \"id\": \"the-polypane-debug-panel\"\n  }, `The Polypane debug panel`), mdx(\"p\", null, `The top section in the debug panel shows you CSS attributes that commonly cause issues, like `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display`), `, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `z-index`), `.`), mdx(\"p\", null, `Below that, it shows the different contexts that the element is in: the offset parent, the containing block and the stacking context.`), mdx(\"p\", null, `Lastly, it shows whether the element itself is an offset parent, containing block or stacking context.`), mdx(\"img\", {\n    src: debugpanel2,\n    alt: \"The debug tab in the Elements panel\",\n    className: \"imgshadow\"\n  }), mdx(\"p\", null, `These three sections make it very easy to figure out what's going on with the layout of an element, and really speed up your CSS layout debugging.`), mdx(\"h2\", {\n    \"id\": \"grid-and-flexbox\"\n  }, `Grid and Flexbox`), mdx(\"p\", null, `That leaves Grid and Flexbox. I'm not going to spend any time on the syntax or specific features of either layout algorithm, instead focusing on how they interact with the previous layout algorithms and concepts like offset parent and stacking context.`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `For Flexbox, check out `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://every-layout.dev/\"\n  }), `Every Layout`), ` by `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://heydonworks.com/\"\n  }), `Heydon Pickering`), ` and `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://piccalil.li/\"\n  }), `Andy Bell`), ` or `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://www.flexboxsimplified.com\"\n  }), `Flexbox Simplified`), ` by `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://www.kevinpowell.co/\"\n  }), `Kevin Powell`), `. For Grid, check out `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://gridbyexample.com/\"\n  }), `Grid by Example`), ` by `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://rachelandrew.co.uk/\"\n  }), `Rachel Andrew`), `.`)), mdx(\"p\", null, `Both Flex and Grid are significantly different from the layout algorithms that came before. That's because they were developed not as a way to lay out web documents, but as a way to lay out `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `web apps`), `.`), mdx(\"h3\", {\n    \"id\": \"the-key-differences\"\n  }, `The key differences`), mdx(\"p\", null, `When you look at Flex and Grid, they each approach layout from a different direction.`), mdx(\"div\", {\n    style: {\n      \"display\": \"grid\",\n      \"gridTemplateColumns\": \"repeat(2, min(250px, 1fr))\",\n      \"gridAutoRows\": \"auto\",\n      \"gap\": \"1rem\",\n      \"padding\": \"1rem 2rem\",\n      \"margin\": \"0 auto\",\n      \"maxWidth\": \"50em\",\n      \"justifyContent\": \"center\"\n    }\n  }, mdx(\"div\", null, mdx(\"h4\", {\n    \"id\": \"flexbox-is-bottom-up\"\n  }, mdx(\"strong\", {\n    parentName: \"h4\"\n  }, `Flexbox`), ` is \"bottom up\"`), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, `Get a bunch of elements`), mdx(\"li\", {\n    parentName: \"ol\"\n  }, `Order them in a row or column`), mdx(\"li\", {\n    parentName: \"ol\"\n  }, `Distribute them according to rules you provide`))), mdx(\"div\", null, mdx(\"h4\", {\n    \"id\": \"grid-is-top-down\"\n  }, mdx(\"strong\", {\n    parentName: \"h4\"\n  }, `Grid`), ` is \"top down\"`), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, `Create a bunch of areas`), mdx(\"li\", {\n    parentName: \"ol\"\n  }, `Determine their sizes and positions of those areas according to rules you provide`), mdx(\"li\", {\n    parentName: \"ol\"\n  }, `Place elements inside those areas`)))), mdx(\"p\", null, `So Flexbox starts with the elements you have and distributed them, while Grid starts with defining the available spaces and then adding the elementes to them.`), mdx(\"p\", null, `Additionally, Flex is fundamentally one-dimensional (though it can wrap to a next line) while Grid is two-dimensional.`), mdx(\"h3\", {\n    \"id\": \"flex-and-grid-versus-normal-flow\"\n  }, `Flex and Grid versus normal flow`), mdx(\"p\", null, `Both are replacements of sorts for normal flow. They reason about the distribution of multiple elements in a specific way, rather than the positioning of a single element in relation to other elements.`), mdx(\"p\", null, `A very big difference between Flex and Grid on one hand and previous positioning on the other hand is that Flex and Grid no longer depend on font properties. The layouts you make and their alignment are based on the generated boxes, not on the font properties of the elements.`), mdx(\"p\", null, `This makes a lot of things much simpler.`), mdx(\"p\", null, `Both also try to make sure that regardless of the elements inside of them, the layout will be adhered to. In Flexbox this means that if an element has a fixed `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `width`), `, but that width doesn't fit in the space the Flex container has available for it, the elements size will be overwritten to make it fit the Flex layout. In Grid, an elements width and height are constrained by the grid area they're placed in.`), mdx(\"h3\", {\n    \"id\": \"flex-and-grid-combined-with-positioning\"\n  }, `Flex and Grid combined with positioning`), mdx(\"p\", null, `Both `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `flex`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `grid`), ` are `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display`), ` properties, separate from the `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position`), ` property. This means that the way to determine offset parents and stacking contexts doesn't change.`), mdx(\"p\", null, `You can take an element out of a flex or grid layout with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: absolute`), ` or `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: fixed`), `. Likewise, each element inside a flex or grid container, including the container itself, can be made an offset parent with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `position: relative`), ` or a stacking context with `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `isolation: isolate`), `.`), mdx(\"h3\", {\n    \"id\": \"what-not-being-dependent-on-font-properties-means\"\n  }, `What not being dependent on font properties means`), mdx(\"p\", null, `Unline `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `vertical-align: middle`), ` which uses the line-height and font properties (as mentioned above) to determine the middle of a `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `line`), `, both flex and grid align based on the boxes they create.`), mdx(\"p\", null, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-items: center`), ` in both layout algorithms will align the boxes of the elements in the middle of the flex or grid boxes, regardless of the font properties or line height of the elements.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-text\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-text\"\n  }), `.grid,\n.flex {\n align-items: center;\n}`))), mdx(\"div\", {\n    style: {\n      \"display\": \"flex\",\n      \"gap\": \"1rem\",\n      \"justifyContent\": \"center\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"display\": \"flex\",\n      \"border\": \"5px solid dodgerblue\",\n      \"alignItems\": \"center\",\n      \"height\": \"150px\",\n      \"gap\": \"1rem\",\n      \"padding\": \"1rem\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    },\n    className: \"item1\"\n  }, \"1\"), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    },\n    className: \"item2\"\n  }, \"2\"), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    },\n    className: \"item3\"\n  }, \"3\")), mdx(\"div\", {\n    style: {\n      \"display\": \"grid\",\n      \"gridTemplateColumns\": \"1fr 1fr 1fr\",\n      \"border\": \"5px solid dodgerblue\",\n      \"alignItems\": \"center\",\n      \"height\": \"150px\",\n      \"gap\": \"1rem\",\n      \"padding\": \"1rem\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    },\n    className: \"item1\"\n  }, \"1\"), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    },\n    className: \"item2\"\n  }, \"2\"), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    },\n    className: \"item3\"\n  }, \"3\"))), mdx(\"p\", null, `This new type of alignment logic is the same in Flex and grid and it worked so well that it was actually added to `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `display: block`), ` as well.`), mdx(\"p\", null, `The `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-content`), ` property lets you vertically center content in block elements, as long as they have a determined height. It was added to CSS Box Alignment level 3 and works across browsers.`), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.block`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `align-content`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` center`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"display\": \"flex\",\n      \"gap\": \"1rem\",\n      \"justifyContent\": \"space-evenly\"\n    }\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"html\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-html\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `div`), ` `, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-name\"\n  }), `class`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token attr-value\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation attr-equals\"\n  }), `=`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`), `block`, mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `\"`)), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `1`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `2`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `<`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `3`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`)), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token tag\"\n  }), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `</`), `div`), mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `>`))))), mdx(\"div\", {\n    style: {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"border\": \"5px solid dodgerblue\",\n      \"alignContent\": \"center\",\n      \"height\": \"300px\",\n      \"width\": \"200px\",\n      \"textAlign\": \"center\",\n      \"margin\": \"auto\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    }\n  }, \"1\"), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    }\n  }, \"2\"), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    }\n  }, \"3\"))), mdx(\"h4\", {\n    \"id\": \"-items-and--content\"\n  }, `*`, `-items and `, `*`, `-content`), mdx(\"p\", null, `Flex and grid both have `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-items`), `, `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-content`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `justify-content`), ` properties. Grid also has `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `justify-items`), `. So what is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `items`), ` and what is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `content`), `?`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `*-items`), ` properties align the individual items, for example inside a grid area.`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `*-content`), ` properties align the items as a group (usually as a row or column).`)), mdx(\"p\", null, `In the example below, we have a simple grid that has repeating rows of 50px high, and three 1fr columns. In the first/left example, we have `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-items: end`), ` which aligns the items to the `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `end of their grid area`), `. In the second example, we set `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-content: end`), `. This keeps the items the full size of their grid area, but aligns the entire group of items to the end of the container`), mdx(\"div\", {\n    style: {\n      \"display\": \"flex\",\n      \"gap\": \"1rem\",\n      \"justifyContent\": \"space-evenly\"\n    }\n  }, mdx(\"div\", {\n    className: \"grid-css-layout-demo align-items-end\"\n  }, mdx(\"div\", null, \"1\"), mdx(\"div\", null, \"2\"), mdx(\"div\", null, \"3\"), mdx(\"div\", null, \"4\"), mdx(\"div\", null, \"5\")), mdx(\"div\", {\n    className: \"grid-css-layout-demo align-content-end\"\n  }, mdx(\"div\", null, \"1\"), mdx(\"div\", null, \"2\"), mdx(\"div\", null, \"3\"), mdx(\"div\", null, \"4\"), mdx(\"div\", null, \"5\"))), mdx(\"h3\", {\n    \"id\": \"grid-and-position-sticky\"\n  }, `Grid and position: sticky`), mdx(\"p\", null, `Though the way to determine offset parents and stacking contexts doesn't change with Flex and Grid, when you combine Grid and position: sticky, that won't work as you might expect.`), mdx(\"p\", null, `The reason for that is the default value that grid has for `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-items`), `, which is `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `stretch`), `. That means that the element with position: sticky already is as tall as the grid area and that means that when it reaches that inset value to get stuck, the bottom of the element is already at the bottom of the grid area and so it never gets stuck.`), mdx(\"p\", null, `It's easy to miss that, because elements in a grid area without a background or border look like they are not filling the entire area.`), mdx(\"p\", null, `An element doesn't `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `have`), ` to fill the entire grid area though. You can set `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-items: start`), ` on the grid container to have all items align to the start of their grid area instead of stretching to fill it, or `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-self: start`), ` on the element itself`), mdx(\"div\", {\n    style: {\n      \"display\": \"flex\",\n      \"gap\": \"1rem\",\n      \"justifyContent\": \"space-evenly\"\n    }\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.grid-container`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token comment\"\n  }), `/* the default */`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `align-items`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` stretch`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `div`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `position`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` sticky`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `top`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 50%`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.start`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n    `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `align-self`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` start`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"display\": \"grid\",\n      \"gridTemplateColumns\": \"1fr  1fr\",\n      \"border\": \"5px solid dodgerblue\",\n      \"height\": \"350px\",\n      \"gap\": \"1rem\",\n      \"padding\": \"1rem\",\n      \"justifyContent\": \"center\",\n      \"margin\": \"2rem auto\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"position\": \"sticky\",\n      \"top\": \"50%\"\n    }\n  }, \"stretch\"), mdx(\"div\", {\n    style: {\n      \"position\": \"sticky\",\n      \"top\": \"50%\",\n      \"alignSelf\": \"start\"\n    }\n  }, \"start\"))), mdx(\"p\", null, `Check out our article: `, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"/blog/getting-stuck-all-the-ways-position-sticky-can-fail/#main\"\n  }), `Getting stuck: all the ways position sticky can fail`), ` for more on this.`), mdx(\"h3\", {\n    \"id\": \"the-final-boss-centering-a-div\"\n  }, `The final boss: centering a `, mdx(\"code\", _extends({\n    parentName: \"h3\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<div>`)), mdx(\"p\", null, `An age old joke about CSS is that it's impossible to center a `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<div>`), ` vertically.`), mdx(\"p\", null, `Now that you know the fundamentals, you know that's not true.`), mdx(\"p\", null, `The reason vertical centering is 'hard' is because CSS is built on normal flow, where the height of elements is determined by their content.`), mdx(\"p\", null, `If the height is determined by the content, and the content is a single line of text, then the height of the element is the height of that line of text. It's already vertically centered, it's just not the height you want.`), mdx(\"p\", null, `With that knowledge, there are actually dozens of ways to vertically center a `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `<div>`), `. But modern CSS gives us one way that's definitely the simplest: `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `place-content`), `.`), mdx(\"p\", null, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `place-content`), ` is a shorthand for the combination of `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `align-content`), ` and `, mdx(\"code\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"language-text\"\n  }), `justify-content`), ` and as we mentioned earlier in the article, that works in Flex, Grid `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `and Block elements`), `. For it to work, your element does have to have a defined height (because if not, the contents define the height).`), mdx(\"div\", {\n    style: {\n      \"display\": \"flex\",\n      \"gap\": \"1rem\",\n      \"justifyContent\": \"space-evenly\"\n    }\n  }, mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"css\"\n  }, mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-css\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token selector\"\n  }), `.container`), ` `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `{`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `height`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` 400px`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n  `, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token property\"\n  }), `place-content`), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `:`), ` center`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `;`), `\n`, mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), `}`)))), mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\",\n      \"height\": \"200px\",\n      \"placeContent\": \"center\",\n      \"width\": \"200px\",\n      \"margin\": \"2rem auto\",\n      \"padding\": \"2rem\"\n    }\n  }, mdx(\"div\", {\n    style: {\n      \"border\": \"5px solid dodgerblue\"\n    }\n  }, \"I'm centered!\"))), mdx(\"p\", null, `That's all it takes. Vertically centering is trivial.`), mdx(\"h2\", {\n    \"id\": \"things-we-left-out\"\n  }, `Things we left out`), mdx(\"p\", null, `The purpose of this article is to explain the fundamentals of CSS layout, but there are more concepts that can help you understand your layouts that we didn't cover:`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Content sizing`), `: how `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `min-content`), `, `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `max-content`), ` and `, mdx(\"code\", _extends({\n    parentName: \"li\"\n  }, {\n    \"className\": \"language-text\"\n  }), `fit-content`), ` work, and how intrinsic sizing works.`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Container queries`), `: how they create new layout contexts.`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Aspect-ratio`), `: how it affects sizing of elements.`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Subgrid`), `: how it works and how it relates to grid.`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, `Honestly, a deeper dive into both `, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Flexbox`), ` and `, mdx(\"strong\", {\n    parentName: \"li\"\n  }, `Grid`), `.`)), mdx(\"p\", null, `Each of these topics deserve their own article and we might cover them in the future.`), mdx(\"h2\", {\n    \"id\": \"conclusion\"\n  }, `Conclusion`), mdx(\"p\", null, `When you get started with CSS layout, it can feel overwhelming. There are a lot of concepts to learn, beyond the mere syntax and available properties. If you don't take the time to understand those concepts, you'll end up always fighting or guessing your way around designing pages.`), mdx(\"p\", null, `CSS is built on a set of small, logical concepts that each are easy to understand, from \"text goes left to right, top to bottom\" to \"everything is a box\" to \"elements can be taken outside of flow\". Each layout algorithm builds upon these concepts, adding new ways to position and align elements to handle more and more complex situations. But the building blocks remain the same.`), mdx(\"p\", null, `Understanding these building blocks of layout makes it easier to reason about CSS, to visualize how the browser is going to lay out your page and how to fix layout issues when they arise.`));\n}\n;\nMDXContent.isMDXComponent = true;","timeToRead":26,"tableOfContents":{"items":[{"url":"#prefer-video","title":"Prefer video?"},{"url":"#galls-law","title":"Gall's law"},{"url":"#everything-is-a-box","title":"Everything is a box"},{"url":"#normal-flow","title":"Normal flow","items":[{"url":"#non-western-languages","title":"Non-western languages"},{"url":"#formatting-context-and-anonymous-boxes","title":"Formatting context and anonymous boxes"},{"url":"#whitespace-and-anonymous-boxes","title":"Whitespace and anonymous boxes","items":[{"url":"#solving-the-whitespace-issue","title":"Solving the whitespace issue","items":[{"url":"#remove-the-whitespace","title":"Remove the whitespace"},{"url":"#disable-wrapping","title":"Disable wrapping"},{"url":"#set-the-font-size-to-0","title":"Set the font-size to 0"},{"url":"#white-space-collapse-discard-in-the-future","title":"White-space-collapse: discard (in the future!)"}]}]},{"url":"#the-box-model","title":"The box model","items":[{"url":"#content-box","title":"Content-box"},{"url":"#border-box","title":"Border-box"}]},{"url":"#how-inline-boxes-work","title":"How inline boxes work","items":[{"url":"#decorations","title":"Decorations"},{"url":"#placement-of-inline-elements","title":"Placement of inline elements"}]},{"url":"#lines-and-baselines","title":"Lines and baselines","items":[{"url":"#inline-elements-sit-on-the-baseline","title":"Inline elements sit on the baseline","items":[{"url":"#fixing-images","title":"'Fixing' images"}]}]},{"url":"#margin-behavior","title":"Margin behavior","items":[{"url":"#margin-collapse","title":"Margin collapse"},{"url":"#margin-collapse-between-parents-and-children","title":"Margin collapse between parents and children"},{"url":"#negative-margins","title":"Negative margins"},{"url":"#centering-block-elements-with-margin-auto","title":"Centering block elements with margin: auto","items":[{"url":"#case-1-everything-is-set-to-auto","title":"Case 1: everything is set to auto"},{"url":"#case-2-the-width-is-auto","title":"Case 2: the width is auto"},{"url":"#case-3-the-width-is-fixed","title":"Case 3: the width is fixed"},{"url":"#case-4-width-and-one-of-the-margins-are-fixed","title":"Case 4: width and one of the margins are fixed"}]}]},{"url":"#inline-block-the-hybrid","title":"Inline-block: The hybrid","items":[{"url":"#display-values-outer-and-inner","title":"Display values: outer and inner"}]},{"url":"#thats-normal-flow","title":"That's Normal Flow","items":[{"url":"#key-takeaways-for-normal-flow","title":"Key takeaways for normal flow"}]}]},{"url":"#other-layout-algorithms","title":"Other layout algorithms"},{"url":"#a-small-detour-sizes-in-percentages","title":"A small detour: sizes in percentages","items":[{"url":"#hold-up-containing-block","title":"Hold up, containing block?"},{"url":"#percentages-for-margin-and-padding","title":"Percentages for margin and padding"}]},{"url":"#positioning-schemes","title":"Positioning schemes","items":[{"url":"#position-relative","title":"Position: relative"},{"url":"#position-absolute","title":"Position: absolute","items":[{"url":"#the-offset-parent","title":"The offset parent","items":[{"url":"#finding-the-offset-parent","title":"Finding the offset parent"}]}]},{"url":"#position-fixed","title":"Position: fixed"},{"url":"#position-sticky","title":"Position: sticky"}]},{"url":"#overview-of-positioning-schemes","title":"Overview of positioning schemes"},{"url":"#the-stacking-context","title":"The stacking context","items":[{"url":"#default-stacking-order","title":"Default stacking order"},{"url":"#reordering-happens-inside-the-stacking-context","title":"Reordering happens inside the stacking context"},{"url":"#creating-a-stacking-context","title":"Creating a stacking context","items":[{"url":"#the-most-common-ones-are","title":"The most common ones are:"},{"url":"#explicit-stacking-context","title":"Explicit stacking context"}]},{"url":"#a-practical-stacking-context-example","title":"A practical stacking context example"},{"url":"#finding-the-stacking-context","title":"Finding the stacking context","items":[{"url":"#the-polypane-debug-panel","title":"The Polypane debug panel"}]}]},{"url":"#grid-and-flexbox","title":"Grid and Flexbox","items":[{"url":"#the-key-differences","title":"The key differences","items":[{"url":"#flexbox-is-bottom-up","title":"Flexbox is \"bottom up\""},{"url":"#grid-is-top-down","title":"Grid is \"top down\""}]},{"url":"#flex-and-grid-versus-normal-flow","title":"Flex and Grid versus normal flow"},{"url":"#flex-and-grid-combined-with-positioning","title":"Flex and Grid combined with positioning"},{"url":"#what-not-being-dependent-on-font-properties-means","title":"What not being dependent on font properties means","items":[{"url":"#-items-and--content","title":"*-items and *-content"}]},{"url":"#grid-and-position-sticky","title":"Grid and position: sticky"},{"url":"#the-final-boss-centering-a-div","title":"The final boss: centering a <div>"}]},{"url":"#things-we-left-out","title":"Things we left out"},{"url":"#conclusion","title":"Conclusion"}]},"excerpt":"When developers say that CSS is hard, they're usually talking about CSS layout. What often gets omitted though is that developers are assumed to understand and…","frontmatter":{"title":"Understanding the fundamentals of CSS Layout","cover":"/blogs/complete/web_development__isometric.svg","date":"2026-01-22","updated":null},"fields":{"slug":"/blog/understanding-the-fundamentals-of-css-layout/","date":"2026-01-21T23:00:00.000Z","ogFileName":"understanding-the-fundamentals-of-css-layout"}}},"pageContext":{"slug":"/blog/understanding-the-fundamentals-of-css-layout/"}},"staticQueryHashes":["4164364741","425175329"]}