Gradient borders in CSS

Good day, dear habrovchane. I present to your attention the translation of the article by Chris Kour.

Suppose you need a gradient border around a certain element. And you think so:

  • There is no simple and obvious CSS API for this.
  • I'll just wrap the element with a linear-gradient background, and then the inner element will block most of this background, except for a thin line filling around it.

It will look something like this:

HTML

<divclass="module-border-wrap"><divclass="module">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vero pariatur corporis quaerat voluptatum eos tempora temporibus nisi voluptates sed, exercitationem sequi dolore culpa incidunt accusamus, quasi unde reprehenderit ea molestias.
</div></div>

SCSS

body {
   height: 100vh;
   margin: 0;
   display: grid;
   place-items: center;
   background: #222;
}
.module-border-wrap {
   max-width: 250px;
   padding: 1rem;
   position: relative;
   background: linear-gradient(to right, red, purple);
   padding: 3px;
}
.module {
   background: #222;
   color: white;
   padding: 2rem;
}

result


If you don't like the idea of ​​the wrapping element, you can use the pseudo-element as long as the z-index is negative in order (this would not have happened if there were many attachments of the parent elements with their own backgrounds).

Here is an example of Stephen Shaw fixing border-radius:

HTML

<divclass="gradient-box"><p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent bibendum, lorem vel tincidunt imperdiet, nibh elit laoreet felis, a bibendum nisl tortor non orci. Donec pretium fermentum felis, quis aliquet est rutrum ut. Integer quis massa ut lacus viverra pharetra in eu lacus. Aliquam tempus odio adipiscing diam pellentesque rhoncus. Curabitur a bibendum est. </p></div>

SCSS

.gradient-box {
   display: flex;
   align-items: center;
   //width: 50vw;
   width: 90%;
   margin: auto;
   max-width: 22em;
   position: relative;
   padding: 30%2em;
   box-sizing: border-box;
   $border: 5px;
   color: #FFF;
   background: #000;
   background-clip: padding-box; /* !importanté */border: solid $border transparent; /* !importanté */border-radius: 1em;
   &:before {
      content: '';
      position: absolute;
      top: 0; right: 0; bottom: 0; left: 0;
      z-index: -1;
      margin: -$border; /* !importanté */border-radius: inherit; /* !importanté */background: linear-gradient(to right, red, orange);
   }
}
html { height: 100%; background: #000; display: flex; }
body { margin: auto; }

result

But don't forget completely about border-imageperhaps the most clueless CSS property of all time. You can use it to get gradient borders even on separate sides:

HTML

<divclass="module">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vero pariatur corporis quaerat voluptatum eos tempora temporibus nisi voluptates sed, exercitationem sequi dolore culpa incidunt accusamus, quasi unde reprehenderit ea molestias.
</div>

CSS

body {
   height: 100vh;
   margin: 0;
   display: grid;
   place-items: center;
   background: #222;
}
.module {
   max-width: 250px;
   padding: 1rem;
   color: white;
   border-width: 3px;
   border-style: solid;
   border-image: 
      linear-gradient(
         to bottom, 
         red, 
         rgba(0, 0, 0, 0)
      ) 1100%;
}

result

Using both border-imageis and border-image-sliceprobably is the easiest syntax to create a gradient border, but unfortunately, this is simply incompatible with border-radius.

HTML

<div><divclass="on-light"><buttonclass="border-gradient border-gradient-purple">
         I have a gradient
      </button></div><divclass="on-dark"><buttonclass="border-gradient border-gradient-purple">
         I have a gradient
      </button></div><divclass="on-light"><buttonclass="border-gradient border-gradient-green">
         I have a gradient
      </button></div><divclass="on-dark"><buttonclass="border-gradient border-gradient-green">
         I have a gradient
      </button></div></div>

SCSS

button {
   background: none;
   text-decoration: inherit;
   font-family: system-ui;
   font-size: 1rem;
   padding: 1rem2rem;
}
.border-gradient {
   border-image-slice: 1;
   border-width: 2px;
}
.border-gradient-purple {
   border-image: linear-gradient(to left, #743ad5, #d53a9d);
}
.border-gradient-green {
   border-image: linear-gradient(to left, #00C853, #B2FF59);
}
body {
   height: 100vh;
   margin: 0;
   display: flex;
   justify-content: center;
   align-items: center;
   > div {
      width: 100%;
      text-align: center;
   }
   > div > div {
      width: 100%;
      padding: 1rem;
   }
}
.on-dark {
   background: #222;
   button {
      color: white;
   }
}

result

Also popular now: