CSS3로 반복되는 육각형 패턴 생성


79

그래서 CSS를 사용하여 반복되는 육각형 패턴을 만들어야합니다. 이미지가 필요한 경우 거기에 갈 수 있지만 가능하면 CSS 만 사용하는 것이 좋습니다.

내가 만들려는 아이디어는 다음과 같습니다.

여기에 이미지 설명 입력

기본적으로 육각형 모양을 만든 다음 그 위에 텍스트 / 이미지를 오버레이하는 방법이 필요합니다. 아직 코드가 많지 않습니다. 어디서부터 시작해야할지 모르겠습니다. 문제는 <div>( http://css-tricks.com/examples/ShapesOfCSS/ ) 와 같이 육각형 모양으로 s를 사용할 수 있지만 연결되지 않는다는 것입니다. 반복되는 육각형 패턴을 사용할 수 있지만 특정 모양에 필요한 텍스트 또는 이미지의 정확한 위치를 지정할 수 없습니다. 미리 도움을 주셔서 감사합니다.


2
CSS 마스크가 있지만 지원은 끔찍합니다. webkit.org/blog/181/css-masks
mddw

<img>배경 이미지 대신 태그를 사용하는 동일한 육각형 패턴 의 경우 <img> 태그로 육각형 격자를 확인할 수 있습니다 .
web-tiki 2014

다양한 크기를 빠르게 갖도록 ScottS 솔루션의 sass 버전을 만들었습니다. 여기에서 확인하십시오 codepen.io/mort3za/pen/wBabaB
Morteza Ziyae 2014

답변:


130

(비록 아나의 대답은 아마도 "에서 생각"에 도심 그녀가 단일 사용하는 방법을 마련 할 수 있다는 사실 광산을 사용하여, 내 후 개월 만에 온 div, 그래서 가치가 추진하고을 너무 그녀의 대답을 체크 아웃 - 그러나 16 진수의 내용은 더 제한적입니다.)

정말 놀라운 질문이었습니다. 물어봐 주셔서 감사합니다. 좋은 점은 다음과 같은 사실입니다.

이 바이올린은 당신이 할 수 있다는 것을 증명합니다!

원래 바이올린을 사용 (바이올린 위의 링크에 나중에 편집 수정) -이 imgur.com 로딩 매우 신뢰할 수있는 보이는되지 않은 이미지, 새로운 바이올린이 사용되도록 photobucket.com 활용 ( 지속성이 있는지 알려주세요 이미지 로딩 문제 ). 설명 코드는 아래의 (에 약간의 차이가 있음으로 간다 때문에 나는 원래 링크를 유지 한 background-size또는 position새로운 바이올린으로는).

아이디어는 귀하의 질문을 읽은 직후에 나에게 왔지만 구현하는 데 시간이 걸렸습니다. 원래는 하나의 div가상 요소 가있는 단일 "16 진수"를 얻으려고 시도했지만 , 내가 알 수 있듯이 background-image(필요한) 회전 할 방법이 없었기 때문에 div오른쪽을 얻기 위해 몇 가지 추가 요소를 추가 해야했습니다. / 헥스의 왼쪽, 그래서 background-image회전 수단으로 의사 요소를 사용할 수 있습니다 .

IE9, FF 및 Chrome에서 테스트했습니다. 이론적으로 CSS3를 지원하는 모든 브라우저 transform에서 작동해야합니다.

첫 번째 메인 업데이트 (설명 추가)

이제 코드 설명을 게시 할 시간이 있습니다.

첫째, 육각형은 30/60도 관계와 삼각법으로 정의되므로 관련된 주요 각도가됩니다. 둘째, 우리는 16 진수 격자가 상주 할 "행"으로 시작합니다. HTML은 다음과 같이 정의됩니다 (추가 div요소는 16 진수를 만드는 데 도움이됩니다).

<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이 행에는 16 진수의 사이에 원하는 공간의 양에 따라 달라집니다 것입니다, 일부 실험은 당신이 원하는 것을 얻기 위해 필요할 수 있습니다.

.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바로 여기, 한 번 정의된다. 왼쪽 이동은 최소한 16 진수의 왼쪽에 추가 된 너비를 수용하는 것입니다. 중앙에 텍스트를 원한다고 가정하면 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;
}

