使用CSS

时间:2016-10-31 20:56:40

标签: css css3 svg css-shapes rounded-corners

我想为全屏布局创建一个sigmoid curve形状,可以在一侧显示装饰性图案背景,在另一侧显示纯色背景,以便放置文字顶部。

我们的目标是拥有一个全屏页面,其中左侧的S形图案充满了图案,而页面的其余部分则只有白色背景。

JSFiddle:Unfinished sigmoid curve

#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);
}
<div id="container">
  <div id="parallelogram">
  </div>
</div>

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

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

更新:我想出了如何使用CSS完全创建shape I need

#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);
}
<div id="container">
  <div id="parallelogram">
  </div>

  <div id="bottom">
    <div id="bottom-corner">
    </div>
  </div>
</div>

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

#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);
}
<div id="container">
  <div id="parallelogram">
  </div>

  <div id="bottom">
    <div id="bottom-corner">
    </div>
  </div>
</div>

稍后更新:经过一些试验和错误后,我最终获得了ridiculously crude hack solution,以达到我所需的视觉效果:

#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;
}
<div id="container">
  <div id="parallelogram">
  </div>
  <div id="bottom-rounded-corner">

  </div>
  <div id="bottom-white">
  </div>
</div>

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

提前谢谢!

1 个答案:

答案 0 :(得分:11)

将SVG用于复杂形状而非CSS:

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

创建sigmoid形状:

使用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用于完成形状。形状需要完整才能完成工作。

&#13;
&#13;
body {
  margin: 0;
}
svg {
  width: 100%;
  height: 100vh;
}
&#13;
<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>
&#13;
&#13;
&#13;

将图案应用于形状:

在上面的演示中,我使用polygoncircle元素创建了一个圆点花样,但在SVG中不必创建它,我们也可以使用image元素并用图像模式填充形状。

如果您想将背景图片(图案)更改为您选择的其他图片,只需在xlink:href标记的image属性中指定图片的网址,如下面的代码段所示。根据您的需求和图片,您可能需要更改heightwidth的{​​{1}}和pattern

image

&#13;
&#13;
<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>
&#13;
body {
  margin: 0;
}
svg {
  width: 100%;
  height: 100vh;
}
&#13;
&#13;
&#13;

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

暗影:

使用SVG <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>元素以及filterfeGaussianBlurfeOffset元素创建阴影效果。 feGaussianBlur元素按指定的标准偏差值模糊源图形(我们的sigmoid),feOffsetfeMergedx值偏移结果图像。原始图像和模糊图像是使用feMerge合并的。添加feFloodfeComposite以防您想要为阴影提供不同的颜色。可以使用dyflood-color属性指定颜色。 (改变SVG阴影颜色的方法取自Joe W的this answer。)

添加文字

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

&#13;
&#13;
text
&#13;
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;
}
&#13;
&#13;
&#13;

我们现在可以尝试使用CSS <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>属性,但browser support for that is pretty poor。这是使用此shape-outside属性的demo。无法在现场托管,因为它需要创建单独的SVG文件。该演示版是W3C CSS Shapes Spec中提供的版本的改编版本。

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

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

  • 创建SVG形状,使其仅为纯色部分(而非图案区域)
  • 将模式应用于shape-outside,然后将SVG绝对放在元素的顶部。 SVG形状(具有白色填充)将防止图案在另一侧可见。
  • 将SVG上的阴影从正常阴影更改为嵌入阴影。 (Inset Shadow的代码完全取自here

&#13;
&#13;
div.container
&#13;
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;
}
&#13;
&#13;
&#13;

以下是替代方法的Plunker Demo。这比前一个要复杂一点,因为在这里我们需要一个SVG来生成纯色区域(用作<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>)和另一个SVG,它是与{{1一起使用的逆向(图案区域) }}