На главную

CSS и вёрстка

Всплывающие уведомления

Всплывающее уведомление четырёх типов: иконка, цветная полоса, полоска обратного отсчёта, шесть позиций на экране и четыре анимации появления.

Настройки

Позиционирование вынесено на обёртку .toast-host. На одном элементе центрирование через translateX(-50%) и анимация появления спорят за transform, и уведомление уезжает из центра ровно в момент показа.

Превью

Условное окно приложения

Сохранено

Изменения применены и уже видны всем.

CSS

.toast-host {
  position: fixed;
  top: 24px;
  right: 24px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.toast {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 340px;
  max-width: calc(100vw - 32px);
  padding: 14px 16px;
  border-radius: 12px;
  background: #ffffff;
  color: #0f172a;
  border-left: 4px solid #16a34a;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
  overflow: hidden;
  animation: toast-in 320ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}

.toast__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(22, 163, 74, 0.14);
  color: #16a34a;
  font-size: 14px;
  font-weight: 700;
}

.toast__title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}

.toast__text {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: #475569;
}

.toast__close {
  flex: none;
  margin-left: auto;
  padding: 2px 6px;
  border: none;
  background: transparent;
  color: #475569;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

.toast__progress {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: 100%;
  transform-origin: left;
  background: #16a34a;
  animation: toast-progress 4s linear forwards;
}

@keyframes toast-in {
  from { opacity: 0; transform: translateX(24px); }
  to { opacity: 1; transform: none; }
}

@keyframes toast-progress {
  from { transform: scaleX(1); }
  to { transform: scaleX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .toast,
  .toast__progress { animation: none; }
}

HTML

<div class="toast-host">
  <div class="toast" role="status" aria-live="polite">
    <span class="toast__icon" aria-hidden="true">✓</span>
    <div>
      <p class="toast__title">Сохранено</p>
      <p class="toast__text">Изменения применены и уже видны всем.</p>
    </div>
    <button class="toast__close" type="button" aria-label="Закрыть уведомление">×</button>
    <span class="toast__progress"></span>
  </div>
</div>

role="status" и aria-live="polite" обязательны: без них уведомления для скринридера просто не существует.