Колесо удачи
    /* делаем везде так, чтобы свойства width и height задавали не размеры контента, а размеры блока */ * { box-sizing: border-box; } /* общие настройки страницы */ body { /* подключаем сетку */ display: grid; /* ставим всё по центру */ place-items: center; /* если что-то не помещается на своё место — скрываем то, что не поместилось */ overflow: hidden; } /* общий блок для всех элементов */ .deal-wheel { /* задаём переменные блока, внутри которого всё будет рисоваться */ /* размеры колеса */ --size: clamp(250px, 80vmin, 700px); /* clamp — функция CSS, которая задаёт три размера: минимальное, предпочтительное и максимальное. В данном случае мы хотим, чтобы колесо было не меньше 250 пикселей, не больше 700 пикселей, но в идеале — 80% от безопасно малой высоты окна браузера */ /* настройки яркости и заливки фона секторов. Нам понадобится описать поведение градиента, это у нас делается через много переменных */ --lg-hs: 0 3%; --lg-stop: 50%; --lg: linear-gradient( hsl(var(--lg-hs) 0%) 0 var(--lg-stop), hsl(var(--lg-hs) 20%) var(--lg-stop) 100% ); /* добавляем позиционирование относительно других элементов */ position: relative; /* подключаем стандартную CSS-сетку */ display: grid; grid-gap: calc(var(--size) / 20); /* выравниваем содержимое блока по центру */ align-items: center; /* задаём имена областей внутри сетки — в CSS теперь можно прямо назвать эти области */ grid-template-areas: "spinner" "trigger"; /* устанавливаем размер шрифта */ font-size: calc(var(--size) / 21); } /* всё, что относится ко внутренним элементам главного блока, будет находиться в области сетки с названием spinner */ .deal-wheel > * { grid-area: spinner; } /* сам блок и кнопка будут находиться в области сетки с названием trigger и будут выровнены по центру */ .deal-wheel .btn-spin { grid-area: trigger; justify-self: center; } // надписи и цвета на секторах const prizes = [ { text: "Скидка 10%", color: "hsl(197 30% 43%)", }, { text: "Дизайн в подарок", color: "hsl(173 58% 39%)", }, { text: "Второй сайт бесплатно", color: "hsl(43 74% 66%)", }, { text: "Скидка 50%", color: "hsl(27 87% 67%)", }, { text: "Блог в подарок", color: "hsl(12 76% 61%)", }, { text: "Скидок нет", color: "hsl(350 60% 52%)", }, { text: "Таргет в подарок", color: "hsl(91 43% 54%)", }, { text: "Скидка 30% на всё", color: "hsl(140 36% 74%)", } ]; // на сколько секторов нарезаем круг const prizeSlice = 360 / prizes.length; // на какое расстояние смещаем сектора друг относительно друга const prizeOffset = Math.floor(180 / prizes.length); // прописываем CSS-классы, которые будем добавлять и убирать из стилей const spinClass = "is-spinning"; const selectedClass = "selected"; // получаем все значения параметров стилей у секторов const spinnerStyles = window.getComputedStyle(spinner); // расставляем текст по секторам const createPrizeNodes = () => { // обрабатываем каждую подпись prizes.forEach(({ text, color, reaction }, i) => { // каждой из них назначаем свой угол поворота const rotation = ((prizeSlice * i) * -1) - prizeOffset; // добавляем код с размещением текста на страницу в конец блока spinner spinner.insertAdjacentHTML( "beforeend", // текст при этом уже оформлен нужными стилями `
  • ${text}
  • ` ); }); }; // рисуем разноцветные секторы const createConicGradient = () => { // устанавливаем нужное значение стиля у элемента spinner spinner.setAttribute( "style", `background: conic-gradient( from -90deg, ${prizes // получаем цвет текущего сектора .map(({ color }, i) => `${color} 0 ${(100 / prizes.length) * (prizes.length - i)}%`) .reverse() } );` ); }; /* сектор колеса */ .spinner { /* добавляем относительное позиционирование */ position: relative; /* подключаем сетку */ display: grid; /* выравниваем всё по центру */ align-items: center; /* добавляем элемент в сетку */ grid-template-areas: "spinner"; /* устанавливаем размеры */ width: var(--size); height: var(--size); /* поворачиваем элемент */ transform: rotate(calc(var(--rotate, 25) * 1deg)); /* рисуем круглую обводку, а всё, что не поместится, — будет скрыто за кругом */ border-radius: 50% }; /* всё, что внутри этого блока, будет находиться в области сетки с названием spinner */ .spinner * { grid-area: spinner; } /* текст на секторах */ .prize { /* включаем «гибкую» вёрстку */ display: flex; align-items: center; /* задаём отступы от краёв блока */ padding: 0 calc(var(--size) / 6) 0 calc(var(--size) / 20); /* устанавливаем размеры */ width: 50%; height: 50%; /* устанавливаем координаты, относительно которых будем вращать текст */ transform-origin: center right; /* поворачиваем текст */ transform: rotate(var(--rotate)); /* запрещаем пользователю выделять мышкой текст на секторах */ user-select: none; } /* кнопка запуска колеса */ .btn-spin { color: white; background: black; border: none; /* берём размер шрифта такой же, как в колесе */ font-size: inherit; /* добавляем отступы от текста внутри кнопки */ padding: 0.9rem 2rem 1rem; /* скругляем углы */ border-radius: 0.5rem; /* меняем внешний вид курсора над кнопкой на руку*/ cursor: pointer; } /* если кнопка нажата и неактивна */ .btn-spin:disabled { /* меняем внешний вид курсора */ cursor: progress; /* делаем кнопку полупрозрачной */ opacity: 0.25; }
    Колесо удачи