两个并排的元素,一个 unknown/variable 宽度,另一个填充水平 space 的剩余部分?

Two side-by-side elements, one unknown/variable width, the other filling up remainder of horizontal space?

我正在开发 UI 内置 HTML/CSS/JS (Angular) 的视频游戏。这个问题特别与 UI 的聊天组件有关,它是一个带有输入字段的聊天框,发送按钮位于其下方的同一行。

输入和提交的简化标记如下所示(删除了所有 angular 标记):

<div class="chat-controls">
    <form class="chat-form">
            <input type="text" class="chat-input" />
    </form>
    <a href class="chat-send btn">Send</a>
</div>

这是我要解决的问题:我们的游戏针对许多不同的语言进行了本地化,这意味着“发送”按钮的水平大小在一种语言与另一种语言之间会根据翻译而有很大差异。因此我无法预测发送按钮的宽度。我希望文本输入框在发送按钮旁边水平填充 space 的其余部分(固定 .chat-controls 宽度 - 可变 .chat-send 宽度 = .chat-input 宽度)。

棘手的部分是我试图在不使用 JS 的情况下以纯 CSS 的方式执行此操作。我知道我可以用 JS 测量 .chat-send 并相应地分配 .chat-input 的宽度(或者做一些像添加 CSS class 到表示语言版本和硬编码的祖先CSS 中每种语言的值),但最灵活和可维护的解决方案将是纯粹的 CSS.

这无法通过向右浮动发送按钮来实现,因为文本输入将在发送按钮下方流动,或者我需要知道发送按钮的宽度才能将 .chat-input 上的右填充分配给补偿。如果 calc() 可以预测兄弟元素的宽度,这将是微不足道的,但遗憾的是它不能。我也玩过 flexbox 一段时间,它似乎不适合这种情况。我目前的解决方法是将发送按钮的宽度设置为当前可以达到的最大尺寸(俄语,大约是英语 "Send" 长度的两倍)但这看起来不太好。

我的问题是:是否有任何合理的方法可以在纯 CSS 中执行此操作,或者我只需要在 JS 中执行此操作?请注意,浏览器兼容性不是问题,因为这是使用 Chromium 嵌入式框架实现的,因此几乎所有内容都受支持。

您可以将 displayflextable 一起使用。

<h1>display:flex;</h1>
<div class="chat-controls">
    <form class="chat-form">
            <input type="text" class="chat-input" />
    </form>
    <a href class="chat-send btn">Send</a>
</div>
<h1>display:table;</h1>
<div class="chat-controls bis">
    <form class="chat-form">
            <input type="text" class="chat-input" />
    </form>
    <a href class="chat-send btn">Send</a>
</div>

使用以下 CSS 来测试两个版本

.chat-controls {
  display:flex;
}
.chat-form {
  flex:1;
}
.chat-input , .bis .chat-form{
  width:100%;
}
.btn {
  padding:0 1em;
}
.bis {
  display:table;
  width:100%;
}
.bis .chat-form, .bis .btn {
  display:table-cell;
}

您可以在这里在线玩它:http://codepen.io/gc-nomade/pen/MYmVZM

float 也是一个选项,如果您不介意在 HTML 中将发送 link/button 放在前面(演示链接中的第三个示例)。