使用CSS的Sigmoid曲线形状

Dim*_*zov 12 css svg rounded-corners css3 css-shapes

我想为全屏布局创建一个S形曲线形状,在一侧显示装饰性图案背景,在另一侧显示纯色背景,以便将文本放置在其上.

我们的目标是拥有一个带有S形状的左上侧的全屏页面,其中包含图案,页面的其余部分只有白色背景.

JSFiddle:未完成的S形曲线

#container {
  padding-top: 10%;
  padding-bottom: 10%;
  background: white url(http://famok.com/wp-content/uploads/2016/10/WhiteOnWhite.jpg) top left / 26px 32px repeat;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#parallelogram {
  margin-left: 35%;
  width: 100%;
  height: 900px;
  -webkit-transform: skew(-15deg);
  -moz-transform: skew(-15deg);
  -o-transform: skew(-15deg);
  transform: skew(-15deg);
  background: white;
  -moz-border-radius: 100px;
  -webkit-border-radius: 100px;
  border-radius: 100px;
  -moz-box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
  -webkit-box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
  box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
}
Run Code Online (Sandbox Code Playgroud)
<div id="container">
  <div id="parallelogram">
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚如何在左下角附近创建(或模拟)倒圆角.

或者可能有一个概念上不同(更好)的解决方案?

更新:我想出了如何使用CSS完全创建我需要形状.

#container {
  padding-top: 100px;
  background: red;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#parallelogram {
  margin-left: 400px;
  width: 100%;
  height: 900px;
  -webkit-transform: skew(-15deg);
  -moz-transform: skew(-15deg);
  -o-transform: skew(-15deg);
  transform: skew(-15deg);
  background: white;
  -moz-border-top-left-radius: 100px;
  -webkit-top-left-border-radius: 100px;
  border-top-left-radius: 100px;
}
#bottom {
  height: 200px;
  width: 100%;
  background: white;
}
#bottom-corner {
  height: 100px;
  width: 300px;
  margin-left: -34px;
  background: red;
  -moz-border-bottom-right-radius: 100px;
  -webkit-bottom-right-border-radius: 100px;
  border-bottom-right-radius: 100px;
  -webkit-transform: skew(-15deg);
  -moz-transform: skew(-15deg);
  -o-transform: skew(-15deg);
  transform: skew(-15deg);
}
Run Code Online (Sandbox Code Playgroud)
<div id="container">
  <div id="parallelogram">
  </div>

  <div id="bottom">
    <div id="bottom-corner">
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

然而,这仍然不是最终解决方案,因为形状不允许我使用我想到的那种背景效果.这是我尝试时会发生的事情:小提琴.

#container {
  padding-top: 100px;
  background: white url(http://famok.com/wp-content/uploads/2016/10/WhiteOnWhite.jpg) bottom left / 26px 32px repeat;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#parallelogram {
  margin-left: 400px;
  width: 100%;
  height: 900px;
  -webkit-transform: skew(-15deg);
  -moz-transform: skew(-15deg);
  -o-transform: skew(-15deg);
  transform: skew(-15deg);
  background: white;
  -moz-border-top-left-radius: 100px;
  -webkit-top-left-border-radius: 100px;
  border-top-left-radius: 100px;
  -moz-box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
  -webkit-box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
  box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
}
#bottom {
  height: 200px;
  width: 100%;
  background: white;
  -moz-box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
  -webkit-box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
  box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
}
#bottom-corner {
  height: 100px;
  width: 300px;
  margin-left: -34px;
  background: white url(http://famok.com/wp-content/uploads/2016/10/WhiteOnWhite.jpg) top left / 26px 32px repeat;
  -moz-border-bottom-right-radius: 100px;
  -webkit-bottom-right-border-radius: 100px;
  border-bottom-right-radius: 100px;
  -webkit-transform: skew(-15deg);
  -moz-transform: skew(-15deg);
  -o-transform: skew(-15deg);
  transform: skew(-15deg);
  -moz-box-shadow: 0 0 15px rgba(0, 0, 0, .4);
  -webkit-box-shadow: 0 0 15px rgba(0, 0, 0, .4);
  box-shadow: 0 0 15px rgba(0, 0, 0, .4);
}
Run Code Online (Sandbox Code Playgroud)
<div id="container">
  <div id="parallelogram">
  </div>

  <div id="bottom">
    <div id="bottom-corner">
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

稍后更新:经过一些试验和错误后,我最终得到了一个荒谬的粗暴黑客解决方案,实现了我所需的视觉效果:

#container {
  padding-top: 100px;
  background: white url(http://famok.com/wp-content/uploads/2016/10/WhiteOnWhite.jpg) top left / 26px 32px repeat;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#parallelogram {
  margin-left: 385px;
  width: 100%;
  height: 900px;
  -webkit-transform: skew(-15deg);
  -moz-transform: skew(-15deg);
  -o-transform: skew(-15deg);
  transform: skew(-15deg);
  background: white;
  -moz-border-top-left-radius: 100px;
  -webkit-top-left-border-radius: 100px;
  border-top-left-radius: 100px;
  -moz-box-shadow: inset 0 15px rgba(0, 0, 0, .4);
  -webkit-box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
  box-shadow: inset 0 0 15px rgba(0, 0, 0, .4);
}
#bottom-rounded-corner {
  height: 122px;
  position: relative;
  width: 200%;
  z-index: 1000;
  margin-top: -80px;
  margin-left: -185px;
  background: url(http://famok.com/wp-content/uploads/2016/11/CornerAndMask.png) top left no-repeat;
}
#bottom-white {
  height: 100px;
  width: 100%;
  background: white;
}
Run Code Online (Sandbox Code Playgroud)
<div id="container">
  <div id="parallelogram">
  </div>
  <div id="bottom-rounded-corner">

  </div>
  <div id="bottom-white">
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

尽量努力实现哈利在下面提出的概念上更好的替代方案,我无法用它来创造我想要的效果.如果有人可以通过展示如何做到这一点,或者通过提出对我的解决方案的优化,我仍然会感激不尽.

先感谢您!

Har*_*rry 11

将SVG用于复杂形状而不是CSS:

正如我在评论中提到的那样,请不要使用CSS来创建这样复杂的形状.SVG是这种复杂内容的推荐工具.SVG易于创建和维护,并且默认情况下它们也具有响应性(可扩展),因此它具有很多优点.


创建S形形状:

使用SVG创建sigmoid曲线形状非常简单,只需要一个路径元素:

  • M0,750 将假想笔移动到靠近SVG元素的左下角(坐标设置略低于SVG的高度,以便在底部有一个可以看到阴影的间隙).
  • L250,750产生从点(0,768)到(250,768)的水平L ine
  • C650,730 500,154 1024,154创建实际曲线.这里前两个坐标是曲线的控制点((650,730),(500,154)),第三个坐标是终点(1024,154).可以通过修改控制点来调整曲线的曲率.
  • L1024,0 0,0 0,750是为了完成形状.形状需要完整才能完成填充.

body {
  margin: 0;
}
svg {
  width: 100%;
  height: 100vh;
}
Run Code Online (Sandbox Code Playgroud)
<svg viewBox='0 0 1024 768' preserveAspectRatio='none'>

  <!-- For the shadow -->
  <defs>
    <filter id="dropShadow">
      <feGaussianBlur in="SourceAlpha" stdDeviation="6" />
      <feOffset dx="3" dy="3" result="offsetBlur" />
      <feFlood flood-color="#AAA" flood-opacity="1" result="offsetColor" />
      <feComposite in="offsetColor" in2="offsetBlur" operator="in" result="offsetBlur" />
      <feMerge>
        <feMergeNode />
        <feMergeNode in="SourceGraphic" />
      </feMerge>
    </filter>
  </defs>
  <!-- End of shadow -->

  <!-- For filling the top-left with pattern -->
  <pattern id='dots' patternUnits='userSpaceOnUse' width='25' height='25'>
    <polygon points='0,0 0,25 25,25 25,0' fill='yellowgreen' />
    <circle cx='12.5' cy='12.5' r='4' fill='rebeccapurple' />
  </pattern>
  <!-- End of pattern -->

  <!-- Actual sigmoid curve -->
  <path d='M0,750 L250,750 C650,730 500,154 1024,154 L1024,0 0,0 0,750' fill='url(#dots)' filter='url(#dropShadow)' />

