I went with Avner Solomon's solution, as proposed in the comments of one of the above sections.
You need a div element wrapping an input and another div element that contains your label:
<div class="input-container">
<!-- this element is hidden from display and screen readers. -->
<div class="input-hidden-label"
aria-hidden="true">
Your placeholder text
</div>
<input class="input"
type="text"
placeholder="Your placeholder text"/>
</div>
Assuming the font styles for the input-hidden-label and the input are the same, you will see a line of text alongside the input. The text will be the same length as the input, give or take a few pixels.
You can then apply these styles:
.input-container {
display: inline-block;
margin-bottom: 2em;
}
.input {
display: inline;
width: 100%;
font-size: 16px;
font-family: Times;
}
.input-hidden-label {
height: 0;
visibility: hidden;
}
This hides the label by giving it height: 0, and removing visibility. But, the width remains. The div that contains the input and the label matches the width of its longest child. If you then set the input to width: 100%, it will match the parent width, which already matches the placeholder.
See this fiddle.
Caveats
This idea is not very accessible, nor is this solution. You should include a label for the input, and not rely on the placeholder itself as a label.