Hvordan lage bølgete former og mønstre i CSS PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Hvordan lage bølgete former og mønstre i CSS

Bølgen er sannsynligvis en av de vanskeligste formene å lage i CSS. Vi prøver alltid å tilnærme det med egenskaper som border-radius og mange magiske tall til vi får noe som føles litt nært. Og det er før vi i det hele tatt kommer inn i bølgete mønstre, som er vanskeligere.

"SVG det!" kan du si, og du har sannsynligvis rett i at det er en bedre vei å gå. Men vi vil se at CSS kan lage fine bølger og koden for det trenger ikke å være helt gal. Og gjett hva? jeg har en online generator for å gjøre det enda mer trivielt!

Hvis du spiller med generatoren, kan du se at CSS-en den spytter ut bare er to gradienter og en CSS-maske-egenskap – bare de to tingene, og vi kan lage alle slags bølgeform eller mønster. For ikke å nevne at vi enkelt kan kontrollere størrelsen og krumningen til bølgene mens vi holder på.

Noen av verdiene kan se ut som "magiske tall” men det er faktisk logikk bak dem, og vi vil dissekere koden og oppdage alle hemmelighetene bak å lage bølger.

Denne artikkelen er en oppfølging av en tidligere hvor jeg bygde alle slags forskjellige sikk-sakk, scoped, scalloped, og ja, bølgete grenser. Jeg anbefaler på det sterkeste å sjekke den artikkelen siden den bruker samme teknikk som vi vil dekke her, men i større detalj.

Matematikken bak bølger

Strengt tatt er det ikke én magisk formel bak bølgete former. Enhver form med kurver som går opp og ned kan kalles en bølge, så vi skal ikke begrense oss til kompleks matematikk. I stedet vil vi reprodusere en bølge ved å bruke det grunnleggende om geometri.

La oss starte med et enkelt eksempel med to sirkelformer:

Hvordan lage bølgete former og mønstre i CSS

Vi har to sirkler med samme radius ved siden av hverandre. Ser du den røde linjen? Den dekker den øvre halvdelen av den første sirkelen og den nedre halvdelen av den andre. Forestill deg nå at du tar den linjen og gjentar den.

En snirklet rød linje i form av bølger.
Hvordan lage bølgete former og mønstre i CSS

Vi ser allerede bølgen. La oss nå fylle den nederste delen (eller den øverste) for å få følgende:

Rødt bølgemønster.
Hvordan lage bølgete former og mønstre i CSS

Tada! Vi har en bølget form, og en som vi kan kontrollere ved å bruke én variabel for sirkelradiene. Dette er en av de enkleste bølgene vi kan lage, og det er den jeg viste meg frem i this forrige artikkel

La oss legge til litt kompleksitet ved å ta den første illustrasjonen og flytte sirklene litt:

To grå sirkler med to stiplede linjer i to som indikerer mellomrom.
Hvordan lage bølgete former og mønstre i CSS

Vi har fortsatt to sirkler med samme radier, men de er ikke lenger horisontalt justert. I dette tilfellet dekker den røde linjen ikke lenger halve arealet av hver sirkel, men et mindre område i stedet. Dette området er begrenset av den stiplede røde linjen. Den linjen krysser punktet der begge sirklene møtes.

Ta nå den linjen og gjenta den, og du får en ny bølge, en jevnere en.

En rød kronglete strek.
Hvordan lage bølgete former og mønstre i CSS
Et rødt bølgemønster.
Hvordan lage bølgete former og mønstre i CSS

Jeg tror du skjønner ideen. Ved å kontrollere posisjonen og størrelsen på sirklene kan vi lage hvilken som helst bølge vi ønsker. Vi kan til og med lage variabler for dem, som jeg vil kalle P og SHhv.

Hvordan lage bølgete former og mønstre i CSS PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Hvordan lage bølgete former og mønstre i CSS

Du har sikkert lagt merke til at i online-generatoren styrer vi bølgen ved hjelp av to innganger. De kartlegger til variablene ovenfor. S er "Størrelsen på bølgen" og P er "bølgens krumning".

jeg definerer P as P = m*S hvor m er variabelen du justerer når du oppdaterer krumningen til bølgen. Dette gjør at vi alltid kan ha samme krumning, selv om vi oppdaterer S.

