Search code examples
htmlcsspositionflexbox

dimensions and position of overflow element with css


I'll start with the code and image which will make it easier to explain what I want to achieve and the problems I'm facing.

 body,
 html {
   width: 100%;
   height: 100%;
   margin: 0px;
   padding: 0px;
 }
 .container {
   box-sizing: border-box;
   width: 100%;
   height: 100%;
   display: flex;
   flex-direction: column;
   padding: 10px;
   border: 1px solid black;
 }
 .topPanel {
   flex-grow: 1;
   background-color: green;
 }
 .bottomPanel {
   padding: 10px 0px;
   position: relative;
   background-color: black;
 }
 .bottomPanel .alert {
   position: relative;
   top: -35px;
   background-color: grey;
   text-align: center;
 }
 .bottomPanel .message {
   color: white;
   text-align: center;
 }
<div class="container">
  <div class="topPanel"></div>
  <div class="bottomPanel">
    <div class="alert">
      alert
    </div>
    <div class="message">
      message
    </div>
  </div>
</div>

(code in JSFiddle)

How it looks:

enter image description here

The topPanel occupies most of the height of the container, and the bottomPanel can vary in it's height.

The alert element needs to have the width of the bottomPanel and be exactly above it (in the code/image there's a gap between them but that's just to show that it's above it, the gap shouldn't be there).
The alert height can also vary, and the height shouldn't be hardcoded but in relation to the bottomPanel.

The alert is in both aspects of logic and semantics should be a child of bottomPanel and not the topPanel.

The problem I'm facing is that with position: relative the height of topPanel includes the height of alert even though it overflows.
If I add overflow then the alert isn't visible.
If I change to position: absolute then the width of the alert isn't extended and width: 100% will make it have the width of the container and not the parent element.

Any ideas how I can make it work with only css?
I thought of maybe using flex here as well, but thought that maybe someone will have a better idea.

Thanks.


Solution

  • Make the .bottomPanel it's own flex-container, add position:relative.

    Then the .alert can be:

    .bottomPanel .alert {
      background-color: rgba(0, 0, 0, 0.5);
      text-align: center;
      position: absolute;
      width: 100%;
      bottom: 100%;
    }
    

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    body,
    html {
      height: 100%;
    }
    .container {
      height: 100%;
      display: flex;
      flex-direction: column;
      padding: 10px;
    }
    .topPanel {
      flex: 1;
      background-color: green;
    }
    .bottomPanel {
      display: flex;
      flex-direction: column;
      background-color: black;
      position: relative;
    }
    .bottomPanel .alert {
      background-color: rgba(0, 0, 0, 0.5);
      text-align: center;
      position: absolute;
      width: 100%;
      bottom: 100%;
      color: white;
    }
    .bottomPanel .message {
      color: white;
      text-align: center;
    }
    <div class="container">
      <div class="topPanel"></div>
      <div class="bottomPanel">
        <div class="alert">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima, voluptatum.
        </div>
        <div class="message">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reiciendis consequatur enim laboriosam excepturi ex nulla dolorum vitae, officia sapiente, laborum? Possimus eius odio, recusandae tempora, soluta harum minus consequatur quibusdam, blanditiis
          in voluptatum sit laborum!
        </div>
      </div>
    </div>