Use justify-content: flex-end and to have vertical scrollbar

前端 未结 5 420
無奈伤痛
無奈伤痛 2020-12-16 09:32

I have chat and I need to scroll all content to bottom. I want to use justify-content: flex-end and to have vertical scrollbar.

相关标签:
5条回答
  • 2020-12-16 10:10

    I just had to face this issue myself and, after concluding it is a bug, I came up with a workaround.

    In summary, don't use justify-content: flex-end but rather put a margin-top: auto on the first child. Unlike flex-end this doesn't break the scrollbar functionality, and it bottom-aligns the contents when they're not overflowing the container.

    Example based on @SrdjanDejanovic's fiddle is at https://jsfiddle.net/peter9477/4t5r0t5b/

    In case the example isn't available, here's the relevant CSS:

    #container {
        overflow-y: auto;
        display: flex;
        flex-flow: column nowrap;
        /* justify-content: flex-end; DO NOT USE: breaks scrolling */
    }
    #container > :first-child {
        margin-top: auto !important;
        /* use !important to prevent breakage from child margin settings */
    }
    

    An alternative workaround that I believe I've also used is to add an extra container for the scrollbar. Use the flex-end on the inner container and have the outer container handle the scrolling. I generally dislike workarounds that require adding dummy elements though, so I prefer my CSS-only solution above.

    0 讨论(0)
  • 2020-12-16 10:11

    You have to turn .session-textchat into a flex column then margin-top: auto on .past-messages to send it to the bottom. Then play with overflow-y: scroll and some jQuery:

    function updateScroll() {
      $("#chat").animate({ scrollTop: $('#chat').prop("scrollHeight")}, 1000);
    }
    updateScroll();
    $("#send_button").on('click', updateScroll);
    .session-textchat {
      display: flex;
      flex-direction: column;
      height: 300px;
      margin-bottom: 30px;
      background: #fff;
      overflow-y: scroll;
    }
    .session-textchat .past-messages {
      margin-top: auto;
      width: 100%;
      max-width: 980px;
    }
    .session-textchat .past-messages .receiver,
    .session-textchat .past-messages .sender {
      width: 100%;
      min-height: 47px;
      margin: 0 0 20px 0;
    }
    .session-textchat .past-messages .receiver .message,
    .session-textchat .past-messages .sender .message {
      position: relative;
      padding: 15px;
      -moz-border-radius: 4px;
      -webkit-border-radius: 4px;
      border-radius: 4px;
    }
    .session-textchat .past-messages .receiver {
      text-align: left;
    }
    .session-textchat .past-messages .receiver .message {
      background: #f4f4f4;
      color: #535353;
    }
    .session-textchat .past-messages .sender {
      text-align: right;
    }
    .session-textchat .past-messages .sender .message {
      background: url("../img/rgbapng/0050ff26.png");
      background: rgba(0, 80, 255, 0.15);
      color: #0050ff;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
    
    <div class="container">
      <div id="chat" class="session-textchat">
        <div class="past-messages">
          <div class="receiver">
            <span class="message">
            Good afternoon David. Welcome to your appointment! How are you today?
          </span>
          </div>
          <div class="sender">
            <span class="message">
            Hello doctor. I feel terrible to be honest.
          </span>
          </div>
          <div class="receiver">
            <span class="message">
            I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
          </span>
          </div>
          <div class="sender">
            <span class="message">
            Hello doctor. I feel terrible to be honest.
          </span>
          </div>
          <div class="receiver">
            <span class="message">
            I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
          </span>
          </div>
        </div>
      </div>
      <div class="form-group">
        <textarea class="form-control" rows="5" id="msg"></textarea>
      </div>
      <div class="form-group text-center">
        <button href="#" id="send_button" class="btn btn-success">Send message</button>
      </div>
    </div>

    Look at this full-screen jsFiddle.

    0 讨论(0)
  • 2020-12-16 10:18

    Probably you've already solved this, but I faced this problem too and found a solution by trial and error, so I'm going to share it.

    Having parent container's display set to flex display: flex and child's items align to flex-end align-items: flex-end will prevent overflow-y: auto to work.

    Instead, you can leave you can use next CSS properties for your parent container (in your case session-textchat):

    display: flex;
    flex-direction: column-reverse; /* 'column' for start, 'column-reverse' for end */
    overflow-y: scroll; /* or overflow-y: auto ... */
    

    This will make your child div appear on the bottom of parent container (it will act like flex-end) and enable vertical scroll if content height is bigger than parent container.

    I made a little jsfiddle for you if this sounds confusing: https://jsfiddle.net/lbartolic/9od4nruy/3/

    In jsfiddle you can see header part, content part and footer. Container has fixed height and each part takes required height to fill the container. Content part _b__content will be scrollable if its content is taller than _b__content's height.

    I hope this will help someone. Cheers.

    0 讨论(0)
  • 2020-12-16 10:22

    It seems to be a common bug among the browsers.

    You should distribute your style onto 2 containers: the outer will be scrolled, and the inner will be a flex container. Also, you need some js to keep your message list scrolled to bottom while adding new messages.

    Here is an example of code:

    markup:

    <div id='outer'>
        <div id='inner-scroll'>
            <div id='inner-flex'>
                <div class='flex-item'>Item 1</div>
                <div class='flex-item'>Item 2</div>
                ...
            </div>
    </div>
    

    style:

    #inner-scroll {
        height: 100%;
        overflow: auto;
    }
    
    #inner-flex {
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        min-height: 100%;
    }
    
    .flex-item { /*nothing*/ }
    

    JS:

    function messagePushCallback()
    {
        var scrollable=document.getElementById('inner-scroll');
        scrollable.scrollTo(0, scrollable.scrollHeight-scrollable.clientHeight);
    }
    
    // for an example
    chat.onMessagePush(messagePushCallback);
    
    window.addEventListener('load', messagePushCallback);
    

    In JS, scrollable.scrollHeight shows the whole height of the element, including the space beyond its visible part, while scrollable.clientHeight is for the height of the visible part.

    0 讨论(0)
  • 2020-12-16 10:24

    Also There is also another Solution

    Remove the justify-content and add flex: 1 1 auto; property to the first element(create an empty div)

    Old

    HTML

    <div class="content-reversed">
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </div>
    

    CSS

    .content-reversed {
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
    }
    

    New

    HTML

    <div class="content-reversed">
      <div class="fix"></div> //add this dummy div
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </div>
    

    CSS

    .content-reversed {
      display: flex;
      flex-direction: column;
    }
    .content-reversed .fix {
       flex: 1 1 auto;
     }
    
    0 讨论(0)
提交回复
热议问题