홀수 16 진수는 "행"과 관련하여 아래로 이동하고 각 짝수는 위로 이동합니다. 시프트 계산 (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요소를 사용하여 16 진수의 "날개"를 만듭니다. 기본 육각 사각형과 같은 크기로 회전 한 다음 기본 육각형 "아래"로 밉니다. 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다시 포장 할 수 있도록 재설정됩니다. 왼쪽 / 오른쪽 여백을 음수로 설정하면 텍스트가 16 진수의 "날개"로 들어갈 수 있습니다.

.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 2013-04-13

@ScottS 그래도 구현하는 데 가장 이상한 문제가 발생했습니다. 나는 트위터의 부트 스트랩 툴킷을 사용하고, 어떻게 든 항상 같이 나타납니다 . 나는 문제를 div.container다음과 같이 요약했다 : 육각형 이이 컨테이너 div 내에 있으면 레이아웃이 엉망이됩니다. 하지만 이상한 점은 각 시나리오 간의 비교를 살펴 보는 것입니다 : linklink . 몇 가지 테스트를 실행했지만 무엇이 육각형을 엉망으로 만들고 있는지 파악할 수 없습니다!
element119 2013-04-13

@ Archio-- 먼저, 16 진수 행의 첫 번째 수준 자식에 대한 코드를 보여 주지만, 이미지의 일부가 누락 되었기 때문에 16 진수의 "날개"를 생성하는 두 번째 수준 자식에 문제가있을 수 있습니다 ( 그래서 디버깅 할 수 없습니다). 문제가 있을 수 있지만 ( overflow: hidden당신이 보여준대로 할 것입니다), 그렇지 않은 것 같습니다. 두 번째 수준 중첩 div및 해당 :before코드를 살펴보십시오.는 div변환에서 회전하지 않거나가 해당 요소와 유사 요소 모두background-image상속하지 않기 때문 입니다. div:before
ScottS

방금 확인했습니다. 둘 다 배경색 ( link )을 상속하는 것 같습니다 . 그들은 또한 회전하고 있습니다. Chrome 웹 검사기에서 회전 된 것을 볼 수 있습니다. 문제는 .csv가 있어도 표시되지 않는다는 것 display:block입니다.
element119

아, 찾은 것 같아요! 문제가 발생한 것 같습니다 z-index. 모든 것이 올바르게 작동하는지 확인하기 위해 지금 조정하고 있습니다.
element119

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 요소의 수를 최소화하고 싶었습니다. 그러나 실제 콘텐츠가있는 자식 요소는 의사 대신 쉽게 사용할 수 있습니다.
Ana

2
당신은 기본적으로 만 교체 필요, 맞아 .content:after함께 .hexagon > *. 영리한.
Thomas W

육각형 사이 의 여백 어떻게 우아하게 변경 될 수 있는지에 대한 생각이 있습니까?
maxheld apr

이상하게도 육각형 전체로 확장되면 이 질문에
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 만 사용하여 완벽하게 반응하는 육각형 격자를 만들 수 있습니다. 아이디어는 거의 모든 브라우저, 심지어 인터넷 익스플로러 6과 호환되는 CSS2.1 overflow : hidden을 사용하여 마스크로 부모 모양을 만드는 것입니다.

모든 종류의 모양의 반응 형 그리드를 만드는 데 사용할 수있는 놀랍도록 간단한 기술이며 문제를 해결하려면 상자 밖에서 생각하면됩니다.

이 기술을 수행하는 방법에 대한 단계별 가이드가 있습니다. https://www.codesmite.com/article/how-to-create-pure-css-hexagonal-grids

이것은 내가 지금까지 찾은 가장 좋은 방법이며 자바 스크립트가 필요하지 않으며 유연하고 반응이 좋습니다.

또한 여기에서 데모하고 다운로드 할 수있는 육각형 내부의 이미지가 포함 된 무료 HTML 템플릿에서이 기술을 사용했습니다. https://www.codesmite.com/freebie/hexa-free-responsive-portfolio-template


0

div 모양 트릭을 구현할 수있는 경우 각 div에 a를 제공하십시오 position:relative(처음에는 top및 설정하여 처음에 모두 하나씩 배치해야 함 left).


JSFiddle에서 예제를 제공 할 수 있습니까? 육각형을 이미지와 텍스트로 채워야하는 경우 div 모양 트릭은 실제로 작동하지 않습니다.
element119

1
예, 단색 모양 만 만들 수 있습니다 : jsfiddle.net/Exceeder/cVqtW 이 div를 배경 이미지의 클리핑 영역으로 사용하거나 텍스트 모양을 만드는 데 사용할 수 없습니다.
Alex Pakka 2012

-2

AFAIK, 순수 CSS에서는 할 수있는 방법이 없습니다. 가장 좋은 방법은 http://www.cssbakery.com/2009/06/background-image.html에 설명 된대로 배경에 마스크 클리핑을 사용하는 것입니다 . 하는 것입니다 (페이지 배경이 단색이거나 적합 할 때만 작동합니다. 페이지 배경과 일치하도록 마스크를 배치합니다.

그런 다음 csstextwrap을 사용하여 텍스트에 맞출 수 있습니다. http://www.csstextwrap.com/examples.php

그래서 비슷한 질문이 많이있었습니다. 예 : div의 텍스트를 삼각형 모양으로 채우는 방법이 있습니까?


Alex, 순수한 CSS3에서 할 수있는 방법이 있음을 알고 싶었습니다 (제 답변 참조).
ScottS 2012
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.