Html 使用 CSS3 生成重复的六边形图案
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10062887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generate repeating hexagonal pattern with CSS3
提问by element119
So, I need to make a repeating hexagonal pattern, using CSS. If images are needed, I can go there, but I'd prefer to just use CSS if possible.
所以,我需要使用 CSS 制作一个重复的六边形图案。如果需要图像,我可以去那里,但如果可能的话,我更愿意只使用 CSS。
Here's an idea of what I'm trying to create:
这是我正在尝试创建的一个想法:
Basically, I just need a way to create the hexagonal shapes, and then overlay text/images on top of them. I don't have much code yet, because I'm not really sure where to start. The problem is, I could just use <div>
s in the shape of a hexagon like shown in (http://css-tricks.com/examples/ShapesOfCSS/), but then they wouldn't be connecting. I could use a repeating hexagon pattern, but then I wouldn't be able to specify the exact location of the text or images I need in specific shapes. Thanks for any help in advance.
基本上,我只需要一种方法来创建六边形形状,然后在它们上面叠加文本/图像。我还没有太多代码,因为我不确定从哪里开始。问题是,我可以只使用<div>
s 中所示的六边形形状(http://css-tricks.com/examples/ShapesOfCSS/),但这样它们就不会连接了。我可以使用重复的六边形图案,但是我将无法在特定形状中指定我需要的文本或图像的确切位置。提前感谢您的任何帮助。
回答by ScottS
(Though Ana's answer came in months after mine, probably using mine as a base to "think from", the fact that she was able to come up with a method using a single div
is worth promoting, so check out her answer too--but note that content in the hex is more limited.)
(虽然安娜的回答是在我的几个月之后出现的,可能是用我的作为“思考”的基础,但她能够想出一种使用单曲的方法这一事实div
值得推广,所以也请查看她的答案——但是请注意,十六进制中的内容更为有限。)
This was a truly amazing question. Thank you for asking it. The great thing is the fact that:
这真是一个了不起的问题。谢谢你的提问。伟大的事情是这样一个事实:
This Fiddle Proves You Can Do It!
这个小提琴证明你可以做到!
Original Fiddle Used(modified in later edit to fiddle link above)--it utilized imgur.com images, which were not seeming to be very reliable in loading, so the new fiddle is using photobucket.com (let me know if there are persistent image loading issues). I've kept the original link because the explanation code below goes with that (there are a few differences in background-size
or position
to the new fiddle).
使用原始小提琴(在以后的编辑中修改为上面的小提琴链接)--它使用了 imgur.com 图像,这些图像在加载时似乎不太可靠,因此新小提琴使用的是 photobucket.com(如果有持久性,请告诉我图片加载问题)。我保留了原始链接,因为下面的解释代码与之相关(新小提琴background-size
或position
新小提琴有一些差异)。
The idea came to me almost instantly after reading your question, but took some time to implement. I originally tried getting a single "hex" with a single div
and just pseudo elements, but as best I could tell, there was no way to just rotate the background-image
(which I needed), so I had to add some extra div
elements to get the right/left sides of the hex, so that I could then use the pseudo elements as a means of background-image
rotation.
阅读您的问题后,我几乎立即想到了这个想法,但需要一些时间来实施。我最初尝试使用单个div
且只是伪元素获得单个“十六进制” ,但据我所知,无法仅旋转background-image
(我需要的),因此我不得不添加一些额外的div
元素来获得正确的/left 的六角形,这样我就可以使用伪元素作为background-image
旋转的手段。
I tested in IE9, FF, and Chrome. Theoretically any browser supporting CSS3 transform
it should work in.
我在 IE9、FF 和 Chrome 中进行了测试。理论上,任何支持 CSS3 的浏览器transform
都应该可以使用。
First Main Update (added explanation)
第一次主要更新(添加说明)
I have some time now to post some code explanation, so here goes:
我现在有一些时间来发布一些代码解释,所以这里是:
First, hexagons are defined by 30/60 degree relationships and trigonometry, so those will be the key angles involved. Second, we start with a "row" for the hex grid to reside in. The HTML is defined as (the extra div
elements help build the hex):
首先,六边形由 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>
We are going to use inline-block
for the hexagon display
, but we don't want them to accidentally wrap to the next line and ruin the grid, so white-space: nowrap
solves that issue. The margin
on this row is going to depend on how much space you want between hex's, and some experimentation may be needed to get what you want.
我们将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;
}
Using the immediate children of the .hexrow
which are just div
elements, we form the basis for the hex shape. The width
will drive the horizontal of the top of the hex, the height
is derived from that number since all the sides are equal length on a regular hexagon. Again, margin is going to depend on spacing, but this is where the "overlap" of the individual hexagons is going to occur to make the grid look occur. The background-image
is defined once, right here. The shift left on it is to accommodate at least the added width for the left side of the hex. Assuming you want centered text, the text-align
handles the horizontal (of course) but the line-height
that matches the height
is going to allow for a vertical centering.
使用.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;
}
Each oddnumber hex we are going to shift down in relation to the "row" and each evenshift up. The shift calculation ( width x cos(30) / 2 ) is also the same as (height / 4).
我们将相对于“行”向下移动每个奇数十六进制,并向上移动每个偶数。移位计算( 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)) */
}
We are using 2 child div
elements to create the "wings" of the hex. They are sized the same as the main hex rectangle, and then rotated, and pushed "below" the main hex. Background-image
is inherited so that the image is the same (of course), because the image in the "wings" is going to be "lined up" to that in the main rectangle. The pseudo elements are used to generate the images, because they need to be "rerotated" back to horizontal (since we rotated the parent div
of them to create the "wings").
我们使用 2 个子div
元素来创建十六进制的“翅膀”。它们的大小与主六角矩形的大小相同,然后旋转并推到主六角“下方”。Background-image
是继承的,因此图像是相同的(当然),因为“翅膀”中的图像将与主矩形中的图像“对齐”。伪元素用于生成图像,因为它们需要“重新旋转”回水平(因为我们旋转div
它们的父元素以创建“翅膀”)。
The :before
of the first will translate its background the width of the negative amount equal to the main portion of the hex plus the original background shift of the main hex. The :before
of the second will change the origin point of the translation and will shift the main width on the x-axis, and half the height on the y-axis.
第: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;
}
This span
houses your text. The line-height
is reset to make the lines of text normal, but the vertical-align: middle
works since the line-height
was larger on the parent. The white-space
is reset so it allows wrapping again. The left/right margin can be set to negative to allow the text to go into the "wings" of the hex.
这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;
}
You can individual target rows and cells in those rows to change images, or span
text settings, or opacity, or accommodate a larger image (to shift it to the place you want), etc. That is what the following do for the second row.
您可以单独定位行和这些行中的单元格以更改图像、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;
}
回答by Ana
It actually can be done with just one element per hexagon and pseudo-elements for the background image and text.
它实际上可以通过每个六边形一个元素和背景图像和文本的伪元素来完成。
demo
演示
Basic HTMLstructure:
基本的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>
You can have may more rows, you just need to have n
hexagons on odd rows and n+/-1
hexagons on even rows.
你可以有更多的行,你只需要n
在奇数行上有六边形,在偶数行上有六边形n+/-1
。
Relevant CSS:
相关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);
}
回答by Starx
I will provide a simple demo of how to create a hexagonal shape.
我将提供一个关于如何创建六边形形状的简单演示。
.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>
回答by Interdruper
Here is another approach using COMPASS/SCSS, that allows easily set the hexagons size and layout:
这是使用 COMPASS/SCSS 的另一种方法,可以轻松设置六边形大小和布局:
回答by Ash
You can create a fully responsive hexagonal grid using only CSS. The idea is to create a parent shape as a mask using CSS2.1 overflow:hidden which is compatible with almost all browsers, even internet explorer 6.
您可以仅使用 CSS 创建一个完全响应的六边形网格。这个想法是使用 CSS2.1 overflow:hidden 创建一个父形状作为遮罩,它几乎与所有浏览器兼容,甚至是 Internet Explorer 6。
It is a surprisingly simple technique that can be used for creating a responsive grid of all kinds of shapes, it just requires thinking outside of the box to solve the problem.
这是一种非常简单的技术,可用于创建各种形状的响应式网格,只需跳出框框思考即可解决问题。
I have an extensive step by step guide on how to do this technique here: https://www.codesmite.com/article/how-to-create-pure-css-hexagonal-grids
我有一个关于如何在此处执行此技术的详细分步指南:https: //www.codesmite.com/article/how-to-create-pure-css-hexagonal-grids
This is the best way I have found so far, requires no javascript and is both fluid and responsive.
这是迄今为止我发现的最好的方法,不需要 javascript,并且既流畅又响应迅速。
I also used the technique in a free HTML template that includes images inside the hexagons which you can demo and download here: https://www.codesmite.com/freebie/hexa-free-responsive-portfolio-template
我还在免费的 HTML 模板中使用了该技术,其中包含六边形内的图像,您可以在此处演示和下载:https: //www.codesmite.com/freebie/hexa-free-responsive-portfolio-template
回答by RozzA
if you are able to implement the div shapes trick, then simply give each div a position:relative
(you would have to initially position them all one by one at first, by also setting top
and left
)
如果您能够实现 div 形状技巧,那么只需给每个 div 一个position:relative
(您必须首先将它们全部一个一个地定位,同时设置top
and left
)
回答by Alex Pakka
AFAIK, there is no way of doing in in pure CSS. Your best bet would be to use mask clipping for backgrounds as explained here: http://www.cssbakery.com/2009/06/background-image.html(this will only work if your page background is solid color or you can fit and position your mask to match page background.
AFAIK,在纯 CSS 中没有办法做到。您最好的选择是对背景使用蒙版剪裁,如下所述:http: //www.cssbakery.com/2009/06/background-image.html(这仅在您的页面背景为纯色或适合并放置您的蒙版以匹配页面背景。
Then you could use csstextwrap to fit in the text: http://www.csstextwrap.com/examples.php
然后你可以使用 csstextwrap 来适应文本:http: //www.csstextwrap.com/examples.php
There was a bunch of similar questions on SO. E.g. Any way to have text in div fill a triangle shape?
SO上有很多类似的问题。例如,有什么方法可以让 div 中的文本填充三角形?