skip to Main Content

I am trying to create a console/CLI type experience using HTML. The input should stay fixed at the bottom of the window, and then commands and output rise up from the bottom and eventually roll off the top of the screen, which allows scrolling once there is enough content to need it.

I’m using Angular for all of this, though I think the only aspect of the design that really makes it Angular specific is the repeating elements (inputs+results using an *ngFor). It would be wonderful if there were a CSS only solution for this, though I’m starting to doubt that one is possible (please prove me wrong!) If I do need to write some javascript to get this behavior, I just want it to play well with Angular (if it isn’t Angular).

(Not shown: input prompt – this part works fine)

HTML

<div id="console-wrapper">
  <div id="console">
    <div class="expression"
         *ngFor="let exp of processorService.expressions">
      <pre class="input">{{exp.input}}</pre>
      <pre class="output">{{exp.output}}</pre>
    </div>
    <div id="anchor"></div>
  </div>
</div>

CSS

#console {
  overflow: scroll;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 20px;
  height: 100%; /*auto; for a different set of problems*/
}
#console * {
  overflow-anchor: none;
}
#anchor {
  overflow-anchor: auto !important;
}

I can get the scrolling behavior I would like, but only if the height of the container div is 100%. If I take this approach, it has two problems:

  1. The content (inputs+results) begin at the top of the container rather than the bottom.
  2. Once there is enough content to create a scrollbar, it doesn’t scroll as new elements are added. The overflow-anchor property partially fixes this, but only after the user scrolls to the bottom themselves the first time.

If I position:absolute the content to try and get it to the bottom, it (of course) all just stacks up on itself.

If I set the height of the container to auto, then the content will begin on the bottom and expand upward exactly as I would like, but once it rolls off the top of the screen, I can’t get scrolling to kick in at all, seemingly no matter what I do.

2

Answers


  1. Chosen as BEST ANSWER

    Ok, I think I figured it out. I needed to add a padded element above the expressions that is 100vh, then, with the anchor element that is already there, it seems to work!

    <div id="console-wrapper">
      <div id="console">
        <div id="pad"></div>
        <div class="expression"
             *ngFor="let exp of processorService.expressions">
          <pre class="input">{{exp.input}}</pre>
          <pre class="output">{{exp.output}}</pre>
        </div>
        <div id="anchor"></div>
      </div>
    </div>
    

    #console {
      overflow: scroll;
      position: absolute;
      left: 0;
      right: 0;
      bottom: 30px;
      height: 100%;
    }
    #console * {
      overflow-anchor: none;
    }
    #pad {
      height: 100vh;
    }
    #anchor {
      overflow-anchor: auto !important;
      height: 1px;
    }
    

  2. One possible way to achieve that with CSS would be to use vertical-align. To be able to use vertical-align, you will have to set the display to either table-cell or inline-block. I guess, you would have to see, which one affects the rest of the CSS the least.

    So, your CSS would become:

    #console {
      overflow: scroll;
      position: absolute;
      left: 0;
      right: 0;
      bottom: 20px;
      height: 100%; /*auto; for a different set of problems*/
      display: inline-block;
      vertical-align: bottom;
    }
    

    or

    #console {
      overflow: scroll;
      position: absolute;
      left: 0;
      right: 0;
      bottom: 20px;
      height: 100%; /*auto; for a different set of problems*/
      display: table-cell;
      vertical-align: bottom;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search