Home > Blockchain >  Center div over another div
Center div over another div

Time:08-20

First of all, I know there are a lot of questions with this title and I went through them.

Here is my case and what I tried. I have some divs with dinamically added content. What I want is to place the status on the middle of the dotted border. My problem is that if the content of let's say first div has two lines, then my status won't be on the middle of the dotted line.

How cand I make the status always stay in the middle of the dotted line regardless of other content?

EDIT: This is the mobile view of the component, on the desktop view the status should stay on the bottom right side of the container.

.container {
  width: 500px;
  border: 1px solid black;
  position: relative
}

.border {
  border-bottom: 1px dashed black;
    margin-left: 0px;
    margin-right: 0px;
    position: relative;
    margin-top: 20px;
    margin-bottom: 20px;
    border-left: 0px;
}

.status {
  height: 32px;
  line-height: 32px;
  border-radius: 7px;
  text-align: center;
  padding: 0px 10px;
  width: -moz-fit-content;
  width: fit-content;
  font-size: 13px;
  font-weight: bold;
  color: red;
  background-color: pink;
  position: absolute;
  top: 60%;
  left: 50%;
  transform: translate(-60%, -50%);
}
.status-wrapper {
  margin-top: 0;
}

.text {
  padding: 10px;
}
<div >
  <div >some text </div>
  <div >some other text</div>
  <div ></div>
  <div >more text</div>
  <div >
    <div >my status</div>
  </div>
</div>

CodePudding user response:

Just wrap border and status in a container and set it to relative.

.container {
      width: 500px;
      border: 1px solid black;
      position: relative
    }

    .border-container {
        position: relative;
    }

    .border {
      border-bottom: 1px dashed black;
        margin-left: 0px;
        margin-right: 0px;
        position: relative;
        margin-top: 20px;
        margin-bottom: 20px;
        border-left: 0px;
    }

    .status {
      z-index: 2;
      height: 32px;
      line-height: 32px;
      border-radius: 7px;
      text-align: center;
      padding: 0px 10px;
      width: -moz-fit-content;
      width: fit-content;
      font-size: 13px;
      font-weight: bold;
      color: red;
      background-color: pink;
      position: absolute;
      top: 60%;
      left: 50%;
      transform: translate(-60%, -50%);
    }
    .status-wrapper {
      margin-top: 0;
    }

    .text {
      padding: 10px;
    }
    <div >   
    <div >some text </div>
    <div >some other text</div>
    <div >some more other text</div>
    <div >some more more other text</div>
    <div >
      <div >
        <div >my status</div>
      </div>
      <div ></div>
    </div>
    <div >more text</div>
  </div>

CodePudding user response:

Can't you just put the status inside the border element? Like this:

.container {
  width: 500px;
  border: 1px solid black;
  position: relative
}

.border {
  border-bottom: 1px dashed black;
    margin-left: 0px;
    margin-right: 0px;
    position: relative;
    margin-top: 20px;
    margin-bottom: 20px;
    border-left: 0px;
}

.status {
  height: 32px;
  line-height: 32px;
  border-radius: 7px;
  text-align: center;
  padding: 0px 10px;
  width: -moz-fit-content;
  width: fit-content;
  font-size: 13px;
  font-weight: bold;
  color: red;
  background-color: pink;
  position: absolute;
  top: 60%;
  left: 50%;
  transform: translate(-60%, -50%);
}
.status-wrapper {
  margin-top: 0;
}

.text {
  padding: 10px;
}
<div >
  <div >some text </div>
  <div >some other text</div>
  <div >
    <div >
      <div >my status</div>
    </div>
  </div>
  <div >more text</div>
</div>

CodePudding user response:

One possible solution is to use display: grid and position the .status-wrapper (along with its child) in the same grid-row as the .border element:

/* using CSS custom properties to allow for easier
   theming and future maintenance: */
:root {
  --color-accent: hsl(0 100% 50% / 1);
  --color-accent-90: hsl(0 100% 90% / 50);
  --color-primary: hsl(0 0% 0% / 1);
  --status-block-size: 32px;
  --white: hsl(0 100% 100% / 0.9);
}

.container {
  /* using the CSS keyword 'currentColor' to assign the
     value of the current color property (assigned or
     inherited) as the border-color: */
  border: 1px solid currentColor;
  /* assigning a custom-property as the color property-
     value, using the var() function: */
  color: var(--color-primary);
  /* using CSS grid for layout: */
  display: grid;
  /* specifying one column taking all available space: */
  grid-template-columns: 1fr;
  /* using CSS logical properties in place of 'width' */
  inline-size: 500px;
}

.border {
  /* again, a CSS logical property; in this instance the
     block-dimension (size along the block-axis) is set
     to 100%; in the English language the inline-axis is
     left-to-right, and the block-axis is top-to-bottom: */
  block-size: 100%;
  /* using repeating-linear-gradient() to create the dashed
     "border" effect: */
  background-image: repeating-linear-gradient(90deg, currentColor 0 5px, transparent 5px 10px);
  /* positioning that imgage at 0 on the inline-axis and 50%
     on the block-axis: */
  background-position: 0 50%;
  /* preventing repeats: */
  background-repeat: no-repeat;
  /* sizing the image to take 100% of the inline-axis
     and 1px on the block-axis (for a 1px 'thick'
     'border': */
  background-size: 100% 1px;
  /* in English, equivalent to 'width': */
  inline-size: 100%;
}

.text {
  padding: 10px;
}

.status-wrapper {
  /* reducing the inline-size of the element to the size
     required to show the content of the element: */
  inline-size: fit-content;
  /* centering the element on the inline-axis: */
  justify-self: center;
}
.status {
  /* again, CSS custom properties for easy theming: */
  background-color: var(--color-accent-90);
  /* setting the border-radius according to the
     font-szie: */
  border-radius: 0.2em;
  color: var(--color-accent);
  justify-self: center;
  /* using an outline to create a visual separation
     between the 'status' and the 'border': */
  outline: 0.3em solid var(--white);
  padding-inline: 10px;
}

.border,
.status-wrapper {
  /* centering the elements on the cross-axis; the
     grid is set to columns (block-axis) but the
     content within is still flowing on the
     inline-axis; so align-self is - as 'cross-axis'
     might suggest - centering vertically (in Enlish
     language websites): */
  align-self: center;
  /* placing both the .border and .status-wrapper
     (and any descendants) in:
       grid-row: 3
       grid-column: 1
      using grid-area shorthand: */
  grid-area: 3 / 1;
  /* centering on the inline-axis within the grid-area: */
  justify-self: center;
}
<div >
  <div >some text </div>
  <div >some other text</div>
  <div ></div>
  <div >more text</div>
  <div >
    <div >my status</div>
  </div>
</div>

JS Fiddle demo.

I like the above solution for its relative simplicity, but dislike it because we're hard-coding the grid-area in which to position both the .border and .status-wrapper. I would much prefer to have the position of the .status-wrapper dynamically allocated to match the 'natural' position of the .border element.

Unfortunately, as yet, I've been unable to find a way to allow for that dynamic behaviour.

References:

  • Related