Search code examples
csslayoutflexboxalignmentpositioning

Layout puzzle: align to Left AND Right plus a Centered box All connected with a Line


I am trying to solve this layout puzzle but am stuck in how to get it as elegant, clean and timeless.

Given:

  • a horizontal line of 1 pixel height stretching inside the container its in
  • a vertically as well as horizontally centered box over this line
  • a left aligned textbox
  • and a right aligned text box

What I have tried, is painstakingly increment the percentages until I reached some kind of a middle... warning, the following code is very graphical and ugly!

CSS

author{color: grey}
box{float: left;
     background: blue;
     margin: 0 0 0 46.4%;
     ...
     /* bad coding feel embarrassed showing this */
}
time{color: grey}

HTML (flexible and can be changed)

<author></author>
<box><img src=""/></box>
<time></time>

I first thought this might be solved in flexbox, using justify-content: space-between however, I cannot figure out how to make the line appear there. So I am open for any suggestions whether it's the good old positioning/float or with flexbox. Maybe it would be nice to try to solve it both ways and see which one is the most elegant?

enter image description here


Solution

  • Here is one way to accomplish that, where you use justify-content: space-between to align the author/box/date and an absolute positioned pseudo element to draw the line

    #wrapper {
      position: relative;
      display: flex;
      justify-content: space-between;
    }
    #wrapper::before {
      content: '';
      position: absolute;
      left: 0; right: 0;
      top: 50%; height: 1px;
      background: gray;
    }
    #wrapper > * {
      position: relative;            /*  instead of 'z-index: -1' on the pseudo so
                                         the line stays below the items  */
    }
    
    #author {}
    
    #date {}
    
    #box {
      width: 50px;
      height: 50px;
      background: blue;
    }
    <div id="wrapper">
      <div id="author">
        Author
      </div>
      <div id="box">
      
      </div>
      <div id="date">
        Date
      </div>
    </div>


    Updated based on a comment

    The #wrapper > * rule can in this case be replaced with setting position: relative on the box, which I recommend in favor of giving it a z-index.


    Updated based on a 2nd comment

    As you have issues with the combo Flexbox/script, here is one version without, with the same markup and an almost as short CSS

    #wrapper {
      position: relative;
    }
    #wrapper::before {
      content: '';
      position: absolute;
      left: 0; right: 0;
      top: 50%; height: 1px;
      background: gray;
    }
    
    #author {
      position: absolute;
      top: 0;
      left: 0;
    }
    
    #date {
      position: absolute;
      top: 0;
      right: 0;
    }
    
    #box { 
      position: relative;
      margin: 0 auto;
      width: 50px;
      height: 50px;
      background: blue;
    }
    <div id="wrapper">
      <div id="author">
        Author
      </div>
      <div id="box">
      
      </div>
      <div id="date">
        Date
      </div>
    </div>