<!-- data-max が上限文字数 --> <div class="bnto-count" data-bnto-count data-max="30"> <textarea rows="3" placeholder="30文字まで入力できます" aria-label="コメント"></textarea> <span class="num" aria-live="polite">あと30文字</span> </div>
.bnto-count { --c1: hsl(168 34% 45%); /* フォーカス色 */ max-width: 290px; } .bnto-count textarea { display: block; width: 100%; min-height: 72px; padding: 10px 12px; border: 2px solid #DFE9F1; border-radius: 12px; background: #fff; font: inherit; line-height: 1.7; resize: vertical; transition: border-color .2s; } .bnto-count textarea:focus { outline: none; border-color: var(--c1); } .bnto-count .num { display: block; margin-top: 6px; text-align: right; font-size: 12px; font-weight: 800; color: #8a8478; } /* 超過したら赤に */ .bnto-count.is-over textarea { border-color: #E0453A; } .bnto-count.is-over .num { color: #E0453A; }
// data-bnto-count を自動検出して初期化(複数設置OK・二重実行OK)
(function () {
document.querySelectorAll('[data-bnto-count]').forEach(function (box) {
if (box.dataset.bntoInit) return;
box.dataset.bntoInit = '1';
var field = box.querySelector('textarea, input');
var num = box.querySelector('.num');
var max = parseInt(box.dataset.max, 10) || 100;
function update() {
var rest = max - field.value.length;
num.textContent = rest >= 0 ? 'あと' + rest + '文字' : Math.abs(rest) + '文字オーバー';
box.classList.toggle('is-over', rest < 0);
}
field.addEventListener('input', update);
update();
});
})();
使い方のコツ
上限は data-max 属性を変えるだけです。「超過しても入力はできるが赤く警告」というSNS風の挙動です。そもそも超過入力を禁止したい場合は textarea に maxlength を併用してください。