Creating a Rainbow Border with Sass

Share this article

Key Takeaways

  • Sass can be used to create a multi-colored or “rainbow” border effect with CSS gradients, offering a more efficient solution than using multiple HTML elements with different background colors and sizes.
  • The Sass function ‘stripes’ can be used to create equally wide color sections, custom-sized color sections, or randomly-sized color sections based on a list of colors. The function checks the number of colors and defines the case (random, custom or equal), then uses the call function from Sass 3.3 to invoke a function based on the defined type.
  • The final result is a clean, concise function for generating a multi-colored border from a list of colors, which is easy to use and well organized. The function can be tested and modified on CodePen.

A lot of modern designs are making good use of a multi-colored border effect (which we might also refer to as a “rainbow” border or “striped” border). For example, look at Treehouse’s blog – it has a multi-colored border under its navigation and it looks really nice.

Treehouse's colored border

However, in my opinion, Treehouse is coding it wrong. Since this is strictly concerned with aesthetics, it should be handled by CSS – and CSS only – without requiring any extra work in the HTML. Treehouse uses 50 span elements, each of them with a specific background color and a specific size, to create its nav border.

Whaaaat?

It’s overkill to dump such a large load of elements into the DOM just so you can create a striped border. Why not use CSS for this? I mean only CSS. Gradients are awesome for this type of task! Yes, you can create multiple colors in this manner using CSS gradients, and it’s quite easy to do.

The only caveat is that gradients are kind of a pain to write. They have a tedious syntax that is very likely to result in mistyping and errors. Plus having to repeat color stops in order to achieve multiple colors is annoying.

Sass to the Rescue!

This is something I wrote about last year on CSS-Tricks – but looking back at my code now, I thought it would be a good idea to revisit the whole thing to see if we can do better, especially since we now have access to Sass 3.3 features.

Before jumping into the code, let’s see what we want to create. I can see three different ways to produce this effect:

  1. Equally wide color sections based on a list of colors.
  2. Custom-sized color sections based on a 2-dimensional list of colors + color stops.
  3. Randomly-sized color sections based on a list of colors with randomly generated color stops.

What I would like to have is a unique function that defers to “private” functions depending on the case we encounter. This keeps the API simple for the user and the code well organized for the developer (AKA you).

The Core Function

@function stripes($colors, $direction: 90deg, $random: false) {
  // If lonely color
  @if length($colors) == 1 { @return $colors; }

  // Else
  $type: 'equal';

  @if $random {
    $type: 'random';
  }

  @else if length(nth($colors, 1)) > 1 {
    $type: 'custom';
  }

  @return linear-gradient($direction, call('_stripes-#{$type}-stops', $colors));
}

Here is what happens: first we check if the $colors variable is a single item, in which case we return it. Else, we define the case we are facing: random, custom or equal. If, like me, you prefer ternary operators, here is what you can do for the same result:

$type: if($random, 'random', if(length(nth($colors, 1)) > 1, 'custom', 'equal'));

Finally, we make good use of the call function from Sass 3.3. This makes it possible for us to invoke a function using its name as a string, meaning we can dynamically call the delayed function based on the defined $type.

Notice that we return a linear-gradient() directly so that calling the function is as easy as background: stripes($colors).

Note: if you are running Sass 3.2 and can’t use the call function, move the @return directives into the conditional statements.

Equal Color Stops

What is quite awesome about the linear-gradient() syntax is that it is based on a comma-separated list. This means a well formatted Sass list can be directly injected into the gradient function. All we have to do is build a comma separated list with each item being a 2-item spaced list consisting of the color and the color stop. For instance: red 10%, blue 10%.

Now let’s get back to our function. The easiest case is definitely one where all the colors are the same width. To define this width, all we have to do is divide 100% by the number of colors in the list. Then we loop through the list and build a clean list for the gradient function.

@function _stripes-equal-stops($colors) {
  $gradients: ();                                                        // 1
  $stops: 100% / length($colors);                                        // 2

  @for $i from 1 to length($colors) {                                    // 3
    $gradients: append($gradients, nth($colors, $i) $i * $stops, comma); // 4
    @if $i < length($colors) {                                        // 5
      $gradients: append($gradients, nth($colors, $i + 1) $i * $stops);  // 6
    }
  }

  @return $gradients;                                                    // 7
}

This may look complicated but it’s actually really simple. Here is what it does:

  1. Instantiate an empty list for our colors and color stops.
  2. Define the width of a color in percentage.
  3. Loop through the colors.
  4. Add the color (nth($colors, $i)) and its color stop ($i * $stops) to the $gradients list.
  5. If there is a color left in the list, append it the same way we just did.
  6. Finally, return the list.

For instance consider a $colors list as red, yellow, green. The result returned by the function will be red 33.33%, yellow 33.33%, yellow 66.66%, green 66.66% resulting in 3 equally-sized sections of color on our line.

Custom Color Stops

We can also accept a two-dimensional list of colors and color stops. Something like red 10%, blue 20%, green 60%. This means the red should take 10% of the total width, the blue should go from 10% to 20%, and the green from 20% to the end. Indeed, the last color stop is not parsed.