m kan være en hvilken som helst verdi mellom 0 og 2. 0 vil gi oss det første spesielle tilfellet der begge sirklene er horisontalt justert. 2 er en slags maksimumsverdi. Vi kan bli større, men etter noen tester fant jeg ut at alt ovenfor 2 produserer dårlige, flate former.

La oss ikke glemme radiusen til sirkelen vår! Det kan også defineres ved hjelp av S og P som dette:

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

Når P er lik 0, vi vil ha R = S/2.

Vi har alt for å begynne å konvertere alt dette til gradienter i CSS!

Lage gradienter

Bølgene våre bruker sirkler, og når vi snakker om sirkler snakker vi om radielle gradienter. Og siden to sirkler definerer bølgen vår, vil vi logisk bruke to radielle gradienter.

Vi starter med det spesielle tilfellet hvor P er lik 0. Her er illustrasjonen av den første gradienten:

Denne gradienten skaper den første krumningen mens den fyller ut hele bunnområdet - "vannet" i bølgen så å si.

Hvordan lage bølgete former og mønstre i CSS PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Hvordan lage bølgete former og mønstre i 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;
}

De --size variabel definerer radius og størrelsen på den radielle gradienten. Hvis vi sammenligner det med S variabel, så er den lik S/2.

La oss nå legge til den andre gradienten:

Den andre gradienten er ikke annet enn en sirkel for å fullføre bølgen vår:

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

Hvis du sjekker forrige artikkel du vil se at jeg bare gjentar det jeg allerede gjorde der.

Jeg fulgte begge artiklene, men gradientkonfigurasjonene er ikke de samme.

Det er fordi vi kan nå det samme resultatet ved å bruke forskjellige gradientkonfigurasjoner. Du vil merke en liten forskjell i justeringen hvis du sammenligner begge konfigurasjonene, men trikset er det samme. Dette kan være forvirrende hvis du ikke er kjent med gradienter, men ikke bekymre deg. Med litt øvelse blir du vant til dem, og du vil selv oppdage at forskjellig syntaks kan føre til samme resultat.

Her er hele koden for vår første bølge:

.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;
}

La oss nå ta denne koden og justere den til der vi introduserer en variabel som gjør denne fullt gjenbrukbar for å lage hvilken som helst bølge vi ønsker. Som vi så i forrige seksjon, er hovedtrikset å flytte sirklene slik at de ikke er mer på linje, så la oss oppdatere posisjonen til hver enkelt. Vi flytter den første opp og den andre ned.

Koden vår vil se slik ut:

.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;
}

Jeg har introdusert en ny --p variabel som har brukt den til å definere midtposisjonen til hver sirkel. Den første gradienten bruker 50% calc(-1*var(--p)), så midten beveger seg opp mens den andre bruker calc(var(--size) + var(--p)) for å flytte den ned.

En demo er verdt tusen ord:

Sirklene er verken på linje eller berører hverandre. Vi plasserte dem langt fra hverandre uten å endre radiene deres, så vi mistet bølgen vår. Men vi kan fikse ting ved å bruke den samme matematikken vi brukte tidligere for å beregne den nye radiusen. Husk at R = sqrt(P² + S²)/2. I vårt tilfelle, --size er lik S/2; det samme for --p som også er lik P/2 siden vi flytter begge sirkler. Så avstanden mellom deres midtpunkt er dobbelt så stor som verdien av --p for dette:

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

Det gir oss et resultat av 55.9px.

Vår bølge er tilbake! La oss koble den ligningen til vår 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;
}

Dette er gyldig CSS-kode. sqrt() er en del av spesifikasjonen, men på det tidspunktet jeg skriver dette, er det ingen nettleserstøtte for det. Det betyr at vi trenger et dryss JavaScript eller Sass for å beregne den verdien til vi blir bredere sqrt() Støtte.

Dette er ganske kult: alt som trengs er to gradienter for å få en kul bølge som du kan bruke på et hvilket som helst element ved å bruke mask eiendom. Ikke mer prøving og feiling - alt du trenger er å oppdatere to variabler, og du er i gang!

Reversere bølgen

Hva om vi vil at bølgene skal gå den andre retningen, der vi fyller ut "himmelen" i stedet for "vannet". Tro det eller ei, alt vi trenger å gjøre er å oppdatere to verdier:

.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;
}

