Maintaining scroll position only works when not near the bottom of messages div

前端 未结 3 1699
故里飘歌
故里飘歌 2021-02-20 16:32

I\'m trying to mimic other mobile chatting apps where when you select the send-message textbox and it opens the virtual keyboard, the bottom-most message is still i

3条回答
  •  无人共我
    2021-02-20 17:18

    I think what you want is overflow-anchor

    Support is increasing, but not total, yet https://caniuse.com/#feat=css-overflow-anchor

    From a CSS-Tricks article on it:

    Scroll Anchoring prevents that "jumping" experience by locking the user's position on the page while changes are taking place in the DOM above the current location. This allows the user to stay anchored where they are on the page even as new elements are loaded to the DOM.

    The overflow-anchor property allows us to opt-out of the Scroll Anchoring feature in the event that it is preferred to allow content to be re-flow as elements are loaded.

    Here's a slightly modified version of one of their examples:

    let scroller = document.querySelector('#scroller');
    let anchor = document.querySelector('#anchor');
    
    // https://ajaydsouza.com/42-phrases-a-lexophile-would-love/
    let messages = [
      'I wondered why the baseball was getting bigger. Then it hit me.',
      'Police were called to a day care, where a three-year-old was resisting a rest.',
      'Did you hear about the guy whose whole left side was cut off? He’s all right now.',
      'The roundest knight at King Arthur’s round table was Sir Cumference.',
      'To write with a broken pencil is pointless.',
      'When fish are in schools they sometimes take debate.',
      'The short fortune teller who escaped from prison was a small medium at large.',
      'A thief who stole a calendar… got twelve months.',
      'A thief fell and broke his leg in wet cement. He became a hardened criminal.',
      'Thieves who steal corn from a garden could be charged with stalking.',
      'When the smog lifts in Los Angeles , U. C. L. A.',
      'The math professor went crazy with the blackboard. He did a number on it.',
      'The professor discovered that his theory of earthquakes was on shaky ground.',
      'The dead batteries were given out free of charge.',
      'If you take a laptop computer for a run you could jog your memory.',
      'A dentist and a manicurist fought tooth and nail.',
      'A bicycle can’t stand alone; it is two tired.',
      'A will is a dead giveaway.',
      'Time flies like an arrow; fruit flies like a banana.',
      'A backward poet writes inverse.',
      'In a democracy it’s your vote that counts; in feudalism, it’s your Count that votes.',
      'A chicken crossing the road: poultry in motion.',
      'If you don’t pay your exorcist you can get repossessed.',
      'With her marriage she got a new name and a dress.',
      'Show me a piano falling down a mine shaft and I’ll show you A-flat miner.',
      'When a clock is hungry it goes back four seconds.',
      'The guy who fell onto an upholstery machine was fully recovered.',
      'A grenade fell onto a kitchen floor in France and resulted in Linoleum Blownapart.',
      'You are stuck with your debt if you can’t budge it.',
      'Local Area Network in Australia : The LAN down under.',
      'He broke into song because he couldn’t find the key.',
      'A calendar’s days are numbered.',
    ];
    
    function randomMessage() {
      return messages[(Math.random() * messages.length) | 0];
    }
    
    function appendChild() {
      let msg = document.createElement('div');
      msg.className = 'message';
      msg.innerText = randomMessage();
      scroller.insertBefore(msg, anchor);
    }
    setInterval(appendChild, 1000);
    html {
      height: 100%;
      display: flex;
    }
    
    body {
      min-height: 100%;
      width: 100%;
      display: flex;
      flex-direction: column;
      padding: 0;
    }
    
    #scroller {
      flex: 2;
    }
    
    #scroller * {
      overflow-anchor: none;
    }
    
    .new-message {
      position: sticky;
      bottom: 0;
      background-color: blue;
      padding: .2rem;
    }
    
    #anchor {
      overflow-anchor: auto;
      height: 1px;
    }
    
    body {
      background-color: #7FDBFF;
    }
    
    .message {
      padding: 0.5em;
      border-radius: 1em;
      margin: 0.5em;
      background-color: white;
    }

    Open this on mobile: https://cdpn.io/chasebank/debug/PowxdOR

    What that's doing is basically disabling any default anchoring of the new message elements, with #scroller * { overflow-anchor: none }

    And instead anchoring an empty element #anchor { overflow-anchor: auto } that will always come after those new messages, since the new messages are being inserted before it.

    There has to be a scroll to notice a change in anchoring, which I think is generally good UX. But either way, the current scroll position should be maintained when the keyboard opens.

提交回复
热议问题