Як створити хвилясті фігури та візерунки в CSS PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Як створити хвилясті фігури та візерунки в CSS

Хвиля, ймовірно, одна з найважчих форм для створення в CSS. Ми завжди намагаємося наблизити його за допомогою таких властивостей, як border-radius і багато магічних чисел, поки ми не отримаємо щось, що здасться нам близьким. І це ще до того, як ми навіть потрапимо до хвилеподібних візерунків, які є складнішими.

«SVG це!» ви могли б сказати, і ви, мабуть, праві, що це кращий шлях. Але ми побачимо, що CSS може створювати гарні хвилі, а код для нього не обов’язково повинен бути божевільним. І вгадайте що? я маю онлайн генератор щоб зробити це ще більш тривіальним!

Якщо ви пограєте з генератором, ви побачите, що CSS, який він видає, складається лише з двох градієнтів і властивості маски CSS — лише ці дві речі, і ми можемо створити будь-яку форму хвилі чи візерунок. Не кажучи вже про те, що ми можемо легко контролювати розмір і кривизну хвиль.

Деякі значення можуть виглядати так:магічні числа”, але за ними насправді є логіка, і ми розберемо код і відкриємо всі секрети створення хвиль.

Ця стаття є продовженням попередній де я побудував різноманітні зигзагоподібні, розширені, фестончасті та так, хвилясті межі. Я настійно рекомендую переглянути цю статтю, оскільки в ній використовується та ж техніка, яку ми тут розглянемо, але більш детально.

Математика за хвилями

Власне кажучи, за хвилястими формами не ховається жодна магічна формула. Будь-яку фігуру з кривими, які йдуть вгору і вниз, можна назвати хвилею, тому ми не збираємося обмежуватися складною математикою. Замість цього ми відтворимо хвилю, використовуючи основи геометрії.

Почнемо з простого прикладу, використовуючи дві форми кола:

Як створити хвилясті фігури та візерунки в CSS

У нас два кола з однаковим радіусом поруч. Ви бачите цю червону лінію? Він охоплює верхню половину першого кола та нижню половину другого. А тепер уявіть, що ви берете цей рядок і повторюєте його.

Звивиста червона лінія у формі хвиль.
Як створити хвилясті фігури та візерунки в CSS

Ми вже бачимо хвилю. Тепер давайте заповнимо нижню частину (або верхню), щоб отримати наступне:

Червона хвиля візерунок.
Як створити хвилясті фігури та візерунки в CSS

Тада! У нас є хвиляста форма, яку ми можемо контролювати за допомогою однієї змінної для радіусів кола. Це одна з найпростіших хвиль, яку ми можемо зробити, і саме на ній я показувався this Попередня стаття

Давайте трохи ускладнимо, візьмемо першу ілюстрацію та трохи перемістимо кола:

Два сірі кола з двома пунктирними лініями, що вказують на відстань.
Як створити хвилясті фігури та візерунки в CSS

У нас все ще є два кола з однаковими радіусами, але вони більше не вирівняні по горизонталі. У цьому випадку червона лінія охоплює не половину площі кожного кола, а меншу область. Ця область обмежена пунктирною червоною лінією. Ця лінія перетинає точку зустрічі обох кіл.

Тепер візьміть цю лінію та повторіть її, і ви отримаєте іншу хвилю, більш плавну.

Червона хвиляста лінія.
Як створити хвилясті фігури та візерунки в CSS
Червона хвиля візерунок.
Як створити хвилясті фігури та візерунки в CSS

Думаю, ви зрозуміли. Керуючи положенням і розміром кіл, ми можемо створити будь-яку хвилю, яку забажаємо. Ми навіть можемо створити для них змінні, які я буду називати P та S, відповідно.

Як створити хвилясті фігури та візерунки в CSS PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.
Як створити хвилясті фігури та візерунки в CSS

Ви, мабуть, помітили, що в онлайн-генераторі ми керуємо хвилею за допомогою двох входів. Вони відображаються на зазначені вище змінні. S це «Розмір хвилі» і P є «кривиною хвилі».

