复杂的平行四边形按钮形状

时间:2015-11-28 00:02:42

标签: css css3 svg css-shapes

我想知道是否可以在CSS3中执行这样的复杂按钮?我不知道从哪里开始。我可以很容易地做类似梯形的形状,但是添加边框似乎是不可能的。我错过了什么吗?

(PS:图片是Deus Ex Human Revolution)

enter image description here

1 个答案:

答案 0 :(得分:5)

正如您自己指出的那样,生成相关的形状非常简单,下面是如何实现它的示例片段。基本思想是使用伪元素,向其添加background然后将其倾斜。父项上的overflow: hidden会切掉不需要的形状部分,从而最终形成形状。



ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  list-style-position: inside;
}
li {
  position: relative;
  height: 40px;
  width: 300px;
  margin: 10px;
  padding-right: 30px;
  line-height: 40px;
  text-align: right;
  text-transform: uppercase;
  border-radius: 8px;
  color: crimson;
  overflow: hidden;
}
li:after {
  position: absolute;
  content: '';
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  background: rgba(0, 0, 0, 0.5);
  transform: skew(45deg);
  z-index: -1;
}

/* just for demo */

body {
  background: url(http://lorempixel.com/800/500/abstract/2);
}
*, *:after, *:before {
  box-sizing: border-box;
}

<ul>
  <li>Menu Text 1</li>
  <li>Menu Text 2</li>
  <li>Menu Text 3</li>
</ul>
&#13;
&#13;
&#13;

但是,为使用此方法创建的形状添加边框非常困难,并且在形状与其边框之间需要透明区域的事实使得它几乎不可能。

我们可以在下面的代码段中使用clip-path,这样就可以使用伪元素添加边框,但这种方法有以下缺点:

  • Firefox和IE(所有版本)不支持clip-path的纯CSS版本。
  • 即使只有Chrome和Firefox支持基于内嵌SVG的clip-path
  • 虽然可以修改clip-path以在背景和边框之间产生透明区域,但这会使其变得极其复杂并且几乎无法维护。
  • 指定透明或半透明的背景颜色会导致问题,因为后面还有另一个元素,因此颜色会像下面的代码段一样混合。

&#13;
&#13;
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  list-style-position: inside;
}
li {
  position: relative;
  height: 40px;
  width: 300px;
  margin: 10px;
  padding-right: 30px;
  line-height: 40px;
  text-align: right;
  text-transform: uppercase;
  border-radius: 8px;
  background: crimson;
  color: crimson;
  -webkit-clip-path: polygon(0% 0%, 0% 50%, 10% 100%, 100% 100%, 100% 50%, 90% 0%);
  clip-path: polygon(0% 0%, 0% 50%, 10% 100%, 100% 100%, 100% 50%, 90% 0%);
}
li:after {
  position: absolute;
  content: '';
  height: calc(100% - 4px);
  width: calc(100% - 4px);
  left: 2px;
  top: 2px;
  border-radius: 7px;
  background: rgba(0, 0, 0, 0.5);
  -webkit-clip-path: polygon(0% 0%, 0% calc(50% - 1px), 10% 100%, 100% 100%, 100% calc(50% + 1px), 90% 0%);
  clip-path: polygon(0% 0%, 0% calc(50% - 1px), 10% 100%, 100% 100%, 100% calc(50% + 1px), 90% 0%);
  z-index: -1;
}

/* just for demo */

body {
  background: url(http://lorempixel.com/800/500/abstract/2);
}
*, *:after, *:before {
  box-sizing: border-box;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<ul>
  <li>Menu Text 1</li>
  <li>Menu Text 2</li>
  <li>Menu Text 3</li>
</ul>
&#13;
&#13;
&#13;

考虑到上述所有情况,我建议你使用SVG 来制作如此复杂的形状。使用SVG,我们可以使用path元素创建边框和形状的填充。

&#13;
&#13;
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  list-style-position: inside;
}
li {
  position: relative;
  height: 40px;
  width: 300px;
  margin: 10px;
  padding-right: 30px;
  line-height: 40px;
  text-align: right;
  text-transform: uppercase;
  border-radius: 8px;
  color: crimson;
}
li.active {
  width: 350px;
  height: 50px;
  line-height: 50px;
}
svg #fill {
  fill: rgba(0, 0, 0, 0.5);
}
svg #border {
  stroke: crimson;
  stroke-width: 2;
  fill: transparent;
}
li svg {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
  z-index: -1;
}

/* just for demo */

body {
  background: url(http://lorempixel.com/800/500/abstract/2);
}
*, *:after, *:before {
  box-sizing: border-box;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<svg viewBox='0 0 300 40' height='0' width='0'>
  <defs>
    <g id='shape'>
      <path d='M8,0 A8,8 0 0,0 0,8 L0,20 30,40 292,40 A8,8 0 0,0 300,32 L300,20 270,0z' id='fill' />
    </g>
    <g id='shape-bordered'>
      <path d='M9,1 A8,8 0 0,0 1,9 L1,20 30,39 292,39 A8,8 0 0,0 299,32 L299,20 270,1z' id='border' />
      <path d='M10,4 A7,7 0 0,0 4,6 L4,19 31,36 290,36 A5,5 0 0,0 296,34 L296,21 269,4z' id='fill' />
    </g>
  </defs>
</svg>
<ul>
  <li class='active'>
    <svg viewBox='0 0 300 40' preserveAspectRatio='none'>
      <use xlink:href='#shape-bordered' />
    </svg>Menu Text 1</li>
  <li>
    <svg viewBox='0 0 300 40' preserveAspectRatio='none' vector-effect='non-scaling-stroke'>
      <use xlink:href='#shape' />
    </svg>Menu Text 2</li>
  <li>
    <svg viewBox='0 0 300 40' preserveAspectRatio='none'>
      <use xlink:href='#shape' />
    </svg>Menu Text 3</li>
</ul>
&#13;
&#13;
&#13;

(SVG可能会进一步调整。上面的代码片段只是一个示例,用于说明可以实现的目标。)