Home > Mobile >  CSS - display: flex and position: absoulte moves anchor point
CSS - display: flex and position: absoulte moves anchor point

Time:01-25

I have a flex element and three children. The second child should overlap the first using position absolute, like this:

Expected:

Expected

Note that the second child should be on top of the first child, not next to it.

However, setting display: flex on the parent seems to shift the anchor or reference point of the absolute element to start of the div. The actual outcome is this:

Actual result:

Actual

Putting the second child in the first or third element is not an option, because they have overflow: scroll. So is using any other display property on the parent, because my layout relies on display: flex. I know these solutions have been suggested on other posts, however, I have not found a question/answer that addresses the problem with these constraints.

It would be okay to use something else but display: absolute on the second child, like a negative margin, but I couldn't get this to work either.

If anyone knows if this is even possible or has any suggestions it would be greatly appreciated.

To see it in action here is my code, simplified to demonstrate the issue:

body{
  color: white;
}
.wrapper{
  display: flex;
}
.wrapper .a{
  background-color: blue;
  flex-grow: 1;
}
.wrapper .b{
  position: absolute;
  background-color: rgba(255, 0, 0, 0.5);
  min-width: 40px;
}
.wrapper .c{
  background-color: green;
  min-width: 40px;
}
<div >
  <div >A</div>
  <div >B</div>
  <div >C</div>
</div>

CodePudding user response:

It appears to the left of your div because it's been taken out of the flow of the document. In fact, it's actually positioned relative to the viewport and not the parent wrapper. To make it positioned to the wrapper, set position: relative to the wrapper class to create a new containing block

To ensure it overlaps the end of div 'a' I've used the 'right' property to move the right hand edge leftwards by a value that I've set usnig a custom property that I've set to both that and div 'c'. See annotated example below.

.wrapper {
  position: relative;
  display: flex;
  color: white;
  --element-c-width: 40px; /* set this to both set the width of div 'c' and how far we move div 'b' leftwards */
}

.a {
  background-color: blue;
  flex-grow: 1;
}

.b {
  position: absolute;
  background-color: rgba(255, 0, 0, 0.5);
  min-width: 40px;
  right: var(--element-c-width); /* from the right hand side of the wrapper div, move it leftwards by this value */
}

.c {
  background-color: green;
  min-width: var(--element-c-width);
}
<div >
  <div >A</div>
  <div >B</div>
  <div >C</div>
</div>

CodePudding user response:

Add position: relative; to the parent

When an element is given position: absolute; property, it'll be positioned against the nearest parent element with relative, absolute, or fixed positioning. If it doesn't find it, it'll be positioned against the body. In this case, you might want to add position: relative; to the .wrapper element as it's the reference point for absolute positioning.

Add a positioning value to the element

By definition, position: absolute; element will be absolutely positioned with a particular value set. That is, how far away from top, right, bottom, or/and left edges. When you don't provide any value, it'll just be stuck to the top left corner, which is what's happening here.

Need a set value for the positioning

position: absolute; takes an element out of a normal content flow. That is, elements around it won't affect its size or positioning; thus absolute position. To achieve what you showed in the diagram, you need to specify the width for .c element and use the same exact value to position the .b element from the right edge.

See the snippet below for reference.

body{
  color: white;
  --width: 80px;
}
.wrapper{
  display: flex;
  position: relative;
}
.wrapper .a{
  background-color: blue;
  flex-grow: 1;
}
.wrapper .b{
  position: absolute;
  right: var(--width);
  background-color: rgba(255, 0, 0, 0.5);
  min-width: 40px;
}
.wrapper .c{
  background-color: green;
  width: var(--width);
}
<div >
  <div >A</div>
  <div >B</div>
  <div >C</div>
</div>

CodePudding user response:

try this instead:

.wrapper {
  display: flex;
  justify-content: center;
  align-items: stretch;
  width: 100%;
  position: relative;
  height: 100px;
}

.wrapper div {
  flex: 1;
  flex-basis: calc(100% / 3) position:absolute;
}

.wrapper .a {
  background-color: blue;
  flex-grow: 2;
}

.wrapper .b {
  background-color: rgba(255, 0, 0, 0.5);
}

.wrapper .c {
  background-color: green;
}
<div >
  <div >A</div>
  <div >B</div>
  <div >C</div>
</div>
and make sure to set .a as flex-grow:2; and paretn div's position as relative, and its children's as absolute

  • Related