Создание повторяющегося шестиугольного шаблона с помощью CSS3

Итак, мне нужно сделать повторяющийся гексагональный шаблон, используя CSS. Если нужны изображения, я могу пойти туда, но я предпочел бы просто использовать CSS, если это возможно.

Вот идея того, что я пытаюсь создать:

enter image description here

В принципе, мне просто нужен способ создания шестиугольных фигур, а затем поверх них накладывать текст/изображения. У меня пока мало кода, потому что я не совсем уверен, с чего начать. Проблема в том, что я мог бы просто использовать <div> в форме шестиугольника, как показано в (http://css-tricks.com/examples/ShapesOfCSS/), но тогда они не будут" t быть подключением. Я мог бы использовать повторяющийся образец шестиугольника, но тогда я не смог бы указать точное местоположение текста или изображений, которые мне нужны в определенных фигурах. Спасибо за любую помощь заранее.

Ответ 1

(Хотя ответ Ана был получен через несколько месяцев после моего, вероятно, используя мой в качестве основы для "мыслить", тот факт, что она могла придумать метод с использованием одного div, стоит поощрять, поэтому проверить ее ответ - но обратите внимание, что содержимое в шестнадцатеричном формате более ограничено.)

Это был действительно потрясающий вопрос. Спасибо, что спросили об этом. Самое замечательное в том, что:

Эта скрипка доказывает, что вы можете это сделать!

Исходный скрипт используется (изменено в более позднем редактировании, чтобы перейти на ссылку выше) - он использовал изображения imgur.com, которые не казались быть очень надежным в загрузке, поэтому новая скрипка использует photobucket.com(дайте мне знать, если есть проблемы с постоянной загрузкой изображений). Я сохранил исходную ссылку, потому что приведенный ниже пояснительный код (с некоторыми отличиями в background-size или position есть новая скрипка).

Идея пришла ко мне почти мгновенно после прочтения вашего вопроса, но потребовалось некоторое время для ее реализации. Я изначально пытался получить один "шестнадцатеричный" с одним 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;
}

Каждое нечетное число hex мы будем сдвигаться относительно "строки", и каждый из них сдвигается вверх. Расчет сдвига (ширина x cos (30)/2) также совпадает с (высота/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 - это reset, чтобы строки текста были нормальными, но vertical-align: middle работает, так как line-height больше на родительском. white-space - reset, поэтому он позволяет снова обертывать. Левое/правое поле можно установить на отрицательное, чтобы текст мог попасть в "крылья" шестнадцатеричного.

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

Ответ 2

Фактически это может быть сделано только с одним элементом на шестиугольник и псевдоэлементы для фонового изображения и текста.

демонстрация

Основная структура 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); 
}

Ответ 3

Я дам простое описание того, как создать гексагональную форму.

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

Ответ 4

Вот еще один подход, использующий COMPASS/SCSS, который позволяет легко установить размер и расположение шестиугольников:

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

Ответ 5

если вы можете реализовать трюк формы div, просто дайте каждому div a position:relative (сначала вы должны сначала поместить их по одному, установив top и left)

Ответ 6

Вы можете создать полностью отзывчивую гексагональную сетку, используя только CSS. Идея состоит в том, чтобы создать родительскую форму в виде маски с использованием переполнения CSS2.1: скрытый, который совместим почти со всеми браузерами, даже 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

Ответ 7

AFAIK, в чистом CSS нет способа сделать это. Лучше всего использовать обрезку маски для фона, как описано здесь: http://www.cssbakery.com/2009/06/background-image.html (это будет работать только в том случае, если фон страницы сплошного цвета или вы можете поместиться и поместить свою маску в соответствие с фоном страницы.

Затем вы можете использовать csstextwrap для вставки в текст: http://www.csstextwrap.com/examples.php

На SO была куча подобных вопросов. Например. В любом случае, чтобы текст в div заполнил форму треугольника?