Fireship Curves Video


Uncategorized

Updated Aug 27th, 2021

I can’t get anything done because this guy puts out so much good content so damn frequently and as soon as I see a new one I have to drop what I’m doing and dig in deeply.

This one was published 8/19/21

The SVG technique is really the way to go, it is so easy to implement.

Official Title: “Wavy Backgrounds with CSS or SVG // Beginner HTML Tutorial”

Real developers like curves.

Transition between each content section elegantly with waves, blobs, or ripples using three techniques: 1.) CSS Border Radius, 2.) CSS Simpler 3.) SVG Backgrounds and 4.) Animated Morphing Blobs with JS

Much easier than it looks thanks to some awesome tools out there that you have probably never heard of.

Get started with plain “index.html” file

Tip#1: Emmet snippet ” ! ” to easily create HTML boilerplate

Tip#2: Emmet snippet using ” * ” to create multiples and ” > ” to add a sibling and ” + ” to add a child

section*8>(h1{Nice Curves})+p>lorem

<!-- Enter this then hit tab -->

Tip#3: gracefully serve app locally by running “npx serve” in the command line and you will be linked to http://localhost:5000 so navigate to that URL to see your UI, (this requires node to be installed).

Install a google font by going to fonts.google.com and using an HTML snippet using the <link> element.

Use inline <style> tags to define styles for this project. Start by creating a “body” tag and setting it’s “margin” to 0. Define the font-family to the one you grabbed from “Google fonts” and set the “color” and “background” properties. target the section element to set the position to relative to allow the children to be “absolutely positioned” within it which we will do later.

body {
  margin: 0;
  font-family: 'Prompt', sans-serif;
  color: white;
  background: #202731;
  overflow-x: hidden;
}

section {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 400px;
  padding: 100px 20vw;
}

.blue {
  background: #3c31dd;
}

.red {
  background: #dd3f31;
}

.pink {
  background: #ff0066;
}

.dark {
  background: #0f0f10;
}

Tip#4: When working with CSS flexbox in the browser, see all properties in the dev tools so you don’t have to memorize the all, (which you likely will in time anyway).

Add a few utility classes to distinguish between different colors so we can easily set the section to the color using CSS classes.

CSS Border-Radius

This CSS example is the most difficult example in the video but shown to see that it is possible.

Implement our first curve by adding an empty “div” element with a class of “curve” inside of the “section” below any heading and paragraph elements. We typically don’t want empty “div” elements lying around in your code so avoid doing this when possible.

<section>
  <h3>Section Title</h3>
  <div class="curve"></div>
</section>
.curve {
  position: absolute;
  height: 225px;
  width: 100%;
  bottom: 0;
}

The “::before” and “::after” pseudo elements are like invisible HTML elements that we can target with our CSS and in this example we will use each one to create a circle that we will intersect together to create the illusion of a curve. The tricky part is getting the circles to line up their location properly to give them the illusion of a curve.

Note: If the CSS border-radius property has one value it would create a perfect circle but by giving it a second value, this creates an ellipse. The first is the vertical radius and the second is the horizontal radius.

This takes a lot of trial and error using “transform: translate()” technique to move on the X and Y axis. Use “z-index” on the “::after” element to ensure the darker element sits on top. User the browser dev tools to play with the values until you get something that looks good. The current implementation causes the content to overflow horizontally but set the “overflow-x” property to “hidden” on the body element.

.curve::before {
  content: '';
  display: block;
  position: absolute;
  border-radius: 100% 50%;
  width: 55%;
  height: 100%;
  background: #202731;
  transform: translate(85%, 60%);
}

.curve::after {
  content: '';
  display: block;
  position: absolute;
  border-radius: 100% 50%;
  width: 55%;
  height: 100%;
  background: #3c31dd;
  transform: translate(-4%, 40%);
  z-index: -1;
}

Note: I originally could not get this to work in a React app with a “Section” component. This was because I had the overflow-x and overflow-y set to hidden on the section and not the body. The left circle needs to overflow the bottom border of the parent and the right one does not. The overflow hidden was preventing this obviously.

I was able to get this working but, as mentioned, very difficult to have line up.

CSS Technique #2 – Simpler Than Border-Radius

This above example gets the job done for a wave-like curve but there is another CSS trick that is better suited for curves with a single ellipse or circle, (like smiley face or hill).

In the HTML add a class of “bubble” to one section and a class of “dark” to a section below it.

Easily add a curve here by targeting the “bubble” class “::after” element and giving it an elliptical border-radius on the top-left and top-right followed by absolute-positioning to put it in the appropriate location.

