How to create a curve between two gradient using C

2020-02-01 03:42发布

I have two divs with distinct gradient background and I need to create a S-Shape curve between them.

enter image description here

Here's the example fiddle for gradient divs: https://jsfiddle.net/JerryGoyal/rjyfc46c/2/

<div id="section1">

</div>
<div id="section2">

</div>
#section1{
  height:200px;
  background: linear-gradient(to bottom right, #ad3, #add);
}
#section2{
  height:200px;
  background: linear-gradient(to bottom right, #de350b, #0065ff);
}

There are couple of things which crossed my mind but:

- svg: don't know how to handle other gradient div.
- border-radius: failed to get truly S-like curve plus it gets ugly when I resize the screen.
- clip-path: not supported by some browsers https://caniuse.com/css-clip-path
- png image: nope! needs to be dynamic content.

any help would be appreciated!


P.S: a must read for future readers: https://css-tricks.com/creating-non-rectangular-headers/

1条回答
手持菜刀,她持情操
2楼-- · 2020-02-01 04:32

Here is a solution using linearGradient with SVG.

.container {
  width: 500px;
  height: 200px;
  background:linear-gradient(to bottom right, #de350b, #0065ff);
}
svg {
  width:100%;
}
<div class="container">
  <svg mlns='http://www.w3.org/2000/svg' viewBox="0 0 64 64">
    <defs>
    <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" stop-color="#ad3" />
      <stop offset="100%" stop-color="#add" />
    </linearGradient>
  </defs>
    <path d='M0 10 C30 28 38 0 64 10 L64 0 L0 0 Z'  fill="url(#grad)"/>
  </svg>
</div>

SVG curve gradients

Here is also a useful online tool to easily edit the shape (simply append the path to the url to edit ithttp://jxnblk.com/paths/?d=M0 10 C30 28 38 0 64 10 L64 0 L0 0 Z )


Another idea with the same SVG used as a background so you can easily handle content above it:

.container {
  width: 500px;
  height: 200px;
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="500" ><defs><linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="%23ad3" /><stop offset="100%" stop-color="%23add" /></linearGradient></defs><path d="M0 10 C30 28 38 0 64 10 L64 0 L0 0 Z"  fill="url(%23grad)"/></svg>'), 
  linear-gradient(to bottom right, #de350b, #0065ff);
  
  display:flex;
  justify-content:space-around;
  align-items:center;
  flex-direction:column;
  color:#fff;
}
<div class="container">
<p>TOP</p>
<p>BOTTOM</p>
</div>


In case you want a pure CSS solution with no SVG involved here is one using mask and radial-gradient:

.box {
  height:200px;
  position:relative;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  height:100%;
  background: linear-gradient(to bottom right, #ad3, #add);
}
.box:after {
  -webkit-mask:
    radial-gradient(100% 80% at top   ,white 79.5%,transparent 80%) left,
    radial-gradient(100% 80% at bottom,transparent 79.5%,white 80%) right;
  mask:
    radial-gradient(100% 80% at top   ,white 79.5%,transparent 80%) left,
    radial-gradient(100% 80% at bottom,transparent 79.5%,white 80%) right;
  -webkit-mask-size:50.1% 100%;
  -webkit-mask-repeat:no-repeat;
  mask-size:50.1% 100%;
  mask-repeat:no-repeat;
  background:linear-gradient(to bottom right, #de350b, #0065ff);
}
<div class="box">

</div>

CSS curve linear gradient mask

Adjust the different values to control the curve. The trick is to make sure both are the same and start at the same point to create a contiguous shape. You can introduce CSS variables to easily control this:

.box {
  height:200px;
  margin:10px;
  position:relative;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  height:100%;
  background: linear-gradient(to bottom right, #ad3, #add);
}
.box:after {
  -webkit-mask:
    radial-gradient(var(--r1,100%) var(--r2,80%) at top   ,white 79.5%,transparent 80%) left,
    radial-gradient(var(--r1,100%) var(--r2,80%) at bottom,transparent 79.5%,white 80%) right;
  mask:
    radial-gradient(var(--r1,100%) var(--r2,80%) at top   ,white 79.5%,transparent 80%) left,
    radial-gradient(var(--r1,100%) var(--r2,80%) at bottom,transparent 79.5%,white 80%) right;
  -webkit-mask-size:50.1% 100%;
  -webkit-mask-repeat:no-repeat;
  mask-size:50.1% 100%;
  mask-repeat:no-repeat;
  background:linear-gradient(to bottom right, #de350b, #0065ff);
}
<div class="box">

</div>

<div class="box" style="--r1:82%;--r2:97%">

</div>

<div class="box" style="--r1:126%;--r2:72%">

</div>

CSS mask gradient curve

To make things more funny we can add a border between both gradient following the curve where we can place another gradient!

.box {
  height:200px;
  margin:10px;
  position:relative;
  background:linear-gradient(to right,blue,black);
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  left:0;
  right:0;
  height:calc(100% - var(--b,10px)); /*control the gap here*/
  -webkit-mask:
    radial-gradient(var(--r1,100%) var(--r2,80%) at var(--p1,top)   ,white 79.5%,transparent 80%) var(--d1,right),
    radial-gradient(var(--r1,100%) var(--r2,80%) at var(--p2,bottom),transparent 79.5%,white 80%) var(--d2,left);
  mask:
    radial-gradient(var(--r1,100%) var(--r2,80%) at var(--p1,top)   ,white 79.5%,transparent 80%) var(--d1,right),
    radial-gradient(var(--r1,100%) var(--r2,80%) at var(--p2,bottom),transparent 79.5%,white 80%) var(--d2,left);
  -webkit-mask-size:50.1% 100%;
  -webkit-mask-repeat:no-repeat;
  mask-size:50.1% 100%;
  mask-repeat:no-repeat;
}
.box:before {
  top:0;
  background:linear-gradient(to bottom right, #de350b, #0065ff);
}
.box:after {
  bottom:0;
  background: linear-gradient(to bottom right, #ad3, #add);
  --p1:bottom;
  --p2:top;
  --d1:left;
  --d2:right;
}
<div class="box">

</div>

<div class="box" style="--r1:82%;--r2:97%;--b:20px">

</div>

<div class="box" style="--r1:126%;--r2:72%;--b:5px">

</div>

CSS curve shape mulitple gradient

查看更多
登录 后发表回答