Blog

Pseudo-Linear Gradient Top and Bottom Borders in CSS3 and LESS


While doing yet another tweak to my portfolio, I decided to see if there was a native way in CSS to get a linear gradient on a border of an element. Inherently, no. Not really.

However... there is a way to mimic this effect in CSS3 for the top and bottom borders, through the magic of the ::before and ::after pseudoclasses.

For the purposes example, I'm going to put this in LESS as well, as that's how I did it. You can use pure CSS3 if you so desire, however.

In this example, we are using a <div> element with the class foo, and having it stretch across the screen with negative margins to get around the padding-left and padding-right inherent in Bootstrap's container-fluid class.

<div class="foo">
    <p>Here is some content</p>
    <p>Here is some more content.</p>
</div>

Now, let's set up the initial CSS for foo:

.foo {
    background: linear-gradient(darken(@white, 30%), darken(@white, 5%), darken(@white, 30%));
    margin-left: -15px;
    margin-right: -15px;
    padding: 0 25px;
}

But we don't have our borders... or linear-gradient top and bottom borders for that matter. Well, this is where the ::before and ::after pseudo-classes come in!

.foo::before {
    display: block;
    height: 2px;
    width: calc(~"100% + 50px");
    margin: 0 -25px 10px;
    background: linear-gradient(to left, lighten(@black, 5%), lighten(@black, 15%),lighten(@black, 60%),lighten(@black, 5%));
content: "";
}

.foo::after {
    display: block;
    height: 2px;
    width: calc(~"100% + 50px");
    margin: 10px -25px 0;
    background: linear-gradient(to left, lighten(@black, 5%), lighten(@black, 15%),lighten(@black, 60%),lighten(@black, 5%));
content:""
}

What happens is, before the <div>, the ::before is creating a block-level element with a height of 2px, a width of 100% plus the 50px to ensure our border will be long enough to compensate for the 25px padding, and setting margins for no top margin, side margins of -25px (to further compensate for the main <div>'s padding), and a 10px bottom margin to emulate what would have been a top padding of 10px on the main div. (Note: in LESS, you will need a tilde and to put the 100% + 50px in quotes, otherwise the LESS compiler will interpret it as 150%, and that tends to cause horizontal scrollbars to show up, which we don't want. Pure CSS3 if using a .css file will not require that.).

IMPORTANT: The content: ""; part is VERY important. Without that line in your ::before and ::after, the pseudo-gradient border will not render!

The ::after on the <div> is similar but uses the margin of 10px for the top (to simulate 10px bottom padding on the main <div>), -25px side margins as before, and no bottom margin.

The linear-gradient on the background for the ::before and ::after is where the magic happens. You can set this gradient to be what you want. In this case, I'm lightening a LESS class of @black, or hex color code #000000 (or #000 if you want the shorthand notation).

Below is the non-LESS CSS version of the above:

.foo {
  background: linear-gradient(#b3b3b3, #f2f2f2, #b3b3b3);
  margin-left: -15px;
  margin-right: -15px;
  padding: 0 25px;
}

.foo::before {
  display: block;
  height: 2px;
  width: calc(100% + 50px);
  margin: 0 -25px 10px;
  background: linear-gradient(to left, #0d0d0d, #262626, #999999, #0d0d0d);
content: "";
}

.foo::after {
  display: block;
  height: 2px;
  width: calc(100% + 50px);
  margin: 10px -25px 0;
  background: linear-gradient(to left, #0d0d0d, #262626, #999999, #0d0d0d);
content: "";
}

Feel free to copy it into your code and try it out. You may need to adjust width if you're not using Bootstrap, or not using container-fluid in your Bootstrap code (or if you've adjusted the margins and padding on those classes).

Links

Archive