.bubble::after {
  content: '';
  border-top-left-radius: 50% 100%;
  border-top-right-radius: 50% 100%;
  position: absolute;
  bottom: 0;
  height: 85%;
  width: 100%;
  background-color: #0f0f10;
  z-index: -1;
}

This example is very similar to the last one in many ways but far more simple. Good to use CSS for a simple curve like this. Dropping the height to like 25% is more reasonable. For more complex curves you would want to use SVG background technique.

SVG Background

This SVG technique is great for more complex curves.

To make our SVG we could use a design tool like Figma or use a purpose-built-web-app like “shapedivider.app” to automatically draw the SVG and provide the required CSS to add it to the UI instantly. Makes our lives easier.

Mess around with the tool and hit download. Copy and paste the SVG Code and CSS code from the modal to implement into your project. Update the class name to something easier like wave.

This technique is very easy to implement. May want to get a little creative with putting SVG code in a component or using some CSS properties to tweak slightly without bloating CSS code.

Take things to yet another level by using another mind-blowing useful tool called “app.haikei.app.” The layered waves option was used in the example and hit changed the direction to top so the layered waves were on the top. Select colors that go with your UI. Change the aspect ratio to something like 960×300 or something long and skinny, and make note of these values because we will need it later. Download as SVG to add the entire SVG file into your project. Create a “spacer” class in the CSS so we can use the relatively new CSS “aspectRatio” feature so we don’t have to manage the aspect ratio manually.

.spacer {
  aspect-ratio: 960/300;
  width: 100%;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

You may want to use this “spacer” class multiple times so create a second “layer1” class that defines the SVG graphic you want to use leveraging the “background-image” CSS property and setting it to a URL via “url(‘./yourRelativePath.svg’)” property.

.layer1 {
  background-image: url('./whatEvs.svg');
}

From here we go the HTML and between two sections add an empty “div” element with these two classes to apply this as the transition between two sections. As mentioned earlier, this is considered a bad practice but it is acceptable in this case and this is definitely the easiest way to get the job done.

<div class="spacer layer1"></div>

Looks awesome.

Note: And don’t forget about the “original,” getwaves.io) although the other tools mentioned look great.

Animated Morphing Blobs in JS Example

Really makes the web page come to life.

In the HTML, add the “pink” class to a section and just above and below that section add another empty “div” element with the “spacer” and “layer2” classes as we did in the previous example.

<div class="spacer layer2 flip"></div>

<section class="">
  <!-- Content Goes Here -->
</section>

<div class="spacer layer2"></div>

We add this new “flip” class (a utility class) to rotate the SVG image by 180 degrees across the vertical axis.

Also create a “layer2” class to bring in a second SVG image by creating another empty div with the same classes below the section with the “pink” class.

.flip {
  transform: rotate(180deg);
}

.layer2 {
  background-image: url('./whatEvs2.svg');
}

To generate the blob in the middle, go back to the “hakei” app and create two random graphics with the blob shape. Download and drag into your project files. Open them up to see the raw SVG source code. Copy and paste the “group” into the HTML file in the section. Right click on the SVG code in VSCode after pasting into the section and hit “format option.”

Delete the “rect” element as we just want the “path.” We want a second path by grabbing from the “blob2.svg” file, looking into the “g” element and cut/paste. This may seem complicated, and we could use a tool like Figma, but that is beyond the scope of this vide.

In order to animate we need to give each path an id, (like blob1 and blob2).

Usually a morph it difficult to pull off but we will use a tool called, kute.js (pronounced cutie?), which feels similar to “greensock” (GSAP). Link here.

Leverage this by installing via the CDN link used inside of an HTML <script> element into the “<Head>” of the document. Note that in Next.js this will go in the “_document.js” file.

At the bottom of the “<section>,” but still inside, we will add a <script> tag that references a global “KUTE” object and its “.fromTo()” method.

We can use the “fromTo()” method to tween across with a configuration object as the last argument with some powerful options to go back and forth between the two animation points. Then call the “tween.start()” method and that’s all it takes to create an SVG morphing animation with JS. The “yoyo” makes it go back and forth between the two animation states.

<script>
const tween = KUTE.fromTo(
  'blob#1',
  {path: 'blob#1'},
  {path: 'blob#2'},
  {repeat: 999, duration: 3000, yoyo: true}
)

tween.start()
</script>

Pasting the code above into JSX threw some errors, may have been the TypeScript compiler as well. Look into framer motion or another library like GSAP if this a feature you are after.

Make the second blob have an visibility of hidden so it is not visible when the animation first starts.

<g transform="..."  style="visibility: hidden"> 

Also add some basic positioning in the CSS to position the blob directly underneath the main content in that section.

.blob-motion {
  position: absolute;
  transform: translateY(-20%);
}