Атрибут maxlength (от английского «максимальная длина») задаёт, сколько знаков можно ввести в текстовое поле. Когда лимит достигнут, браузер перестаёт принимать новые знаки. Работает атрибут в <input> и <textarea>, числом в кавычках, без скриптов.
В этой статье
- Атрибут maxlength в HTML: что это и для чего нужен
- Для каких тегов и типов input работает maxlength
- Какое значение можно записать в maxlength
- Что делает maxlength при наборе, вставке и замене выделенного
- Почему maxlength не обрезает value из разметки и из скрипта
- Как maxlength считает знаки: эмодзи, акценты и переводы строк
- Что делает maxlength при отправке формы: tooLong
- Счётчик знаков для textarea с maxlength
- Как ограничить длину числового поля, если maxlength не работает
- Как менять maxlength через JavaScript и jQuery
- Maxlength не защищает данные: проверка на сервере
- Частые ошибки с атрибутом maxlength
- Шпаргалка по атрибуту maxlength
Атрибут maxlength в HTML: что это и для чего нужен
Лимит нужен там, где длина заранее известна: логин, индекс, код из письма, короткий комментарий. Записывают его одним числом в открывающем теге.
<label for="login">Логин</label>
<input id="login" maxlength="10">
Наберите больше десяти знаков: лишние не появятся. Свойство maxLength показывает, какой лимит прочитал браузер.
Лимит действует на набор с клавиатуры и на вставку из буфера. Сообщений об ошибке при этом нет: знак просто не появляется, поэтому посетителю полезно показать лимит рядом с полем.
Для каких тегов и типов input работает maxlength
Атрибут работает у <input> с текстовыми типами и у <textarea>. У <select>, <button> и <div> его нет. Из типов input лимит принимают text, search, url, tel, email и password. У number браузер лимит не учитывает, хотя свойство maxLength при этом читается.
<input type="text" maxlength="3">
<input type="tel" maxlength="3">
<input type="number" maxlength="3"> <!-- не работает -->
<textarea maxlength="3"></textarea>
Выберите поле и наберите 12345. Везде, кроме number, влезут только три знака, у number лимит не действует.
| Где прописан maxlength | Что получится | Работает |
|---|---|---|
text, search, url, tel | Лишние знаки не вводятся | Да |
email, password | Лишние знаки не вводятся | Да |
<textarea> | Лишние знаки не вводятся | Да |
number | Лимит не действует | Нет |
date, time, month, week | Значение задаёт сам браузер | Нет смысла |
color, range, checkbox, radio, file | Текста в этих полях нет | Нет смысла |
<select>, <button>, <div> | Атрибута у этих тегов нет | Нет |
Подробнее о значениях type рассказано в уроке «Поля ввода: input и его типы ».
Какое значение можно записать в maxlength
Записывать нужно целое число не меньше нуля. Дробное число браузер обрежет до целой части, а текст после цифр отбросит: записи maxlength="5.7" и maxlength="5px" дают лимит в пять знаков. Отрицательное число, слово и пустая строка отключают лимит совсем. Запись maxlength="0" запрещает любой ввод.
<input maxlength="5">
<input maxlength="5.7"> <!-- лимит 5 -->
<input maxlength="-5"> <!-- лимита нет -->
<input maxlength="abc"> <!-- лимита нет -->
<input maxlength="0"> <!-- ввод запрещён -->
Выберите значение и наберите abcdefghij. Свойство maxLength показывает -1, когда лимита нет.
Если атрибута нет, свойство maxLength равно -1. Поэтому запись вроде maxlength="abc" вместо числа не ломает страницу, но и ничего не ограничивает.
Что делает maxlength при наборе, вставке и замене выделенного
Браузер ограничивает не только набор по клавишам. При вставке из буфера он берёт столько знаков, сколько ещё помещается: если лимит пять, а в поле уже два знака, из вставляемой строки уйдут в поле три. При замене выделенного текста учитывается длина новой строки, а не старой.
<input maxlength="5" value="ab">
<!-- после вставки 1234567 в конец получится ab123 -->
<!-- если выделить всё и заменить, получится 12345 -->
Первая кнопка вставляет строку в конец поля, вторая заменяет выделенный текст. Лишнее отбрасывается.
Если поле уже заполнено до лимита, вставка в середину ничего не добавит: сначала нужно удалить часть текста. Событие beforeinput срабатывает на каждую попытку ввода, а input только тогда, когда текст реально изменился.
Почему maxlength не обрезает value из разметки и из скрипта
Лимит проверяет только ввод посетителя. Если значение длиннее лимита записано в разметке через value или присвоено из скрипта, браузер сохранит его как есть. Поле при этом считается верным, пока посетитель его не изменит.
<input id="i" maxlength="3" value="abcdefgh">
<script>
i.value = '123456'; // длиннее лимита, но поле верное
console.log(i.validity.tooLong); // false</script>
Сначала поле верное, хотя в нём восемь знаков. Нажмите Backspace в конце поля: теперь свойство tooLong равно true.
После первой правки браузер сравнивает длину с лимитом и помечает поле неверным: проверка checkValidity() возвращает false. Удалять лишнее при этом приходится самому посетителю, браузер текст не обрезает.
Как maxlength считает знаки: эмодзи, акценты и переводы строк
Длина считается в кодовых единицах UTF-16, а не в знаках, которые видит человек. Буквы кириллицы и латиницы занимают одну единицу, а смайлик две. Браузер не разрезает смайлик пополам: если для него не хватает места, он не появится. Знак из двух кодов, например «e» и отдельный акцент, считается как две единицы и может потерять акцент.
<input maxlength="4">
<!-- абв : 3 единицы, влезает -->
<!-- смайлик : 2 единицы, после абв не влезает -->
<!-- e и акцент : 2 единицы -->
Добавьте абв, потом смайлик: он не поместится. Строка «символов на глаз» считается через Intl.Segmenter.
В <textarea> переносы строк считаются за один знак, это показала проверка в браузере. По данным MDN, в WebView на iOS до версии 17 перенос считался за два знака, поэтому на старых устройствах лимит в <textarea> может выбираться раньше.
Что делает maxlength при отправке формы: tooLong
Поле считается неверным, если пользователь изменил текст и тот оказался длиннее лимита. Такая форма не отправляется: на поле срабатывает событие invalid, а свойство validity.tooLong становится true. Если же текст длиннее лимита попал в поле из разметки или скрипта и посетитель его не трогал, форма уйдёт на сервер целиком.
<form>
<input name="a" maxlength="3" value="abcdefgh">
<button type="submit">Отправить</button>
</form>
Первая отправка проходит: поле не правили. После Backspace в конце поля отправка блокируется.
Текст сообщения браузер берёт свой и показывает на языке посетителя. Подробнее о проверке полей рассказано в уроке «Встроенная валидация форм ». Если нужна и нижняя граница, добавьте minlength, а обязательность задаёт атрибут required. Поля с readonly и disabled длину не проверяют.
Счётчик знаков для textarea с maxlength
Раз лимит молча останавливает ввод, рядом с полем показывают счётчик. Значение берут из свойств maxLength и value.length на событии input. Когда осталось мало знаков, счётчик можно выделить, но не одним цветом: нужен ещё и текст.
<textarea id="t" maxlength="60"></textarea>
<p>Осталось знаков: <b id="n"></b></p>
<script>
function show() {
n.textContent = t.maxLength - t.value.length;
}
t.addEventListener('input', show);
show();
</script>
Наберите текст в поле: число уменьшается, а в конце становится красным и жирным.
Не вешайте на счётчик aria-live: экранный диктор будет читать число после каждой буквы. Лучше сообщать лимит в тексте метки заранее, например «не больше 60 знаков».
Как ограничить длину числового поля, если maxlength не работает
У поля type="number" лимит по знакам не работает, там ограничивают само число атрибутами min и max. Если нужны цифры фиксированной длины, например индекс или код из СМС, подойдёт type="text" с подсказкой для клавиатуры inputmode="numeric" и шаблоном pattern.
<!-- число в границах -->
<input type="number" min="0" max="999">
<!-- цифры фиксированной длины -->
<input type="text" inputmode="numeric"
maxlength="6" pattern="[0-9]{6}">
Если сохранить maxlength у type="number", браузер примет сколько угодно знаков. Тип tel тоже принимает maxlength, но клавиатура на телефоне при этом будет цифровой.
Как менять maxlength через JavaScript и jQuery
Читать и менять лимит можно через свойство maxLength. Если атрибута нет, свойство равно -1, а присвоить -1 нельзя: браузер вернёт ошибку IndexSizeError. Чтобы снять лимит, атрибут удаляют методом removeAttribute('maxlength'). Изменение лимита уже введённый текст не обрезает.
const input = document.querySelector('input');
input.maxLength = 4; // лимит 4
input.setAttribute('maxlength', 'abc'); // лимита нет
input.removeAttribute('maxlength'); // лимита нет, maxLength = -1
input.maxLength = -1; // IndexSizeError
Нажмите кнопку и наберите abcdefghij. Запись abc лимит снимает, а присвоение -1 даёт ошибку IndexSizeError.
В jQuery для этого есть методы attr() и removeAttr(). Результат тот же, что и в обычном JavaScript.
$('#t').attr('maxlength', 4); // лимит 4
$('#t').prop('maxLength', 4); // то же самое
$('#t').removeAttr('maxlength'); // убрать лимит
Без библиотеки достаточно одной строки: input.maxLength = 4.
Maxlength не защищает данные: проверка на сервере
Атрибут работает только в браузере посетителя. Любой человек может убрать maxlength в инструментах разработчика, записать длинное значение из скрипта или отправить запрос без браузера. Для сервера такая форма неотличима от настоящей.
<form>
<input name="a" maxlength="5">
</form>
<script>
// то же самое делает посетитель в консоли
a.removeAttribute('maxlength');
</script>
Уберите атрибут, наберите длинную строку и отправьте: на сервер уходит всё, что в поле. До снятия лимита видно, что отправляется не больше пяти знаков.
Поэтому длину нужно проверять ещё и на сервере. В C# и ASP.NET Core для этого у свойства модели добавляют серверные атрибуты [MaxLength] или [StringLength], а в других языках есть свои аналоги. Кроме того, у столбца в базе данных тоже есть предел длины, и он защитит данные от переполнения.
Частые ошибки с атрибутом maxlength
Большая часть ошибок с maxlength связана с ожиданием, что атрибут считает знаки так, как их видит человек, или что он защищает данные. В таблице собраны такие записи и то, к чему они приводят.
| Запись | Что получится | Как правильно |
|---|---|---|
<input type="number" maxlength="3"> | Лимит не работает | Ограничить число через min и max или взять type=text |
<select maxlength="3">, <div maxlength="3"> | Атрибута у этих тегов нет | Прописывать maxlength у input и textarea |
maxlength="3 знака" | Браузер читает число до первой нецифры | Писать только цифры |
maxlength="abc", maxlength="-5" | Лимит отключён молча | Записать целое число не меньше нуля |
maxlength="0" | В поле нельзя ввести ни одного знака | Для запрета ввода взять readonly или disabled |
<input maxlength="5" value="abcdefgh"> | Значение из разметки не обрезается | Сократить value или проверить длину скриптом |
input.value = longText | Скрипт обходит лимит | Обрезать строку через slice до записи |
| Лимит 1 для смайлика | Смайлик не помещается, он занимает две единицы | Считать в единицах UTF-16 или взять запас |
minlength больше maxlength | Поле всегда неверное | Следить, чтобы minlength не превышал maxlength |
| Лимит без подсказки | Посетитель не понимает, почему не вводится | Показать счётчик или написать лимит в метке |
aria-live на счётчике | Диктор читает число после каждой буквы | Сообщить лимит в тексте метки |
| maxlength как единственная защита | Атрибут снимается в инструментах разработчика | Проверять длину на сервере |
Шпаргалка по атрибуту maxlength
Когда нужно быстро вспомнить запись, ищите задачу в левом столбце. Правый столбец показывает, какой тег пригодится.
| Что нужно | Что прописать | Тег |
|---|---|---|
| Лимит в текстовом поле | <input maxlength="10"> | <input> |
| Лимит в многострочном поле | <textarea maxlength="60"> | <textarea> |
| Лимит у кода из цифр | <input inputmode="numeric" maxlength="6"> | <input> |
| Нижняя граница длины | <input minlength="3" maxlength="10"> | <input> |
| Прочитать лимит | input.maxLength | <input> |
| Изменить лимит из JS | input.maxLength = 4 | <input> |
| Снять лимит | input.removeAttribute('maxlength') | <input> |
| Проверить длину после правки | input.validity.tooLong | <input> |
| Счётчик знаков | t.maxLength - t.value.length | <textarea> |
| Метка с лимитом | <label for="t">Не больше 60 знаков</label> | <label> |