</svg>
Run Code Online (Sandbox Code Playgroud)


将图案应用于形状:

在上面的演示中,我使用了polygoncircle元素创建了一个圆点图案,但是在SVG本身内部创建它并不是必须的,我们也可以使用image元素并用图像模式填充形状.

如果要将背景图像(图案)更改为您选择的其他图像,只需xlink:hrefimage标记的属性中指定图像的URL,如下面的代码段所示.根据您的需要和形象,你可能不得不改变heightwidthpatternimage.

<pattern id='dots' patternUnits='userSpaceOnUse' width='25' height='25'>
  <image xlink:href='https://yourwebsite.com/yourpath' x='0' y='0' width='15' height='15' />
</pattern>
Run Code Online (Sandbox Code Playgroud)

body {
  margin: 0;
}
svg {
  width: 100%;
  height: 100vh;
}
Run Code Online (Sandbox Code Playgroud)
<svg viewBox='0 0 1024 768' preserveAspectRatio='none'>
  <defs>
    <filter id="dropShadow">
      <feGaussianBlur in="SourceAlpha" stdDeviation="6" />
      <feOffset dx="3" dy="3" result="offsetBlur" />
      <feFlood flood-color="#AAA" flood-opacity="1" result="offsetColor" />
      <feComposite in="offsetColor" in2="offsetBlur" operator="in" result="offsetBlur" />
      <feMerge>
        <feMergeNode />
        <feMergeNode in="SourceGraphic" />
      </feMerge>
    </filter>
    <pattern id='dots' patternUnits='userSpaceOnUse' width='36.6' height='46'>
      <image xlink:href='http://famok.com/wp-content/uploads/2016/10/WhiteOnWhite.jpg' x='0' y='0' width='36.6' height='46' />
    </pattern>
  </defs>
  <path d='M0,750 L250,750 C650,730 500,154 1024,154 L1024,0 0,0 0,750' fill='url(#dots)' filter='url(#dropShadow)' />
</svg>
Run Code Online (Sandbox Code Playgroud)

注意:上面演示中使用的图像不是我自己的.它取自互联网.


影子:

阴影效果是通过使用SVG创建的filter元件具有沿feGaussianBlur,feOffsetfeMerge元件.所述feGaussianBlur元件由指定的标准偏差值和所述模糊了源图形(我们的乙状结肠)feOffset通过偏移所产生的图像dx,dy的值.原始图像和模糊的图像是合并使用feMerge.在feFloodfeComposite添加,以防万一你想给的阴影不同的颜色.可以使用flood-colorflood-opacity属性指定颜色.(改变SVG阴影颜色的方法取自Joe W.的答案)


添加文字:

现在这是整个事情中非常棘手的一点.如果您只需要将文本放在页面的纯色区域,那么您需要仔细使用定位属性.如果文本很小或只是一行文本,那么我们可以使用SVG text元素本身,就像我之前链接的演示一样.如果不是那么你必须确保文本的容器盒不与sigmoid形状的区域重叠.

