I am working on a video game UI that is built in HTML/CSS/JS (Angular). This question has specifically to do with the chat component of the UI, which is a chat box with an input field and send button on the same line beneath it.
The simplified markup for the input and submit looks like this (removed all the angular markup):
<div class="chat-controls">
<form class="chat-form">
<input type="text" class="chat-input" />
</form>
<a href class="chat-send btn">Send</a>
</div>
Here's the problem I'm trying to solve: our game is localized for many different languages, meaning that the horizontal size of the Send button varies dramatically from one language to the next depending on the translation. Therefore I cannot predict the Send button width. I would like the text input box to fill the remainder of the space horizontally next to the send button (fixed .chat-controls
width - variable .chat-send
width = .chat-input
width).
The tricky part is I'm trying to do this in pure CSS without using JS. I know I can measure .chat-send
with JS and assign the width of .chat-input
accordingly (or do something like add a CSS class to an ancestor that denotes the language version and hardcode the values for each language in CSS), but the most flexible and maintainable solution would be pure CSS.
This cannot be achieved with floating the send button right, since the text input will then either flow underneath the send button or I need to know the width of the send button to assign right padding on .chat-input
to compensate. If calc()
could predict the width of a sibling element this would be trivial, but alas it cannot. I played with flexbox for a while as well and it doesn't seem appropriate for this situation. My current fix is to make the send button the width of the maximum size it can currently be (Russian, which is about twice the length of "Send" in English) but this doesn't look too good.
My question is: is there any reasonable way to do this in pure CSS, or do I just need to do it in JS? Note that browser compatibility is not an issue as this is implemented with Chromium Embedded Framework so just about everything is supported.
you can use display
with either flex
or table
.
<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>
with this following CSS to test both version
.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;
}
You can play with it online here : http://codepen.io/gc-nomade/pen/MYmVZM
float
is also an option if you do not mind to put the send link/button ahead in HTML (third exemple in the demo linked).