【问题标题】:Generate repeating hexagonal pattern with CSS3使用 CSS3 生成重复的六边形图案
【发布时间】:2012-04-21 05:12:12
【问题描述】:

所以,我需要使用 CSS 制作一个重复的六边形图案。如果需要图片,我可以去那里,但如果可能的话,我宁愿只使用 CSS。

这是我要创建的想法:

基本上,我只需要一种方法来创建六边形,然后在它们上面叠加文本/图像。我还没有太多代码,因为我不确定从哪里开始。问题是,我可以只使用六边形的<div>s,如 (http://css-tricks.com/examples/ShapesOfCSS/) 所示,但它们不会连接。我可以使用重复的六边形图案,但是我无法指定特定形状中所需的文本或图像的确切位置。感谢您提前提供任何帮助。

【问题讨论】:

标签: html css css-shapes


【解决方案1】:

(虽然安娜的回答比我晚了几个月,可能以我的作为“思考”的基础,但她能够使用单个div 提出一种方法这一事实值得推广,所以@987654321 @--但请注意,十六进制中的内容更有限。)

这真是一个了不起的问题。谢谢你问。最棒的是:

This Fiddle Proves You Can Do It!

Original Fiddle Used(在稍后的编辑中修改为上面的小提琴链接)——它使用了 imgur.com 图像,这些图像在加载时似乎不是很可靠,所以新的小提琴正在使用 photobucket.com(let我知道是否存在持续的图像加载问题)。我保留了原始链接,因为下面的解释代码与此相关(background-sizeposition 与新小提琴有一些差异)。

阅读您的问题后,我几乎立即想到了这个想法,但需要一些时间来实施。我最初尝试使用单个 div 和仅伪元素获取单个“十六进制”,但据我所知,没有办法只旋转 background-image(我需要),所以我不得不添加一些额外的div 元素来获取十六进制的右侧/左侧,这样我就可以使用伪元素作为background-image 旋转的手段。

我在 IE9、FF 和 Chrome 中进行了测试。理论上任何支持 CSS3 transform 的浏览器都应该在其中工作。

第一次主要更新(添加说明)

我现在有时间发布一些代码解释,所以这里是:

首先,六边形是由 30/60 度关系和三角函数定义的,因此这些将是涉及的关键角度。其次,我们从十六进制网格所在的“行”开始。HTML 定义为(额外的div 元素有助于构建十六进制):

<div class="hexrow">
    <div>
        <span>First Hex Text</span>
        <div></div>
        <div></div>
    </div>
    <div>
        <span>Second Hex Text</span>
        <div></div>
        <div></div>
    </div>
    <div>
        <span>Third Hex Text</span>
        <div></div>
        <div></div>
    </div>
</div>

我们将使用inline-block 表示六边形display,但我们不希望它们意外换行并破坏网格,因此white-space: nowrap 解决了这个问题。此行上的margin 将取决于您想要的十六进制之间的空间,并且可能需要进行一些实验才能得到您想要的。

.hexrow {
    white-space: nowrap;
    /*right/left margin set at (( width of child div x sin(30) ) / 2) 
    makes a fairly tight fit; 
    a 3px bottom seems to match*/
    margin: 0 25px 3px;
}

使用.hexrow 的直接子元素,它们只是div 元素,我们形成了十六进制形状的基础。 width 将驱动六边形顶部的水平方向,height 来自该数字,因为在正六边形上所有边的长度都相等。同样,边距将取决于间距,但这是各个六边形的“重叠”将发生的地方,以使网格看起来出现。 background-image 定义一次,就在这里。左移是为了至少容纳十六进制左侧的附加宽度。假设您想要居中文本,text-align 处理水平(当然),但匹配 heightline-height 将允许垂直居中。

.hexrow > div {
    width: 100px;
    height: 173.2px; /* ( width x cos(30) ) x 2 */
    /* For margin:
    right/left = ( width x sin(30) ) makes no overlap
    right/left = (( width x sin(30) ) / 2) leaves a narrow separation
    */
    margin: 0 25px;
    position: relative;
    background-image: url(http://i.imgur.com/w5tV4.jpg);
    background-position: -50px 0; /* -left position -1 x width x sin(30) */
    background-repeat: no-repeat;
    color: #ffffff;
    text-align: center;
    line-height: 173.2px; /*equals height*/
    display: inline-block;
}

每个奇数 十六进制数我们将相对于“行”向下移动,每个偶数 向上移动。移位计算(width x cos(30) / 2)也和(height / 4)一样。

.hexrow > div:nth-child(odd) {
    top: 43.3px; /* ( width x cos(30) / 2 ) */
}

.hexrow > div:nth-child(even) {
    top: -44.8px; /* -1 x( ( width x cos(30) / 2) + (hexrow bottom margin / 2)) */
}

我们正在使用 2 个子 div 元素来创建十六进制的“翅膀”。它们的大小与主六角矩形相同,然后旋转并推到主六角“下方”。 Background-image 被继承,因此图像是相同的(当然),因为“翅膀”中的图像将与主矩形中的图像“对齐”。伪元素用于生成图像,因为它们需要“重新旋转”回水平(因为我们旋转了它们的父级 div 以创建“翅膀”)。

第一个的:before 会将其背景转换为负数的宽度,等于十六进制的主要部分加上主十六进制的原始背景偏移。第二个的:before 会改变平移的原点,并且会在x 轴上移动主宽度,在y 轴上移动一半高度。

.hexrow > div > div:first-of-type {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: -1;
    overflow: hidden;
    background-image: inherit;

    -ms-transform:rotate(60deg); /* IE 9 */
    -moz-transform:rotate(60deg); /* Firefox */
    -webkit-transform:rotate(60deg); /* Safari and Chrome */
    -o-transform:rotate(60deg); /* Opera */
    transform:rotate(60deg);
}

.hexrow > div > div:first-of-type:before {
    content: '';
    position: absolute;
    width: 200px; /* width of main + margin sizing */
    height: 100%;
    background-image: inherit;
    background-position: top left;
    background-repeat: no-repeat;
    bottom: 0;
    left: 0;
    z-index: 1;

    -ms-transform:rotate(-60deg) translate(-150px, 0); /* IE 9 */
    -moz-transform:rotate(-60deg) translate(-150px, 0); /* Firefox */
    -webkit-transform:rotate(-60deg) translate(-150px, 0); /* Safari and Chrome */
    -o-transform:rotate(-60deg) translate(-150px, 0); /* Opera */
    transform:rotate(-60deg) translate(-150px, 0);

    -ms-transform-origin: 0 0; /* IE 9 */
    -webkit-transform-origin: 0 0; /* Safari and Chrome */
    -moz-transform-origin: 0 0; /* Firefox */
    -o-transform-origin: 0 0; /* Opera */
    transform-origin: 0 0;
}

.hexrow > div > div:last-of-type {
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: -2;
    overflow: hidden;
    background-image: inherit;

    -ms-transform:rotate(-60deg); /* IE 9 */
    -moz-transform:rotate(-60deg); /* Firefox */
    -webkit-transform:rotate(-60deg); /* Safari and Chrome */
    -o-transform:rotate(-60deg); /* Opera */
    transform:rotate(-60deg);
}

.hexrow > div > div:last-of-type:before {
    content: '';
    position: absolute;
    width: 200px; /* starting width + margin sizing */
    height: 100%;
    background-image: inherit;
    background-position: top left;
    background-repeat: no-repeat;
    bottom: 0;
    left: 0;
    z-index: 1;

    /*translate properties are initial width (100px) and half height (173.2 / 2 = 86.6) */
    -ms-transform:rotate(60deg) translate(100px, 86.6px); /* IE 9 */
    -moz-transform:rotate(60deg) translate(100px, 86.6px); /* Firefox */
    -webkit-transform:rotate(60deg) translate(100px, 86.6px); /* Safari and Chrome */
    -o-transform:rotate(60deg) translate(100px, 86.6px); /* Opera */
    transform:rotate(60deg) translate(100px, 86.6px);

    -ms-transform-origin: 100% 0; /* IE 9 */
    -webkit-transform-origin: 100% 0; /* Safari and Chrome */
    -moz-transform-origin: 100% 0; /* Firefox */
    -o-transform-origin: 100% 0; /* Opera */
    transform-origin: 100% 0;
}

这个span 包含您的文本。 line-height 被重置以使文本行正常,但 vertical-align: middle 有效,因为 line-height 在父级上更大。 white-space 被重置,因此它允许再次包装。可以将左右边距设置为负数,以允许文本进入十六进制的“翅膀”。

.hexrow > div > span {
    display: inline-block;
    margin: 0 -30px;
    line-height: 1.1;
    vertical-align: middle;
    white-space: normal;
}

您可以单独定位行和这些行中的单元格以更改图像,或span 文本设置,或不透明度,或容纳更大的图像(将其移动到您想要的位置)等。这就是以下内容为第二行做。

.hexrow:nth-child(2) > div:nth-child(1) {
    background-image: url(http://i.imgur.com/7Un8Y.jpg);
}

.hexrow:nth-child(2) > div:nth-child(1) > span {
    /*change some other settings*/
    margin: 0 -20px;
    color: black;
    font-size: .8em;
    font-weight: bold;
}

.hexrow:nth-child(2) > div:nth-child(2) {
    background-image: url(http://i.imgur.com/jeSPg.jpg);
}

.hexrow:nth-child(2) > div:nth-child(3) {
    background-image: url(http://i.imgur.com/Jwmxm.jpg);
    /*you can shift a large background image, but it can get complicated
    best to keep the image as the total width (200px) and height (174px)
    that the hex would be.
    */
    background-position: -150px -120px;
    opacity: .3;
    color: black;
}

.hexrow:nth-child(2) > div:nth-child(3) > div:before {
    /*you can shift a large background image, but it can get complicated
    best to keep the image as the total width (200px) and height (174px)
    that the hex would be.
    */
    background-position: -100px -120px; /* the left shift is always less in the pseudo elements by the amount of the base shift */
}

.hexrow:nth-child(2) > div:nth-child(4) {
    background-image: url(http://i.imgur.com/90EkV.jpg);
    background-position: -350px -120px;
}

.hexrow:nth-child(2) > div:nth-child(4) > div:before {
    background-position: -300px -120px;
}

【讨论】:

  • 感谢您提供了如此详尽、透彻和天才的答案,太棒了!
  • @ScottS 我在实现它时遇到了最奇怪的问题。我正在使用 Twitter 的 Bootstrap 工具包,不知何故它总是看起来像 this。我已将问题缩减为div.container:当六边形位于此容器 div 中时,布局变得混乱。奇怪的是,看看每个场景之间的比较:linklink。我进行了一些测试,但我无法弄清楚是什么弄乱了六边形!
  • @Archio--首先,您显示了十六进制行的第一级子代的代码,但问题可能出在生成十六进制“翅膀”的第二级子代上是缺少图像的一部分(所以我无法调试)。问题可能已经存在(overflow: hidden 会按照您的说明进行操作),但似乎并非如此。查看第二级嵌套div 及其:before 代码,因为div 可能没有在变换中旋转,或者background-image 没有继承到@ 的both 987654373@ 及其:before 伪元素。
  • 我刚刚检查过——它们似乎都继承了背景颜色 (link)。它们也在旋转,我可以看到它们在 Chrome Web 检查器中旋转。问题是他们只是没有显示,即使他们有display:block
  • 啊,我想我找到了!看起来问题是z-index。我现在正在调整它以确保一切正常。
【解决方案2】:

实际上,每个六边形只需要一个元素,背景图像和文本使用伪元素即可。

demo

基本HTML结构:

<div class='row'>
    <div class='hexagon'></div>
</div>
<div class='row'>
    <div class='hexagon content ribbon' data-content='This is a test!!! 
    9/10'></div><!--
    --><div class='hexagon content longtext' data-content='Some longer text here.
       Bla bla bla bla bla bla bla bla bla bla blaaaah...'></div>
</div>

你可以有更多的行,你只需要在奇数行有n六边形,在偶数行有n+/-1六边形。

相关CSS

* { box-sizing: border-box; margin: 0; padding: 0; }
.row { margin: -18.5% 0; text-align: center; }
.row:first-child { margin-top: 7%; }
.hexagon {
    position: relative;
    display: inline-block;
    overflow: hidden;
    margin: 0 8.5%;
    padding: 16%;
    transform: rotate(30deg) skewY(30deg) scaleX(.866); /* .866 = sqrt(3)/2 */
}
.hexagon:before, .content:after {
    display: block;
    position: absolute;
    /* 86.6% = (sqrt(3)/2)*100% = .866*100% */
    top: 6.7%; right: 0; bottom: 6.7%; left: 0; /* 6.7% = (100% -86.6%)/2 */
    transform: scaleX(1.155) /* 1.155 = 2/sqrt(3) */ 
               skewY(-30deg) rotate(-30deg);
    background-color: rgba(30,144,255,.56);
    background-size: cover;
    content: '';
}
.content:after { content: attr(data-content); }
/* add background images to :before pseudo-elements */
.row:nth-child(n) .hexagon:nth-child(m):before {
    background-image: 
        url(background-image-mxn.jpg); 
}

【讨论】:

  • 这真的值得更多的支持!如此简洁,演示真正展示了多功能性。唯一的缺点可能是内容存储在属性中,而不是元素本身。
  • 您可以将内容放在子元素中:) 我只想尽量减少此处需要的 HTML 元素的数量。但是可以很容易地使用具有实际内容的子元素来代替伪元素。
  • 你说得对,基本上只需要将.content:after替换成.hexagon &gt; *即可。巧妙。
  • 对如何优雅地改变六边形之间的边距有什么想法吗?
  • 奇怪的是,如果扩展到一大堆六边形,这在 safari 上会出现故障,根据 this question
【解决方案3】:

您可以仅使用 CSS 创建一个完全响应的六边形网格。 这个想法是使用 CSS2.1 overflow:hidden 创建一个父形状作为掩码,它与几乎所有浏览器兼容,甚至 Internet Explorer 6。

这是一种非常简单的技术,可用于创建各种形状的响应式网格,只需跳出框框思考即可解决问题。

我在此处提供了有关如何执行此技术的详细分步指南: https://www.codesmite.com/article/how-to-create-pure-css-hexagonal-grids

这是迄今为止我发现的最好的方法,不需要 javascript,并且既流畅又响应迅速。

我还在一个免费的 HTML 模板中使用了该技术,该模板包含六边形内的图像,您可以在此处演示和下载:https://www.codesmite.com/freebie/hexa-free-responsive-portfolio-template

【讨论】:

    【解决方案4】:

    我将提供一个如何创建六边形的简单演示。

    .hex {
      width: 40px;
      height: 70px;
      margin: 20px;
      overflow: hidden;
    }
    
    .hex:before {
      content: "";
      transform: rotate(45deg);
      background: #f00;
      width: 50px;
      height: 50px;
      display: inline-block;
      margin: 10px -5px 10px -5px;
    }
    <div class="hex">
    </div>

    【讨论】:

      【解决方案5】:

      这是另一种使用 COMPASS/SCSS 的方法,可以轻松设置六边形的大小和布局:

      http://codepen.io/interdruper/pen/GrBEk

      【讨论】:

        【解决方案6】:

        如果你能够实现 div 形状技巧,那么只需给每个 div 一个 position:relative(你必须首先将它们一个一个地定位,同时设置 topleft

        【讨论】:

        • 你能举个 JSFiddle 的例子吗?如果我需要用图像和文本填充六边形,那么 div 形状技巧并没有真正起作用。
        • 是的,您将只能创建单色形状:jsfiddle.net/Exceeder/cVqtW 无法将此 div 用作背景图像的剪切区域或塑造文本。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-17
        • 2015-09-23
        • 2012-07-29
        • 2016-07-28
        • 1970-01-01
        相关资源
        最近更新 更多