body {
  margin: 0;
}
div.container {
  position: relative;
  width: 100%;
  height: 100vh;
}
svg {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
}
.container div {
  position: absolute;
  top: 50%;
  right: 0px;
  height: 30vh;
  width: 33.33%;
  font-size: 20px;
}
Run Code Online (Sandbox Code Playgroud)
<div class='container'>
  <svg viewBox='0 0 1024 768' preserveAspectRatio='none'>

    <defs>
      <!-- For the shadow -->
      <filter id="dropShadow">
        <feGaussianBlur in="SourceAlpha" stdDeviation="6" />
        <feOffset dx="3" dy="3" result="offsetBlur" />
        <feFlood flood-color="#AAA" flood-opacity="1" result="offsetColor" />
        <feComposite in="offsetColor" in2="offsetBlur" operator="in" result="offsetBlur" />
        <feMerge>
          <feMergeNode />
          <feMergeNode in="SourceGraphic" />
        </feMerge>
      </filter>
      <!-- End of shadow -->

      <!-- For filling the top-left with pattern -->
      <pattern id='dots' patternUnits='userSpaceOnUse' width='25' height='25'>
        <polygon points='0,0 0,25 25,25 25,0' fill='yellowgreen' />
        <circle cx='12.5' cy='12.5' r='4' fill='rebeccapurple' />
      </pattern>
      <!-- End of pattern -->
    </defs>

    <!-- Actual sigmoid curve -->
    <path d='M0,750 L250,750 C650,730 500,154 1024,154 L1024,0 0,0 0,750' fill='url(#dots)' filter='url(#dropShadow)' />

  </svg>
  <div>Hello! Here is some text that is placed on the solid colored area of the page.</div>
</div>
Run Code Online (Sandbox Code Playgroud)

我们可以尝试使用CSS shape-outside属性,但目前浏览器对此的支持非常差.这是使用此属性的演示shape-outside.无法在现场托管,因为它需要创建单独的SVG文件.该演示是W3C CSS Shapes Spec中提供的版本的改编版本.


替代方法:(将模式应用于容器而不是SVG)

由于您不希望图像被压扁或拉伸,因此另一种方法是执行以下操作:

  • 创建SVG形状,使其仅为纯色部分(而不是图案区域)
  • 将图案应用于div.container,然后将SVG绝对放在元素的顶部.SVG形状(具有白色填充)将防止图案在另一侧可见.
  • 将SVG上的阴影从正常阴影更改为插入阴影.(Inset Shadow的代码完全取自此处.

body {
  margin: 0;
}
div.container {
  position: relative;
  background: white url(http://famok.com/wp-content/uploads/2016/10/WhiteOnWhite.jpg) top left / 26px 32px repeat;
  width: 100%;
  height: 100vh;
}
svg {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
}
.container div {
  position: absolute;
  top: 50%;
  right: 0px;
  height: 30vh;
  width: 33.33%;
  font-size: 20px;
}
Run Code Online (Sandbox Code Playgroud)
<div class='container'>
  <svg viewBox='0 0 1024 768' preserveAspectRatio='none'>
    <defs>
      <filter id="dropShadow" x="-50%" y="-50%" width="200%" height="200%">
        <feComponentTransfer in=SourceAlpha>
          <feFuncA type="table" tableValues="1 0" />
        </feComponentTransfer>
        <feGaussianBlur stdDeviation="6" />
        <feOffset dx="2" dy="2" result="offsetblur" />
        <feFlood flood-color="#AAA" result="color" />
        <feComposite in2="offsetblur" operator="in" />
        <feComposite in2="SourceAlpha" operator="in" />
        <feMerge>
          <feMergeNode in="SourceGraphic" />
          <feMergeNode />
        </feMerge>
      </filter>
    </defs>
    <path d='M0,750 L250,750 C650,730 500,154 1024,154 L1024,768 0,768 0,750' fill='white' filter='url(#dropShadow)' />
  </svg>
  <div>Hello! Here is some text that is placed on the solid colored area of the page.</div>
</div>
Run Code Online (Sandbox Code Playgroud)

这是替代方法的Plunker演示.这比前一个复杂一点,因为在这里我们需要一个SVG来产生纯色区域(用作img)和另一个SVG,它是与之相关的逆(图案区域)shape-outside.