Bas
Bas

Reputation: 1433

CSS Flexbox with position absolute confusion

I'm confused how this works could someone walk me through what exactly happened?

body,
html {
  padding: 0;
  margin: 0;
  height: 100vh;
  width: 100%;
}

.chat-break {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 20px;

}

.chat-break .line {
  border-bottom: 1px solid #ddd;
  width: 100%;
}

.chat-break .date {
  color: #B5B5B5;
  position: absolute;
  background-color: #fff;
  padding-left: 8px;
  padding-right: 8px;
  
}
<div class="chat-break">
    <div class="line">
    </div>
    
    <p class="date">Today</p>
</div>
  

My understanding:

Upvotes: 4

Views: 3879

Answers (1)

Dai
Dai

Reputation: 155658

Preface:

  • The top, right, bottom, and left properties are collectively referred to as "box inset" properties.
  • Keep in mind that all CSS properties that aren't explicitly set will have default values that are either "initial" values or inherited values.
    • So unless explicitly specified otherwise, every element has position: static;.
    • The initial value for all of the box-inset properties is auto, regardless of their element's position and display property.
      • But the behaviour of the auto value does depend on the element's position and/or formatting context.
  • CSS has a lot of surprising and counter-intuitive behaviour.

Why <div class="line"> fills the width of the page:

  • <div class="chat-break"> has display: flex;, which makes it a flex-parent.
    • All immediate child elements (with certain exceptions) of a flex-parent, that have position: static, are flex-items.

    • Therefore<div class="line"> is a flex-item.

    • Therefore<p class="date"> is not a flex-item because it has position: absolute;.

      • (Generally speaking) elements with position: absolute; are not subject to their layout-container's layout rules and are re-positioned with absolute-coordinates where the origin is in their-closet-ancestor-element-without-position: static; (yes, that's a mouthful).
        • This is why position: relative; is being applied to <div class="chat-break">.
  • Therefore <div class="chat-break"> is a flex-parent with only one flex-item, despite having two element children.
    • And because it has justify-content: center; it means that its single flex-item (<div class="line">) will be centered.
  • Also, because <div class="chat-break"> has display: flex; (rather than display: inline-flex) it means that <div class="chat-break"> is a block-level element, so it fills the width of its container, which is <body>, which fills the width of the viewport.
    • And because <div class="line"> also has width: 100%; (which becomes flex-basis: 100%;) it means the <div class="line"> will fill the width of <div class="chat-break">.
    • Therefore <body>, <div class="chat-break">, and <div class="line"> (in that order) will fill the width of the viewport.

Why <p class="date"> is centered:

  • As <p class="date"> uses auto for all its box inset properties (i.e. top, right, etc) with position: absolute; then the computed value of those properties is the same as if <p class="date"> was position: static;.
    • However, if <p class="date"> was position: static; then it would be a flex-item and would share its flex row with <div class="line"> - which would mean it would be located somewhere off to the right of the line (due to justify-content: center;).
      • But it's actually centered, because this is a special-case scenario that's specifically specified in the specification...

        https://www.w3.org/TR/css-flexbox-1/#abspos-items

        4.1. Absolutely-Positioned Flex Children

        As it is out-of-flow, an absolutely-positioned child of a flex container does not participate in flex layout.

        The static position of an absolutely-positioned child of a flex container is determined such that the child is positioned as if it were the sole flex item in the flex container, assuming both the child and the flex container were fixed-size boxes of their used size. For this purpose, auto margins are treated as zero.

It's well-worth reading the rest of the section as it also covers other brain-stretching scenarios, like "what if align-self: center; is used"?

Upvotes: 6

Related Questions