【问题标题】:How do I create a cut-out hexagon shape?如何创建切出的六边形?
【发布时间】:2016-03-28 19:39:44
【问题描述】:

如何使用 CSS 创建切出的六边形?

我所说的六边形切割是这样的:

我能够创建一个带有背景图像的六边形,但我需要它与图像中的一样。

.hexagon {
  position: relative;
  width: 300px;
  height: 173.21px;
  margin: 86.60px 0;
  background-image: url('https://placeimg.com/300/400/any');
  background-size: auto 346.4102px;
  background-position: center;
}

.hexTop,
.hexBottom {
  position: absolute;
  z-index: 1;
  width: 212.13px;
  height: 212.13px;
  overflow: hidden;
  -webkit-transform: scaleY(0.5774) rotate(-45deg);
  -ms-transform: scaleY(0.5774) rotate(-45deg);
  transform: scaleY(0.5774) rotate(-45deg);
  background: inherit;
  left: 43.93px;
}

/* Counter transform the background image on the caps */
.hexTop:after,
.hexBottom:after {
  content: "";
  position: absolute;
  width: 300.0000px;
  height: 173.20508075688775px;
  -webkit-transform:  rotate(45deg) scaleY(1.7321) translateY(-86.6025px);
  -ms-transform:      rotate(45deg) scaleY(1.7321) translateY(-86.6025px);
  transform:          rotate(45deg) scaleY(1.7321) translateY(-86.6025px);
  -webkit-transform-origin: 0 0;
  -ms-transform-origin: 0 0;
  transform-origin: 0 0;
  background: inherit;
}

.hexTop {
  top: -106.0660px;
}

.hexTop:after {
  background-position: center top;
}

.hexBottom {
  bottom: -106.0660px;
}

.hexBottom:after {
  background-position: center bottom;
}

.hexagon:after {
  content: "";
  position: absolute;
  top: 0.0000px;
  left: 0;
  width: 300.0000px;
  height: 173.2051px;
  z-index: 2;
  background: inherit;
}
<div class="hexagon">
  <div class="hexTop"></div>
  <div class="hexBottom"></div>
</div>

【问题讨论】:

  • 或者只使用 SVG 甚至是 PNG..方式更简单。除非绝对有必要,否则真的没有压倒一切的理由在这里使用 CSS。
  • 这是@Paulie_D 没想到的好方法
  • 完全同意保利的观点。 SVG 如果经常被遗忘,不管它是否有出色的浏览器支持。 SVG 应该是任何人的网络开发工具库中众所周知的资产。

标签: html css svg css-shapes


【解决方案1】:

对于这个透明切割六边形,我建议使用inline SVGpath element

svg{
  display: block;
  width: 70%;
  height: auto;
  margin: 0 auto;
}

path{
  transition: fill .5s;
  fill: #E3DFD2;
}
path:hover{
  fill: pink;
}
body{background:url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-position:center;background-size:cover;}
<svg viewbox="-10 -2 30 14">
  <path d=" M-10 -2 H30 V14 H-10z M2.5 0.66 L0 5 2.5 9.33 7.5 9.33 10 5 7.5 0.66z" />
</svg>

六边形蒙版点计算:

六边形坐标很容易计算。对于上述方向的正六边形:

width = height / sin(60deg)
sin(60deg) ~=0.866

如果宽度为 10(如上例),则坐标为:

您可以在第二个M 之后的d 属性中找到这些坐标。

为什么使用 SVG?

在这种情况下使用 SVG 的主要优点是:

  • 可维护性(例如:假设您需要更改遮罩的颜色。在 SVG 中,您需要更改的内容很清楚,并且只有一个属性需要更改。)
  • 更短的代码
  • 您可以轻松地使用图像或渐变来填充蒙版
  • 保持形状的边界并仅在与蒙版相关的填充上触发鼠标事件(在示例中悬停透明六边形)。

mask element 的原始示例:

body{background:url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-position:center;background-size:cover;}

