JSFiddle - React, Tailwind, and code Playground

HTML

<label for="txtFirstName">First Name (<span id="fnLengthInfo"></span>)</label>
 <br>
 <input type="text" id="txtFirstName" class="txtInput" data-maxbytesize="8" size="15" value="Ráðúlfr">

 <br><br>
 <label for="txtLastName">Last Name (<span id="lnLengthInfo"></span>)</label>
 <br>
 <input type="text" id="txtLastName" class="txtInput" data-maxbytesize="12" size="15" value="þåræsdøttirð">

CSS

input {
   font-size: 2em;
   padding: 5px;
 }

 input.invalid {
   border: 1px solid red;
   background-color: #fae1dc;
   color: red;
 }

JavaScript

document.querySelectorAll('.txtInput').forEach(e => {
  e.addEventListener('input', OnInput_TxtInput);
})

function OnInput_TxtInput(event) {
  const txtInputTarget = event.target;
  const txtInputValue = txtInputTarget.value;
  const txtInputId = txtInputTarget.id;
  const displayName = txtInputTarget.dataset.displayname;
  const byteLengthOfInput = getStringByteLength(txtInputValue);
  const charLength = txtInputValue.length;
  const maxByteSize = parseInt(txtInputTarget.dataset.maxbytesize);

  if (byteLengthOfInput > maxByteSize) {
    txtInputTarget.classList.add('invalid');
  } else {
    txtInputTarget.classList.remove('invalid');
  }

  let lengthInfoElement = document.getElementById('fnLengthInfo');
  if (txtInputId === 'txtLastName') {
    lengthInfoElement = document.getElementById('lnLengthInfo');
  }
  lengthInfoElement.innerHTML = `Byte Length: ${byteLengthOfInput} | Char Length: ${charLength}`;
}

function getStringByteLength(str) {
  str = typeof(str) === 'string' ? str : '';
  const byteSize = new Blob([str]).size;
  return byteSize;
}