Я визначу P as P = m*S де m це змінна, яку ви регулюєте під час оновлення кривизни хвилі. Це дозволяє нам завжди мати однакову кривизну, навіть якщо ми оновлюємо S.

m може бути будь-яким значенням між 0 та 2. 0 дасть нам перший окремий випадок, коли обидва кола вирівняні горизонтально. 2 є різновидом максимального значення. Ми можемо збільшити, але після кількох тестів я виявив, що все вище 2 створює погані, плоскі форми.

Не забуваймо радіус нашого кола! Це також можна визначити за допомогою S та P подобається це:

R = sqrt(P² + S²)/2

Коли P дорівнює 0, ми матимемо R = S/2.

У нас є все, щоб почати перетворювати все це в градієнти в CSS!

Створення градієнтів

Наші хвилі використовують кола, а коли ми говоримо про кола, ми говоримо про радіальні градієнти. І оскільки два кола визначають нашу хвилю, ми логічно будемо використовувати два радіальних градієнти.

Ми почнемо з конкретного випадку P дорівнює 0. Ось ілюстрація першого градієнта:

Цей градієнт створює першу кривизну, заповнюючи всю область дна — так би мовити, «воду» хвилі.

Як створити хвилясті фігури та візерунки в CSS PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.
Як створити хвилясті фігури та візерунки в CSS
.wave {
  --size: 50px;

  mask: radial-gradient(var(--size) at 50% 0%, #0000 99%, red 101%) 
    50% var(--size)/calc(4 * var(--size)) 100% repeat-x;
}

Команда --size змінна визначає радіус і розмір радіального градієнта. Якщо порівнювати з S змінна, то вона дорівнює S/2.

Тепер давайте додамо другий градієнт:

Другий градієнт - це не що інше, як коло для завершення нашої хвилі:

radial-gradient(var(--size) at 50% var(--size), blue 99%, #0000 101%) 
  calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%

Якщо ви перевіряєте попередня стаття ви побачите, що я просто повторюю те, що вже робив там.

Я стежив за обома статтями, але конфігурації градієнта не однакові.

Це тому, що ми можемо досягти того самого результату, використовуючи різні конфігурації градієнта. Ви помітите невелику різницю у вирівнюванні, якщо порівняти обидві конфігурації, але трюк той самий. Це може заплутати вас, якщо ви не знайомі з градієнтами, але не хвилюйтеся. З деякою практикою ви звикнете до них і самі побачите, що різний синтаксис може призвести до того самого результату.

Ось повний код нашої першої хвилі:

.wave {
  --size: 50px;

  mask:
    radial-gradient(var(--size) at 50% var(--size),#000 99%, #0000 101%) 
      calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--size) at 50% 0px, #0000 99%, #000 101%) 
      50% var(--size)/calc(4 * var(--size)) 100% repeat-x;
}

Тепер давайте візьмемо цей код і налаштуємо його так, щоб ми ввели змінну, яка робить його повністю придатним для повторного використання для створення будь-якої хвилі, яку ми хочемо. Як ми бачили в попередньому розділі, основний трюк полягає в тому, щоб перемістити кола, щоб вони більше не були вирівняні, тому давайте оновимо положення кожного з них. Першу перемістимо вгору, а другу вниз.

Наш код буде виглядати так:

.wave {
  --size: 50px;
  --p: 25px;

  mask:
    radial-gradient(var(--size) at 50% calc(var(--size) + var(--p)), #000 99%, #0000 101%) 
      calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--size) at 50% calc(-1*var(--p)), #0000 99%, #000 101%) 
      50% var(--size) / calc(4 * var(--size)) 100% repeat-x;
}

Я ввів новий --p змінна, яка використовувала її для визначення центральної позиції кожного кола. Перший градієнт використовується 50% calc(-1*var(--p)), тому його центр рухається вгору, поки другий використовується calc(var(--size) + var(--p)) щоб перемістити його вниз.

Демонстрація варта тисячі слів:

Кола не вирівнюються і не торкаються одне одного. Ми рознесли їх далеко один від одного, не змінюючи їхні радіуси, тому ми втратили нашу хвилю. Але ми можемо виправити ситуацію, використовуючи ту саму математику, яку використовували раніше для обчислення нового радіуса. Пам'ятайте, що R = sqrt(P² + S²)/2. У нашому випадку --size дорівнює S/2; те саме для --p що також дорівнює P/2 оскільки ми рухаємо обидва кола. Отже, відстань між їхніми центрами подвоєна --p для цього:

R = sqrt(var(--size) * var(--size) + var(--p) * var(--p))

Це дає нам результат 55.9px.

Наша хвиля повертається! Давайте підключимо це рівняння до нашого CSS:

.wave {
  --size: 50px;
  --p: 25px;
  --R: sqrt(var(--p) * var(--p) + var(--size)*var(--size));

  mask:
    radial-gradient(var(--R) at 50% calc(var(--size) + var(--p)), #000 99%, #0000 101%) 
      calc(50% - 2*var(--size)) 0 / calc(4 * var(--size)) 100%,
    radial-gradient(var(--R) at 50% calc(-1*var(--p)), #0000 99%, #000 101%) 
      50% var(--size)/calc(4 * var(--size)) 100% repeat-x;
}

Це дійсний код CSS. sqrt() є частиною специфікації, але на момент, коли я це пишу, браузер не підтримує його. Це означає, що нам потрібна допомога JavaScript або Sass, щоб обчислити це значення, поки ми не станемо ширшими sqrt() support.

Це до біса круто: потрібні лише два градієнти, щоб отримати прохолодну хвилю, яку можна застосувати до будь-якого елемента за допомогою mask власність. Більше ніяких проб і помилок — усе, що вам потрібно, це оновити дві змінні, і все готово!

Розворот хвилі

Що, якщо ми хочемо, щоб хвилі йшли в іншому напрямку, де ми заповнюємо «небо» замість «води». Вірте чи ні, все, що нам потрібно зробити, це оновити два значення:

.wave {
  --size: 50px;
  --p: 25px;
  --R: sqrt(var(--p) * var(--p) + var(--size) * var(--size));

  mask:
    radial-gradient(var(--R) at 50% calc(100% - (var(--size) + var(--p))), #000 99%, #0000 101%)
      calc(50% - 2 * var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--R) at 50% calc(100% + var(--p)), #0000 99%, #000 101%) 
      50% calc(100% - var(--size)) / calc(4 * var(--size)) 100% repeat-x;
}

Все, що я там зробив, це додав зміщення, що дорівнює 100%, виділені вище. Ось результат:

Ми можемо розглянути більш зручний синтаксис, використовуючи значення ключових слів, щоб зробити це ще простіше:

.wave {
  --size: 50px;
  --p: 25px;
  --R: sqrt(var(--p)*var(--p) + var(--size) * var(--size));

  mask:
    radial-gradient(var(--R) at left 50% bottom calc(var(--size) + var(--p)), #000 99%, #0000 101%) 
      calc(50% - 2 * var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--R) at left 50% bottom calc(-1 * var(--p)), #0000 99%, #000 101%) 
      left 50% bottom var(--size) / calc(4 * var(--size)) 100% repeat-x;
}

Ми використовуємо left та bottom ключові слова для визначення сторін і зміщення. За замовчуванням у браузері встановлено значення left та top — тому ми використовуємо 100% щоб перемістити елемент вниз. Насправді ми рухаємо його з top by 100%, тому це насправді те саме, що сказати bottom. Читати набагато легше, ніж математику!

З цим оновленим синтаксисом все, що нам потрібно зробити, це поміняти місцями bottom та цінності top — або навпаки — змінити напрямок хвилі.

І якщо ви хочете отримати як верхню, так і нижню хвилю, ми об’єднуємо всі градієнти в одній декларації:

.wave {
  --size: 50px;
  --p: 25px;
  --R: sqrt(var(--p)*var(--p) + var(--size)*var(--size));

  mask:
    /* Gradient 1 */
    radial-gradient(var(--R) at left 50% bottom calc(var(--size) + var(--p)), #000 99%, #0000 101%) 
      left calc(50% - 2*var(--size)) bottom 0 / calc(4 * var(--size)) 51% repeat-x,
    /* Gradient 2 */
    radial-gradient(var(--R) at left 50% bottom calc(-1 * var(--p)), #0000 99%, #000 101%) 
      left 50% bottom var(--size) / calc(4 * var(--size)) calc(51% - var(--size)) repeat-x,
    /* Gradient 3 */
    radial-gradient(var(--R) at left 50% top calc(var(--size) + var(--p)), #000 99%, #0000 101%) 
      left calc(50% - 2 * var(--size)) top 0 / calc(4 * var(--size)) 51% repeat-x,
    /* Gradient 4 */
    radial-gradient(var(--R) at left 50% top calc(-1 * var(--p)), #0000 99%, #000 101%) 
      left 50% top var(--size) / calc(4 * var(--size)) calc(51% - var(--size)) repeat-x;
}

Якщо ви перевірите код, ви побачите, що окрім об’єднання всіх градієнтів, я також зменшив їх висоту з 100% до 51% так, щоб вони обидва покривали половину елемента. так, 51%. Нам потрібен цей маленький додатковий відсоток для невеликого перекриття, щоб уникнути прогалин.

А як щодо лівої та правої сторін?

Це твоє домашнє завдання! Візьмемо те, що ми зробили з верхньою та нижньою сторонами, і спробуємо оновити значення, щоб отримати значення справа та зліва. Не хвилюйтеся, це легко, і єдине, що вам потрібно зробити, це поміняти значення.

Якщо у вас виникнуть проблеми, ви завжди можете скористатися онлайн генератор перевірити код і візуалізувати результат.

Хвилясті лінії

Раніше ми зробили нашу першу хвилю за допомогою червоної лінії, а потім заповнили нижню частину елемента. Як щодо цієї хвилястої лінії? Це теж хвиля! Ще краще, якщо ми зможемо контролювати його товщину за допомогою змінної, щоб ми могли використовувати його повторно. Давайте зробимо це!

Ми не будемо починати з нуля, а скоріше візьмемо попередній код і оновимо його. Перше, що потрібно зробити, це оновити колірні межі градієнтів. Обидва градієнти починаються від прозорого кольору до непрозорого або навпаки. Щоб імітувати лінію або межу, нам потрібно почати з прозорого, перейти до непрозорого, потім знову повернутися до прозорого:

#0000 calc(99% - var(--b)), #000 calc(101% - var(--b)) 99%, #0000 101%

Думаю, ви вже здогадалися, що --b змінна — це те, що ми використовуємо для керування товщиною лінії. Давайте застосуємо це до наших градієнтів:

Так, результат далеко не хвиляста лінія. Але придивившись уважніше, ми можемо побачити, що один градієнт правильно створює нижню кривизну. Отже, все, що нам дійсно потрібно зробити, це виправити другий градієнт. Замість того, щоб зберігати повне коло, давайте зробимо частковий градієнт, як інший.

Ще далеко, але ми маємо обидві потрібні нам кривизни! Якщо ви перевірите код, то побачите, що у нас є два однакових градієнти. Єдиною відмінністю є їх розташування:

.wave {
  --size: 50px;
  --b: 10px;
  --p: 25px;
  --R: sqrt(var(--p)*var(--p) + var(--size)*var(--size));

  --_g: #0000 calc(99% - var(--b)), #000 calc(101% - var(--b)) 99%, #0000 101%;
  mask:
    radial-gradient(var(--R) at left 50% bottom calc(-1*var(--p)), var(--_g)) 
      calc(50% - 2*var(--size)) 0/calc(4*var(--size)) 100%,
    radial-gradient(var(--R) at left 50% top    calc(-1*var(--p)), var(--_g)) 
      50% var(--size)/calc(4*var(--size)) 100%;
}

Тепер нам потрібно налаштувати розмір і положення для остаточної форми. Нам більше не потрібно, щоб градієнт був на всю висоту, тому ми можемо замінити 100% з цим:

/* Size plus thickness */
calc(var(--size) + var(--b))

За цим значенням немає математичної логіки. Він повинен бути достатньо великим для кривизни. Незабаром ми побачимо його вплив на візерунок. Тим часом давайте також оновимо положення, щоб градієнти були вертикально центровані:

.wave {
  --size: 50px;
  --b: 10px;
  --p: 25px;
  --R: sqrt(var(--p)*var(--p) + var(--size)*var(--size));

  --_g: #0000 calc(99% - var(--b)), #000 calc(101% - var(--b)) 99%, #0000 101%;  
  mask:
    radial-gradient(var(--R) at left 50% bottom calc(-1*var(--p)), var(--_g)) 
      calc(50% - 2*var(--size)) 50%/calc(4 * var(--size)) calc(var(--size) + var(--b)) no-repeat,
    radial-gradient(var(--R) at left 50% top calc(-1 * var(--p)), var(--_g)) 50%
      50%/calc(4 * var(--size)) calc(var(--size) + var(--b)) no-repeat;
}

Ще не зовсім там:

Один градієнт потрібно перемістити трохи вниз, а інший трохи вгору. Обидва повинні рухатися на половину свого зросту.

Ми майже на місці! Нам потрібно невелике виправлення, щоб радіус мав ідеальне перекриття. Обидві лінії повинні бути зміщені на половину межі (--b) товщина:

Ми отримали це! Ідеальна хвиляста лінія, яку ми можемо легко налаштувати, керуючи декількома змінними:

.wave {
  --size: 50px;
  --b: 10px;
  --p: 25px;
  --R: calc(sqrt(var(--p) * var(--p) + var(--size) * var(--size)) + var(--b) / 2);

  --_g: #0000 calc(99% - var(--b)), #000 calc(101% - var(--b)) 99%, #0000 101%;
  mask:
    radial-gradient(var(--R) at left 50% bottom calc(-1 * var(--p)), var(--_g)) 
     calc(50% - 2*var(--size)) calc(50% - var(--size)/2 - var(--b)/2) / calc(4 * var(--size)) calc(var(--size) + var(--b)) repeat-x,
    radial-gradient(var(--R) at left 50% top calc(-1*var(--p)),var(--_g)) 
     50%  calc(50% + var(--size)/2 + var(--b)/2) / calc(4 * var(--size)) calc(var(--size) + var(--b)) repeat-x;
}

Я знаю, що для розуміння логіки потрібно трохи. Це добре, і, як я вже сказав, створити хвилясту форму в CSS нелегко, не кажучи вже про складну математику, що стоїть за цим. Ось чому онлайн генератор є паличкою-виручалочкою — ви можете легко отримати остаточний код, навіть якщо ви не повністю розумієте його логіку.

Хвилясті візерунки

Ми можемо зробити візерунок із щойно створеної хвилястої лінії!

О ні, код візерунка буде ще складніше зрозуміти!

Зовсім ні! У нас уже є код. Все, що нам потрібно зробити, це видалити repeat-x з того, що ми вже маємо, і тоді. 🎉

Гарний хвилястий візерунок. Пам’ятаєш рівняння, яке я сказав, що ми переглянемо?

/* Size plus thickness */
calc(var(--size) + var(--b))

Ну, це те, що контролює відстань між лініями візерунка. Ми можемо створити з цього змінну, але немає потреби в складності. Я навіть не використовую змінну для цього в генераторі. Можливо, я зміню це пізніше.

Ось той же шаблон, що йде в іншому напрямку:

Я надаю вам код у цій демонстрації, але я хочу, щоб ви розібрали його та зрозуміли, які зміни я зробив, щоб це сталося.

Спрощення коду

У всіх попередніх демонстраціях ми завжди визначаємо --size та --p самостійно. Але ви пам’ятаєте, як я згадував раніше, що онлайн-генератор оцінює P як дорівнює m*S, Де m контролює кривизну хвилі? Визначивши фіксований множник, ми можемо працювати з однією конкретною хвилею, і код може стати легшим. Це те, що нам знадобиться в більшості випадків: певна хвиляста форма та змінна для контролю її розміру.

Давайте оновимо наш код і представимо m змінна:

.wave {
  --size: 50px;
  --R: calc(var(--size) * sqrt(var(--m) * var(--m) + 1));

  mask:
    radial-gradient(var(--R) at 50% calc(var(--size) * (1 + var(--m))), #000 99%, #0000 101%) 
      calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--R) at 50% calc(-1 * var(--size) * var(--m)), #0000 99%, #000 101%) 
      50% var(--size) / calc(4 * var(--size)) 100% repeat-x;
  }

Як бачите, нам більше не потрібно --p змінна. Я замінив його на var(--m)*var(--size), і відповідно оптимізував деякі математики. Тепер, якщо ми хочемо працювати з конкретною хвилястою формою, ми можемо опустити --m змінну та замініть її на фіксоване значення. Спробуймо .8 наприклад.

--size: 50px;
--R: calc(var(--size) * 1.28);

mask:
  radial-gradient(var(--R) at 50% calc(1.8 * var(--size)), #000 99%, #0000 101%) 
    calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%,
  radial-gradient(var(--R) at 50% calc(-.8 * var(--size)), #0000 99%, #000 101%) 
    50% var(--size) / calc(4 * var(--size)) 100% repeat-x;

Бачите, як код став легшим? Лише одна змінна для контролю вашої хвилі, плюс вам більше не потрібно покладатися на неї sqrt() який не підтримує браузер!

Ви можете застосувати ту саму логіку до всіх демонстрацій, які ми бачили, навіть для хвилястих ліній і візерунка. Я почав із детального математичного пояснення та дав загальний код, але вам може знадобитися простіший код у реальному випадку використання. Це те, що я роблю весь час. Я рідко використовую загальний код, але завжди розглядаю спрощену версію, особливо тому, що в більшості випадків я використовую деякі відомі значення, які не потрібно зберігати як змінні. (Спойлер попередження: Наприкінці я поділюся кількома прикладами!)

Обмеження цього підходу

З математичної точки зору створений нами код мав би дати нам ідеальні хвилясті форми та візерунки, але насправді ми зіткнемося з деякими дивними результатами. Отже, так, цей метод має свої обмеження. Наприклад, онлайн-генератор здатний давати погані результати, особливо з хвилястими лініями. Частково проблема виникає через особливу комбінацію значень, через яку результат спотворюється, наприклад використання великого значення товщини межі порівняно з розміром:

Як створити хвилясті фігури та візерунки в CSS PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.
Як створити хвилясті фігури та візерунки в CSS

В інших випадках проблема, пов’язана з деяким заокругленням, призведе до розбіжності та проміжків між хвилями:

Як створити хвилясті фігури та візерунки в CSS PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.
Як створити хвилясті фігури та візерунки в CSS

Тим не менш, я все ще вважаю, що метод, який ми розглянули, залишається хорошим, оскільки він створює плавні хвилі в більшості випадків, і ми можемо легко уникнути поганих результатів, граючи з різними значеннями, поки не досягнемо ідеального результату.

Підводячи підсумок

Я сподіваюся, що після цієї статті ви більше не будете мучитися методом проб і помилок, щоб побудувати хвилясту форму чи візерунок. На додачу до онлайн-генератора, у вас є всі математичні секрети створення будь-якої хвилі!

На цьому стаття закінчується, але тепер у вас є потужний інструмент для створення химерних дизайнів із використанням хвилястих форм. Ось натхнення для початку…

Що з вами? Скористайтеся моїм онлайн-генератором (або напишіть код вручну, якщо ви вже вивчили всю математику напам’ять) і покажіть мені свої творіння! Давайте мати гарну колекцію в розділі коментарів.

Часова мітка:

Більше від CSS-хитрощі