svg{
  display: block;
  width: 70%;
  height: auto;
  margin: 0 auto;
}
<svg viewbox="-10 -2 30 14" >
  <defs>
    <mask id="mask" x="0" y="0" width="10" height="10">
      <rect x="-10" y="-2" width="40" height="16" fill="#fff"/>
      <polygon points="2.5 0.66 7.5 0.66 10 5 7.5 9.33 2.5 9.33 0 5" />
    </mask>
  </defs>
  <rect x="-10" y="-5" width="30" height="20" mask="url(#mask)" fill="#E3DFD2"/>
</svg>

【讨论】:

  • 这真是太好了:)
  • @web-tiki - 你能分享一个链接,这些(坐标)点和 svg 是如何工作的。有没有什么工具可以直接创建六边形,或者全部计算
  • @DeepakYadav 我在答案中添加了坐标计算的更多解释。
  • @DeepakYadav:这些是 SVG 命令。 M是“将笔移到”,L是“在提到的点之间画线”,H是水平线,V是垂直线,z是关闭路径(即画一条连接起点和终点的线)。您可以在this MDN article 中找到有关这些命令的更多信息。
  • 谁会猜到 web-tiki 会回答六边形的问题?这是他的强项
【解决方案2】:

这种形状可以通过使用元素填充六边形的外部来实现。应该对每个元素应用不同的transform:rotate(xdeg) 才能达到这种效果。

这是一个创建此效果的 sn-p。

注意:下面的 sn-p 应该是响应式的,所以如果它看起来坏了,请看下面的。

* {
    margin: 0;
    padding: 0;
}

body, html {
    width: 100%;
    height: 100%;
}

body {
    display: flex;
    align-items: center;
    background: url('https://placeimg.com/800/600/any');
    background-size: cover;
    background-attachment: fixed;
}

.container {
    width: 50%;
    height: 50%;
    position: relative;
    margin: 0 auto;
    overflow: hidden;
    border: 10px solid #009688;
}

.cut:after {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    background: #009688;
    transform-origin: 0% 100%;
    transform: rotate(-60deg);
    top: 0;
}

.cut:before {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    background: #009688;
    transform-origin: 0% 0%;
    transform: rotate(60deg);
    top: 0;
}

.container:after {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    background: #009688;
    transform-origin: 100% 0%;
    transform: rotate(-60deg);
    top: 0;
}

.container:before {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    background: #009688;
    transform-origin: 100% 100%;
    transform: rotate(60deg);
    top: 0;
}
<div class="container">
    <div class="cut"></div>
</div>

固定高度和宽度(全屏观看效果更好):

* {
    margin: 0;
    padding: 0;
}

body, html {
    width: 100%;
    height: 100%;
}

body {
    display: flex;
    align-items: center;
    background: url('https://placeimg.com/800/600/any');
    background-size: cover;
    background-attachment: fixed;
}

.container {
    width: 500px;
    height: 300px;
    position: relative;
    margin: 0 auto;
    overflow: hidden;
    border: 10px solid #009688;
}

.cut:after {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    background: #009688;
    transform-origin: 0% 100%;
    transform: rotate(-60deg);
    top: 0;
}

.cut:before {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    background: #009688;
    transform-origin: 0% 0%;
    transform: rotate(60deg);
    top: 0;
}

.container:after {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    background: #009688;
    transform-origin: 100% 0%;
    transform: rotate(-60deg);
    top: 0;
}

.container:before {
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
    background: #009688;
    transform-origin: 100% 100%;
    transform: rotate(60deg);
    top: 0;
}
<div class="container">
    <div class="cut"></div>
</div>

这就是切出的六边形的工作原理:

