Background with gradient responsive

2020-02-07 07:15发布

问题:

I have the following code: (Fiddle)

body {
  background-color: red;
}
#grad1 {
  height: 100px;
  width: 100%;
  background: linear-gradient(521deg, rgba(138, 138, 138, 0) 50%, rgba(138, 138, 138, 0) 31.9%, #fff 0.1%, #fff 0%);
}
<div id="grad1"></div>

I basically want the width to be responsive and the gradient's shape to be maintained even though the width changes.

What I've tried:

  1. Set the width to 100% this doesn't work because its an empty div

That's about it, I have no other ideas to be honest. I'd appreciate if someone could help.


This is what I'm using it for: (the images are just an example to show what happens/what I mean)

But if I have a bigger device this happens:

回答1:

Solution: (TL;DR)

If you need responsive gradients, it is always better to use the to [side] [side] syntax instead of using angles. Below is a snippet that would produce a responsive triangle.

body {
  background-color: red;
}
#grad1 {
  height: 100px;
  width: 100%;
  background: linear-gradient(to bottom right, rgba(255, 255, 255, 0) 49.9%, rgba(255, 255, 255, 1) 50.1%);
}
<div id="grad1"></div>


Explanation:

The reason why the gradient in question becomes a triangle at smaller widths and becomes sort of a trapezoid at larger width can be understood if we have a detailed look at how the angle of the gradient affects the start and end points of the gradient.

Why the angled linear gradient produces different shapes at different widths?

Linear gradients are always defined by an axis (which is referred to as the gradient line). This can be thought of as a line that is drawn through the center of the box that contains the gradient (the black line in the below screenshot) and is rotated by the angle of the gradient. The 0deg line starts at bottom and goes upwards whereas 90deg line goes towards right.

In addition to the gradient line, gradients also have an imaginary start point and an end point. The start line of the gradient is the perpendicular line from top-left corner (the corner that's in the same quadrant as the gradient line's starting point) of the box to the gradient line and the end line is the perpendicular line from the bottom-right corner (opposite corner) of the box to the gradient line.

Each point on this imaginary gradient line will have a certain color depending on the gradient definition. In the below case, I have used a gradient that is transparent for 50% and is white for rest. So all points on the top half of the gradient line will be transparent and those on the bottom half will be white in color.

As you can see in the below screenshot, the distance between the start and end points become more and more as the width of the box increases and this affects the mid point also (the mid green line). So, the point from where the gradient becomes white changes as the width increases and thus the shape also changes.

Why the side to side linear gradient maintains the shape at all widths?

When the side to side syntax is used, the gradient line is angled such that it points into (or towards) the same quadrant in which the specified corner is (for this case, it points towards the 2nd quadrant because that is where the bottom right corner of the box is). Its is also angled in such a way that it is perpendicular to a line that connects the two neighbouring corners of the box (in this case, it'd be the bottom left corner and top right corner). Since the angle of the gradient line is automatically adjusted such that it is perpendicular to the diagonal (line connecting the two neighbouring corners), it always produces a triangle for a half-n-half gradient.


The below snippet is not the solution (that is on top). This is what I used to create the screenshot above and thought of leaving it here for fun :D

For angled gradient:

div {
  position: relative;
  display: inline-block;
  height: 100px;
  background: linear-gradient(521deg, transparent 50%, white 50%);
  margin: 200px 50px;
  border: 1px solid black;
}
#div-large {
  width: 400px;
}
#div-small {
  width: 200px;
}
div:after {
  position: absolute;
  content: '';
  width: calc(100% + 24px);
  left: -12px;
  background: linear-gradient(to right, transparent calc(50% - 1px), black calc(50% - 1px), black calc(50% + 1px), transparent calc(50% + 1px)), linear-gradient(to right, green 6px, transparent 6px);
  background-position: 0px 0px, 0px, calc(50% - 1px);
  background-repeat: no-repeat, repeat-x;
  background-size: 100% 100%, 12px 2px;
  border-top: 2px dashed green;
  border-bottom: 2px dashed green;
  transform: rotate(521deg);
}
#div-large:after{
  height: calc(100% + 125px);
  top: -64px;
}
#div-small:after{
  height: calc(100% + 60px);
  top: -32px;
}
body {
  background: sandybrown;
}
<div id='div-small'></div>
<div id='div-large'></div>

