UI-компоненты
Интерактивные пакеты услуг
Блок тарифов для сайтов услуг, клиник, обучения и корпоративных сайтов. Пользователь переключает формат оплаты, выбирает пакет и сразу видит понятную сводку перед заявкой.
Пакеты услуг
Цены понятнее, когда пакет можно выбрать сразу
Посетитель переключает формат оплаты, сравнивает пакеты и видит краткую сводку перед заявкой.
Базовый
Для первого обращения или небольшой задачи.
2 500 ₽- Первичная консультация
- Краткие рекомендации
- План следующих шагов
Расширенный
Для регулярной работы и понятного результата.
4 500 ₽- Подробная диагностика
- Индивидуальный план
- Поддержка после встречи
Комплексный
Для задач, где нужен полный цикл сопровождения.
7 000 ₽- Расширенная работа
- Контроль динамики
- Отчёт и рекомендации
<section class="package-lab">
<div class="package-lab__head">
<span class="package-lab__badge">Пакеты услуг</span>
<h2>Цены понятнее, когда пакет можно выбрать сразу</h2>
<p>
Посетитель переключает формат оплаты, сравнивает пакеты и видит краткую сводку перед заявкой.
</p>
<div class="package-lab__switch">
<button class="active" type="button" data-period="once">Разово</button>
<button type="button" data-period="month">Месяц</button>
</div>
</div>
<div class="package-lab__grid">
<div class="package-lab__cards">
<article class="package-card active" data-package="start">
<span class="package-card__label">Старт</span>
<h3>Базовый</h3>
<p>Для первого обращения или небольшой задачи.</p>
<strong><span data-price-once="2500" data-price-month="8500">2 500</span> ₽</strong>
<ul>
<li>Первичная консультация</li>
<li>Краткие рекомендации</li>
<li>План следующих шагов</li>
</ul>
<button type="button">Выбрать</button>
</article>
<article class="package-card package-card--featured" data-package="pro">
<span class="package-card__label">Чаще выбирают</span>
<h3>Расширенный</h3>
<p>Для регулярной работы и понятного результата.</p>
<strong><span data-price-once="4500" data-price-month="14500">4 500</span> ₽</strong>
<ul>
<li>Подробная диагностика</li>
<li>Индивидуальный план</li>
<li>Поддержка после встречи</li>
</ul>
<button type="button">Выбрать</button>
</article>
<article class="package-card" data-package="max">
<span class="package-card__label">Максимум</span>
<h3>Комплексный</h3>
<p>Для задач, где нужен полный цикл сопровождения.</p>
<strong><span data-price-once="7000" data-price-month="22000">7 000</span> ₽</strong>
<ul>
<li>Расширенная работа</li>
<li>Контроль динамики</li>
<li>Отчёт и рекомендации</li>
</ul>
<button type="button">Выбрать</button>
</article>
</div>
<aside class="package-summary">
<span class="package-summary__eyebrow">Выбранный пакет</span>
<h3 class="package-summary__title">Базовый</h3>
<p class="package-summary__text">Для первого обращения или небольшой задачи.</p>
<div class="package-summary__price">
<span class="package-summary__price-value">2 500</span> ₽
</div>
<div class="package-summary__meta">
<span class="package-summary__period">Разовая оплата</span>
<span class="package-summary__benefit">Можно начать без долгих согласований</span>
</div>
<button class="package-summary__button" type="button">
Оставить заявку
</button>
</aside>
</div>
</section>
.package-lab {
padding: 46px;
border-radius: 28px;
overflow: hidden;
background:
radial-gradient(circle at 12% 18%, rgba(59, 130, 246, 0.30), transparent 32%),
radial-gradient(circle at 88% 82%, rgba(34, 197, 94, 0.18), transparent 34%),
linear-gradient(135deg, #020617, #0f172a);
}
.package-lab__head {
max-width: 880px;
margin-bottom: 34px;
}
.package-lab__badge {
display: inline-flex;
margin-bottom: 16px;
padding: 8px 13px;
border-radius: 999px;
color: #bbf7d0;
background: rgba(34, 197, 94, 0.12);
border: 1px solid rgba(34, 197, 94, 0.35);
font-size: 13px;
}
.package-lab__head h2 {
margin: 0 0 16px;
color: #ffffff;
font-size: clamp(32px, 5vw, 56px);
line-height: 1.02;
letter-spacing: -0.05em;
}
.package-lab__head p {
color: #cbd5e1;
font-size: 17px;
line-height: 1.7;
}
.package-lab__switch {
display: inline-flex;
gap: 8px;
padding: 6px;
border: 1px solid #334155;
border-radius: 999px;
background: rgba(15, 23, 42, 0.78);
}
.package-lab__switch button {
border: 0;
border-radius: 999px;
padding: 10px 16px;
color: #cbd5e1;
background: transparent;
cursor: pointer;
}
.package-lab__switch button.active {
color: #ffffff;
background: linear-gradient(135deg, #16a34a, #2563eb);
}
.package-lab__grid {
display: grid;
grid-template-columns: 1.25fr 0.75fr;
gap: 24px;
align-items: start;
}
.package-lab__cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.package-card,
.package-summary {
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 26px;
background: rgba(15, 23, 42, 0.78);
box-shadow: 0 28px 80px rgba(2, 6, 23, 0.5);
}
.package-card {
display: flex;
flex-direction: column;
padding: 24px;
cursor: pointer;
transition: 0.25s ease;
}
.package-card:hover,
.package-card.active {
transform: translateY(-4px);
border-color: #3b82f6;
}
.package-card--featured {
background:
radial-gradient(circle at top right, rgba(59, 130, 246, 0.20), transparent 35%),
rgba(15, 23, 42, 0.86);
}
.package-card__label {
width: fit-content;
margin-bottom: 16px;
padding: 7px 11px;
border: 1px solid rgba(96, 165, 250, 0.45);
border-radius: 999px;
color: #bfdbfe;
background: rgba(59, 130, 246, 0.16);
font-size: 12px;
}
.package-card h3 {
margin: 0 0 10px;
color: #ffffff;
font-size: 24px;
}
.package-card p {
color: #94a3b8;
}
.package-card strong {
margin: 12px 0 18px;
color: #ffffff;
font-size: 34px;
letter-spacing: -0.04em;
}
.package-card ul {
display: grid;
gap: 10px;
margin: 0 0 22px;
padding: 0;
list-style: none;
}
.package-card li {
color: #cbd5e1;
}
.package-card li::before {
content: "✓";
margin-right: 8px;
color: #22c55e;
}
.package-card button,
.package-summary__button {
margin-top: auto;
border: 0;
border-radius: 16px;
padding: 14px 16px;
color: #ffffff;
background: linear-gradient(135deg, #2563eb, #9333ea);
cursor: pointer;
transition: 0.25s;
}
.package-card button:hover,
.package-summary__button:hover {
transform: translateY(-2px);
}
.package-summary {
position: sticky;
top: 110px;
padding: 28px;
overflow: hidden;
}
.package-summary::before {
content: "";
position: absolute;
width: 240px;
height: 240px;
right: -100px;
top: -100px;
border-radius: 50%;
background: radial-gradient(circle, rgba(34, 197, 94, 0.25), transparent 70%);
}
.package-summary > * {
position: relative;
z-index: 2;
}
.package-summary__eyebrow {
color: #94a3b8;
}
.package-summary__title {
margin: 14px 0 12px;
color: #ffffff;
font-size: 34px;
}
.package-summary__text {
color: #cbd5e1;
line-height: 1.7;
}
.package-summary__price {
margin: 22px 0;
color: #ffffff;
font-size: clamp(42px, 7vw, 64px);
font-weight: 800;
letter-spacing: -0.06em;
}
.package-summary__meta {
display: grid;
gap: 10px;
margin-bottom: 22px;
}
.package-summary__meta span {
border: 1px solid #334155;
border-radius: 16px;
padding: 12px;
color: #dbeafe;
background: #020617;
}
.package-summary.is-updated {
animation: packagePulse 0.3s ease;
}
@keyframes packagePulse {
from {
opacity: 0.76;
transform: scale(0.985);
}
to {
opacity: 1;
transform: scale(1);
}
}
@media (max-width: 1000px) {
.package-lab__grid,
.package-lab__cards {
grid-template-columns: 1fr;
}
.package-summary {
position: static;
}
}
@media (max-width: 560px) {
.package-lab {
padding: 26px 18px;
}
.package-lab__switch {
display: grid;
grid-template-columns: 1fr 1fr;
width: 100%;
}
}
const packageSwitchButtons = document.querySelectorAll(".package-lab__switch button");
const packageCards = document.querySelectorAll(".package-card");
const packageSummary = document.querySelector(".package-summary");
const packageSummaryTitle = document.querySelector(".package-summary__title");
const packageSummaryText = document.querySelector(".package-summary__text");
const packageSummaryPrice = document.querySelector(".package-summary__price-value");
const packageSummaryPeriod = document.querySelector(".package-summary__period");
const packageSummaryBenefit = document.querySelector(".package-summary__benefit");
let currentPeriod = "once";
let currentPackage = document.querySelector(".package-card.active");
const packageBenefits = {
start: "Можно начать без долгих согласований",
pro: "Оптимально для регулярной работы",
max: "Подходит для полного сопровождения"
};
function formatPackagePrice(value) {
return new Intl.NumberFormat("ru-RU").format(value);
}
function updatePackageSummary() {
const title = currentPackage.querySelector("h3").textContent;
const text = currentPackage.querySelector("p").textContent;
const priceElement = currentPackage.querySelector("[data-price-once]");
const price = priceElement.dataset[currentPeriod === "once" ? "priceOnce" : "priceMonth"];
packageSummary.classList.remove("is-updated");
void packageSummary.offsetWidth;
packageSummary.classList.add("is-updated");
packageSummaryTitle.textContent = title;
packageSummaryText.textContent = text;
packageSummaryPrice.textContent = formatPackagePrice(price);
packageSummaryPeriod.textContent = currentPeriod === "once" ? "Разовая оплата" : "Оплата за месяц";
packageSummaryBenefit.textContent = packageBenefits[currentPackage.dataset.package];
}
function updateVisiblePrices() {
packageCards.forEach(function (card) {
const priceElement = card.querySelector("[data-price-once]");
const price = priceElement.dataset[currentPeriod === "once" ? "priceOnce" : "priceMonth"];
priceElement.textContent = formatPackagePrice(price);
});
}
packageSwitchButtons.forEach(function (button) {
button.addEventListener("click", function () {
packageSwitchButtons.forEach(item => item.classList.remove("active"));
button.classList.add("active");
currentPeriod = button.dataset.period;
updateVisiblePrices();
updatePackageSummary();
});
});
packageCards.forEach(function (card) {
card.addEventListener("click", function () {
packageCards.forEach(item => item.classList.remove("active"));
card.classList.add("active");
currentPackage = card;
updatePackageSummary();
});
});
updateVisiblePrices();
updatePackageSummary();