Alt jeg gjorde der var å legge til en offset lik 100%, uthevet ovenfor. Her er resultatet:

Vi kan vurdere en mer brukervennlig syntaks ved å bruke søkeordverdier for å gjøre det enda enklere:

.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;
}

Vi bruker left og bottom nøkkelord for å spesifisere sidene og forskyvningen. Som standard er nettleseren som standard left og top – det er derfor vi bruker 100% for å flytte elementet til bunnen. I virkeligheten flytter vi det fra top by 100%, så det er egentlig det samme som å si bottom. Mye lettere å lese enn matematikk!

Med denne oppdaterte syntaksen er alt vi trenger å gjøre å bytte bottom forum top — eller omvendt — for å endre retningen på bølgen.

Og hvis du ønsker å få både topp- og bunnbølger, kombinerer vi alle gradientene i en enkelt erklæring:

.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;
}

Hvis du sjekker koden, vil du se at i tillegg til å kombinere alle gradientene, har jeg også redusert høyden deres fra 100% til 51% slik at de begge dekker halvparten av elementet. Ja, 51%. Vi trenger den lille ekstra prosenten for en liten overlapping som unngår hull.

Hva med venstre og høyre side?

Det er leksene dine! Ta det vi gjorde med topp- og bunnsiden og prøv å oppdatere verdiene for å få høyre og venstre verdi. Ikke bekymre deg, det er enkelt og det eneste du trenger å gjøre er å bytte verdier.

Hvis du har problemer, kan du alltids bruke nettgeneratoren for å sjekke koden og visualisere resultatet.

Bølgede linjer

Tidligere laget vi vår første bølge ved hjelp av en rød linje, og fylte deretter den nederste delen av elementet. Hva med den bølgete linjen? Det er også en bølge! Enda bedre er det hvis vi kan kontrollere tykkelsen med en variabel slik at vi kan gjenbruke den. La oss gjøre det!

Vi skal ikke starte fra bunnen av, men heller ta den forrige koden og oppdatere den. Det første du må gjøre er å oppdatere fargestoppene til gradientene. Begge gradientene starter fra en gjennomsiktig farge til en ugjennomsiktig farge, eller omvendt. For å simulere en linje eller kantlinje, må vi starte fra gjennomsiktig, gå til ugjennomsiktig og deretter tilbake til gjennomsiktig igjen:

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

Jeg tror du allerede har gjettet at --b variabel er det vi bruker for å kontrollere linjetykkelsen. La oss bruke dette på gradientene våre:

Ja, resultatet er langt fra en bølget linje. Men ser vi nøye, kan vi se at en gradient skaper bunnkurvaturen riktig. Så alt vi egentlig trenger å gjøre er å rette opp den andre gradienten. I stedet for å holde en hel sirkel, la oss lage en delvis som den andre gradienten.

Fortsatt langt, men vi har begge krumningene vi trenger! Hvis du sjekker koden, vil du se at vi har to like gradienter. Den eneste forskjellen er plasseringen deres:

.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%;
}

Nå må vi justere størrelsen og plasseringen for den endelige formen. Vi trenger ikke lenger gradienten til å være i full høyde, så vi kan erstatte 100% med dette:

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

Det er ingen matematisk logikk bak denne verdien. Den trenger bare å være stor nok for krumningen. Vi vil se effekten på mønsteret om litt. I mellomtiden, la oss også oppdatere posisjonen for å sentrere gradientene vertikalt:

.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;
}

Fortsatt ikke helt der:

Den ene gradienten må bevege seg litt ned og den andre litt opp. Begge må bevege seg halvparten av høyden.

Vi er nesten der! Vi trenger en liten fiksering for at radiusen skal ha en perfekt overlapping. Begge linjene må forskyves med halve grensen (--b) tykkelse:

Vi har det! En perfekt bølget linje som vi enkelt kan justere ved å kontrollere noen få variabler:

.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;
}

Jeg vet at det tar litt tid å forstå logikken. Det er greit, og som jeg sa, det er ikke lett å lage en bølget form i CSS, for ikke å nevne den vanskelige matematikken bak. Det er derfor online generator er en livredder - du kan enkelt få den endelige koden selv om du ikke helt forstår logikken bak den.

Bølgete mønstre

Vi kan lage et mønster fra den bølgete linjen vi nettopp har laget!