For side to side gradient:

div {
  position: relative;
  display: inline-block;
  height: 100px;
  margin: 200px 50px;
  border: 1px solid black;
}
#div-large {
  width: 400px;
  background: linear-gradient(526deg, transparent 50%, white 50%);
}
#div-small {
  width: 200px;
  background: linear-gradient(513.5deg, transparent 50%, white 50%);
}
div:after {
  position: absolute;
  content: '';
  width: calc(100% + 24px);
  left: -12px;
  background: linear-gradient(to right, transparent calc(50% - 1px), black calc(50% - 1px), black calc(50% + 1px), transparent calc(50% + 1px)), linear-gradient(to right, green 6px, transparent 6px);
  background-position: 0px 0px, 0px, calc(50% - 1px);
  background-repeat: no-repeat, repeat-x;
  background-size: 100% 100%, 12px 2px;
  border-top: 2px dashed green;
  border-bottom: 2px dashed green;
}
#div-large:after{
  height: calc(100% + 93px);
  top: -48px;
  transform: rotate(526deg);
}
#div-small:after{
  height: calc(100% + 78px);
  top: -41px;
  transform: rotate(513.5deg);
}
body {
  background: sandybrown;
}
<div id='div-small'></div>
<div id='div-large'></div>

Disclaimer: My explanation is heavily influenced by this MDN page but I've tried to put as much of it in my own words as possible :)



回答2:

You could alternatively use 2 pseudo elements to generate the design you want.

body {
  margin: 0;
  padding: 0;
  color: black;
  background: #eee;
}
h1 {
  padding: 0 1em;
}
p {
  padding: 1em;
}
.grad {
  background: black;
  color: white;
  position: relative;
  margin-top: 50px;
  margin-bottom: 50px;
}
.grad:before,
.grad:after {
  content: '';
  position: absolute;
  left: 0;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 0 0 50px 100vw;
  border-color: transparent transparent #000000 transparent;
}
.grad:before {
  top: -50px;
}
.grad:after {
  bottom: -50px;
  border-width: 50px 100vw 0 0;
  border-color: #000000 transparent transparent transparent;
}
<h1>Title</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis laoreet scelerisque risus, eu scelerisque libero condimentum ut. Ut ac sapien placerat, suscipit odio vitae, vestibulum neque. Donec dui tortor, consequat rhoncus malesuada pharetra, dignissim
  sit amet mauris. Curabitur finibus arcu volutpat laoreet laoreet. Pellentesque mattis quam eget elit eleifend auctor. Fusce et nunc lobortis, laoreet leo sed, lacinia lorem. Nunc gravida eu eros et consequat.</p>
<div class="grad">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis laoreet scelerisque risus, eu scelerisque libero condimentum ut. Ut ac sapien placerat, suscipit odio vitae, vestibulum neque. Donec dui tortor, consequat rhoncus malesuada pharetra, dignissim
    sit amet mauris. Curabitur finibus arcu volutpat laoreet laoreet. Pellentesque mattis quam eget elit eleifend auctor. Fusce et nunc lobortis, laoreet leo sed, lacinia lorem. Nunc gravida eu eros et consequat.
  </p>
</div>
<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis laoreet scelerisque risus, eu scelerisque libero condimentum ut. Ut ac sapien placerat, suscipit odio vitae, vestibulum neque. Donec dui tortor, consequat rhoncus malesuada pharetra, dignissim
  sit amet mauris. Curabitur finibus arcu volutpat laoreet laoreet. Pellentesque mattis quam eget elit eleifend auctor. Fusce et nunc lobortis, laoreet leo sed, lacinia lorem. Nunc gravida eu eros et consequat.
</p>



回答3:

When you set % it really means that it is a percentage of its container. After you set grad1 to be 100% of the width of the body.

Try setting the body width to 100%.