You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go开发简易聊天界面 CSS布局导致底部消息无法全部显示

问题描述

使用Go语言开发简易聊天应用时,CSS样式出现异常:预期页面完整展示所有消息段落,但消息内容累计到展示区域底部时,部分消息被遮挡无法正常显示,实际效果如下:
消息被底部表单遮挡的实际效果
当前单文件整合的HTML/CSS/JavaScript代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>CodeChallenge</title>
    <style>
        .form {
            position: fixed;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: #f9f9f9;
            border-top: 1px solid #78b8ef;
            padding: 5px 10px;
        }
        .form .placeholder,
        .form .input-message,
        .form button {
            display: block;
            margin-bottom: 5px;
        }
        .form .input-message {
            padding: 7px;
            border: 1px solid #ecebeb;
            border-radius: 4px;
            width: -webkit-fill-available;
        }
        .form button {
            width: 100%;
            color: white;
            padding: 7px 10px;
            border-radius: 4px;
            background-color: #78b8ef;
            border: 1px solid #5a9ed8;
        }
        .container {
            margin-bottom: 50px;
        }
        .container p {
            display: block;
        }
    </style>
</head>
<body>
    <div class="container"></div>
    <div class="form">
        <form onsubmit="app.doSendMessage(); return false;">
            <div class="placeholder">
                <label>Hello <b class="username"></b>. Say something:</label>
            </div>
            <input class="input-message" type="text" placeholder="Enter message">
            <button type="submit">Send</button>
        </form>
    </div>

    <script type="application/javascript">
        var app = {}
        app.ws = undefined
        app.container = undefined

        app.print = function (message) {
            let el = document.createElement("p")
            el.innerHTML = message
            app.container.append(el)
        }

        app.doSendMessage = function () {
            var messageRaw = document.querySelector('.input-message').value
            app.ws.send(JSON.stringify({
                Message: messageRaw
            }));

            var message = '<b>me</b>: ' + messageRaw
            app.print(message)
        }

        app.init = function () {
            if (!(window.WebSocket)) {
                alert('Your browser does not support WebSocket')
                return
            }


            var name = getCookie("username");


            document.querySelector('.username').innerText = name

            app.container = document.querySelector('.container')

            app.ws = new WebSocket("ws://localhost:8081/socket/ws?username=" + name)
            app.ws.onopen = function () {
                fetch('http://localhost:8081/message?limit=50')
                    .then(response=>response.json())
                    .then(data=>{
                        console.log(data)
                        data.sort(function(a,b){
                            return new Date(a.RegisterDate) - new Date(b.RegisterDate);
                        });
                        console.log(data)
                        data.forEach(obj => {
                            let message = '<b>' + obj.From + '</b>: ' + obj.Message + ' ' + obj.RegisterDate
                            app.print(message)
                    })})
                .then(() => {
                    var message = '<b>me</b>: connected'
                    app.print(message)
                }
                )

            }

            app.ws.onmessage = function (event) {
                var res = JSON.parse(event.data)

                var message = ''
                if (res.Type === 'New User') {
                    message = 'User <b>' + res.From + '</b>: connected'
                } else if (res.Type === 'Leave') {
                    message = 'User <b>' + res.From + '</b>: disconnected'
                } else {
                    message = '<b>' + res.From + '</b>: ' + res.Message
                }

                app.print(message)
            }
        }

        window.onload = app.init

        function getCookie(cName) {
            const name = cName + "=";
            const cDecoded = decodeURIComponent(document.cookie);
            console.log(cDecoded)
            const cArr = cDecoded.split('; ');
            console.log(cDecoded)
            let res;
            cArr.forEach(val => {
                if (val.indexOf(name) === 0) res = val.substring(name.length);
            })
            return res
        }
    </script>
</body>
</html>
故障原因
  • 底部发送表单使用position: fixed固定在视口底部,脱离正常文档流,原本给消息容器.container设置的margin-bottom: 50px远小于表单实际渲染高度(表单包含提示文本、输入框、按钮三个块级元素,加上内边距、外边距总高度约130px),导致靠近底部的消息被表单遮挡。
  • 新消息追加到DOM后没有自动滚动逻辑,历史消息加载完成、新消息发送/接收时,页面不会自动定位到最新消息位置,需要手动拖动滚动条才能查看。
修复方法
  1. 调整消息容器底部留白:放弃硬编码固定margin值,在初始化逻辑中动态获取底部表单的实际高度,自动计算需要预留的底部空间,从根源避免内容被遮挡,同时优化消息段落的排版样式。
    将原有CSS中.container和.container p的样式替换为:
    .container {
        padding: 0 10px;
    }
    .container p {
        display: block;
        margin: 8px 0;
        word-break: break-all;
    }
    
    在app.init方法中,获取到container元素的代码后新增动态设置留白的逻辑:
    app.container = document.querySelector('.container')
    // 动态计算底部表单高度,设置对应留白,额外加10px避免内容贴边
    const formEl = document.querySelector('.form')
    app.container.style.marginBottom = formEl.offsetHeight + 10 + 'px'
    
  2. 新增自动滚动到底部逻辑:每次新增消息后,自动将页面滚动到最底部,保证最新消息始终可见。修改app.print方法:
    app.print = function (message) {
        let el = document.createElement("p")
        el.innerHTML = message
        app.container.append(el)
        // 滚动到页面底部展示最新消息
        window.scrollTo({
            top: document.body.scrollHeight,
            behavior: 'smooth'
        })
    }
    
修复效果

所有历史消息、实时接收/发送的消息都不会被底部表单遮挡,消息加载、新消息到来时页面会平滑滚动到最新消息位置,排版间距符合聊天应用的常规使用习惯。

内容的提问来源于stack exchange,提问作者Wincenty Bertoni Lech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 21:15:48