<div>
  <autowidth-input placeholder='abc'></autowidth-input>
</div>
autowidth-input {
  min-width: 50px;
}
const template = document.createElement('template');
 
template.innerHTML = `
  <style>
    :host {
      display: inline-block;
      vertical-align: top;
      align-items: center;
      position: relative;
      /*border: solid 1px;*/
    }
    :host::after {
      width: auto;
      min-width: 1em;
      content: attr(data-value) ' ';
      visibility: hidden;
      white-space: pre-wrap;
      font: inherit;
    }
    input {
      font: inherit;
      width: 100%;
      min-width: 1em;
      position: absolute;
    }
  </style>
  <input size='1'></input>
`;
 
class AutoWidthInput extends HTMLElement {
  _input: HTMLInputElement;
  constructor() {
    super();
    this._shadowRoot = this.attachShadow({ mode: 'open' });
    this._shadowRoot.appendChild(template.content.cloneNode(true));
    this._input = this._shadowRoot.querySelector('input')
  }
  
  connectedCallback () {
    this._input.addEventListener('input', (e) => {
      this.dataset.value = this._input.value;
    });
  }
  public get value() {
    return this._input.value;
  }
  public set value(v: string) {
    this._input.value = v;
  }
  static get observedAttributes (): string[] {
    return ['placeholder'];
  }

  attributeChangedCallback (name: string, oldVal: string | null, newVal: string | null) {
      this._input.setAttribute(name, newVal);
  }

}
 
window.customElements.define('autowidth-input', AutoWidthInput);
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.