使用CSS3生成重复的六角形图案


79

因此,我需要使用CSS制作重复的六角形图案。如果需要图像,我可以去那里,但如果可能的话,我宁愿只使用CSS。

这是我要创建的内容的想法:

在此处输入图片说明

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


2
有CSS掩码,但是支持很糟糕:webkit.org/blog/181/css-masks
mddw 2012年

对于使用<img>标签而不是背景图像的相同六边形图案,可以使用<img>标签检查六边形网格
web-tiki 2014年

我制作了一个简单的ScottS解决方案版本,以快速拥有不同的尺寸。在此处检查codepen.io/mort3za/pen/wBabaB
Morteza Ziyae 2014年

Answers:


130

(尽管Ana的答案是在我的几个月后提出的,可能以我的作为基础来“思考”,但她能够提出一种使用单个方法的事实div值得推广,因此也请查看她的答案-但是请注意,十六进制中的内容受到限制。)

这是一个真正令人惊讶的问题。感谢您的询问。伟大的事实是:

这个小提琴证明您可以做到!

原始小提琴(在以后的编辑中对小提琴的链接进行了修改)-它使用了imgur.com图像,加载时似乎不太可靠,所以新的小提琴正在使用photobucket.com(让我知道是否存在持久性图片加载问题)。我已经把原来的链接,因为解释下面的代码与(也有在一些区别进入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放置文本,则该句柄将水平放置(当然),但与line-height匹配的则将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;
}

1
感谢您给出这样一个经过充分解释,彻底和天才的答案,这太棒了!
element119

@ScottS我一直在实现它时遇到最奇怪的问题。我使用Twitter的引导工具包,并以某种方式它总是出现像这样。我将问题缩小为div.container:当六边形位于此容器div中时,布局变得混乱。不过,很奇怪的是,看一下每个场景之间的比较:linklink。我进行了一些测试,但我不知道是什么弄乱了六角形!
element119

@Archio-首先,显示十六进制行的第一级子代的代码,但是第二级子代可能会生成十六进制的“翅膀”,这可能是问题所在,因为这是图像丢失的一部分(因此我无法调试)。问题可能在那里(overflow: hidden您会做的事情确实如此),但事实并非如此。再看第二个级别嵌套div及其:before代码,因为很可能要么div没有在变换旋转,或者background-image没有继承到双方div和它的:beforepseudoelement。
ScottS 2012年

我刚刚检查了一下-它们似乎都继承了背景色(link)。它们也在旋转,我可以看到它们在Chrome Web检查器中处于旋转状态。问题在于,即使它们显示了,它们也没有显示display:block
element119

啊,我想我找到了!看起来是问题所在z-index。我现在对其进行调整,以确保一切正常。
element119 2012年

53

实际上,可以使用每个六边形一个元素和用于背景图像和文本的伪元素来完成此操作。

演示

基本的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); 
}

5
这确实值得更多的投票!如此简洁明了,该演示确实展示了其多功能性。唯一的缺点可能是内容存储在属性中,而不是元素本身。
Thomas W

您可以将内容放在子元素中:)我只想在这里减少HTML元素的数量。但是具有实际内容的子元素可以轻松地使用,而不是伪元素。
2013年

2
你说得对,基本上只需要更换.content:after.hexagon > *。巧妙。
Thomas W

关于如何优雅地更改六边形之间的边距的任何想法?
maxheld

奇怪的是,根据这个问题
将使

2

我将提供有关如何创建六边形形状的简单演示。

.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>



1

您可以仅使用CSS创建完全响应的六角形网格。这个想法是使用CSS2.1overflow: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-sensitive-portfolio-template


0

如果您能够实现div形状技巧,则只需为每个div分配一个即可position:relative(您首先必须首先将它们全部定位,也需要设置topleft


您可以在JSFiddle中举个例子吗?如果我需要用图像和文本填充六边形,div形状技巧将无法真正起作用。
element119

1
是的,您将只能创建单色形状:jsfiddle.net/Exceeder/cVqtW不能使用该div作为背景图像或文本形状的剪切区域。
亚历克斯·帕卡

-2

AFAIK,在纯CSS中无法实现。最好的选择是对背景使用蒙版剪切,如下所示: http //www.cssbakery.com/2009/06/background-image.html(这仅在您的页面背景为纯色或适合时才适用)并放置遮罩以匹配页面背景。

然后,您可以使用csstextwrap使其适合文本:http : //www.csstextwrap.com/examples.php

关于SO有很多类似的问题。例如,有什么办法让div中的文本填充三角形?


Alex,只是想让您知道在纯CSS3中有一种方法(请参阅我的回答)。
ScottS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.