Å nei, koden til mønsteret blir enda vanskeligere å forstå!

Ikke i det hele tatt! Vi har allerede koden. Alt vi trenger å gjøre er å fjerne repeat-x fra det vi allerede har, og tada. 🎉

Et fint bølgemønster. Husker du ligningen jeg sa vi skulle se på igjen?

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

Vel, det er dette som styrer avstanden mellom linjene i mønsteret. Vi kan lage en variabel ut av det, men det er ikke behov for mer kompleksitet. Jeg bruker ikke engang en variabel for det i generatoren. Kanskje jeg endrer det senere.

Her er det samme mønsteret som går i en annen retning:

Jeg gir deg koden i den demoen, men jeg vil at du skal dissekere den og forstå hvilke endringer jeg gjorde for å få det til.

Forenkling av koden

I alle de tidligere demoene definerer vi alltid --size og --p uavhengig. Men husker du hvordan jeg nevnte tidligere at online-generatoren evaluerer P som lik m*S, Hvor m kontrollerer bølgens krumning? Ved å definere en fast multiplikator kan vi jobbe med én bestemt bølge og koden kan bli enklere. Dette er det vi trenger i de fleste tilfeller: en spesifikk bølgeform og en variabel for å kontrollere størrelsen.

La oss oppdatere koden vår og introdusere m variabel:

.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;
  }

Som du kan se, trenger vi ikke lenger --p variabel. Jeg erstattet den med var(--m)*var(--size), og optimaliserte noe av matematikken deretter. Nå, hvis vi ønsker å jobbe med en bestemt bølgeform, kan vi utelate --m variabel og erstatte den med en fast verdi. La oss prøve .8 for eksempel.

--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;

Ser du hvordan koden er enklere nå? Bare én variabel for å kontrollere bølgen din, pluss at du ikke lenger trenger å stole på sqrt() som ikke har støtte for nettlesere!

Du kan bruke den samme logikken på alle demoene vi så selv for de bølgete linjene og mønsteret. Jeg startet med en detaljert matematisk forklaring og ga den generiske koden, men du kan finne at du trenger enklere kode i en reell brukstilfelle. Dette er hva jeg gjør hele tiden. Jeg bruker sjelden den generiske koden, men jeg vurderer alltid en forenklet versjon, spesielt at jeg i de fleste tilfeller bruker noen kjente verdier som ikke trenger å lagres som variabler. (Spoiler varsel: Jeg vil dele noen eksempler på slutten!)

Begrensninger for denne tilnærmingen

Matematisk burde koden vi laget gi oss perfekte bølgete former og mønstre, men i virkeligheten vil vi møte noen merkelige resultater. Så, ja, denne metoden har sine begrensninger. For eksempel er nettgeneratoren i stand til å gi dårlige resultater, spesielt med bølgete linjer. En del av problemet skyldes en spesiell kombinasjon av verdier der resultatet blir forvrengt, som å bruke en stor verdi for kanttykkelsen sammenlignet med størrelsen:

Hvordan lage bølgete former og mønstre i CSS PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Hvordan lage bølgete former og mønstre i CSS

For de andre tilfellene er det problemet knyttet til en eller annen avrunding som vil resultere i feiljustering og gap mellom bølgene:

Hvordan lage bølgete former og mønstre i CSS PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Hvordan lage bølgete former og mønstre i CSS

Når det er sagt, tror jeg fortsatt metoden vi dekket forblir en god, fordi den produserer jevne bølger i de fleste tilfeller, og vi kan enkelt unngå de dårlige resultatene ved å spille med forskjellige verdier til vi får den perfekt.

Innpakning opp

Jeg håper at du etter denne artikkelen ikke lenger vil famle rundt med prøving og feiling for å bygge en bølget form eller mønster. I tillegg til nettgeneratoren, du har alle de matematiske hemmelighetene bak å lage hvilken som helst type bølge du vil!

Artikkelen slutter her, men nå har du et kraftig verktøy for å lage fancy design som bruker bølgete former. Her er inspirasjon til å komme i gang...

Hva med deg? Bruk min online generator (eller skriv koden manuelt hvis du allerede har lært all matematikken utenat) og vis meg kreasjonene dine! La oss ha en god samling i kommentarfeltet.

Tidstempel:

Mer fra CSS triks