Jon Surrell
Jon Surrell

Reputation: 9637

Is it possible to make a hard-edged gradient on a large element?

I ran into a problem using a linear-gradient on a particularly large element.

On smaller elements, a hard edge can be achieved with the following:

background-image: linear-gradient(180deg, #000, #000 33%, #0f0 0);

However when the element has a very large height, the edge is soft. You can see in the following image and example below, the second version has a soft edge when the element is very large and the same gradient is applied.

hard and soft edged gradients

I have tried many variations on the linear gradient and have been unable to achieve a hard edge on the large version. Is there a way to apply a gradient with a hard edge on a large element?

HTML example:

div {
  height: 5000px;
  background-repeat: no-repeat;
  margin-bottom: 1em;
  background-image: linear-gradient(180deg, #000, #000 20px, #0f0 0);
}
div:first-child {
  height: 100px;
}
<div></div>
<div></div>

Edit

The goal of this gradient is for use with another background image, so I prefer techniques that are compatible with the following (don't cover the image):

div {
  height: 5000px;
  background-repeat: no-repeat;
  margin-bottom: 1em;
  background-image: url(http://placehold.it/600x20), linear-gradient(180deg, #000, #000 20px, #0f0 0);
}
<div></div>

Edit 2

Thanks to @Tarun, this appears to be browser related. The above image is a screenshot from Chromium 45. Safari and Firefox appear to render correctly.

Edit 3

There is an open bug report for chromium about this issue.

Upvotes: 13

Views: 15350

Answers (6)

Jonas de Herdt
Jonas de Herdt

Reputation: 451

This creates a gradient with a sharp edge. The fractional digits are forcing the browser to render high fidelity edge.

background-image: linear-gradient(90deg, rgba(229,159,0,1) 0%, rgba(229,159,0,1) 49.99%, rgba(130,163,0,1) 50%, rgba(130,163,0,1) 100%);

Upvotes: 0

diziaq
diziaq

Reputation: 7805

You need to repeat each color, and each percent rate of linear-gradient in a tricky, but expressive way. Let's see it in a six colors sample to understand the principle. This approach works for any size of block.

div {
  height: 100px;
  background-repeat: no-repeat;
  margin-bottom: 1em;
  background-image:
      linear-gradient(90deg,
                       red,
                       red     17%,
                       orange  17%, 
                       orange  34%, 
                       yellow  34%,
                       yellow  51%,
                       black   51%,
                       black   68%,
                       green   68%,
                       green   85%,
                       blue    85%);
}
  
<div></div>

Upvotes: 5

Tarun
Tarun

Reputation: 456

This works for me.

background: linear-gradient(to bottom, black 0% ,black 20% ,green 20% ,green 100%);

edit: I've tried to do exactly what you're doing in the question, and I'm getting a hard edge on both boxes. Your problem must be related to your browser.

edit 2: confirmed comparison

Upvotes: 10

Aaron
Aaron

Reputation: 10440

You could use box shadow for the same effect.

div {
  height: 5000px;
}
div {
  background: #0f0;
  box-shadow: inset 0 100px 0 0 #000;
}
<div></div>

Upvotes: 7

Pepelius
Pepelius

Reputation: 1609

You could use a bit more codespace and set up your gardient like following:

background: #4c4c4c;
background: linear-gradient(to bottom,  #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#131313',GradientType=0 );

The solid background setting is there to make sure your page is showing some color if the browser somehow fails to support this type of gardient or its filter.

It is also preferred to include -moz, -o and other browser-based fixups to make sure.

Upvotes: 0

Jon Surrell
Jon Surrell

Reputation: 9637

I've found an alternative using gradients to achieve the same effect, however I think it should be possible to achieve this with 1 gradient, so I consider this a work-around.

The trick is to use multiple backgrounds with 2 gradients that don't change color. Then just define background-size to achieve the hard edge effect. See the working snippet:

div {
  height: 5000px;
  background-repeat: no-repeat;
  margin-bottom: 1em;
  background-image: linear-gradient(#000, #000), linear-gradient(#0f0, #0f0);
  background-size: 100% 20px, 100%;
}
div:first-child {
  height: 100px;
}
<div></div>
<div></div>

Upvotes: 17

Related Questions