【讨论】:

    【解决方案3】:

    SVG 是处理此类事情的最佳工具,其最大的贡献因素是它更容易创建和维护 SVG 等形状。

    但这些可以通过 CSS transform 以另一种方式完成,也可以使用更简单的转换。我们需要做的就是利用skew变换并根据需要的形状设置倾斜角度。

    对于六边形,每边之间的角度为 120 度,因此元素必须倾斜 +/- 30 度。对于五边形,每边之间的角度为 108 度,因此下半部分的倾斜角度为 +/- 18 度,但上半部分的倾斜角度为 +/- 36 度。对于钻石,每边之间的角度为 90 度,因此倾斜角度为 +/-45 度。

    这种方法的几个积极点是:(并不是 SVG 没有这些

    • 使用这种方法创建的形状具有响应性(尝试将鼠标悬停在演示中的形状上
    • 鉴于 IE8 即将淘汰(Microsoft 自己从 2016 年 1 月起停止对 IE8 的支持),因此对转换的支持非常好。这与 SVG 相比还不错,因为 SVG 具有相同的浏览器支持。

    虽然使用 CSS 有很多缺点

    • 需要额外的元素才能生成形状。
    • 这些仅适用于 IE9+(即支持转换的浏览器)。缺点不是与 SVG 相比,而是总体而言。
    • 除抠图以外的区域填充不能是渐变或图像。它只能是纯色。
    • 可以添加悬停效果(如演示中所示),但它会在鼠标悬停在剪切区域上时触发,因为它仍然是容器的一部分,即使它是透明的。

    .shape {
      position: relative;
      height: 100px;
      border: 20px solid palevioletred;
      overflow: hidden;
    }
    .shape.hexagon {
      width: calc(100px + (100px * 0.577)); /* width = height + (height * tan 30) for hexagon */
    }
    .shape.pentagon {
      width: calc(100px * 1.051); /* width = height * 1.618/1.539 for pentagon (Source: Wiki - https://en.wikipedia.org/wiki/Pentagon */
    }
    .shape.diamond {
      width: 100px; /* height = width for diamond */
    }
    .hexagon .inner, .pentagon .inner, .diamond .inner {
      position: absolute;
      height: 100%;
      width: 50%;
      top: 0px;
      left: 85%;
    }
    .diamond .inner {
      left: 100%;
    }
    .shape:after, .shape:before {
      position: absolute;
      content: '';
      height: 50%;
      width: 50%;
      left: -35%;
      background: palevioletred;
    }
    .shape.diamond:before, .shape.diamond:after {
      left: -50%;
    }
    .hexagon .inner:after, .hexagon .inner:before, .pentagon .inner:after,
    .pentagon .inner:before, .diamond .inner:after, .diamond .inner:before {
      position: absolute;
      content: '';
      height: 50%;
      width: 100%;
      left: 0px;
      background: palevioletred;
    }
    .shape.hexagon:before, .hexagon .inner:after {
      transform: skew(-30deg);
    }
    .shape.hexagon:after, .hexagon .inner:before {
      transform: skew(30deg);
    }
    .shape.pentagon:before {
      transform: skew(-36deg);
    }
    .shape.pentagon:after{
      transform: skew(18deg);
    }
    .shape.diamond:before, .diamond .inner:after {
      transform: skew(-45deg);
    }
    .shape.diamond:after, .diamond .inner:before {
      transform: skew(45deg);
    }
    .pentagon .inner:before {
      transform: skew(36deg);
    }
    .pentagon .inner:after {
      transform: skew(-18deg);
    }
    .shape:before, .inner:before {
      top: 0px;
      transform-origin: right bottom;
    }
    .shape:after, .inner:after {
      bottom: 0px;
      transform-origin: right top;
    }
    
    /* just for demonstrating responsiveness */
    
    .shape {
      float: left;
      margin: 10px;
      transition: all 1s linear;
    }
    .shape:hover{ height: 150px; }
    .shape.hexagon:hover { width: calc(150px + (150px * 0.577)); }
    .shape.pentagon:hover { width: calc(150px * 1.051); }
    .shape.diamond:hover { width: 150px; }
    body {
      background: url(http://lorempixel.com/500/500/nature/6) fixed;
      background-size: cover;
    }
    <div class='shape hexagon'>
      <div class='inner'></div>
    </div>
    <div class='shape pentagon'>
      <div class='inner'></div>
    </div>
    <div class='shape diamond'>
      <div class='inner'></div>
    </div>

    【讨论】:

    • 在动画期间,上半部分偶尔会与下半部分分开一帧左右。
    • @DanielF:是的,我确实注意到了,但没有给予太多关注,因为添加过渡只是为了证明形状可以自动适应不同的尺寸。这不是答案的主要部分:)我会尝试看看我是否可以做点什么。
    【解决方案4】:

    SVG 方法显然很好!但我尝试通过 CSS 完成它!不知怎的,我设法把它弄到了这里......

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0
    }
    .relative {
      position: relative;
    }
    .absolute {
      position: absolute;
    }
    body {
      background: url('http://lorempicsum.com/up/627/300/4') no-repeat top left;
      background-size: cover;
      padding-top: 10%;
    }
    .parent {
      margin: 0 auto;
      display: table;
      width: 400px;
      height: 230px;
      text-align: center;
      table-layout: fixed;
    }
    .orange {
      display: table-cell;
      vertical-align: middle;
      background: transparent;
      width: 100%;
      height: 230px;
      margin: 0 auto;
      overflow: hidden;
      position: relative;
      border-left: 137px solid orange;
      border-right: 137px solid orange;
    }
    .one,
    .two {
      position: relative;
      width: 126px;
      height: auto;
      display: block;
      border-left: 28px solid orange;
      border-right: 28px solid orange;
      margin: 0 auto;
    }
    .one {
      border-top: 60px solid transparent;
      border-bottom: 60px solid orange;
    }
    .two {
      border-top: 60px solid orange;
      border-bottom: 60px solid transparent;
    }
    <div class="parent">
      <div class="orange">
        <div class="two"></div>
        <div class="one"></div>
      </div>
    </div>

    【讨论】:

    • 是的!我只是想纯粹通过 CSS 来尝试这个东西,
    【解决方案5】:

    这个答案说明了仅使用一个元素的成本

    SVG 是实现此目的的工具。任何 CSS 替代方案都可能非常老套和古怪,所以我说最好是使用 SVG。

    使用 CSS

    使用的属性是:

    • box-shadows(用于透明区域周围的颜色)
    • 透视变换、旋转
    • 溢出隐藏
    • 伪元素

    body {
      background:url('http://i.imgur.com/TYP4Xka.jpg');
    }
    #box {
      height: 400px;
      width: 400px;
      position: relative;
      box-shadow: inset 70px 0 0 #444, inset -70px 0 0 #444, inset 0 0 0 50px #444;
      overflow: hidden;
    }
    
    #box:before {
      content: "";
      position: absolute;
      height: 150px; 
      width: 259.8px; /* w = h * sqrt(3) bcoz w = 2*h*cos(30deg) */
      top: 125px; /* (parentHeight - pseudoHeight)/2 */
      left: 70.1px; /* (parentWidth - pseudoWidth)/2 */
      -webkit-transform: rotate(60deg);
      -moz-transform: rotate(60deg);
      transform: rotate(60deg);
      box-shadow: 70px 0 0 #444, -70px 0 0 #444;
    }
    
    #box:after {
      content: "";
      position: absolute;
      height: 150px; 
      width: 259.8px;
      top: 125px;
      left: 70.1px;
      -webkit-transform: rotate(120deg);
      -moz-transform: rotate(120deg);
      transform: rotate(120deg);
      box-shadow: 70px 0 0 #444, -70px 0 0 #444;
    }
    &lt;div id="box"&gt;&lt;/div&gt;

    注意

    您也可以在动画中改变形状,但请注意。不要在任何东西上使用很多盒子阴影,尤其是动画。 Box-shadow 的 CPU 使用率非常高

    【讨论】:

      猜你喜欢
      • 2019-07-23
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多