Счётчик количества товара: кнопка +/– с анимацией и валидацией (HTML + CSS + JS)
3686
Время чтения: 11 минут
На любом интернет-магазине кнопка «+/–» в карточке товара — это не просто элемент, а конвертер. По данным Яндекс.Метрики, 68% пользователей бросают корзину, если нельзя быстро изменить количество. В 2025 году счётчик должен быть: адаптивным, доступным, с анимацией, валидацией (минимум 1) и работать без перезагрузки. Покажем, как сделать современный счётчик на чистом HTML, CSS и JS — копируйте, вставляйте, меняйте цвета. Полный код, демо, вариации и чек-лист.

Как работает счётчик
Пользователь нажимает «+» — количество растёт. Нажимает «–» — падает до 1. При 1 кнопка «–» становится серой (класс .min). Всё плавно, без JS-фреймворков. Адаптивно: на мобильных кнопки крупнее, на десктопе — компактно. Для анимации мы используем CSS transition, а не CSS animation — это обеспечивает плавное изменение стилей при наведении без лишней нагрузки на браузер. В отличие от JS-анимаций, которые могут тормозить интерфейс, CSS-анимации работают на уровне GPU и не грузят основной поток, что особенно важно для производительности на слабых устройствах. Реактивные эффекты (hover, focus, click) реализованы через встроенные псевдоклассы, что делает код легче и быстрее.
HTML: минимальная разметка
<div class="quantity">
<button class="quantity__btn quantity__btn--minus min" type="button" aria-label="Уменьшить">-</button>
<input class="quantity__input" type="text" value="1" readonly>
<button class="quantity__btn quantity__btn--plus" type="button" aria-label="Увеличить">+</button>
</div>
Вы будете получать статьи по нашим направлениям, советы и кейсы предпринимателей
CSS: стиль + анимация
.quantity {
display: flex;
align-items: center;
gap: 8px;
font-family: Helvetica, sans-serif;
}
.quantity__btn {
width: 36px;
height: 36px;
background: #35e201;
color: #fff;
border: none;
border-radius: 6px;
font-weight: 600;
font-size: 18px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
.quantity__btn:hover {
background: #2cc700;
transform: scale(1.05);
}
.quantity__btn.min {
background: #989797;
cursor: not-allowed;
}
.quantity__btn.min:hover {
background: #989797;
transform: none;
}
.quantity__input {
width: 60px;
height: 36px;
text-align: center;
font-weight: 700;
font-size: 16px;
border: 1px solid #ddd;
border-radius: 6px;
background: #fff;
}
/* Адаптивность */
@media (max-width: 480px) {
.quantity__btn,
.quantity__input {
width: 44px;
height: 44px;
font-size: 20px;
}
.quantity__input {
width: 70px;
}
}
JS: логика и валидация
document.querySelectorAll('.quantity').forEach(counter => {
const input = counter.querySelector('.quantity__input');
const minus = counter.querySelector('.quantity__btn--minus');
const plus = counter.querySelector('.quantity__btn--plus');
plus.addEventListener('click', () => {
let value = parseInt(input.value);
input.value = ++value;
if (value > 1) minus.classList.remove('min');
});
minus.addEventListener('click', () => {
let value = parseInt(input.value);
if (value > 1) {
input.value = --value;
if (value === 1) minus.classList.add('min');
}
});
});
Вариации: 3 стиля под ваш бренд
| Стиль | Цвет | Когда использовать |
|---|---|---|
| Зелёный | #35e201 | Экология, здоровье |
| Синий | #007bff | Техника, финансы |
| Красный | #e74c3c | Акции, распродажи |
Чек-лист: ваш счётчик готов
- Работает на мобильных и десктопе
- Кнопка «–» неактивна при 1
- Анимация при наведении (через CSS transition, а не JS, чтобы не нагружать процессор)
- ARIA-метки для скринридеров
- Не ломает верстку при любом количестве
- JS не конфликтует с другими счётчиками
Типичные ошибки при внедрении счётчика
Даже простой элемент может сломать UX, если допустить эти 5 ошибок. Проверьте свой код:
- Кнопка «–» не блокируется при 1. Пользователь уходит в минус — получает 0 или -1. В корзине ошибка, товар не добавляется. Решение: класс
.minи условиеif (value > 1). - Нет атрибута
readonlyу поля ввода. Клиент вводит «abc» или «100500» — ломается валидация. Поле должно бытьreadonly, чтобы управление шло только через кнопки. - Счётчик не адаптирован под мобильные. На iPhone кнопки 36px — слишком мелко для пальца. Палец промахивается, пользователь злится. Решение: media-запрос с увеличением до 44px.
- Нет ARIA-атрибутов. Скринридеры не озвучивают изменение количества. Это нарушает WCAG 2.1. Добавьте
aria-labelи динамически обновляйтеaria-valuenow. - JS привязан к ID, а не к классу. Если на странице два счётчика, второй не работает. Используйте
querySelectorAll('.quantity')— код обработает все экземпляры.
Часто задаваемые вопросы
Можно без JS?
Нельзя. Нужна валидация. Альтернатива — <input type="number">, но UX хуже. Кроме того, без JS вы не сможете динамически управлять классами для анимации и блокировки кнопок.
Как передать в корзину?
Добавьте data-product-id="123" и отправляйте через fetch. Если используете несколько счётчиков на странице (например, в списке товаров или в аккордеоне), убедитесь, что каждый элемент имеет уникальный идентификатор для корректной обработки.
Хотите счётчик под ваш бренд? Закажите разработку интернет-магазина — счётчики, корзина, оплата за 14 дней.