<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Temani Afif - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Temani Afif - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 19 May 2026 04:42:35 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/temani-afif/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Create Zig-Zag CSS Loaders Using One Element ]]>
                </title>
                <description>
                    <![CDATA[ In a previous article, I showed you how to create filling CSS loaders collection where each loader was built using a single HTML element. Here, you’ll learn more about loaders by creating the Zig-Zag collection. Here is an overview of what you’ll be ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/zig-zag-css-loaders/</link>
                <guid isPermaLink="false">673e738139346c3d3174676e</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ animations ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Wed, 20 Nov 2024 23:40:49 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1732045303831/af9240a9-6a25-4b13-a397-102ee098db78.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In <a target="_blank" href="https://www.freecodecamp.org/news/filling-css-loaders">a previous article</a>, I showed you how to create filling CSS loaders collection where each loader was built using a single HTML element. Here, you’ll learn more about loaders by creating <a target="_blank" href="https://css-loaders.com/zig-zag/">the Zig-Zag collection</a>.</p>
<p>Here is an overview of what you’ll be building:</p>
<div class="embed-wrapper"><iframe height="500" style="width:100%;height:500px" src="https://codepen.io/t_afif/embed/preview/RwXdvKj/83804c95907793e888c3036d7dd29251?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/RwXdvKj/83804c95907793e888c3036d7dd29251">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>You can also check <a target="_blank" href="https://css-loaders.com/zig-zag/">my online collection</a> to see up to 20 variations using a zig-zag shape.</p>
<p>We won’t study all the variations but I will show you a few tricks that’ll help you create as many variations as you want.</p>
<h2 id="heading-how-to-create-a-zig-zag-shape">How to Create a Zig-Zag Shape</h2>
<p>The first step is to create a zig-zag shape. For this, you can grab the code from my CSS shape website: <a target="_blank" href="https://css-shape.com/zig-zag-line/">https://css-shape.com/zig-zag-line/</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731707755150/f1782db9-fa7f-472e-b771-cfc1c2046e0c.png" alt="Zig-Zag shape from css-shape.com" class="image--center mx-auto" width="1150" height="456" loading="lazy"></p>
<p>You can adjust the different variables to get the zig-zag you want. In our case, I will use an easier version with no variables.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">47px</span>; <span class="hljs-comment">/* control the size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">5</span>;
  <span class="hljs-attribute">background</span>:
   <span class="hljs-built_in">conic-gradient</span>(from <span class="hljs-number">135deg</span> at top,#<span class="hljs-number">000</span> <span class="hljs-number">90deg</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">0</span>) top,
   <span class="hljs-built_in">conic-gradient</span>(from <span class="hljs-number">135deg</span> at top,#<span class="hljs-number">0000</span> <span class="hljs-number">90deg</span>,#<span class="hljs-number">000</span> <span class="hljs-number">0</span>) bottom;
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">20%</span> <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">background-repeat</span>: repeat-x;
}
</code></pre>
<p>And here is a figure to illustrate how those gradients create the shape:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731708477342/bbe3e0b6-24a2-498d-992b-4ee152b0d74c.png" alt="Color gradients created by the code" class="image--center mx-auto" width="838" height="292" loading="lazy"></p>
<p>The first gradient created the red part while the second one created the green part. We have two triangle shapes that repeat horizontally.</p>
<p>Since we have five repetitions, I used <code>aspect-ratio: 5</code> and <code>20% (100%/5)</code> in the <code>background-size</code>. You can make it more generic by introducing a variable to control the number of repetitions but as I said previously, I am going to keep things simple.</p>
<p>I want to point out that when using gradients, you can achieve the same result by using different syntaxes. For example, I can update the previous code with the following:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">47px</span>; <span class="hljs-comment">/* control the size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">5</span>;
  <span class="hljs-attribute">background</span>:
   <span class="hljs-built_in">conic-gradient</span>(from <span class="hljs-number">135deg</span> at top   ,#<span class="hljs-number">000</span> <span class="hljs-number">90deg</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">0</span>),
   <span class="hljs-built_in">conic-gradient</span>(from -<span class="hljs-number">45deg</span> at bottom,#<span class="hljs-number">000</span> <span class="hljs-number">90deg</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">0</span>) <span class="hljs-number">12.5%</span> <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">20%</span> <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">background-repeat</span>: repeat-x;
}
</code></pre>
<p>It’s still the same output but with a different syntax for the second gradient. Did you notice the repeated part within the gradients? That part controls the coloration and we can define it as a variable to avoid repetition and be able to update the color only once in the code.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">47px</span>; <span class="hljs-comment">/* control the size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">5</span>;
  <span class="hljs-attribute">--c</span>:<span class="hljs-number">#000</span> <span class="hljs-comment">/* the color */</span> <span class="hljs-number">90deg</span>,<span class="hljs-number">#0000</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">background</span>:
   <span class="hljs-built_in">conic-gradient</span>(from <span class="hljs-number">135deg</span> at top   ,var(--c)),
   <span class="hljs-built_in">conic-gradient</span>(from -<span class="hljs-number">45deg</span> at bottom,var(--c)) <span class="hljs-number">12.5%</span> <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">20%</span> <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">background-repeat</span>: repeat-x;
}
</code></pre>
<p>Now we have our zig-zag shape and we are ready to animate it.</p>
<h2 id="heading-how-to-animate-the-zig-zag-shape">How to Animate the Zig-Zag Shape</h2>
<p>Since we’re using a background, we’ll animate the <code>background-position</code> to get our first loader. The idea is to move the gradients horizontally and create an infinite movement.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">47px</span>; <span class="hljs-comment">/* control the size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">5</span>;
  <span class="hljs-attribute">--c</span>:<span class="hljs-number">#000</span> <span class="hljs-comment">/* the color */</span> <span class="hljs-number">90deg</span>,<span class="hljs-number">#0000</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">background</span>:
   <span class="hljs-built_in">conic-gradient</span>(from <span class="hljs-number">135deg</span> at top   ,var(--c)),
   <span class="hljs-built_in">conic-gradient</span>(from -<span class="hljs-number">45deg</span> at bottom,var(--c)) <span class="hljs-number">12.5%</span> <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">20%</span> <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">background-repeat</span>: repeat-x;
  <span class="hljs-attribute">animation</span>: loading .<span class="hljs-number">8s</span> infinite linear;
}

<span class="hljs-keyword">@keyframes</span> loading {
  0%   {<span class="hljs-attribute">background-position</span>: <span class="hljs-number">0</span>   <span class="hljs-number">0</span>,<span class="hljs-number">12.5%</span> <span class="hljs-number">100%</span>}
  100% {<span class="hljs-attribute">background-position</span>: <span class="hljs-number">25%</span> <span class="hljs-number">0</span>,<span class="hljs-number">37.5%</span> <span class="hljs-number">100%</span>}
}
</code></pre>
<p>Note how we increased the X value of the <code>background-position</code> by <code>25%</code>. In case you are wondering what the logic behind that value is, here is the formula:</p>
<p><code>0.2 / (1 - 0.2) = .25 = 25%</code></p>
<p><code>.2</code> corresponds to the <code>20%</code> used inside the <code>background-size</code>.</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/poMBgQO/5ddc67ad2324e68680f9d1071e46dc96?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/poMBgQO/5ddc67ad2324e68680f9d1071e46dc96">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>We have our first loader! Actually, two loaders because we can easily change the direction of the movement by adding <code>animation-direction: reverse</code>.</p>
<p>Let’s try a different animation: using <code>clip-path</code> and the <code>inset()</code> value. We can easily adjust this technique to create many variations.</p>
<p>Let’s start with a basic example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-comment">/* same code as previously */</span>
  <span class="hljs-attribute">animation</span>: loading .<span class="hljs-number">8s</span> infinite linear;
}
<span class="hljs-keyword">@keyframes</span> loading {
  0%   {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">100%</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>)}
  100% {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>    <span class="hljs-number">0</span> <span class="hljs-number">0</span>)}
}
</code></pre>
<p>The <code>inset()</code> value creates a rectangle where only the part inside it will be visible. For this, we define a distance from each side of the element (top, right, bottom, left).</p>
<p>Logically, <code>inset(0 0 0 0)</code> shows the whole element since all the distances are equal to 0, but <code>inset(0 100% 0 0)</code> completely hides the element since the right value is equal to 100%. So it will touch the opposite edge, creating an empty rectangle.</p>
<p>By animating that right value from <code>100%</code> to <code>0</code> we create a reveal animation. Another loader variation!</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/WNVWrVy/f6214a24e77a0ad6694d3a5bf93d2a23?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/WNVWrVy/f6214a24e77a0ad6694d3a5bf93d2a23">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>If you inspect the code of the second animation, you will see that I did the same thing but with the left side.</p>
<p>We can also have a sliding effect if we animate both the left and right values while keeping their difference constant.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-comment">/* same code as previously */</span>
  <span class="hljs-attribute">animation</span>: loading .<span class="hljs-number">8s</span> infinite linear;
}
<span class="hljs-keyword">@keyframes</span> loading {
  0%   {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">60%</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>  )}
  100% {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>   <span class="hljs-number">0</span> <span class="hljs-number">60%</span>)}
}
</code></pre>
<p>The right value animates from <code>60%</code> to <code>0</code> and the left one from <code>0</code> to <code>60%</code>, so we have a constant difference equal to <code>60%</code> which will create the illusion of a sliding rectangle. Another cool loader!</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/wvVZGwy/71a0f6a7bf177c51252230d7e272fb57?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/wvVZGwy/71a0f6a7bf177c51252230d7e272fb57">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>By trying different combinations of <code>inset()</code> values, you can get a lot of CSS loaders. Give it a try! You can also check <a target="_blank" href="https://css-loaders.com/zig-zag/">my online collection</a> and try to identify the variations that use <code>clip-path: inset()</code>.</p>
<h2 id="heading-how-to-create-a-discrete-animation">How to Create a Discrete Animation</h2>
<p>To achieve a discrete animation, you can use the <code>steps()</code> timing function instead of <code>linear</code>. Let’s start with the first example using <code>steps(2)</code>.</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/YzmbzGL/28874aa2a6066deb4d06fdbefaaade62?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/YzmbzGL/28874aa2a6066deb4d06fdbefaaade62">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>We can do the same with almost all the variations. Let’s try with the ones that use <code>clip-path: inset()</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-comment">/* same code as previously */</span>
  <span class="hljs-attribute">animation</span>: loading .<span class="hljs-number">8s</span> infinite <span class="hljs-built_in">steps</span>(<span class="hljs-number">5</span>);
}
<span class="hljs-keyword">@keyframes</span> loading {
  0%   {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">100%</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>)}
  100% {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>    <span class="hljs-number">0</span> <span class="hljs-number">0</span>)}
}
</code></pre>
<p>We have five repetitions so let’s see what we’ll get with <code>steps(5)</code>.</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/JjgqjNr/9a6b43cda41ed9ec9cb49ea9bdaabb56?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/JjgqjNr/9a6b43cda41ed9ec9cb49ea9bdaabb56">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>At the moment, it’s not good because we don’t see all the repetition. The animation stops at 4 repetitions, but we need to see the whole element (5 repetitions). The count starts from 0 so what we really need is 6 steps instead of 5 to show all the repetitions.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-comment">/* same code as previously */</span>
  <span class="hljs-attribute">animation</span>: loading .<span class="hljs-number">8s</span> infinite <span class="hljs-built_in">steps</span>(<span class="hljs-number">6</span>);
}
<span class="hljs-keyword">@keyframes</span> loading {
  0%   {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">100%</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>)}
  100% {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>    <span class="hljs-number">0</span> <span class="hljs-number">0</span>)}
}
</code></pre>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/RwXmKje/df2744eb1e707246a628b22ce96c7e4c?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/RwXmKje/df2744eb1e707246a628b22ce96c7e4c">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>Even with 6 steps, the result is still not good but don’t worry, it’s not a bug. The default behavior of <code>steps()</code> gives us that output but we can update it to get the expected output:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-comment">/* same code as previously */</span>
  <span class="hljs-attribute">animation</span>: loading .<span class="hljs-number">8s</span> infinite <span class="hljs-built_in">steps</span>(<span class="hljs-number">6</span>,jump-none);
}
<span class="hljs-keyword">@keyframes</span> loading {
  0%   {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">100%</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>)}
  100% {<span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>    <span class="hljs-number">0</span> <span class="hljs-number">0</span>)}
}
</code></pre>
<p>If you’re not familiar with <code>jump-none</code>, it’s a value that can fix most of your issues when working with <code>steps()</code>. I wrote a short article about it if you want more details: “<a target="_blank" href="https://css-tip.com/steps/">How to correctly use steps() with animations</a>“</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/JjgqEpO/5433bef4c1b86de39837108b68ca8eba?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/JjgqEpO/5433bef4c1b86de39837108b68ca8eba">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>Our animation looks perfect now! We can also make it an 11-step animation (<code>5×2 + 1</code>) and get another cool loader.</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/vYowgRV/47df83689104665da6997c41a5825efb?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/vYowgRV/47df83689104665da6997c41a5825efb">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>Even the sliding effect can have its discrete variation.</p>
<div class="embed-wrapper"><iframe height="300" style="width:100%" src="https://codepen.io/t_afif/embed/preview/bGXyZpO/799d03f2d573655e6522476418c6006a?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/bGXyZpO/799d03f2d573655e6522476418c6006a">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>Can you figure out why I am using 4 and 7 steps? I’ll let you do the calculation as a small exercise.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article showed you how to create zig-zag shapes, how to animate them using <code>clip-path</code>, and how to make a discrete animations. You can also consider more tricks like using both pseudo-elements to have two shapes.</p>
<p>I didn’t explore all the variations but you now have the recipe to create most of them!</p>
<p>You can explore <a target="_blank" href="https://css-loaders.com/zig-zag/">my Zig-Zag loaders collection</a> to study other variations and try to create your own loader. It’s a good opportunity to practice what you have learned from this article.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create Filling CSS Loaders Using One Element ]]>
                </title>
                <description>
                    <![CDATA[ In a previous article, I showed you how to create two types of CSS loaders: a spinner and a progress bar. In this article, you’ll learn about another variation called a filling CSS loader. I think a demo is worth thousands of words, so check out this... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/filling-css-loaders/</link>
                <guid isPermaLink="false">6719336f56c24fb7d4fc62b3</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ loaders ]]>
                    </category>
                
                    <category>
                        <![CDATA[ animations ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Wed, 23 Oct 2024 17:33:35 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729637821745/50ff0461-350c-441c-9726-b838d3ef0a5c.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-css-only-loader">a previous article</a>, I showed you how to create two types of CSS loaders: a spinner and a progress bar. In this article, you’ll learn about another variation called a filling CSS loader.</p>
<p>I think a demo is worth thousands of words, so check out this Codepen:</p>
<div class="embed-wrapper"><iframe height="450" style="width:100%;height:450px" src="https://codepen.io/t_afif/embed/preview/ExqvRXO/77e4af243170fc28a0c8193a55b7ffe5?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/ExqvRXO/77e4af243170fc28a0c8193a55b7ffe5">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>In the above Pen, I’m showing you four different CSS filler-style loaders – but we can make even more. You can check out <a target="_blank" href="https://css-loaders.com/filling/">this collection</a> I created to see more than 20 different loaders.</p>
<p>You might think the article is going to be super long – I mean, how long will it take to explain how to create 20 different CSS loaders?</p>
<p>Well don’t worry – this tutorial will be super quick, because I’ll show a few CSS tricks that help you create as many variation as you want. The loaders look different, but all of them rely on the same techniques. By simply adjusting a few setting you can get a whole new loader.</p>
<h2 id="heading-the-initial-loader-configuration">The Initial Loader Configuration</h2>
<p>Like all <a target="_blank" href="https://css-loaders.com/">the CSS Loaders</a> I create, the HTML code is a simple as a single element. Nothing more! Here’s what it looks like:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"loader"</span>&gt;</span>Loading<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Then we apply the following CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">text-transform</span>: uppercase;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#0000</span>; <span class="hljs-comment">/* or transparent */</span>
  <span class="hljs-attribute">-webkit-text-stroke</span>: <span class="hljs-number">1px</span> <span class="hljs-number">#000</span>;
}
</code></pre>
<p>Nothing fancy so far. We make the text transparent and we add a black stroke to it. Here’s what that looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729506785632/fe01d18e-6d7d-4d49-a5d0-ef6766c51241.png" alt="The &quot;loading&quot; text with a black stroke and transparent color" class="image--center mx-auto" width="476" height="190" loading="lazy"></p>
<p>The <code>-webkit-text-stroke</code> is still tagged as experimental, but it has <a target="_blank" href="https://caniuse.com/mdn-css_properties_-webkit-text-stroke">good browser support</a> so you should be able to use it without any issues. This said, it’s always good to test your code in different browsers to make sure everything works fine.</p>
<h2 id="heading-how-to-fill-the-text-with-colors">How to Fill the Text with Colors</h2>
<p>Now it’s time to fill our text (that’s why this technique is called the Filling CSS loaders!). To do this, we are going to rely on gradients and <code>background-clip: text</code>. Here’s the code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">conic-gradient</span>(#<span class="hljs-number">000</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>);
  <span class="hljs-attribute">background-position</span>: left;
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">40%</span> <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">background-repeat</span>: no-repeat;
  <span class="hljs-attribute">background-clip</span>: text;
}
</code></pre>
<p>Or the shorthand version if you prefer more compact code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">background</span>: 
    <span class="hljs-built_in">conic-gradient</span>(#<span class="hljs-number">000</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>) text
    left/<span class="hljs-number">40%</span> <span class="hljs-number">100%</span> no-repeat;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729507914013/b8991ffe-0b81-4ae0-a356-c102023c2f6c.png" alt="the difference between with and without background-clip: text" class="image--center mx-auto" width="873" height="190" loading="lazy"></p>
<p>The above figure illustrates the difference between using or not using <code>background-clip: text</code>. It’s pretty clear that the left result is what we are aiming for. We are limiting the background coloration to only the text instead of the whole element.</p>
<p>The <code>conic-gradient(#000 0 0)</code> looks strange, right? It lets you have a one-color gradient. I wrote a small tip about it that I invite you to read to understand why we’re using that particular syntax in this article, “<a target="_blank" href="https://css-tip.com/one-color-gradient/">How to correctly define a one-color gradient</a>“.</p>
<h2 id="heading-how-to-create-the-filling-loaders">How to Create the Filling Loaders</h2>
<p>Believe it or not, we’re almost done because we have everything we need to make the CSS loaders. For the first loader, we simply animate the <code>background-size</code> as follows:</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#l1</span> {
  <span class="hljs-attribute">animation</span>: l1 <span class="hljs-number">1s</span> linear infinite;
}
<span class="hljs-keyword">@keyframes</span> l1 {  <span class="hljs-comment">/*  width  height */</span>
  0% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">0%</span>   <span class="hljs-number">100%</span>}
  <span class="hljs-selector-tag">to</span> {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">120%</span> <span class="hljs-number">100%</span>}
}
</code></pre>
<p>We start with a width equal to <code>0%</code> until we reach a width equal to <code>120%</code>. I could have used <code>100%</code>, but I want the full coloration to stay longer so I am using a value bigger than <code>100%</code>. As for the height (the second value of the <code>background-size</code>), it remains at <code>100%</code>.</p>
<p>The second loader uses the same animation, but instead of a linear timing function, we use <code>steps()</code> to have a discrete animation.</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#l2</span> {
  <span class="hljs-attribute">font-family</span>: monospace;
  <span class="hljs-attribute">animation</span>: l2 <span class="hljs-number">2s</span> <span class="hljs-built_in">steps</span>(<span class="hljs-number">8</span>, jump-none) infinite;
}
<span class="hljs-keyword">@keyframes</span> l2 {
  0% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">0%</span>           <span class="hljs-number">100%</span>}
  <span class="hljs-selector-tag">to</span> {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">100%</span> <span class="hljs-number">100%</span>}
}
</code></pre>
<p>The text contains 7 characters so we use 8 steps (<code>N + 1</code>). I am also using a monospace font to make sure all the characters have the same width. In case you are wondering about the <code>jump-none</code> value, read the following: <a target="_blank" href="https://css-tip.com/steps/">How to correctly use steps() with animations</a>.</p>
<p><a target="_blank" href="https://css-tip.com/steps/">That’s basically the main trick. By animat</a>ing the background properties, we create different kinds of loaders. It’s either the <code>background-size</code> like the previous ones or the <code>background-position</code> like the below:</p>
<div class="embed-wrapper"><iframe height="400" style="width:100%;height:400px" src="https://codepen.io/t_afif/embed/preview/bGXogOx/59e12d693e164ac69804a554bbac8588?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/bGXogOx/59e12d693e164ac69804a554bbac8588">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>Can you figure out how they work before checking my code? This will be your first homework!</p>
<h2 id="heading-how-to-use-multiple-gradients">How to Use Multiple Gradients</h2>
<p>Using one gradient is enough to create a lot of variations – but we can do even more if we introduce multiple gradients. If you check the fourth loader of the first demo, you’ll see that I’m using seven gradients – one gradient per character.</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#l4</span> {
  <span class="hljs-attribute">font-family</span>: monospace;
  <span class="hljs-attribute">--g</span>: <span class="hljs-built_in">conic-gradient</span>(#<span class="hljs-number">000</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>) no-repeat text;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--g) <span class="hljs-number">0</span>,<span class="hljs-built_in">var</span>(--g) <span class="hljs-number">1ch</span>,<span class="hljs-built_in">var</span>(--g) <span class="hljs-number">2ch</span>,<span class="hljs-built_in">var</span>(--g) <span class="hljs-number">3ch</span>,<span class="hljs-built_in">var</span>(--g) <span class="hljs-number">4ch</span>,<span class="hljs-built_in">var</span>(--g) <span class="hljs-number">5ch</span>,<span class="hljs-built_in">var</span>(--g) <span class="hljs-number">6ch</span>;
  <span class="hljs-attribute">background-position-y</span>: bottom;
  <span class="hljs-attribute">animation</span>: l4 <span class="hljs-number">3s</span> infinite;
}
<span class="hljs-keyword">@keyframes</span> l4 {
  0%     {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   }
  14<span class="hljs-selector-class">.28</span>% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   }
  28<span class="hljs-selector-class">.57</span>% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   }
  42<span class="hljs-selector-class">.85</span>% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   }
  57<span class="hljs-selector-class">.14</span>% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   }
  71<span class="hljs-selector-class">.43</span>% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   ,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   }
  85<span class="hljs-selector-class">.71</span>% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">0</span>   }
  100%   {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>,<span class="hljs-number">1ch</span> <span class="hljs-number">100%</span>}
}
</code></pre>
<p>I’m using the same gradient, so we consider a CSS variable <code>--g</code> to avoid repetition. Then, I call that variable 7 times inside the background property. All the gradients have the same Y position (<code>bottom</code>) but a different X position. That’s why you see the <code>0, 1ch, 2ch, …,6ch</code>.</p>
<p>Now if you check the animation, I’m simply animating the height of each gradient individually. At <code>0%</code>, all of them have a height equal to <code>0</code>. Then I update their height one by one until all of them are at <code>100%</code>. The width doesn’t change – it’s always equal to <code>1ch</code> (the width of one character).</p>
<p>It may look difficult at first glance, but if you think about it one gradient at a time, it’s pretty simple.</p>
<p>What about the third loader, you might ask? For that one, I will rely on <a target="_blank" href="https://css-generators.com/wavy-shapes/">my online generator for wavy shapes</a> to generate the gradient configuration:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729635835522/2f8726a3-e6bb-4949-8846-8408dad56a64.png" alt="Screenshot of the wavy shape generator" class="image--center mx-auto" width="1292" height="517" loading="lazy"></p>
<p>Then I animate the <code>background-position</code> like below:</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#l3</span> {
  <span class="hljs-attribute">background</span>:
    <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">1.13em</span> at <span class="hljs-number">50%</span> <span class="hljs-number">1.6em</span>,#<span class="hljs-number">000</span> <span class="hljs-number">99%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">101%</span>) <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> - <span class="hljs-number">1.6em</span>) <span class="hljs-number">0</span>/<span class="hljs-number">3.2em</span> <span class="hljs-number">100%</span>,
    <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">1.13em</span> at <span class="hljs-number">50%</span> -<span class="hljs-number">0.8em</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">99%</span>,#<span class="hljs-number">000</span> <span class="hljs-number">101%</span>) <span class="hljs-number">50%</span> .<span class="hljs-number">8em</span>/<span class="hljs-number">3.2em</span> <span class="hljs-number">100%</span> repeat-x;
  <span class="hljs-attribute">background-clip</span>: text;
  <span class="hljs-attribute">animation</span>: l3 <span class="hljs-number">2s</span> linear infinite;
}
<span class="hljs-keyword">@keyframes</span> l3 {
  0% {<span class="hljs-attribute">background-position</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> - <span class="hljs-number">1.6em</span>) <span class="hljs-number">0</span>,     <span class="hljs-number">50%</span>          .<span class="hljs-number">8em</span>}
  <span class="hljs-selector-tag">to</span> {<span class="hljs-attribute">background-position</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> + <span class="hljs-number">1.6em</span>) <span class="hljs-number">0</span>,<span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> + <span class="hljs-number">3.2em</span>) .<span class="hljs-number">8em</span>}
}
</code></pre>
<p>This one is probably a bit trickier, but it’s another example to illustrate all the possibilities. From the simple gradient configuration to the most complex one, we can create as many loaders as we want.</p>
<p>What about creating your own CSS loader? You can use what you have learned from the article and try to create a loader that is not part of <a target="_blank" href="https://css-loaders.com/filling/">my collection</a>. The best way to learn is to practice – so give it a try!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By creating some cool loaders, we went through a bunch of CSS tricks related to gradients and backgrounds. Even if creating loaders is not your goal, you can always re-use the same tricks to do something else.</p>
<p>Don’t forget to check my <a target="_blank" href="https://css-tip.com/">CSS Tip blog</a> where I am sharing cool CSS tricks and demos.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create Curved-Edge and Rounded-Edge Shapes Using CSS ]]>
                </title>
                <description>
                    <![CDATA[ In a previous article, I showed you how to create some fancy shapes that you can use as section dividers on your websites (a slanted divider, an arrow divider, and others). In this article, we will study and learn how to make more CSS shapes using th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/rounded-and-curved-edge-css-shapes/</link>
                <guid isPermaLink="false">670d963aff55e287d6962c67</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Mon, 14 Oct 2024 22:07:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728902609915/17a0da8c-143b-4160-8133-bc865c1b535b.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In <a target="_blank" href="https://www.freecodecamp.org/news/section-divider-using-css/">a previous article</a>, I showed you how to create some fancy shapes that you can use as section dividers on your websites (a slanted divider, an arrow divider, and others). In this article, we will study and learn how to make more CSS shapes using the same technique.</p>
<p>Here is an overview of the shapes we’ll look at here, applied to the header of my freeCodeCamp profile:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728811438184/24597334-f2be-4bb1-83f2-11045bc8cacc.png" alt="CSS Shapes: Rounded &amp; Curved edges " class="image--center mx-auto" width="1144" height="448" loading="lazy"></p>
<p>Cool right? Both designs are commonly used as section dividers. We will learn together how to create such shapes with some simple code.</p>
<p>Before we start, you can find the code of the shapes we are making (and more!) within <a target="_blank" href="https://css-shape.com/">my online collection</a>. You can easily copy the code from there – but don’t go away right now! Understanding the logic behind the code is also important and will help you customize it to fit your needs.</p>
<h2 id="heading-how-to-create-a-rounded-edge-using-clip-path">How to Create a Rounded Edge using <code>clip-path</code></h2>
<p>Let’s start with the first shape: <a target="_blank" href="https://css-shape.com/rounded-edge/">The rounded edge</a>. It may sound surprising, but the code to create such a shape is as simple as one CSS declaration:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.rounded-edge</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(<span class="hljs-number">85%</span> <span class="hljs-number">100%</span> at top);
}
</code></pre>
<p>Let’s draw a figure to understand how an “ellipse” creates a rounded edge shape.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728813578343/a4560ca7-c2db-41b6-a3ed-9661ab15ef0b.png" alt="Illustrating the ellipse value of the clip-path" class="image--center mx-auto" width="1106" height="379" loading="lazy"></p>
<p>We start with a rectangle element with no <code>clip-path</code> applied to it. Then, we add <code>clip-path: ellipse(50% 100% at top)</code>. As you can see, we have the ellipse shape. Its center is at the “top center” of the element and its radii are equal to <code>50%</code> horizontally and <code>100%</code> vertically. The shape is overflowing the element boundaries, which is why we only see the bottom half part of it. The top half is clipping nothing.</p>
<p>So you might be wondering: I said “top center”, but why in the code do we only have “top”?</p>
<p>By default, if we don’t specify the position it will be the center of the element. This is equivalent to “<code>center</code>”, “<code>center center</code>”, “<code>50%</code>” or “<code>50% 50%</code>”. Note how we can either define one value or two values. If the second value is omitted, it will be equal to “<code>center</code>” so defining “<code>top</code>” is the same as “<code>top center</code>”.</p>
<p>You don’t need to remember all the cases. Using the keywords such as "<code>top</code>”, “<code>left</code>”, and so on is, most of the time, enough – unless you need to create a custom shape (we will see this later on).</p>
<p>Let’s get back to the previous figure. If we increase the horizontal radius and make it bigger than 50% (85% for example), the ellipse will get bigger and will logically cover a bigger area. You start to see the trick, right? In the end, it’s only a portion at the bottom of the ellipse that is visible – the rounded edge we want!</p>
<p>As a bonus, it’s responsive, since we are relying on percentage values. The horizontal radius is relative to the width while the vertical one is relative to the height. This said, you can also rely on pixel values if you want a fixed size for your ellipse. In some cases, it can give a better result.</p>
<p>Here is a demo showing both cases. Resize the screen to notice the difference:</p>
<div class="embed-wrapper"><iframe height="500" style="width:100%;height:500px" src="https://codepen.io/t_afif/embed/preview/mdNRvEB/8d8fdd895914c59ab86257ed94f9f71a?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/mdNRvEB/8d8fdd895914c59ab86257ed94f9f71a">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>So what about the other variation? We just have to change “top” with “bottom”, right?</p>
<p>Exactly! By changing the center of the ellipse, you change the placement of the rounded edge and easily get the four directions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728817085669/307215e8-f40a-4999-a36f-db6a70d3d1b7.png" alt="Four variations of the rounded edges" class="image--center mx-auto" width="746" height="498" loading="lazy"></p>
<p>You can also get a more custom shape if you adjust the center of the ellipse using percentage values. Like for example using <code>30% 0%</code> to get a rounded edge shifted to the left (note that <code>top</code> is equivalent to <code>50% 0%</code>).</p>
<div class="embed-wrapper"><iframe height="350" style="width:100%;height:350px" src="https://codepen.io/t_afif/embed/preview/vYogbZe/eee85304e8d8c22b625e81b0ee6e8a33?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/vYogbZe/eee85304e8d8c22b625e81b0ee6e8a33">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>A lot of possibilities with only one line of code!</p>
<p>Go check <a target="_blank" href="https://css-shape.com/rounded-edge/">the online version</a> where you can find more examples and easily customize the shape by adjusting the existing code.</p>
<h2 id="heading-how-to-create-a-curved-edge-using-mask">How to Create a Curved Edge using <code>mask</code></h2>
<p>Let’s move to the second shape: <a target="_blank" href="https://css-shape.com/curved-edge/">the curved edge</a>. This one is also pretty easy to create as it requires one line of code as well.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-edge</span> {
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">60%</span> <span class="hljs-number">70px</span> at bottom,#<span class="hljs-number">0000</span> <span class="hljs-number">100%</span>,#<span class="hljs-number">000</span>);
}
</code></pre>
<p>This time, we are going to rely on <code>mask</code> instead of <code>clip-path</code> but the logic is the same. We will hide some parts of the element and keep the remaining visible. When using mask, the hidden part is the transparent color of the gradient (the <code>#0000</code>) while the visible part is the opaque color of the gradient (the <code>#000</code>).</p>
<p>It doesn’t really matter which color you use, only the transparency of the color matters. So you are free to use any color syntax you want. Here’s an example using the <code>rgb()</code> syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-edge</span> {
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">60%</span> <span class="hljs-number">70px</span> at bottom,rgb(<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>/<span class="hljs-number">0%</span>) <span class="hljs-number">100%</span>,<span class="hljs-built_in">rgb</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>/<span class="hljs-number">100%</span>));
}
</code></pre>
<p>Or color names:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-edge</span> {
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">60%</span> <span class="hljs-number">70px</span> at bottom,transparent <span class="hljs-number">100%</span>,black);
}
</code></pre>
<p>And here is a figure to illustrate how it works.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728830604961/6468c949-d783-43b7-8d0a-81fb39ecf2c7.png" alt="Overview of the radial-gradient" class="image--center mx-auto" width="1117" height="457" loading="lazy"></p>
<p>Similar to the ellipse function of the <code>clip-path</code>, the <code>radial-gradient()</code> will also create an ellipse shape. The only difference is that this time we will hide the inside part of the ellipse and show the outside part. And thanks to the overflowing part, we get the curved shape we want.</p>
<p>I think you know the rest of the story now. By adjusting the radii and the position of the center of the ellipse, we get the different variations. As a small homework assignment, try to update the previous code to get the top, left, and right directions. You can compare what you have found with <a target="_blank" href="https://css-shape.com/curved-edge/">my implementation</a>.</p>
<p>When using this method, make sure you have enough space at the bottom. Unlike the rounded edge, the curved edge may hide some of your content at the bottom so it’s always good to include a padding equal to the vertical radius.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-edge</span> {
  <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">70px</span>;
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">60%</span> <span class="hljs-number">70px</span> at bottom,#<span class="hljs-number">0000</span> <span class="hljs-number">100%</span>,#<span class="hljs-number">000</span>);
}
</code></pre>
<h2 id="heading-how-to-combine-both-of-these-css-shapes">How to Combine Both of These CSS Shapes</h2>
<p>What about having both curves so you can create <a target="_blank" href="https://css-shape.com/curved-rectangle/">a curved rectangle shape</a>? It’s possible by simply combining both bits of code like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-rectangle</span> {
  <span class="hljs-comment">/* curved edge at the bottom */</span>
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">60%</span> <span class="hljs-number">70px</span> at bottom,#<span class="hljs-number">0000</span> <span class="hljs-number">100%</span>,#<span class="hljs-number">000</span>);
  <span class="hljs-comment">/* rounded edge at the top */</span>
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(<span class="hljs-number">80%</span> <span class="hljs-number">100%</span> at bottom);
}
</code></pre>
<p>See it in play:</p>
<div class="embed-wrapper"><iframe height="400" style="width:100%;height:450px" src="https://codepen.io/t_afif/embed/preview/VwoPOwm/8f71a34ba272ac1cb7d96ff7d494239b?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/VwoPOwm/8f71a34ba272ac1cb7d96ff7d494239b">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>And the opposite effect by changing <code>bottom</code> with <code>top</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-rectangle</span> {
  <span class="hljs-comment">/* curved edge at the top */</span>
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">60%</span> <span class="hljs-number">70px</span> at top,#<span class="hljs-number">0000</span> <span class="hljs-number">100%</span>,#<span class="hljs-number">000</span>);
  <span class="hljs-comment">/* rounded edge at the bottom */</span>
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(<span class="hljs-number">80%</span> <span class="hljs-number">100%</span> at top);
}
</code></pre>
<div class="embed-wrapper"><iframe height="450" style="width:100%;height:450px" src="https://codepen.io/t_afif/embed/preview/ZEgLNEZ/56d77b755720ce445225af72a32e7941?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/ZEgLNEZ/56d77b755720ce445225af72a32e7941">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>You will notice that I am either using <code>top</code> everywhere or <code>bottom</code> everywhere which makes both pieces of code easy to remember.</p>
<p>Now you might be wondering – how can we have the same curves and the top and bottom?</p>
<p>As you may have noticed, both curves don’t match, which makes the whole shape kind of broken. But we can fix this. We need to make sure both parts of the code create the same ellipse shape by setting the same radii.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-header</span> {
  <span class="hljs-comment">/* curved edge at the top */</span>
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">80%</span> <span class="hljs-number">100%</span> at top,#<span class="hljs-number">0000</span> <span class="hljs-number">100%</span>,#<span class="hljs-number">000</span>);
  <span class="hljs-comment">/* rounded edge at the bottom */</span>
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(<span class="hljs-number">80%</span> <span class="hljs-number">100%</span> at top);
}
</code></pre>
<p>Note the “<code>80% 100% at top</code>” which is the same in both declarations – but nothing will be visible if we use this code. Don’t forget that the <code>clip-path</code> will hide the outside part of the ellipse while the gradient will hide the inside part. So if both ellipses are the same, everything will be hidden.</p>
<p>To fix this, we have to offset the gradient and move it to the top to get the following:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-rectangle</span> {
  <span class="hljs-comment">/* curved edge at the top */</span>
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">80%</span> <span class="hljs-number">100%</span> at <span class="hljs-number">50%</span> -<span class="hljs-number">78%</span> /* instead of <span class="hljs-number">50%</span> <span class="hljs-number">0%</span> */,#<span class="hljs-number">0000</span> <span class="hljs-number">100%</span>,#<span class="hljs-number">000</span>);
  <span class="hljs-comment">/* rounded edge at the bottom */</span>
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(<span class="hljs-number">80%</span> <span class="hljs-number">100%</span> at top);
}
</code></pre>
<p>The shape is now perfect and both curves are aligned.</p>
<div class="embed-wrapper"><iframe height="450" style="width:100%;height:450px" src="https://codepen.io/t_afif/embed/preview/GRVWKZM/32ab225612d6ffade20cbef6c43100fa?default-tab=result" title="Embedded content" loading="lazy">
  See the Pen <a href="https://codepen.io/t_afif/pen/GRVWKZM/32ab225612d6ffade20cbef6c43100fa">
  Untitled</a> by Temani Afif (<a href="https://codepen.io/t_afif">@t_afif</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe></div>

<p>If you don’t like to use magic numbers like the “-78%”, we can consider some math to get accurate results:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-rectangle</span> {
  <span class="hljs-attribute">--c</span>: <span class="hljs-number">80</span>; <span class="hljs-comment">/* control the curve */</span>

  <span class="hljs-attribute">mask</span>: 
    <span class="hljs-built_in">radial-gradient</span>(calc(var(--c)*<span class="hljs-number">1%</span>) <span class="hljs-number">100%</span> 
     at <span class="hljs-number">50%</span> <span class="hljs-built_in">calc</span>(-<span class="hljs-number">100%</span>*cos(asin(<span class="hljs-number">50</span>/var(--c)))),
     <span class="hljs-number">#0000</span> <span class="hljs-number">100%</span>,<span class="hljs-number">#000</span>);
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(calc(var(--c)*<span class="hljs-number">1%</span>) <span class="hljs-number">100%</span> at top);
}
</code></pre>
<p>The code looks more complex (I will skip the boring geometry explanation) but you can easily control the curve by adjusting a single value.</p>
<p>So what about the bottom version? We update the code like the below:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-rectangle</span> {
  <span class="hljs-attribute">--c</span>: <span class="hljs-number">80</span>; <span class="hljs-comment">/* control the curve */</span>

  <span class="hljs-attribute">mask</span>: 
    <span class="hljs-built_in">radial-gradient</span>(calc(var(--c)*<span class="hljs-number">1%</span>) <span class="hljs-number">100%</span> 
     at <span class="hljs-number">50%</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> + <span class="hljs-number">100%</span>*cos(asin(<span class="hljs-number">50</span>/var(--c)))),
     <span class="hljs-number">#0000</span> <span class="hljs-number">100%</span>,<span class="hljs-number">#000</span>);
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(calc(var(--c)*<span class="hljs-number">1%</span>) <span class="hljs-number">100%</span> at bottom);
}
</code></pre>
<p>The <code>top</code> of the <code>clip-path</code> becomes <code>bottom</code> and inside the gradient, we use <code>100% + X</code> instead of <code>-X</code> where <code>X</code> is the offset. You can always find all the code within <a target="_blank" href="https://css-shape.com/curved-rectangle/">my online collection</a>.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>How many lines of code do you have to remember? Only two lines of code – that’s all! You can create a rounded edge using <code>clip-path</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.rounded-edge</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(<span class="hljs-number">85%</span> <span class="hljs-number">100%</span> at top);
}
</code></pre>
<p>And you can create a curved edge using <code>mask</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-edge</span> {
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">60%</span> <span class="hljs-number">70px</span> at top,#<span class="hljs-number">0000</span> <span class="hljs-number">100%</span>,#<span class="hljs-number">000</span>);
}
</code></pre>
<p>And by combining both, you get a curved rectangle:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.curved-rectangle</span> {
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">80%</span> <span class="hljs-number">100%</span> at <span class="hljs-number">50%</span> -<span class="hljs-number">78%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">100%</span>,#<span class="hljs-number">000</span>);
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">ellipse</span>(<span class="hljs-number">80%</span> <span class="hljs-number">100%</span> at top);
}
</code></pre>
<p>You don’t have to remember the verbose version where I am using math. Most of the time, you don’t really need to have accurate values and you can manually adjust the position until you get it right.</p>
<p>Don’t forget to bookmark <a target="_blank" href="https://css-shape.com/">my online collection of CSS shapes</a> if you want to easily copy the code of any shape. I also recommend reading my “<a target="_blank" href="https://www.smashingmagazine.com/2024/05/modern-guide-making-css-shapes/">Modern guide for making CSS shapes</a>” to know the secret behind creating more CSS shapes.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn CSS radial-gradient by Building Background Patterns ]]>
                </title>
                <description>
                    <![CDATA[ If you are new to CSS gradients, you may have heard about something called radial-gradient(). If you have never used it before, you are in the right place to learn about it. In this tutorial, I will focus on some real and practical examples to explai... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/css-radial-gradient/</link>
                <guid isPermaLink="false">66bb55d924c949cee2fb6be3</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Tue, 19 Apr 2022 01:12:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/pattern-header.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you are new to CSS gradients, you may have heard about something called <code>radial-gradient()</code>. If you have never used it before, you are in the right place to learn about it.</p>
<p>In this tutorial, I will focus on some real and practical examples to explain the secrets behind <code>radial-gradient()</code> and how it works.</p>
<p>CSS Gradients are usually used to create fancy patterns, so I have selected a few of them made with only <code>radial-gradient()</code>. By building them, we will learn everything about these gradients.</p>
<h2 id="heading-radial-gradient-pattern-1">radial-gradient pattern #1</h2>
<p>Let's start with the most basic pattern.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/pattern-1.png" alt="Pattern made with radial-gradient" width="600" height="400" loading="lazy"></p>
<p><em>Pattern made with radial-gradient</em></p>
<p>Nothing complex so far – we are simply repeating circles. Circles, ellipses, half-circles, a quarter of circles, and so on...all are different shapes that we can create using <code>radial-gradient()</code>.</p>
<p>To make it simple, we can consider the ellipse as the main shape since a circle is a particular case of an ellipse. Then by hiding some parts we get half of a circle, a quarter of a circle, and so on.</p>
<p>Let's zoom in on the pattern to identify the different values.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-128.png" alt="Illustration of the different values of the pattern" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the different values of the pattern</em></p>
<p>We are drawing inside an area that has dimensions of <code>100px*100px</code> which is our <code>background-size</code>. We will consider a horizontal radius equal to <code>50%</code> and a vertical one equal to <code>50%</code> and the center of our shape will be the center of the area.</p>
<p>An ellipse is defined with two radii called the "horizontal radius" and the "vertical radius". If both are equal (like in our case) we get a circle.</p>
<p>This will give us the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50%</span> <span class="hljs-number">50%</span> at center, ???);
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>   
}
</code></pre>
<p>We defined the setting of our gradient, and now we need to define the color configuration. We will draw a circle that will not touch the edge of the <code>background-size</code> area. From the <code>50%</code>, we will have <code>80%</code> of the main color and the remaining will be transparent.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50%</span> <span class="hljs-number">50%</span> at center, #c39f76 <span class="hljs-number">0%</span> <span class="hljs-number">80%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">81%</span> <span class="hljs-number">100%</span>);
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>   
}
</code></pre>
<p>Basically, we first define the center and size of our ellipse (the <code>50% 50% at center</code>) then we fill it with a gradient coloration (the <code>c39f76 0 80%,#0000 81% 100%</code>). We get a full circle in this case because both radii are equal ( <code>50%</code> of <code>100px</code> ) and because we have no transition between the colors.</p>
<p>We have the main color from <code>0%</code> to <code>80%</code> and transparent from <code>81%</code> to <code>100%</code>. (We should have used <code>80%</code> instead of <code>81%</code> but we keep a small transition to avoid jagged edges.)</p>
<p>We can optimize the above code by removing the default values to get this:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50%</span> <span class="hljs-number">50%</span>,#c39f76 <span class="hljs-number">80%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">81%</span>);
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>   
}
</code></pre>
<p>The position is by default the center and we can omit <code>0%</code> and <code>100%</code> from the color configuration.</p>
<p>The above is not the only syntax to achieve that pattern. We can also use:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">40%</span> <span class="hljs-number">40%</span>,#c39f76 <span class="hljs-number">99%</span>,#<span class="hljs-number">0000</span>);
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>   
}
</code></pre>
<p>We reduce the radius of our circle and we increase the percentage of the main color. Note that I didn't define any percentage with the transparent color since it should be <code>100%</code> (the default value) that we can omit.</p>
<p>We can also use:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">radial-gradient</span>(#c39f76 <span class="hljs-number">56%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">57%</span>);
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>   
}
</code></pre>
<p>We omit the radius and the browser will use a default setting that needs another color configuration.</p>
<p>You don't have to memorize all the cases, just stick to one easy way (I recommend the first one). Later, with practice, you will discover different ways to achieve the same result and you will be able to optimize your syntax to reduce the amount of code used as I did with the last example.</p>
<h2 id="heading-radial-gradient-pattern-2">radial-gradient pattern #2</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/pattern-2.png" alt="Pattern made with radial-gradient" width="600" height="400" loading="lazy"></p>
<p><em>Pattern made with radial-gradient</em></p>
<p>For this one, I will use 2 <code>radial-gradient()</code>s. Let's not forget that we can have as many background layers as we want. This is a great feature that allows us to build complex patterns by combining different gradients with different configurations.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-129.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We are keeping the same <code>background-size</code> here, but we are using different positions for our circles. The code will be the following:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background-image</span>: 
     <span class="hljs-built_in">radial-gradient</span>(?? at <span class="hljs-number">25%</span> <span class="hljs-number">25%</span>,??),
     <span class="hljs-built_in">radial-gradient</span>(?? at <span class="hljs-number">75%</span> <span class="hljs-number">75%</span>,??);
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>; 
}
</code></pre>
<p>For the radius configuration, if we do some math, we can find that we need <code>25%</code> for both circles to touch the edges. So we can use this code:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background-image</span>: 
     <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">25%</span> <span class="hljs-number">25%</span> at <span class="hljs-number">25%</span> <span class="hljs-number">25%</span>,#c39f76 <span class="hljs-number">80%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">81%</span>),
     <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">25%</span> <span class="hljs-number">25%</span> at <span class="hljs-number">75%</span> <span class="hljs-number">75%</span>,#c39f76 <span class="hljs-number">80%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">81%</span>);
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>; 
}
</code></pre>
<p>We can also use <code>closest-side</code> instead of <code>25% 25%</code>. I know, it's a strange value, but it means "use a value of radius that allows the circle to touch the closest side to its center". This value is useful and can save us from dealing with some complex calculations.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background-image</span>: 
     <span class="hljs-built_in">radial-gradient</span>(closest-side at <span class="hljs-number">25%</span> <span class="hljs-number">25%</span>,#c39f76 <span class="hljs-number">80%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">81%</span>),
     <span class="hljs-built_in">radial-gradient</span>(closest-side at <span class="hljs-number">75%</span> <span class="hljs-number">75%</span>,#c39f76 <span class="hljs-number">80%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">81%</span>);
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>; 
}
</code></pre>
<p><code>radial-gradient()</code> provide us with 3 other similar values ( <code>closest-corner</code>, <code>farthest-side</code>, and <code>farthest-corner</code>). We either define an explicit size for our radius or we use those values and the browser will automatically find the radius based on specific rules.</p>
<p>As I said previously, you don't need to memorize everything. I am trying to focus on the basics of <code>radial-gradient()</code> while providing as much information as possible that you may use later.</p>
<h2 id="heading-radial-gradient-pattern-3">radial-gradient pattern #3</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/pattern-3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>I am increasing the difficulty with this one. After the 1st and 2nd patterns, we can now try a more complex pattern. This one is also made using two gradients where we will not have full circles but a combination of two half circles.</p>
<p>Below is an illustration to help you understand the puzzle. I am using different colors to easily identify each gradient.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-130.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The center for the first gradient is placed at <code>50% 100%</code> while the second one is placed at <code>50% 0%</code> but we can also use <code>top</code> and <code>bottom</code> as their equivalent values.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background-image</span>: 
     <span class="hljs-built_in">radial-gradient</span>(?? at top   ,??),
     <span class="hljs-built_in">radial-gradient</span>(?? at bottom,??);
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>; 
}
</code></pre>
<p>For the radius, we can use <code>50% 50%</code> like we did before, but this time I will try something different and consider <code>50px</code> which is half the <code>background-size</code>.</p>
<p>When using a pixel value or any unit that's different from a percentage, we can specify only one radius and the browser will understand that we want a circle with that radius. This is still another way to define the size of our shape in addition to percentage and the specific values.</p>
<p>Our circle is touching the edge so the code will be:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background-image</span>: 
     <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50px</span> at top   ,#c39f76 <span class="hljs-number">99%</span>,#<span class="hljs-number">0000</span>),
     <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50px</span> at bottom,#c39f76 <span class="hljs-number">99%</span>,#<span class="hljs-number">0000</span>);
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>; 
}
</code></pre>
<p>Yes, the above will not give us the pattern we're going for – we still need a final touch. If you check the previous illustration, you'll notice that the second gradient (the green one) is shifted to the right by half the size. In other words, we need to update its <code>background-position</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background-image</span>: 
     <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50px</span> at top   ,#c39f76 <span class="hljs-number">99%</span>,#<span class="hljs-number">0000</span>),
     <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50px</span> at bottom,#c39f76 <span class="hljs-number">99%</span>,#<span class="hljs-number">0000</span>);
   <span class="hljs-attribute">background-position</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>, <span class="hljs-number">50px</span> <span class="hljs-number">0</span>;
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>; 
}
</code></pre>
<p>We can optimize the code a little by using the shorthand version:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background</span>: 
     <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50px</span> at top   ,#c39f76 <span class="hljs-number">99%</span>,#<span class="hljs-number">0000</span>),
     <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50px</span> at bottom,#c39f76 <span class="hljs-number">99%</span>,#<span class="hljs-number">0000</span>) <span class="hljs-number">50px</span> <span class="hljs-number">0</span>;
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>; 
}
</code></pre>
<p>And since we are dealing with pixel values, we can add a CSS variable to make the code easy to adjust.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">--s</span>: <span class="hljs-number">100px</span>;
   <span class="hljs-attribute">background</span>: 
     <span class="hljs-built_in">radial-gradient</span>(calc(var(--s)/<span class="hljs-number">2</span>) at top   ,<span class="hljs-number">#c39f76</span> <span class="hljs-number">99%</span>,<span class="hljs-number">#0000</span>),
     <span class="hljs-built_in">radial-gradient</span>(calc(var(--s)/<span class="hljs-number">2</span>) at bottom,<span class="hljs-number">#c39f76</span> <span class="hljs-number">99%</span>,<span class="hljs-number">#0000</span>) <span class="hljs-built_in">calc</span>(var(--s)/<span class="hljs-number">2</span>) <span class="hljs-number">0</span>;
   <span class="hljs-attribute">background-size</span>: <span class="hljs-built_in">var</span>(--s) <span class="hljs-built_in">var</span>(--s); 
}
</code></pre>
<p>Instead of updating different values, we change only one!</p>
<h2 id="heading-radial-gradient-pattern-4">radial-gradient pattern #4</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/pattern-4.png" alt="Pattern background made with radial-gradient" width="600" height="400" loading="lazy"></p>
<p><em>Pattern background made with radial-gradient</em></p>
<p>At first glance, this background looks a bit complex. But if we can identify the correct pattern it becomes easy.</p>
<p>This is the most difficult part when dealing with such a background. Sometimes it's not easy to identify the different background layers. My advice to get better at this exercise is to practice.</p>
<p>Intuitively, you may think that the pattern is this one and you will struggle to find the gradients</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-131.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>but it's not. The real pattern is this one</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-132.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We have 4 circles placed at the corners with a small overflow. The code will be:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background</span>: 
     <span class="hljs-built_in">radial-gradient</span>(closest-corner at <span class="hljs-number">20%</span> <span class="hljs-number">20%</span>,#c39f76 <span class="hljs-number">98%</span>,#<span class="hljs-number">0000</span>),
     <span class="hljs-built_in">radial-gradient</span>(closest-corner at <span class="hljs-number">80%</span> <span class="hljs-number">20%</span>,#c39f76 <span class="hljs-number">98%</span>,#<span class="hljs-number">0000</span>),
     <span class="hljs-built_in">radial-gradient</span>(closest-corner at <span class="hljs-number">20%</span> <span class="hljs-number">80%</span>,#c39f76 <span class="hljs-number">98%</span>,#<span class="hljs-number">0000</span>),
     <span class="hljs-built_in">radial-gradient</span>(closest-corner at <span class="hljs-number">80%</span> <span class="hljs-number">80%</span>,#c39f76 <span class="hljs-number">98%</span>,#<span class="hljs-number">0000</span>);
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>;
}
</code></pre>
<p>A good use for <code>closest-corner</code> to define the radius. For each layer, the browser will draw a circle placed at a specific position and touch the closest corner. This setting allows us to use an easy color configuration while having the needed overflow.</p>
<p>We can also use <code>closest-side</code> like below:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">background</span>: 
     <span class="hljs-built_in">radial-gradient</span>(closest-side at <span class="hljs-number">20%</span> <span class="hljs-number">20%</span>,#c39f76 <span class="hljs-number">140%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">141%</span>),
     <span class="hljs-built_in">radial-gradient</span>(closest-side at <span class="hljs-number">80%</span> <span class="hljs-number">20%</span>,#c39f76 <span class="hljs-number">140%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">141%</span>),
     <span class="hljs-built_in">radial-gradient</span>(closest-side at <span class="hljs-number">20%</span> <span class="hljs-number">80%</span>,#c39f76 <span class="hljs-number">140%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">141%</span>),
     <span class="hljs-built_in">radial-gradient</span>(closest-side at <span class="hljs-number">80%</span> <span class="hljs-number">80%</span>,#c39f76 <span class="hljs-number">140%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">141%</span>);
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>;
}
</code></pre>
<p>The only new thing in the above code is the color configuration where I am using values that are bigger than <code>100%</code>. Since I am using <code>closest-side</code> to define the radius, I need to get bigger than <code>100%</code> to create the overflow.</p>
<p>Don't forget such a trick, it can be helpful. The color values are not limited to the range <code>[0% 100%]</code> – they can go bigger.</p>
<p>In such situation, we can also rely on a CSS variable to avoid the repetition of the color configuration:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
   <span class="hljs-attribute">--c</span>: <span class="hljs-number">#c39f76</span> <span class="hljs-number">98%</span>,<span class="hljs-number">#0000</span>;
   <span class="hljs-attribute">background</span>: 
     <span class="hljs-built_in">radial-gradient</span>(closest-corner at <span class="hljs-number">20%</span> <span class="hljs-number">20%</span>,var(--c)),
     <span class="hljs-built_in">radial-gradient</span>(closest-corner at <span class="hljs-number">80%</span> <span class="hljs-number">20%</span>,var(--c)),
     <span class="hljs-built_in">radial-gradient</span>(closest-corner at <span class="hljs-number">20%</span> <span class="hljs-number">80%</span>,var(--c)),
     <span class="hljs-built_in">radial-gradient</span>(closest-corner at <span class="hljs-number">80%</span> <span class="hljs-number">80%</span>,var(--c));
   <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>;
}
</code></pre>
<h2 id="heading-radial-gradient-pattern-5">radial-gradient pattern #5</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/pattern-5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Pattern made with radial-gradient</em></p>
<p>Here's another non-intuitive pattern that may confuse many of you. You may see it as a circle that is half-filled and you might be wondering how it's possible to achieve that. In reality, it's a combination of two half circles like below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-133.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And here's their code:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background</span>:
    <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50%</span> <span class="hljs-number">50%</span> at left ,#<span class="hljs-number">0000</span> <span class="hljs-number">70%</span>,#c39f76 <span class="hljs-number">71%</span> <span class="hljs-number">80%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">81%</span>),
    <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">50%</span> <span class="hljs-number">50%</span> at right,#c39f76 <span class="hljs-number">0</span> <span class="hljs-number">80%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">81%</span>);
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>;
}
</code></pre>
<p>This time, we are using a different color configuration for each one. The first one has 3 colors (transparent, then the main color, then transparent again). The second has the same color configuration we used with the previous examples.</p>
<p>This pattern is a good example to show how different colors configuration can be another way to get complex background patterns.</p>
<h2 id="heading-radial-gradient-pattern-6">radial-gradient pattern #6</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/pattern-6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is another pattern where it's not easy to identify the different layers – but if we look closely we can see two circles</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-134.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The big circle is our first layer</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-135.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>It's a circle placed at the center of the area (defined with <code>background-size</code> as usual) but this time the color configuration is not as usual. I am using a transparent color for the inside part and the main color outside. It should be noted that we have a small overflow as well.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">54%</span> <span class="hljs-number">54%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">98%</span>,#c39f76);
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>;
}
</code></pre>
<p>As you can see, I am using <code>54%</code> instead of <code>50%</code> to create the overflow.</p>
<p>The second layer is a smaller circle with white color as the main color. The whole code will be:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background</span>: 
    <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">10%</span> <span class="hljs-number">10%</span>,#fff <span class="hljs-number">98%</span>,#<span class="hljs-number">0000</span>),
    <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">54%</span> <span class="hljs-number">54%</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">98%</span>,#c39f76) <span class="hljs-number">50px</span> <span class="hljs-number">50px</span>;
  <span class="hljs-attribute">background-size</span>:<span class="hljs-number">100px</span> <span class="hljs-number">100px</span>;
}
</code></pre>
<p>Note the use of <code>50px 50px</code>. Like with the 3rd pattern, we need to shift one of the layers by half the size to get the correct result – otherwise both circles will have the same center which is not the intended result.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-137.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-radial-gradient-pattern-7">radial-gradient pattern #7</h2>
<p>Here's the last pattern before we end:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/pattern-7.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With this last example, I want to introduce <code>repeating-radial-gradient()</code> which is another way to write <code>radial-gradient()</code>.</p>
<p>Our pattern is as follows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-138.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can achieve the above using <code>radial-gradient()</code> but the color configuration will get too lengthy (transparent, main color, transparent, main color, and so on).</p>
<p>In this case, the color configuration is nothing but a repeated pattern of "transparent, main color" and <code>repeating-radial-gradient()</code> is made for such a purpose. It allows us to define a pattern color configuration.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">repeating-radial-gradient</span>(#<span class="hljs-number">0000</span> <span class="hljs-number">0%</span> <span class="hljs-number">12%</span>,#c39f76 <span class="hljs-number">13%</span> <span class="hljs-number">26%</span> );
  <span class="hljs-attribute">background-size</span>:<span class="hljs-number">100px</span> <span class="hljs-number">100px</span>;
}
</code></pre>
<p>The above means that we have <code>12%</code> of transparent color and then <code>13%</code> of the main color ( <code>26 - 13 = 13</code>) then we repeat the same until we cover all the area.</p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>Through exploring how to create different background patterns, we covered the basics of <code>radial-gradient()</code>.</p>
<p>The article ends here, but this is just the beginning. <code>radial-gradient()</code> is more complex than the simple examples we just saw – but now you have the needed tools to practice and get used to it.</p>
<p>Go ahead and try to build your own pattern using <code>radial-gradient()</code>. If you need some inspiration, check <a target="_blank" href="https://css-pattern.com/">my collection of CSS Patterns</a> (more than 100 using CSS gradients). I also have <a target="_blank" href="https://verpex.com/blog/website-tips/how-to-create-background-pattern-using-css-conic-gradient">another article about <code>conic-gradient()</code></a> if you want a follow up to this one.</p>
<p>Here’s another reference to get more details:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/radial-gradient">https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/radial-gradient</a></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Section Divider Using CSS ]]>
                </title>
                <description>
                    <![CDATA[ It's always cool to have a fancy section divider on your website. And it's even better if we can make them responsive and easy to adjust. This is what you will learn in this article. We will explore different section dividers made using only CSS and ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/section-divider-using-css/</link>
                <guid isPermaLink="false">66bb55e15a83db22bea9842f</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Fri, 25 Feb 2022 21:46:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/section-divider.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>It's always cool to have a fancy section divider on your website. And it's even better if we can make them responsive and easy to adjust. This is what you will learn in this article.</p>
<p>We will explore different section dividers made using only CSS and some optimized code that's easy to manipulate.</p>
<p>Here's an example of section dividers in action:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-90.png" alt="Overview of 2 sections Dividers applied to the FreeCodeCamp header" width="600" height="400" loading="lazy"></p>
<p><em>Overview of 2 sections Dividers applied to the FreeCodeCamp header</em></p>
<p>Before we dig into the technical part, I have created an <a target="_blank" href="https://css-generators.com/section-divider/">online generator</a> for section dividers. All you have to do is to select your configuration and get the CSS code in no time.</p>
<p>Alright, I can hear saying: "Why a boring tutorial? I'll simply use the generator whenever I need it!"</p>
<p>Sure, you can do that – but it's always good to know what's happening under the hood so you understand the code you are using and so you're able to manually adjust it.</p>
<p>Then you'll be able to create your own personalized divider after understanding the ones I made!</p>
<p>So let's dive in and learn how it's done.</p>
<h2 id="heading-how-to-create-a-slanted-divider-for-your-website">How to Create a Slanted Divider for Your Website</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/slanted-divider.png" alt="Illustration of a slanted divider" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of a slanted divider</em></p>
<p>In the above figure, we have two elements separated with a slanted gap. To achieve this effect, we will cut a portion from each one. Let's look at a step-by-step illustration to better understand.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-81.png" alt="A step-by-step illustration to create a slanted divider" width="600" height="400" loading="lazy"></p>
<p><em>A step-by-step illustration to create a slanted divider</em></p>
<p>Initially, we have two elements placed above each other. We first start by cutting the bottom part of the top element (step (2)) using <code>clip-path</code> like below:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">clip-path</span>: <span class="hljs-selector-tag">polygon</span>(0 0,100% 0,100% 100%,0 <span class="hljs-selector-tag">calc</span>(100% <span class="hljs-selector-tag">-</span> 50<span class="hljs-selector-tag">px</span>));
</code></pre>
<p>We have a four points path where we make the bottom left one a bit higher to create the cut effect. You can notice the use of <code>calc(100% - 50px)</code> instead of <code>100%</code>.</p>
<p>We do the same for the second element in step (3) using:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">clip-path</span>: <span class="hljs-selector-tag">polygon</span>(0 0,100% 50<span class="hljs-selector-tag">px</span>,100% 100%,0 100%);
</code></pre>
<p>This time we are lowering the top right corner by the same amount of pixels (<code>50px</code> instead of <code>0</code>). If you are not familiar with <code>clip-path</code>, here is a figure to better see the points.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-82.png" alt="Illustration of the clip-path points" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the clip-path points</em></p>
<p>The points are nothing but x,y coordinates in a 2D space with the range <code>[0 100%]</code>. You can easily identify the four corners, and from there we can find any other points.</p>
<p>Finally, we add a negative <code>margin-top</code> to the second element to reduce the space and get a gap equal to <code>10px</code>. The final code will be:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> calc(<span class="hljs-number">100%</span> - <span class="hljs-number">50px</span>));
}
<span class="hljs-selector-class">.bottom</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">50px</span>,<span class="hljs-number">100%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> <span class="hljs-number">100%</span>);
  <span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">40px</span>;
}
</code></pre>
<p>That's the code you will get from the <a target="_blank" href="https://css-generators.com/section-divider/">the online generator</a> I made. We can improve it by introducing CSS variables:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--size</span>: <span class="hljs-number">50px</span>; <span class="hljs-comment">/* size of the cut */</span>
  <span class="hljs-attribute">--gap</span>: <span class="hljs-number">10px</span>;  <span class="hljs-comment">/* the gap */</span>
}
<span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> calc(<span class="hljs-number">100%</span> - var(--size)));
}
<span class="hljs-selector-class">.bottom</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> var(--size),<span class="hljs-number">100%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> <span class="hljs-number">100%</span>);
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-built_in">calc</span>(var(--gap) - <span class="hljs-built_in">var</span>(--size));
}
</code></pre>
<p>As I said in the introduction, we have some simple code that's easy to adjust that produces a responsive section divider.</p>
<h2 id="heading-how-to-create-a-full-width-arrow-divider-for-your-website">How to Create a Full-Width Arrow Divider for Your Website</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-83.png" alt="Illustration of the full-width arrow divider" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the full-width arrow divider</em></p>
<p>This one is pretty similar to the previous divider. We will simply deal with more <code>clip-path</code> points.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-84.png" alt="A step-by-step illustration to create a full width arrow divider" width="600" height="400" loading="lazy"></p>
<p><em>A step-by-step illustration to create a full width arrow divider</em></p>
<p>I think you probably have the idea by now. We follow the same steps and we end with the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> calc(<span class="hljs-number">100%</span> - <span class="hljs-number">50px</span>),<span class="hljs-number">50%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - <span class="hljs-number">50px</span>));
}
<span class="hljs-selector-class">.bottom</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">50%</span> <span class="hljs-number">50px</span>,<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> <span class="hljs-number">100%</span>);
  <span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">40px</span>;
}
</code></pre>
<p>And below is another illustration to understand the new points we are using for this section divider.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-85.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the clip-path points</em></p>
<p>At first glance, it may look difficult but it's really pretty easy.</p>
<p>We are creating shapes by linking different points inside the 2D space of our element. The trick is to create 2 "puzzle shapes" (I just coined this term) to create the illusion of a section divider. With some practice, you can easily create your divider by following the same logic.</p>
<p>Before we move to the next one here is the code using CSS variables:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--size</span>: <span class="hljs-number">50px</span>; <span class="hljs-comment">/* size of the cut */</span>
  <span class="hljs-attribute">--gap</span>: <span class="hljs-number">10px</span>;  <span class="hljs-comment">/* the gap */</span>
}
<span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> calc(<span class="hljs-number">100%</span> - var(--size)),<span class="hljs-number">50%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--size)));
}
<span class="hljs-selector-class">.bottom</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">50%</span> var(--size),<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> <span class="hljs-number">100%</span>);
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-built_in">calc</span>(var(--gap) - <span class="hljs-built_in">var</span>(--size));
}
</code></pre>
<p>You can already see a pattern in the code of our dividers since we are using the same technique. Two <code>clip-path</code>, a negative <code>margin-top</code>, and two CSS variables. As simple as that!</p>
<h2 id="heading-how-to-create-an-arrow-divider-for-your-website">How to Create an Arrow Divider for Your Website</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-86.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the arrow divider</em></p>
<p>This divider is a bit trickier than the previous ones because I will add another variable which is the angle of the arrow. The technique remains the same but we will have more math to calculate the coordinates of the points.</p>
<p>For this one, my <a target="_blank" href="https://css-generators.com/section-divider/">online generator</a> will be very useful (especially if you're not comfortable with math formulas) so you can easily get the final values without trouble.</p>
<p>For the curious ones, here is the generic code:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--size</span>: <span class="hljs-number">50px</span>;   <span class="hljs-comment">/* size of the cut */</span>
  <span class="hljs-attribute">--gap</span>: <span class="hljs-number">10px</span>;    <span class="hljs-comment">/* the gap */</span>
  <span class="hljs-attribute">--angle</span>: <span class="hljs-number">90deg</span>; <span class="hljs-comment">/* angle of the arrow */</span>
}
<span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> calc(<span class="hljs-number">100%</span> - var(--size)),<span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> + tan(var(--angle)/<span class="hljs-number">2</span>)*<span class="hljs-built_in">var</span>(--size)) <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--size)),<span class="hljs-number">50%</span> <span class="hljs-number">100%</span>,<span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> - tan(var(--angle)/<span class="hljs-number">2</span>)*<span class="hljs-built_in">var</span>(--size)) <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--size)),<span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--size)));
}
<span class="hljs-selector-class">.bottom</span> {
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,calc(<span class="hljs-number">50%</span> - tan((<span class="hljs-number">180deg</span> - var(--angle))/<span class="hljs-number">4</span>)*<span class="hljs-built_in">var</span>(--gap) - <span class="hljs-built_in">tan</span>(var(--angle)/<span class="hljs-number">2</span>)*<span class="hljs-built_in">var</span>(--size)) <span class="hljs-number">0</span>,<span class="hljs-number">50%</span> <span class="hljs-built_in">calc</span>(var(--size) + (<span class="hljs-number">1</span>/<span class="hljs-built_in">sin</span>(var(--angle)/<span class="hljs-number">2</span>) - <span class="hljs-number">1</span>)*<span class="hljs-built_in">var</span>(--gap)),<span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> + tan((<span class="hljs-number">180deg</span> - var(--angle))/<span class="hljs-number">4</span>)*<span class="hljs-built_in">var</span>(--gap) + <span class="hljs-built_in">tan</span>(var(--angle)/<span class="hljs-number">2</span>)*<span class="hljs-built_in">var</span>(--size)) <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">100%</span>,<span class="hljs-number">0</span> <span class="hljs-number">100%</span>);
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-built_in">calc</span>(var(--gap) - <span class="hljs-built_in">var</span>(--size));
}
</code></pre>
<p>I can hear you screaming seeing this, but don't worry if you don't fully understand it. I am still creating different shapes using <code>clip-path</code> but this time the calculation is a bit more complex.</p>
<p>The above is valid CSS code but at the time of writing this, there is no support for trigonometric functions so it won't work in any browser. Either you calculate the values manually or use <a target="_blank" href="https://css-generators.com/section-divider/">the online generator</a> to get the <code>clip-path</code> values.</p>
<p>Until now, we have made 3 different dividers using the same technique. Each time we consider a new shape by playing with the <code>clip-path</code> values. You can create any divider using the same technique, and the combinations are unlimited. The only limit is your imagination.</p>
<p>It's a good exercise to get familiar with <code>clip-path</code>. What I recommend is using a pen and paper to draw the shape you have in mind. You identify the different points of your shape. Then you convert them into <code>clip-path</code> values.</p>
<p>You can find a lot of online tools that can help you. My favorite one is: <a target="_blank" href="https://bennettfeely.com/clippy/">https://bennettfeely.com/clippy/</a></p>
<h2 id="heading-how-to-create-a-rounded-divider-for-your-website">How to Create a Rounded Divider for Your Website</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-87.png" alt="Illustration of the rounded divider" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the rounded divider</em></p>
<p>For this divider, we are going to use <code>mask</code> instead of <code>clip-path</code>. The difference between <code>clip-path</code> and <code>mask</code> is that <code>mask</code> relies on images to cut/hide parts of an element. When talking about images we also talk about gradients.</p>
<p>Here is an illustration to understand what kind of gradients we need:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-89.png" alt="Illustration of the gradients used with the mask property" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the gradients used with the mask property</em></p>
<p>For the first element, we need two gradients: a <code>linear-gradient()</code> to create a rectangular shape at the top, leaving a space at the bottom, and a <code>radial-gradient()</code> to create a circle placed at the bottom. Both of them combined will give us the final shape for the first element.</p>
<p>The second element needs only one <code>radial-gradient()</code> to create a hole at the top to complete the puzzle.</p>
<p>Our code will be:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">mask</span>: 
    <span class="hljs-built_in">linear-gradient</span>(#<span class="hljs-number">000</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>) top/<span class="hljs-number">100%</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - <span class="hljs-number">50px</span>) no-repeat,
    <span class="hljs-built_in">radial-gradient</span>(farthest-side,#<span class="hljs-number">000</span> <span class="hljs-number">98%</span>,#<span class="hljs-number">0000</span>) bottom/<span class="hljs-number">100px</span> <span class="hljs-number">100px</span> no-repeat;
}
<span class="hljs-selector-class">.bottom</span> {
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(<span class="hljs-number">60px</span> at <span class="hljs-number">50%</span> -<span class="hljs-number">10px</span>,#<span class="hljs-number">0000</span> <span class="hljs-number">98%</span>,#<span class="hljs-number">000</span>);
  <span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">40px</span>;
}
</code></pre>
<p>And with CSS variables it will be:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--size</span>: <span class="hljs-number">50px</span>; <span class="hljs-comment">/* size of the cut */</span>
  <span class="hljs-attribute">--gap</span>: <span class="hljs-number">10px</span>;  <span class="hljs-comment">/* the gap */</span>
}
<span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">mask</span>: 
    <span class="hljs-built_in">linear-gradient</span>(#<span class="hljs-number">000</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>) top/<span class="hljs-number">100%</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--size)) no-repeat,
    <span class="hljs-built_in">radial-gradient</span>(farthest-side,#<span class="hljs-number">000</span> <span class="hljs-number">98%</span>,#<span class="hljs-number">0000</span>) bottom/<span class="hljs-built_in">calc</span>(<span class="hljs-number">2</span>*var(--size)) <span class="hljs-built_in">calc</span>(<span class="hljs-number">2</span>*var(--size)) no-repeat;
}
<span class="hljs-selector-class">.bottom</span> {
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">radial-gradient</span>(calc(var(--gap) + <span class="hljs-built_in">var</span>(--size)) at <span class="hljs-number">50%</span> <span class="hljs-built_in">calc</span>(-<span class="hljs-number">1</span>*var(--gap)),<span class="hljs-number">#0000</span> <span class="hljs-number">98%</span>,<span class="hljs-number">#000</span>);
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-built_in">calc</span>(var(--gap) - <span class="hljs-built_in">var</span>(--size));
}
</code></pre>
<p>Even with the mask method, the code pattern is still the same as the one using clip-path.</p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>Now, in addition to having a <a target="_blank" href="https://css-generators.com/section-divider/">cool online generator for section dividers</a>, you also know the secret behind creating them.</p>
<p>You may have noticed in the generator that each divider comes with 2 directions but I only explained one for each divider. I did this on purpose to let you try to understand what values we need to update to get the opposite direction. You can do it – it's not difficult and you will learn a lot by doing it.</p>
<p>I will be releasing more generators in the future so bookmark this link: <a target="_blank" href="https://css-generators.com/">https://css-generators.com/</a> and follow me <a target="_blank" href="https://twitter.com/ChallengesCss">on Twitter</a> to not miss them.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a CSS-Only Ribbon for Your Website ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever noticed those fancy ribbons on websites that alert users to some special feature or event? They're great to have, but for many developers, it's a nightmare to create them. You can easily find a lot of ready-to-use code for such a compon... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/make-a-css-only-ribbon/</link>
                <guid isPermaLink="false">66bb55de5a83db22bea9842d</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Tue, 08 Feb 2022 19:33:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/final-header-ribbon.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever noticed those fancy ribbons on websites that alert users to some special feature or event? They're great to have, but for many developers, it's a nightmare to create them.</p>
<p>You can easily find a lot of ready-to-use code for such a component, but they are not easy to update. You also have to deal with a lot of trial and error until you get them to work correctly.</p>
<p>In this post, I will show you how to create two types of ribbons with some simple CSS code where you don't need to bother yourself with tweaking a lot of values.</p>
<p>Here's what we'll create in this article:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-18.png" alt="Rotated Ribbon &amp; Folder Ribbon" width="600" height="400" loading="lazy"></p>
<p><em>Rotated Ribbon &amp; Folded Ribbon</em></p>
<p>Below is the full code for both ribbons so you can see how simple it is:</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/dyZOBex/55e02b7d8b1dffb5c1a63473d5724dee" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<details>
  <summary>Click to see the full code</summary>
<pre><code class="language-html">  <div class="box">
    <div class="ribbon-2">Folded Ribbon</div>
  </div>
  <div class="ribbon-1 left">Rotated Ribbon</div>
  <div class="ribbon-1 right">Rotated Ribbon</div></code></pre>
<pre><code class="language-css">  .ribbon-1 {
    position: fixed;
    background: #08769b;
    box-shadow: 0 0 0 999px #08769b;
    clip-path: inset(0 -100%);
  }
  .left {
    inset: 0 auto auto 0;
    transform-origin: 100% 0;
    transform: translate(-29.3%) rotate(-45deg);
  }
  .right {
    inset: 0 0 auto auto;
    transform-origin: 0 0;
    transform: translate(29.3%) rotate(45deg);
  }

  .ribbon-2 {
    --f: 10px; /<em> control the folded part</em>/
    --r: 15px; /<em> control the ribbon shape </em>/
    --t: 10px; /<em> the top offset </em>/

    position: absolute;
    inset: var(--t) calc(-1<em>var(--f)) auto auto;
    padding: 0 10px var(--f) calc(10px + var(--r));
    clip-path: 
      polygon(0 0,100% 0,100% calc(100% - var(--f)),calc(100% - var(--f)) 100%,
        calc(100% - var(--f)) calc(100% - var(--f)),0 calc(100% - var(--f)),
        var(--r) calc(50% - var(--f)/2));
    background: #BD1550;
    box-shadow: 0 calc(-1</em>var(--f)) 0 inset #0005;
  }


  .box {
    max-width:500px;
    height:200px;
    margin:50px auto 0;
    background:lightblue;
    position:relative;
  }</code></pre>
</details>

<h2 id="heading-how-to-create-a-rotated-ribbon-with-css">How to create a Rotated Ribbon with CSS</h2>
<p>This type of ribbon is, in most cases, used to place a piece of fixed information on the top of the screen. But we can also use it inside an element within the page.</p>
<p>To understand how to create such a ribbon, let's look at a step-by-step illustration:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-19.png" alt="Step-by-Step illustration of the Rotated Ribbon" width="600" height="400" loading="lazy"></p>
<p><em>Step-by-Step illustration of the Rotated Ribbon</em></p>
<p>First, we start by placing our element on the top left corner of the screen. The red borders in the illustration are the boundaries of the screen (or the element where you want to place the Ribbon).</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.ribbon</span> {
  <span class="hljs-attribute">position</span>: fixed;
  <span class="hljs-attribute">inset</span>: <span class="hljs-number">0</span> auto auto <span class="hljs-number">0</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#08769b</span>;
}
</code></pre>
<p>Nothing complex so far. If you are not familiar with the <code>inset</code> property, it's nothing but the shorthand for <code>top</code>, <code>right</code>, <code>bottom</code>, and <code>left</code>.</p>
<p>Next, we perform a translation to the left by using <code>translate(-29.3%)</code>.</p>
<p>After the translation, we rotate our element using <code>rotate(-45deg)</code> and the code becomes this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.ribbon</span> {
  <span class="hljs-attribute">position</span>: fixed;
  <span class="hljs-attribute">inset</span>: <span class="hljs-number">0</span> auto auto <span class="hljs-number">0</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#08769b</span>;
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">100%</span> <span class="hljs-number">0</span>; <span class="hljs-comment">/* or top left */</span>
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(-<span class="hljs-number">29.3%</span>) <span class="hljs-built_in">rotate</span>(-<span class="hljs-number">45deg</span>);
}
</code></pre>
<p>You are probably wondering what is the secret of the strange value <code>29.3%</code>? Well, it's equal to <code>100% * (1 - cos(45deg))</code>.</p>
<p>I will avoid starting a "boring" math explanation, but you can see that after we did the rotation, the element is perfectly placed (both its top corners are touching the edges). The translation is the key to having that perfect placement.</p>
<p>You can also notice the use of <code>transform-origin: top left</code>. In the third step, I had to rotate the element from its top left corner.</p>
<p>Now our element is correctly placed but we have a few gaps to fill. I will use a "big" <code>box-shadow</code> to do that. In the figure, I used a green color to illustrate but you should consider it as the same color as the background.</p>
<p>Next we need to clip the shadow to only show the left and right parts of it. To do this I will be using <code>clip-path</code>. I will use <code>inset(0 -100%)</code> which means clip the top and bottom shadow (the value <code>0</code>) and show some of the left right shadow (<code>-100%</code>).</p>
<p><code>100%</code> is a random value that needs to be very big. It can be for example <code>999px</code> or <code>100vmax</code> – any value to make sure we keep the left and right part of the shadow.</p>
<p>Now we'll see the final result in the sixth step. We still have some overflowing shadows but no one can see them since we are placing our element at the corner of the screen.</p>
<p>If you will be placing the ribbon inside another element don't forget to use <code>overflow: hidden</code> on the parent element and also replace <code>fixed</code> with <code>absolute</code></p>
<p>Our final code will be:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.ribbon-1</span> {
  <span class="hljs-attribute">position</span>: fixed;
  <span class="hljs-attribute">inset</span>: <span class="hljs-number">0</span> auto auto <span class="hljs-number">0</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#08769b</span>;
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">100%</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(-<span class="hljs-number">29.3%</span>) <span class="hljs-built_in">rotate</span>(-<span class="hljs-number">45deg</span>);
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">999px</span> <span class="hljs-number">#08769b</span>;
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> -<span class="hljs-number">100%</span>);
}
</code></pre>
<p>With only 7 declarations we have our rotated ribbon. You will note that our code is generic and doesn't depend on the text content. Whatever the content of the ribbon, it will always get placed correctly. You can even have multi-lines of text.</p>
<p>To place the ribbon at the top right corner, we just need to update a few values. Even better, let's have two classes to easily control the placement:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.ribbon-1</span> {
  <span class="hljs-attribute">position</span>: fixed;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#08769b</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">999px</span> <span class="hljs-number">#08769b</span>;
  <span class="hljs-attribute">clip-path</span>: <span class="hljs-built_in">inset</span>(<span class="hljs-number">0</span> -<span class="hljs-number">100%</span>);
}
<span class="hljs-selector-class">.left</span> {
  <span class="hljs-attribute">inset</span>: <span class="hljs-number">0</span> auto auto <span class="hljs-number">0</span>; <span class="hljs-comment">/* top and left equal to 0 */</span>
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">100%</span> <span class="hljs-number">0</span>; <span class="hljs-comment">/* OR top right */</span>
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(-<span class="hljs-number">29.3%</span>) <span class="hljs-built_in">rotate</span>(-<span class="hljs-number">45deg</span>);
}
<span class="hljs-selector-class">.right</span> {
  <span class="hljs-attribute">inset</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> auto auto; <span class="hljs-comment">/* top and right equal to 0 */</span>
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>; <span class="hljs-comment">/* OR top left */</span>
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(<span class="hljs-number">29.3%</span>) <span class="hljs-built_in">rotate</span>(<span class="hljs-number">45deg</span>);
}
</code></pre>
<p>I think the code is self-explanatory and the changes between right and left are simple to understand.</p>
<h2 id="heading-how-to-create-a-folded-ribbon-with-css">How to Create a Folded Ribbon with CSS</h2>
<p>Let's tackle the second type of ribbon the same way we did with the previous one using a step-by-step illustration.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-20.png" alt="Step-by-Step illustration of the Folded Ribbon" width="600" height="400" loading="lazy"></p>
<p><em>Step-by-Step illustration of the Folded Ribbon</em></p>
<p>First, we'll start by placing our element at the right side of the parent element.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.ribbon-2</span> {
  <span class="hljs-attribute">--t</span>: <span class="hljs-number">10px</span>; <span class="hljs-comment">/* the top offset */</span>

  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">inset</span>: <span class="hljs-built_in">var</span>(--t) <span class="hljs-number">0</span> auto auto;
  <span class="hljs-attribute">padding</span>:<span class="hljs-number">0</span> <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#BD1550</span>;

}
</code></pre>
<p>I will consider a variable to control the offset from the top which means that we can easily control the position of the Ribbon by adjusting that variable. Since we are using <code>position: absolute</code>, we should not forget to add <code>position: relative</code> to the parent element of the Ribbon.</p>
<p>I will also add some padding on the left and right sides. There is no particular logic behind the <code>10px</code> – you can choose the value you want.</p>
<p>Now I will introduce another variable that will control the folded part. I will be using this variable to define an inset shadow <code>box-shadow: 0 calc(-1*var(--f)) 0 #0005</code>.</p>
<p>As you can see in the figure above, this shadow will add a semi-transparent black overlay on the bottom having a height equal to the variable <code>--f</code>. I will also increase the bottom padding to contain that shadow <code>padding: 0 10px var(--f)</code>.</p>
<p>Next, using the same variable <code>--f</code> I will move the ribbon a bit to the right by replacing <code>right:0</code> with <code>right: calc(-1*var(--f))</code>.</p>
<p>The code so far looks like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.ribbon-2</span> {
  <span class="hljs-attribute">--t</span>: <span class="hljs-number">10px</span>; <span class="hljs-comment">/* the top offset */</span>
  <span class="hljs-attribute">--f </span>:<span class="hljs-number">10px</span> <span class="hljs-comment">/* control the folded part */</span>

  position: absolute;
  <span class="hljs-attribute">inset</span>: <span class="hljs-built_in">var</span>(--t) <span class="hljs-built_in">calc</span>(-<span class="hljs-number">1</span>*var(--f)) auto auto; <span class="hljs-comment">/* the right value is here*/</span>
  <span class="hljs-attribute">padding</span>:<span class="hljs-number">0</span> <span class="hljs-number">10px</span> <span class="hljs-built_in">var</span>(--f);
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#BD1550</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(-<span class="hljs-number">1</span>*var(--f)) <span class="hljs-number">0</span> inset <span class="hljs-number">#0005</span>; 
}
</code></pre>
<p>The code may look strange (and the result as well) but everything will make sense in the next step when we create the final shape.</p>
<p>In the fourth step (the last one), we will introduce <code>clip-path</code> to cut our element. I will also add another variable <code>--r</code> to control the arrow shape of the ribbon.</p>
<p>Before adding the clip-path, I will first increase the left padding to have the necessary space for the arrow shape:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">padding</span>: 0 10<span class="hljs-selector-tag">px</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--f</span>) <span class="hljs-selector-tag">calc</span>(10<span class="hljs-selector-tag">px</span> + <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--r</span>));
</code></pre>
<ul>
<li><p>The top padding is equal to <code>0</code>.</p>
</li>
<li><p>The right padding is equal to <code>10px</code> (a random value)</p>
</li>
<li><p>The bottom padding is defined by <code>--f</code></p>
</li>
<li><p>The left padding is equal to <code>10px</code> (same as right) plus a value defined by the new variable <code>--r</code></p>
</li>
</ul>
<p>Now let's add the <code>clip-path</code>. Here is an illustration to understand the path that will lead us to the final shape.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/image-22.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the clip-path</em></p>
<p>The path is defined using 7 points. Starting for point (1) and following the arrow we have the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">clip-path</span>: <span class="hljs-selector-tag">polygon</span>(
  0 0,  <span class="hljs-comment">/* (1) */</span>
  100% 0, <span class="hljs-comment">/* (2) */</span>
  100% <span class="hljs-selector-tag">calc</span>(100% <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--f</span>)), <span class="hljs-comment">/* (3) */</span>
  <span class="hljs-selector-tag">calc</span>(100% <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--f</span>)) 100%, <span class="hljs-comment">/* (4) */</span>
  <span class="hljs-selector-tag">calc</span>(100% <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--f</span>)) <span class="hljs-selector-tag">calc</span>(100% <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--f</span>)), <span class="hljs-comment">/* (5) */</span>
  0 <span class="hljs-selector-tag">calc</span>(100% <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--f</span>)), <span class="hljs-comment">/* (6) */</span>
  <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--r</span>) <span class="hljs-selector-tag">calc</span>(50% <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--f</span>)/2) <span class="hljs-comment">/* (7) */</span>
)
</code></pre>
<p>Don't worry if you are not familiar with <code>clip-path</code> – this may look a bit strange to you. You don't need to manipulate that path. All you need to update the CSS variables to control the overall shape.</p>
<p>This said it's good to play with that path by changing some values in order to better understand how it works.</p>
<p>We are done. Our final code is:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.ribbon-2</span> {
  <span class="hljs-attribute">--f</span>: <span class="hljs-number">10px</span>; <span class="hljs-comment">/* control the folded part*/</span>
  <span class="hljs-attribute">--r</span>: <span class="hljs-number">15px</span>; <span class="hljs-comment">/* control the ribbon shape */</span>
  <span class="hljs-attribute">--t</span>: <span class="hljs-number">10px</span>; <span class="hljs-comment">/* the top offset */</span>

  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">inset</span>: <span class="hljs-built_in">var</span>(--t) <span class="hljs-built_in">calc</span>(-<span class="hljs-number">1</span>*var(--f)) auto auto;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">10px</span> <span class="hljs-built_in">var</span>(--f) <span class="hljs-built_in">calc</span>(<span class="hljs-number">10px</span> + var(--r));
  <span class="hljs-attribute">clip-path</span>: 
    <span class="hljs-built_in">polygon</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> <span class="hljs-number">0</span>,<span class="hljs-number">100%</span> calc(<span class="hljs-number">100%</span> - var(--f)),<span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--f)) <span class="hljs-number">100%</span>,
      <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--f)) <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--f)),<span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--f)),
      <span class="hljs-built_in">var</span>(--r) <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> - var(--f)/<span class="hljs-number">2</span>));
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#BD1550</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(-<span class="hljs-number">1</span>*var(--f)) <span class="hljs-number">0</span> inset <span class="hljs-number">#0005</span>;
}
</code></pre>
<p>You can adjust the values of the variables to get different results:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/right-ribbon.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Like we did with the rotated ribbon, we can update a few values to change the position of this one from right to left – but this time I will not give you the code. I will let you try to find it alone 😉</p>
<p>It's a good exercise to figure out which value you have to update especially for the <code>clip-path</code>. You can always <a target="_blank" href="https://twitter.com/ChallengesCss">reach out to me</a> if you have any questions.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Now you know how to create beautiful ribbons for your websites using just CSS.</p>
<p>If you want more, check my <a target="_blank" href="https://css-generators.com/ribbon-shapes/">online collection of Ribbon Shapes</a> where you will find different variations similar to what we did in this article.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a CSS-Only Loader Using One Element ]]>
                </title>
                <description>
                    <![CDATA[ If you have a website, it's helpful to have a loader so users can tell something is happening once they've clicked a link or button. You can use this loader component in a lot of places, and it should be as simple as possible. In this post, we will s... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-css-only-loader/</link>
                <guid isPermaLink="false">66bb55dcf55324ca867c88d7</guid>
                
                    <category>
                        <![CDATA[ animation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Fri, 14 Jan 2022 21:11:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/01/header-loader.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you have a website, it's helpful to have a loader so users can tell something is happening once they've clicked a link or button.</p>
<p>You can use this loader component in a lot of places, and it should be as simple as possible.</p>
<p>In this post, we will see how to build two types of loaders with only one <code>&lt;div&gt;</code> and a few lines of CSS code. Not only this but we will make them customizable so you can easily create different variations from the same code.</p>
<p>Here's what we'll build:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/final-loader.gif" alt="CSS-only Spinner and Progress Loader" width="600" height="400" loading="lazy"></p>
<p><em>CSS-only Spinner and Progress Loader</em></p>
<h2 id="heading-how-to-create-a-spinner-loader">How to Create a Spinner Loader</h2>
<p>Below is a demo of what we are building:</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/PoJyaNy" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<details>
    <summary>Click to see the full code</summary>
<pre><code class="language-html"> <div class="loader"></div>
 <div class="loader"></div>
 <div class="loader"></div>
 <div class="loader"></div></code></pre>
<pre><code class="language-css"> .loader {
   --b: 10px;  /<em> border thickness </em>/
   --n: 10;    /<em> number of dashes</em>/
   --g: 10deg; /<em> gap between dashes</em>/
   --c: red;   /<em> the color </em>/

   width: 100px; /<em> size </em>/
   aspect-ratio: 1;
   border-radius: 50%;
   padding: 1px;
   background: conic-gradient(#0000,var(--c)) content-box;
   -webkit-mask:
     repeating-conic-gradient(#0000 0deg,
        #000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
        #0000     calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
     radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
           mask:
     repeating-conic-gradient(#0000 0deg,
        #000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
        #0000     calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
     radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
   -webkit-mask-composite: destination-in;
           mask-composite: intersect;
   animation: load 1s infinite steps(var(--n));
 }
 @keyframes load {to{transform: rotate(1turn)}}</code></pre>
</details>

<p>We have 4 different loaders using the same code. By only changing a few variables, we can generate a new loader without needing to touch the CSS code.</p>
<p>The variables are defined like below:</p>
<ul>
<li><p><code>--b</code> defines the border thickness.</p>
</li>
<li><p><code>--n</code> defines the number of dashes.</p>
</li>
<li><p><code>--g</code> defines the gap between dashes. Since we're dealing with a circular element, this one is an angle value.</p>
</li>
<li><p><code>--c</code> defines the color.</p>
</li>
</ul>
<p>Here is an illustration to see the different variables.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-50.png" alt="CSS Variables of the Spinner loader" width="600" height="400" loading="lazy"></p>
<p><em>CSS Variables of the Spinner loader</em></p>
<p>Let's tackle the CSS code. We will use another figure to illustrate a step-by-step construction of the loader.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-51.png" alt="Step-by-Step illustration of the Spinner Loader" width="600" height="400" loading="lazy"></p>
<p><em>Step-by-Step illustration of the Spinner Loader</em></p>
<p>We first start by creating a circle like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>; <span class="hljs-comment">/* size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
}
</code></pre>
<p>Nothing complex so far. Note the use of <code>aspect-ratio</code> which allows us to only modify one value (the <code>width</code>) in order to control the size.</p>
<p>Then we add a conic gradient coloration from transparent to the defined color (the variable <code>--c</code>):</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">width</span>:<span class="hljs-number">100px</span>; <span class="hljs-comment">/* size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">conic-gradient</span>(#<span class="hljs-number">0000</span>,var(--c));
}
</code></pre>
<p>In this step, we introduce the <code>mask</code> property to hide some parts of the circle in a repetitive manner. This will depend on the <code>--n</code> and <code>--d</code> variables. If you look closely at the figure, we will notice the following pattern:</p>
<pre><code class="lang-python">visible part
invisible part
visible part
invisible part
etc
</code></pre>
<p>To do this, we use <code>repeating-conic-gradient(#000 0 X, #0000 0 Y)</code>. From <code>0</code> to <code>X</code> we have an opaque color (visible part) and from <code>X</code> to <code>Y</code> we have a transparent one (invisible part).</p>
<p>We introduce our variables:</p>
<ul>
<li><p>We need a gap equal to <code>g</code> between each visible part so the formula between <code>X</code> and <code>Y</code> will be <code>X = Y - g</code>.</p>
</li>
<li><p>We need <code>n</code> visible part so the formula of <code>Y</code> should be <code>Y = 360deg/n</code>. A full circle is <code>360deg</code> so we simply divide it by <code>n</code></p>
</li>
</ul>
<p>Our code so far is:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>; <span class="hljs-comment">/* size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">conic-gradient</span>(#<span class="hljs-number">0000</span>,var(--c));
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">repeating-conic-gradient</span>(#<span class="hljs-number">000</span> <span class="hljs-number">0</span> calc(<span class="hljs-number">360deg</span>/var(--n) - <span class="hljs-built_in">var</span>(--g)) , <span class="hljs-number">#0000</span> <span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">360deg</span>/var(--n))
}
</code></pre>
<p>This next step is the trickiest one, because we need to apply another mask to create a kind of hole in order to get the final shape. To do this we will logically use a <code>radial-gradient()</code> with our variable <code>b</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">radial-gradient</span>(<span class="hljs-selector-tag">farthest-side</span>,<span class="hljs-selector-id">#0000</span> <span class="hljs-selector-tag">calc</span>(100% <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--b</span>)),<span class="hljs-selector-id">#000</span> 0)
</code></pre>
<p>A full circle from where we remove a thickness equal to <code>b</code>.</p>
<p>We add this to the previous mask:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>; <span class="hljs-comment">/* size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">conic-gradient</span>(#<span class="hljs-number">0000</span>,var(--c));
  <span class="hljs-attribute">mask</span>: 
   <span class="hljs-built_in">radial-gradient</span>(farthest-side,#<span class="hljs-number">0000</span> calc(<span class="hljs-number">100%</span> - var(--b)),<span class="hljs-number">#000</span> <span class="hljs-number">0</span>),
   <span class="hljs-built_in">repeating-conic-gradient</span>(#<span class="hljs-number">000</span> <span class="hljs-number">0</span> calc(<span class="hljs-number">360deg</span>/var(--n) - <span class="hljs-built_in">var</span>(--g)) , <span class="hljs-number">#0000</span> <span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">360deg</span>/var(--n))
}
</code></pre>
<p>We have two mask layers, but the result is not what we want. We get the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-52.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>It may look strange but it's logical. The "final" visible part is nothing but the sum of each visible part of each mask layer. We can change this behavior using <code>mask-composite</code>. I would need a whole article to explain this property so I will simply give the value.</p>
<p>In our case, we need to consider <code>intersect</code> (and <code>destination-out</code> for the prefixed property). Our code will become:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>; <span class="hljs-comment">/* size */</span>
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">conic-gradient</span>(#<span class="hljs-number">0000</span>,var(--c));
  <span class="hljs-attribute">mask</span>: 
    <span class="hljs-built_in">radial-gradient</span>(farthest-side,#<span class="hljs-number">0000</span> calc(<span class="hljs-number">100%</span> - var(--b)),<span class="hljs-number">#000</span> <span class="hljs-number">0</span>),
    <span class="hljs-built_in">repeating-conic-gradient</span>(#<span class="hljs-number">000</span> <span class="hljs-number">0</span> calc(<span class="hljs-number">360deg</span>/var(--n) - <span class="hljs-built_in">var</span>(--g)) , <span class="hljs-number">#0000</span> <span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">360deg</span>/var(--n));
  <span class="hljs-attribute">-webkit-mask-composite</span>: destination-in;
          <span class="hljs-attribute">mask-composite</span>: intersect;
}
</code></pre>
<p>We are done with the shape! We are only missing the animation. The latter is an infinite rotation.</p>
<p>The only thing to note is that I am using a <code>steps</code> animation to create the illusion of fixed dashes and moving colors.</p>
<p>Here is an illustration to see the difference</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/steps-final.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>A Linear Animation vs a Steps Animation</em></p>
<p>The first one is a linear and continuous rotation of the shape (not what we want) and the second one is a discrete animation (the one we want).</p>
<p>Here is the full code including the animation:</p>
<details>
    <summary>Click to see the full code</summary>
<pre><code class="language-html"> <div class="loader"></div>
 <div class="loader"></div>
 <div class="loader"></div>
 <div class="loader"></div></code></pre>
<pre><code class="language-css"> .loader {
   --b: 10px;  /<em> border thickness </em>/
   --n: 10;    /<em> number of dashes</em>/
   --g: 10deg; /<em> gap between dashes</em>/
   --c: red;   /<em> the color </em>/

   width: 100px; /<em> size </em>/
   aspect-ratio: 1;
   border-radius: 50%;
   padding: 1px;
   background: conic-gradient(#0000,var(--c)) content-box;
   -webkit-mask:
     repeating-conic-gradient(#0000 0deg,
        #000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
        #0000     calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
     radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
           mask:
     repeating-conic-gradient(#0000 0deg,
        #000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
        #0000     calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
     radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
   -webkit-mask-composite: destination-in;
           mask-composite: intersect;
   animation: load 1s infinite steps(var(--n));
 }
 @keyframes load {to{transform: rotate(1turn)}}</code></pre>
</details>

<p>You will notice a few differences with the code I used in the explanation:</p>
<ul>
<li><p>I am adding <code>padding: 1px</code> and setting the background to <code>content-box</code></p>
</li>
<li><p>There is <code>+/1deg</code> between the colors of the <code>repeating-conic-gradient()</code></p>
</li>
<li><p>There are a few percentages of difference between the color inside the <code>radial-gradient()</code></p>
</li>
</ul>
<p>Those are some corrections to avoid visual glitches. Gradients are known to produce "strange" results in some cases so we have to adjust some values manually to avoid them.</p>
<h2 id="heading-how-to-create-a-progress-loader">How to Create a Progress Loader</h2>
<p>Like the previous one loader, let's start with an overview:</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/bGoNddg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<details>
    <summary>Click to see the full code</summary>
<pre><code class="language-html"> <div class="loader"></div>
 <div class="loader"></div>
 <div class="loader"></div>
 <div class="loader"></div></code></pre>
<pre><code class="language-css"> .loader {
   --n:5;    /<em> control the number of stripes </em>/
   --s:30px; /<em> control the width of stripes </em>/
   --g:5px;  /<em> control the gap between stripes </em>/

   width:calc(var(--n)<em>(var(--s) + var(--g)) - var(--g));
   height:30px;
   padding:var(--g);
   margin:5px auto;
   border:1px solid;
   background:
     repeating-linear-gradient(90deg,
       currentColor  0 var(--s),
       #0000 0 calc(var(--s) + var(--g))
     ) left / calc((var(--n) + 1)</em>(var(--s) + var(--g))) 100% 
     no-repeat content-box;
   animation: load 1.5s steps(calc(var(--n) + 1)) infinite;
 }
 @keyframes load {
   0% {background-size: 0% 100%}
 }</code></pre>
</details>

<p>We have the same configuration as the previous loader. CSS variables that control the loader:</p>
<ul>
<li><p><code>--n</code> defines the number of dashes/stripes.</p>
</li>
<li><p><code>--s</code> defines the width of each stripe.</p>
</li>
<li><p><code>--g</code> defines the gap between stripes.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-53.png" alt="Illustration of the CSS Variables" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the CSS Variables</em></p>
<p>From the above figure we can see that the width of the element will depend on the 3 variables. The CSS will be as follows:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">calc</span>(var(--n)*(<span class="hljs-built_in">var</span>(--s) + <span class="hljs-built_in">var</span>(--g)) - <span class="hljs-built_in">var</span>(--g));
  <span class="hljs-attribute">height</span>: <span class="hljs-number">30px</span>; <span class="hljs-comment">/* use any value you want here */</span>
  <span class="hljs-attribute">padding</span>: <span class="hljs-built_in">var</span>(--g);
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid;
}
</code></pre>
<p>We use <code>padding</code> to set the gap on each side. Then the width will be equal to the number of stripes multiplied by their width and the gap. We remove one gap because for <code>N</code> stripes we have <code>N-1</code> gaps.</p>
<p>To create the stripes we will use the below gradient.</p>
<pre><code class="lang-python">repeating-linear-gradient(<span class="hljs-number">90</span>deg,
  currentColor <span class="hljs-number">0</span> var(--s),
  <span class="hljs-comment">#0000        0 calc(var(--s) + var(--g))</span>
 )
</code></pre>
<p>From <code>0</code> to <code>s</code> is the defined color and from <code>s</code> to <code>s + g</code> a transparent color (the gap).</p>
<p>I am using <code>currentColor</code> which is the value of the <code>color</code> property. Note that I didn't define any color inside <code>border</code> so it will also use to the value of <code>color</code>. If we want to change the color of the loader, we only need to set the <code>color</code> property.</p>
<p>Our code so far:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">calc</span>(var(--n)*(<span class="hljs-built_in">var</span>(--s) + <span class="hljs-built_in">var</span>(--g)) - <span class="hljs-built_in">var</span>(--g));
  <span class="hljs-attribute">height</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-built_in">var</span>(--g);
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid;
  <span class="hljs-attribute">background</span>:
    <span class="hljs-built_in">repeating-linear-gradient</span>(<span class="hljs-number">90deg</span>,
      currentColor  <span class="hljs-number">0</span> var(--s),
      <span class="hljs-number">#0000</span> <span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(var(--s) + <span class="hljs-built_in">var</span>(--g))
    ) left / <span class="hljs-number">100%</span> <span class="hljs-number">100%</span> content-box no-repeat;
}
</code></pre>
<p>I am using <code>content-box</code> to make sure the gradient doesn't cover the padding area. Then I define a size equal to <code>100% 100%</code> and a left position.</p>
<p>It's time for the animation. For this loader, we will animate the <code>background-size</code> from <code>0% 100%</code> to <code>100% 100%</code> which means the width of our gradient from <code>0%</code> to <code>100%</code></p>
<p>Like the previous loader, we will rely on <code>steps()</code> to have a discrete animation instead of a continuous one.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/steps-2-final.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>A Linear Animation vs a Steps Animation</em></p>
<p>The second one is what we want to create, and we can achieve it by adding the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">animation</span>: load <span class="hljs-number">1.5s</span> <span class="hljs-built_in">steps</span>(var(--n)) infinite;
}
<span class="hljs-keyword">@keyframes</span> load {
  0% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">0%</span> <span class="hljs-number">100%</span>}
}
</code></pre>
<p>If you look closely at the last figure, you will notice that the animation is not complete. We are missing one stripe at the end, even if we have used <code>N</code>. This is not a bug but how <code>steps()</code> is supposed to work.</p>
<p>To overcome this, we need to add an extra step. We increase the <code>background-size</code> of our gradient to contain <code>N+1</code> stripes and use <code>steps(N+1)</code>. This will get us to the final code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.loader</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">calc</span>(var(--n)*(<span class="hljs-built_in">var</span>(--s) + <span class="hljs-built_in">var</span>(--g)) - <span class="hljs-built_in">var</span>(--g));
  <span class="hljs-attribute">height</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-built_in">var</span>(--g);
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">5px</span> auto;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid;
  <span class="hljs-attribute">background</span>:
    <span class="hljs-built_in">repeating-linear-gradient</span>(<span class="hljs-number">90deg</span>,
      currentColor  <span class="hljs-number">0</span> var(--s),
      <span class="hljs-number">#0000</span> <span class="hljs-number">0</span> <span class="hljs-built_in">calc</span>(var(--s) + <span class="hljs-built_in">var</span>(--g))
    ) left / <span class="hljs-built_in">calc</span>((var(--n) + <span class="hljs-number">1</span>)*(<span class="hljs-built_in">var</span>(--s) + <span class="hljs-built_in">var</span>(--g))) <span class="hljs-number">100%</span> 
    content-box no-repeat;
  <span class="hljs-attribute">animation</span>: load <span class="hljs-number">1.5s</span> <span class="hljs-built_in">steps</span>(calc(var(--n) + <span class="hljs-number">1</span>)) infinite;
}
<span class="hljs-keyword">@keyframes</span> load {
  0% {<span class="hljs-attribute">background-size</span>: <span class="hljs-number">0%</span> <span class="hljs-number">100%</span>}
}
</code></pre>
<p>Note that the width of the gradient is equal to <code>N+1</code> multiplied by the width of one stripe and a gap (instead of being <code>100%</code> )</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope you enjoyed this tutorial. If you are interested, <a target="_blank" href="https://css-loaders.com/">I have made more than 500 CSS-only single div loaders</a>. I also wrote another <a target="_blank" href="https://dev.to/afif/build-your-css-loader-with-only-one-div-the-dots-3882">tutorial to explain how to create the Dots loader using only background properties</a>.</p>
<p>Find below useful links to get more detail about some properties I have used that I didn't explain thoroughly due to their complexity:</p>
<ul>
<li><p><code>mask-composite</code>: <a target="_blank" href="https://css-tricks.com/mask-compositing-the-crash-course/">https://css-tricks.com/mask-compositing-the-crash-course/</a></p>
</li>
<li><p><code>steps()</code>: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#the_steps_class_of_easing_functions">https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#the_steps_class_of_easing_functions</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Pie Chart Using Only CSS ]]>
                </title>
                <description>
                    <![CDATA[ Pie charts are common components that let you show portions of a whole, and you can use them for many different purposes. You will find a lot of articles around building such a component, but they typically either rely on SVG or a lot of HTML element... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/css-only-pie-chart/</link>
                <guid isPermaLink="false">66bb55d629aa951a4c0628ae</guid>
                
                    <category>
                        <![CDATA[ animation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Thu, 06 Jan 2022 20:41:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/01/header-2-3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Pie charts are common components that let you show portions of a whole, and you can use them for many different purposes.</p>
<p>You will find a lot of articles around building such a component, but they typically either rely on SVG or a lot of HTML elements.</p>
<p>In this post, I will show you how to create a pie chart using CSS and only one element.</p>
<p>Below is an overview of what we are building:</p>
<p></p><details>
  <summary>Click to see the full code</summary><p></p>
<p></p><pre><code class="language-html"><div class="pie"> 20%</div><p></p>
<p></p><div class="pie"> 40%</div><p></p>
<p></p><div class="pie no-round"> 60%</div><p></p>
<p></p><div class="pie animate no-round"> 80%</div><p></p>
<p></p><div class="pie animate"> 90%</div></code></pre><p></p>
<p></p><pre><code class="language-css">@property --p{
  syntax: <p></p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/XWaPXZO" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<p>As you can see in the CodePen above, we have a static pie chart, an animated one, and we can also have rounded edges. All this with a single <code>&lt;div&gt;</code> element.</p>
<p>In addition to that, we can easily adjust the different values using CSS variables so we don't have to bother ourselves with changing the CSS code.</p>
<p>I know the code may look a bit difficult at first glance, but after reading through the explanation below you will be able to confidently make your own pie charts.</p>
<h2 id="heading-the-html-structure-for-the-pie-chart">The HTML Structure for the Pie Chart</h2>
<p>As I mentioned above, we have a single <code>&lt;div&gt;</code> where we add the percentage value (the progress of the pie chart) as the main content:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"pie"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"--p:60;--b:10px;--c:purple;"</span>&gt;</span>60%<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>We also add the CSS variables as inline styles.</p>
<ul>
<li><p><code>--p</code>: This variable should contain the percentage value as a number (without the <code>%</code> sign). It be should the same as the content.</p>
</li>
<li><p><code>--b</code>: This variable will define the thickness of the border.</p>
</li>
<li><p><code>--c</code>: This variable will define the main color.</p>
</li>
</ul>
<p>For the sake of this article and the demo, I am using a one-character variable to keep the code short. But it's better to consider more explicit variables when using the code in a production environment. Examples: <code>--percentage</code>, <code>--border-thickness</code>, and <code>--main-color</code>.</p>
<h2 id="heading-the-css-setting-for-the-pie-chart">The CSS Setting for the Pie Chart</h2>
<p>We first start by styling our content. This part is easy and the code is as follows:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.pie</span> {
  <span class="hljs-attribute">--w</span>: <span class="hljs-number">150px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">var</span>(--w);
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">display</span>: inline-grid;
  <span class="hljs-attribute">place-content</span>: center;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">25px</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">font-family</span>: sans-serif;
}
</code></pre>
<p>I am defining the element as <code>inline-grid</code> to easily place the content at the middle using <code>place-content: center</code>. We use <code>aspect-ratio: 1</code> to make sure the element remains square. We can also use <code>height: var(--w)</code> but it's always good to learn and use a new CSS property.</p>
<p>You may wonder why I am using a variable to define the width instead of simply setting <code>width: 150px</code>. I need to know the value of the width for future usage so I am defining it as a variable.</p>
<p>All the remaining CSS is pretty basic to style the text. Feel free to update it as you want.</p>
<p>Let's move on to the interesting part – the main shape of our component. For this, we will use a pseudo element with the following styles:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.pie</span><span class="hljs-selector-pseudo">:before</span>{
  <span class="hljs-attribute">content</span>: <span class="hljs-string">""</span>;
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">inset</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">conic-gradient</span>(var(--c) <span class="hljs-built_in">calc</span>(var(--p)*<span class="hljs-number">1%</span>),<span class="hljs-number">#0000</span> <span class="hljs-number">0</span>);
}
</code></pre>
<p>A pseudo-element that has <code>position: absolute</code> covers all the area thanks to <code>inset: 0</code>. Yes, it's again a new CSS property which is the shorthand for <code>top</code>, <code>right</code>, <code>bottom</code>, and <code>right</code> (which you can <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/inset">read more about here</a>).</p>
<p>Then we make it a circle ( <code>border-radius: 50%</code>) and we apply a <code>conic-gradient()</code>. Note the use of the CSS variables we defined as inline styles ( <code>--c</code> for the color and <code>--p</code> for the percentage).</p>
<p>Until now, this will give us the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-35.png" alt="Conic-gradient applied to pseudo-element" width="600" height="400" loading="lazy"></p>
<p><em>Conic-gradient applied to pseudo-element</em></p>
<p>We are getting closer! The <code>conic-gradient()</code> is giving us a two-color gradient. From <code>0%</code> to <code>p%</code> the main color and the remaining part is a transparent color (defined with the hexadecimal value <code>#0000</code> ).</p>
<p>To keep only the border part we will use a <code>mask</code> to hide the middle part. We will use a <code>radial-gradient()</code> this time:</p>
<pre><code class="lang-python">radial-gradient(farthest-side,red calc(<span class="hljs-number">99</span>% - var(--b)),blue calc(<span class="hljs-number">100</span>% - var(--b)))
</code></pre>
<p>The above applied as a background will give us the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-36.png" alt="Illustration of the radial-gradient" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the radial-gradient</em></p>
<p>Note the use of the variable <code>--b</code> that defines the thickness of the border (shown as blue in the above).</p>
<p>Now imagine the red part being the invisible part and the blue part the visible one. This is what we will get if we use the same gradient with the <code>mask</code> property:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-37.png" alt="Applying mask to the pseudo element" width="600" height="400" loading="lazy"></p>
<p><em>Applying mask to the pseudo element</em></p>
<p>We have our pie chart with one element and a few lines of CSS code.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.pie</span> {
  <span class="hljs-attribute">--w</span>:<span class="hljs-number">150px</span>;

  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">var</span>(--w);
  <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">display</span>: inline-grid;
  <span class="hljs-attribute">place-content</span>: center;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">25px</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">font-family</span>: sans-serif;
}
<span class="hljs-selector-class">.pie</span><span class="hljs-selector-pseudo">:before</span> {
  <span class="hljs-attribute">content</span>: <span class="hljs-string">""</span>;
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">inset</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">conic-gradient</span>(var(--c) <span class="hljs-built_in">calc</span>(var(--p)*<span class="hljs-number">1%</span>),<span class="hljs-number">#0000</span> <span class="hljs-number">0</span>);
  <span class="hljs-attribute">-webkit-mask</span>:<span class="hljs-built_in">radial-gradient</span>(farthest-side,#<span class="hljs-number">0000</span> calc(<span class="hljs-number">99%</span> - var(--b)),<span class="hljs-number">#000</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--b)));
          <span class="hljs-attribute">mask</span>:<span class="hljs-built_in">radial-gradient</span>(farthest-side,#<span class="hljs-number">0000</span> calc(<span class="hljs-number">99%</span> - var(--b)),<span class="hljs-number">#000</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--b)));
}
</code></pre>
<p>And the HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"pie"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"--p:60;--b:10px;--c:purple;"</span>&gt;</span>60%<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<h3 id="heading-how-to-add-the-the-rounded-edges">How to add the the rounded edges</h3>
<p>For this I will add an extra gradient layer to round the top edge and a pseudo element to round the other edge. Here is an illustration to understand the trick:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-38.png" alt="Illustration of the rounded edges" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of the rounded edges</em></p>
<p>The code for (1) to round the top edge:</p>
<pre><code class="lang-python">.pie:before {
  background:
    radial-gradient(farthest-side,var(--c) <span class="hljs-number">98</span>%,<span class="hljs-comment">#0000) top/var(--b) var(--b) no-repeat,</span>
    conic-gradient(var(--c) calc(var(--p)*<span class="hljs-number">1</span>%),<span class="hljs-comment">#0000 0);</span>
}
</code></pre>
<p>In addition to the <code>conic-gradient()</code> we add a <code>radial-gradient()</code> placed at the top that has a size equal to the border thickness defined by <code>--b</code>.</p>
<p>The code for (2) to round the other edge:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.pie</span><span class="hljs-selector-pseudo">:after</span> {
  <span class="hljs-attribute">content</span>: <span class="hljs-string">""</span>;
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">inset</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> - var(--b)/<span class="hljs-number">2</span>);
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--c);
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate</span>(calc(var(--p)*<span class="hljs-number">3.6deg</span>)) <span class="hljs-built_in">translateY</span>(calc(<span class="hljs-number">50%</span> - var(--w)/<span class="hljs-number">2</span>));
}
</code></pre>
<p>The <code>inset</code> property is setting the size of the pseudo-element to be equal to <code>--b</code>. Remember that it's the shorthand for <code>top</code>, <code>right</code>, <code>bottom</code> and <code>left</code>. If we have</p>
<pre><code class="lang-python">left = right = <span class="hljs-number">50</span>% - b/<span class="hljs-number">2</span>
</code></pre>
<p>this means that from each side we are moving to the center minus an offset equal to <code>b/2</code> – so we end up having a width equal to <code>2*b/2 = b</code>. Same logic for the height.</p>
<p>Now we need to correctly place our element, which is why we use the transform property. Our element is initially placed at the center so we need to first rotate it. Having the percentage we use the "<a target="_blank" href="https://en.wikipedia.org/wiki/Cross-multiplication#Rule_of_three">Rule of three</a>" to get the angle:</p>
<pre><code class="lang-python">angle = percentage*<span class="hljs-number">360</span>deg/<span class="hljs-number">100</span>
</code></pre>
<p>Then we do a translation, and here we will need the width because we have to perform a translation by half the width (<code>w/2</code>).</p>
<p>Ok, ok – you might be a bit lost within all these formulas. Find below an illustration to understand the logic behind the transform property</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-39.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Applying the transform property to the pseudo-element</em></p>
<p>After that, we color the pseudo-element with the main color <code>--c</code> and we are done. We have our pie chart with rounded edges.</p>
<h2 id="heading-how-to-animate-the-pie-chart">How to Animate the Pie Chart</h2>
<p>A static pie chart is good but an animated one is better! To do this we will animate the percentage value <code>--p</code> from <code>0</code> to the defined value. By default, we cannot animate CSS variables, but thanks to <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/@property">the new <code>@property</code> feature</a> it's now possible.</p>
<p>We register the variable:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@property</span> --p{
  <span class="hljs-selector-tag">syntax</span>: '&lt;<span class="hljs-selector-tag">number</span>&gt;';
  <span class="hljs-selector-tag">inherits</span>: <span class="hljs-selector-tag">true</span>;
  <span class="hljs-selector-tag">initial-value</span>: 0;
}
</code></pre>
<p>We create a <code>keyframes</code>:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@keyframes</span> p {
  <span class="hljs-selector-tag">from</span> {<span class="hljs-attribute">--p</span>:<span class="hljs-number">0</span>}
}
</code></pre>
<p>Note that we only need to specify the <code>from</code>. Doing this, the browser will make the <code>to</code> equal, by default, to the value we defined (<code>&lt;div class="pie" style="--p:60;"&gt;60%&lt;/div&gt;</code>).</p>
<p>And finally, we call the animation. You can define the duration/delay as you want.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">animation</span>: <span class="hljs-selector-tag">p</span> 1<span class="hljs-selector-tag">s</span> <span class="hljs-selector-class">.5s</span> <span class="hljs-selector-tag">both</span>;
</code></pre>
<p>Unfortunately, this technique is not widely supported. You can test it on Chromium-based browsers (Chrome and Edge) but it will fail on Firefox and Safari. You can check out <a target="_blank" href="https://caniuse.com/?search=%40property'">Can I Use</a> to keep track of the support.</p>
<p>Before we end, here again is the full code and a demo of the final working product. You can see that I am using two classes to control the rounded edges and the animation so we can easily add/remove them as needed.</p>
<p></p><details>
  <summary>Click to see the full code</summary><p></p>
<p></p><pre><code class="language-html"><div class="pie"> 20%</div><p></p>
<p></p><div class="pie"> 40%</div><p></p>
<p></p><div class="pie no-round"> 60%</div><p></p>
<p></p><div class="pie animate no-round"> 80%</div><p></p>
<p></p><div class="pie animate"> 90%</div></code></pre><p></p>
<p></p><pre><code class="language-css">@property --p{
  syntax: <p></p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/XWaPXZO" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
</code></pre></details></code></pre></details> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Make an Animated Back to Top Button Using Only CSS ]]>
                </title>
                <description>
                    <![CDATA[ Having a "back to top" button on a website is important. It allows users to easily scroll back to the top of the page.  Most websites rely on JavaScript to toggle the visibility of the button based on the amount of scroll. In this post, I will show y... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/css-only-back-to-top-button/</link>
                <guid isPermaLink="false">66bb55d35a83db22bea9842b</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CSS Grid ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temani Afif ]]>
                </dc:creator>
                <pubDate>Mon, 03 Jan 2022 21:18:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/12/header-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Having a "back to top" button on a website is important. It allows users to easily scroll back to the top of the page. </p>
<p>Most websites rely on JavaScript to toggle the visibility of the button based on the amount of scroll. In this post, I will show you how to create such an effect using only CSS.</p>
<p>We will explore two kinds of effects – a "sliding" and a "fading" effect.</p>
<h2 id="heading-how-to-make-a-sliding-back-to-top-button">How to Make a Sliding Back to Top Button</h2>
<p>Here is an overview of what we are building in this part:</p>
<details>
  <summary>Click to see the full code</summary>

  <code>html
  &lt;body&gt;
    &lt;div&gt;
      &lt;!-- your content goes here  --&gt;
    &lt;/div&gt;
    &lt;a href="#" class="top"&gt;Back to Top &amp;#8593;&lt;/a&gt;
  &lt;/body&gt;</code>
  <code>css
  body {
    display: grid;
    grid-template-columns: auto 0px; 
  }

  .top {
    --offset: 50px; 

    position: sticky;
    bottom: 20px;      
    margin-right: 10px; 
    place-self: end;
    margin-top: calc(100vh + var(--offset));

    /* visual styling */
    text-decoration: none;
    padding: 10px;
    font-family: sans-serif;
    color: #fff;
    background: #000;
    border-radius: 100px;
    white-space: nowrap;
  }

  p {
    font-size: 25px;
  }</code>
</details>

<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/9305df2ed45a40db3e654290147665ff" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>If you scroll, the "back to top" button will appear and will stick at the bottom of the page. Click on it and you will get back to the top! </p>
<p>You will find no JavaScript in there. We'll only use CSS to make the button appear when you scroll the page.</p>
<p>It's cool, right? Let's dissect the code to understand the magic behind it.</p>
<h3 id="heading-the-html-structure">The HTML Structure</h3>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- your content goes here  --&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"top"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>Inside the <code>body</code> tag, we create a <code>div</code> where we put the content of the website. Right after that, we add our "back to top" button as a link. </p>
<p>For the sake of the article, I will keep the button as simple as possible but you can use whatever you want (an image, an icon, and so on). All you need is to keep the usage of <code>a</code> combined with <code>href="#"</code>.</p>
<p>That's it! We are done with the HTML structure.</p>
<h3 id="heading-the-css-code">The CSS Code</h3>
<p>We first start by styling our button. For this part, it's up to you to be creative and build your own button. I will use a basic button (<code>&lt;a class="top" href="#"&gt;Back to Top ↑&lt;/a&gt;</code>) styled like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">text-decoration</span>: none;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">font-family</span>: sans-serif;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#000</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">100px</span>;
}
</code></pre>
<p>Which will get us the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/back-to-top.png" alt="back to top button" width="600" height="400" loading="lazy"></p>
<p>Let's move to the main CSS. The effect we are aiming for uses two CSS techniques:</p>
<ol>
<li>CSS Grid to create the main structure</li>
<li><code>position: sticky</code> to be able to keep the button at the bottom of the screen</li>
</ol>
<p>Our structure will be a grid of two columns – one for the content and another one for the "back to top" button. For this, we add the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: auto auto;
}
</code></pre>
<p>This gives us the following result:</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/f356b9aa5d03912dec73d9d4f2305eb7" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>Yes, it looks "ugly" but don't worry. This is due to the default stretch alignment of CSS Grid. We have to disable it and place our button at the bottom using <code>place-self: end</code>.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/1e33f3acf4c05a730eb259b63e9bee82" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>Now let's introduce <code>position: sticky</code> by adding this code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">position</span>: sticky;
  <span class="hljs-attribute">bottom</span>: <span class="hljs-number">20px</span>; 
}
</code></pre>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/97fc75f4e30d29baf2100a6684dc2e32" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>Our button is fixed at the bottom right of our screen thanks to our "sticky" behavior. Now we need to control that behavior to make the button initially hidden. For this, we will use <code>margin-top</code> with a value equal to the screen height (<code>100vh</code> ).</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/d60f76ae3dc8a77a8a3c99a7840b4b87" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>See that? Our button appears only when we scroll the screen and then remains fixed. We are getting closer!</p>
<p>Let's do better by adding an offset. Our <code>margin-top</code> will become:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">--offset</span>: <span class="hljs-number">100px</span>; 

  <span class="hljs-attribute">margin-top</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">100vh</span> + var(--offset));
}
</code></pre>
<p>The above means: "After 100px of scrolling, show the button". To the screen height, we add an offset (that we define using a CSS variable) to control when the button should appear. </p>
<p>The final touch is to make the column width of the button equal to 0 by changing <code>grid-template-columns: auto auto</code> into <code>grid-template-columns: auto 0px</code>.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/a44aaf99ec97bc19418095306ae9cf19" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>Oops, the button is messed up! Since we reduced the space of the button to 0, the latter will try to fit that space by adding line breaks. To fix this, we simply add <code>white-space: nowrap</code> to disable the line breaks.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/6de5b9a160a83b279a33a651f92ff2d8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>We made our first CSS-only "back to top" button with a sliding effect.</p>
<ul>
<li>You can adjust the offset to control when the button should appear</li>
<li>Using <code>bottom</code> and <code>margin-right</code> you can control the distance from the bottom right corner of the screen.</li>
</ul>
<p>Let's not forget that you can easily style the button as you want. Here is another idea using the same code structure:</p>
<details>
  <summary>Click to see the full code</summary>

  <code>html
  &lt;body&gt;
    &lt;div&gt;
      &lt;!-- your content goes here  --&gt;
    &lt;/div&gt;
    &lt;a href="#" class="top"&gt;Back to Top &amp;#8593;&lt;/a&gt;
  &lt;/body&gt;</code>
  <code>css
  body {
    display: grid;
    grid-template-columns: auto 0px; 
  }

  .top {
    --offset: 50px; 

    position: sticky;
    bottom: 20px;      
    margin-right: 10px; 
    place-self: end;
    margin-top: calc(100vh + var(--offset));

    /* visual styling */
    width: 45px;
    aspect-ratio: 1;
    background: #ff8b24;
    border-radius: 10px;
  }

  .top:before {
    content: "";
    position: absolute;
    inset: 30%;
    transform: translateY(20%) rotate(-45deg);
    border-top: 5px solid #fff;
    border-right: 5px solid #fff;
  }

  p {
    font-size: 25px;
  }</code>
</details>

<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/5931fe72a76540644679e8453a8c3b41" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<h2 id="heading-how-to-make-a-fading-back-to-top-button">How to Make a Fading Back to Top Button</h2>
<p>Let's tackle the second type of button where we will have a "fading" effect. Here's an overview of what we will create here:</p>
<details>
  <summary>Click to see the full code</summary>

  <code>html
  &lt;body&gt;
    &lt;div&gt;
      &lt;!-- your content goes here  --&gt;
    &lt;/div&gt;
    &lt;div class="container-top"&gt;
      &lt;a href="#" class="top"&gt;&lt;/a&gt;
    &lt;/div&gt;
  &lt;/body&gt;</code>
  <code>css
  body {
    display: grid;
    grid-template-columns: auto 0px; 
  }

  .container-top {
    --offset: 100px;
    --fade: 120px;

    display: flex;
    align-items: flex-end;
    width: 60px;
    justify-self: end;
    justify-content: flex-end;
    -webkit-mask: linear-gradient(#0000 calc(100vh + var(--offset)), #000 calc(100vh + var(--offset) + var(--fade)));
  }

  .top {
    position: sticky;
    bottom: 20px;      
    margin-right: 10px; 

    /* visual styling */
    width: 100%;
    aspect-ratio: 1;
    background: #ff8b24;
    border-radius: 10px;
  }

  .top:before {
    content: "";
    position: absolute;
    inset: 30%;
    transform: translateY(20%) rotate(-45deg);
    border-top: 5px solid #fff;
    border-right: 5px solid #fff;
  }

  p {
    font-size: 25px;
  }</code>
</details>

<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/ee83bb0f509273da920f7a8b48deea70" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>Like the previous effect, you will find zero JavaScript code. That fading effect is handled with only CSS.</p>
<p>Let's dig into this one!</p>
<h3 id="heading-the-html-structure-1">The HTML structure</h3>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- your content goes here  --&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container-top"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"top"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>It's very similar to the previous example. We've simply added an extra wrapper around our "back to top" button.</p>
<h3 id="heading-the-css-code-1">The CSS code</h3>
<p>I will skip the part where we style the button since it's the same as the previous effect.</p>
<p>This effect also relies on CSS grid and <code>position: sticky</code>. We'll also use a third technique which is the <code>mask</code> property (the one that will simulate the fading effect).</p>
<p>Let's start with the main setting:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: auto auto; 
}

<span class="hljs-selector-class">.container-top</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: flex-end;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">60px</span>;
}

<span class="hljs-selector-class">.top</span> {
  <span class="hljs-attribute">position</span>: sticky;
  <span class="hljs-attribute">bottom</span>: <span class="hljs-number">20px</span>;      
  <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">10px</span>; 
}
</code></pre>
<p>We define our two-column layout where the <code>container-top</code> is the second one. We make the latter a flex container and we place the button at the very bottom using <code>align-items: flex-end</code>. Finally, we use <code>position: sticky</code> to have the button fixed at the bottom right of the screen.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/89a50537ca3c7b6333af56ba55d5b7d2" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>Now let's introduce the <code>mask</code> property to create the fading effect. To understand this trick, I will first use a background to illustrate how it works.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/3ba95f0e83ed5a21f0dbc9cd8e3751d1" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>In the above, I applied the following gradient to <code>container-top</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container-top</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">linear-gradient</span>(green <span class="hljs-number">100vh</span>, red <span class="hljs-number">0</span>);
}
</code></pre>
<p>If you scroll, you will notice that the button will move from the green area to the red one. The green area is equal to the screen height.</p>
<p>Imagine that the green area is the "invisible" part of the <code>container-top</code> and the red one is the "visible" part. This is what <code>mask</code> will be doing if we consider the same gradient.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/612cd0ac11098d0f5030a833e1707d1d" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>In this last demo, we changed <code>background</code> with <code>mask</code> and we used a transparent/opaque combination of colors instead of the green/red one. The button now appears only on scroll!</p>
<p>To get the fading effect, we need to increase the distance between both colors. Let's introduce a CSS variable and update the mask like below:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container-top</span> {
  <span class="hljs-attribute">--fade</span>: <span class="hljs-number">120px</span>;
  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">linear-gradient</span>(#<span class="hljs-number">0000</span> <span class="hljs-number">100vh</span>, #<span class="hljs-number">000</span> calc(<span class="hljs-number">100vh</span> + var(--fade)));
}
</code></pre>
<p>The transparent color ends at <code>100vh</code>, and the opaque one start at <code>100vh + 120px</code>. We have a fading of <code>120px</code> between transparent and opaque which gives us the following result:</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/4b34d1f80f60a281bec7a36cfce16be9" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>We are almost there! Our button is fading like expected. We are simply missing the offset variable to control when the fading effect should happen.</p>
<p>For this, we do the same as the previous effect by introducing the <code>offset</code> variable:</p>
<p>The final touch is to make the column width of <code>container-top</code> equal to 0 using <code>grid-template-columns: auto 0px</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container-top</span> {
  <span class="hljs-attribute">--offset</span>: <span class="hljs-number">100px</span>;
  <span class="hljs-attribute">--fade</span>: <span class="hljs-number">120px</span>;

  <span class="hljs-attribute">mask</span>: <span class="hljs-built_in">linear-gradient</span>(#<span class="hljs-number">0000</span> calc(<span class="hljs-number">100vh</span> + var(--offset)), <span class="hljs-number">#000</span> <span class="hljs-built_in">calc</span>(<span class="hljs-number">100vh</span> + var(--offset) + <span class="hljs-built_in">var</span>(--fade)));
}
</code></pre>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/t_afif/embed/86f79c96520a0c864324db70a6b76c76" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>Our second  "back to top" button is done! Like the previous one, you can easily control the offset, the fading effect, and the position by adjusting the CSS variables, the <code>bottom</code> property, and the <code>margin-right</code> property.</p>
<p>Thank you for reading!</p>
<p>For more CSS tips, follow me on <a target="_blank" href="https://twitter.com/ChallengesCss">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