@function _stripes-custom-stops($colors) {
  $gradients: ();

  @for $i from 1 to length($colors) {
    @if length(nth($colors, $i)) > 1 {
      $color: nth(nth($colors, $i), 1);
      $stop:  nth(nth($colors, $i), 2);

      $gradients: append($gradients, $color $stop, comma);
      @if $i < length($colors) {
        $gradients: append($gradients, nth(nth($colors, $i + 1), 1) $stop);
      }
    }

    @else {
      @warn '`#{nth($colors, $i)}` skipped because it is only one item long while it should be 2: (color, color-stop).';
    }
  }

  @return $gradients;
}

The code is almost the same as in the previous function except instead of computing the color stop, we read it from the second item of the current loop index. In case there is no color stop defined for a color, we warn the user the color is being skipped.

Random Color Stops

Lastly, we can randomly generate our color stops. You may have noticed that in Treehouse’s example, the colors are not the same width; some are shorter, some are longer. If we want to achieve a similar effect, we could compute the color stops with a random function.

At first, I let fate decide the color stops, however I very often found myself facing a massive color taking up 90% of the width, and all the other colors struggling to fit into the remaining space. That sucked! What I wanted was near-equal-sized colors with a slight length variation.

@function _stripes-random-stops($colors) {
  @if length(nth($colors, 1)) > 1 {
    @return _stripes-custom-stops($colors);
  }

  $nb: length($colors);
  $gradients: ();
  $variation: 10;
  $median: 100 / $n;

  @for $i from 1 to $nb {
    $stop: $median * $i; 
    $random: rand($stop - $variation, $stop + $variation) * 1%;
    $gradients: append($gradients, nth($colors, $i) $random, comma);
    @if $i < length($colors) {
      $gradients: append($gradients, nth(nth($colors, $i + 1), 1) $random);
    } 
  }

  @return $gradients;
}

Pretty much the same code as before. But notice how we generate a random number between n - 10% and n + 10%, n being the average color width. This ensures that all color sections will be approximately the same width, without being strictly equal, resulting in a neat little random-sized-colors effect.

Both the random function in Sass 3.3 and the custom Ruby one from CodePen accept only a single argument: the maximum value in order to roll between 1 and the given value. So if we want a function to generate random min and max values, we can do it very easily like this:

@function rand($min, $max) {
  @return random($max - $min) + $min;
}

Final Words + Demo

So there you have a clean and concise function to generate a multi-colored border from a list of colors. As you can see, the code is not that hard to understand, and well organized in the end. The API is rather easy to use as well, so I think we nailed it!

You can play with the code on CodePen:

See the Pen DKhkf by SitePoint (@SitePoint) on CodePen.

Frequently Asked Questions about Creating Rainbow Borders with SASS

How can I create a rainbow border with SASS that is compatible with all browsers?

Creating a rainbow border with SASS that is compatible with all browsers involves using the @for directive to generate a series of classes for each color in the rainbow. You can then use these classes to apply a linear gradient to the border of your element. However, it’s important to note that not all browsers support linear gradients. To ensure compatibility, you can use vendor prefixes like -webkit- and -moz-.

Can I animate the rainbow border created with SASS?

Yes, you can animate the rainbow border created with SASS. This can be achieved by using CSS animations and keyframes. You can create a keyframe animation that changes the background-position of the gradient over time, giving the illusion of movement. Remember to include vendor prefixes for better browser compatibility.

How can I create a solid rainbow border with SASS?

To create a solid rainbow border with SASS, you can use the @for directive to generate a series of classes for each color in the rainbow. Then, apply these classes to the border of your element. Instead of using a gradient, you can use solid colors for each class, creating a solid rainbow effect.

How can I adjust the width of the rainbow border created with SASS?

The width of the rainbow border can be adjusted by changing the border-width property in your SASS file. You can specify the width in pixels, ems, or any other CSS length unit. The border-width property can take one, two, three, or four values, allowing you to set the width of the border individually for each side of the element.

Can I use the rainbow border created with SASS on a specific side of an element?

Yes, you can apply the rainbow border to a specific side of an element. This can be done by using the border-top, border-right, border-bottom, or border-left properties instead of the border property. You can then apply the gradient to the specified side.

How can I create a rainbow border with SASS without using a preprocessor?

If you prefer not to use a preprocessor like SASS, you can create a rainbow border using pure CSS. This involves using the linear-gradient function to create a gradient, and then applying this gradient to the border-image property of your element.

Can I use the rainbow border created with SASS on a rounded element?

Yes, you can apply the rainbow border to a rounded element. This can be done by using the border-radius property in conjunction with the border property. The border-radius property allows you to round the corners of an element, and the border property allows you to apply the gradient.

How can I create a rainbow border with SASS that fades in and out?

To create a rainbow border that fades in and out, you can use CSS animations and keyframes in conjunction with the opacity property. You can create a keyframe animation that changes the opacity of the border over time, giving the illusion of fading in and out.

Can I use the rainbow border created with SASS on a text element?

Yes, you can apply the rainbow border to a text element. This can be done by using the text-decoration property in conjunction with the border property. The text-decoration property allows you to apply a line to the text, and the border property allows you to apply the gradient.

How can I create a rainbow border with SASS that transitions between colors?

To create a rainbow border that transitions between colors, you can use CSS transitions in conjunction with the border property. You can specify a transition on the border property, and then change the color of the border over time, giving the illusion of a color transition.

Kitty GiraudelKitty Giraudel
View Author

Non-binary trans accessibility & diversity advocate, frontend developer, author. Real life cat. She/her.

css colored bordercss gradient rainbowgradient colorsrainbow bordersassstriped border
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week