Pregunta Generar patrón hexagonal repetitivo con CSS3


Entonces, necesito hacer un patrón hexagonal repetitivo, usando CSS. Si se necesitan imágenes, puedo ir allí, pero prefiero usar CSS si es posible.

Aquí hay una idea de lo que intento crear:

enter image description here

Básicamente, solo necesito una forma de crear formas hexagonales, y luego superponer texto / imágenes encima de ellas. Todavía no tengo muchos códigos, porque no estoy seguro de por dónde empezar. El problema es que podría usar <div>s en forma de un hexágono como se muestra en (http://css-tricks.com/examples/ShapesOfCSS/), pero entonces no se estarían conectando. Podría usar un patrón hexagonal repetitivo, pero no podría especificar la ubicación exacta del texto o las imágenes que necesito en formas específicas. Gracias por cualquier ayuda de antemano.


75
2018-04-08 12:45


origen


Respuestas:


(Aunque la respuesta de Ana llegó meses después que la mía, probablemente usando la mía como base para "pensar desde", el hecho de que ella fue capaz de encontrar un método usando un solo div vale la pena promocionarse, entonces echa un vistazo a su respuesta también--pero tenga en cuenta que el contenido en el hex es más limitado.)

Esta fue una pregunta realmente asombrosa. Gracias por preguntar Lo mejor es el hecho de que:

¡Este violín demuestra que puedes hacerlo!

Original Fiddle Used (modificado en el enlace de edición posterior para violín arriba) - utilizó imágenes de imgur.com, que no parecían ser muy confiables en la carga, por lo que el nuevo violín está utilizando photobucket.com (avíseme si persisten problemas de carga de imágenes) Guardo el enlace original porque el código de explicación a continuación va con eso (hay algunas diferencias en background-size o position al nuevo violín).

La idea me llegó casi al instante después de leer su pregunta, pero me tomó un tiempo implementarla. Intenté originalmente obtener un solo "hex" con un solo div y solo pseudo-elementos, pero lo mejor que pude decir, no había forma de simplemente rotar el background-image (que necesitaba), así que tuve que agregar algo más div elementos para obtener los lados derecho / izquierdo del hexágono, para poder usar los pseudo elementos como un medio de background-image rotación.

Probé en IE9, FF y Chrome. En teoría, cualquier navegador compatible con CSS3 transform debería funcionar en.

Primera actualización principal (explicación adicional)

Ahora tengo algo de tiempo para publicar una explicación de código, así que aquí va:

Primero, los hexágonos están definidos por relaciones de 30/60 grados y trigonometría, por lo que esos serán los ángulos clave involucrados. En segundo lugar, comenzamos con una "fila" para que resida la cuadrícula hexadecimal. El HTML se define como (el extra div los elementos ayudan a construir el hex):

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

Vamos a usar inline-block para el hexágono display, pero no queremos que se envuelvan accidentalmente en la siguiente línea y arruinen la cuadrícula, por lo que white-space: nowrap resuelve ese problema los margin en esta fila dependerá de la cantidad de espacio que desee entre hexágonos, y puede ser necesario experimentar para obtener lo que desea.

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

Usando los hijos inmediatos de la .hexrowque son solo div elementos, formamos la base para la forma hexagonal. los width conducirá la horizontal de la parte superior del hexágono, el height se deriva de ese número ya que todos los lados tienen la misma longitud en un hexágono regular. De nuevo, el margen va a depender del espaciado, pero aquí es donde va a ocurrir la "superposición" de los hexágonos individuales para hacer que se vea la rejilla. los background-image se define una vez, aquí mismo. El desplazamiento que queda en él es para acomodar al menos el ancho agregado para el lado izquierdo del hex. Suponiendo que desea texto centrado, el text-align maneja la horizontal (por supuesto) pero el line-height que coincide con el height va a permitir un centrado vertical.

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

Cada impar Número hexadecimal vamos a desplazar hacia abajo en relación con la "fila" y cada incluso cambiar hacia arriba El cálculo de desplazamiento (ancho x cos (30) / 2) también es el mismo que (altura / 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)) */
}

Estamos usando 2 niños div elementos para crear las "alas" del hex. Tienen el mismo tamaño que el rectángulo hexagonal principal, y luego giran y presionan "debajo" del hexágono principal. Background-image se hereda para que la imagen sea la misma (por supuesto), porque la imagen en las "alas" va a estar "alineada" con la del rectángulo principal. Los pseudoelementos se utilizan para generar las imágenes, porque deben volverse a "volver a girar" para volver a horizontales (ya que rotamos el elemento primario div de ellos para crear las "alas").

los :before del primero se traducirá su fondo el ancho de la cantidad negativa igual a la porción principal del hex más el desplazamiento de fondo original del hex principal. los :before del segundo cambiará el punto de origen de la traducción y desplazará el ancho principal en el eje x, y la mitad de la altura en el eje 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;
}

Esta span alberga tu texto. los line-height se restablece para que las líneas de texto sean normales, pero el vertical-align: middle funciona desde el line-height era más grande en el padre. los white-space se reinicia para que permita volver a envolver. El margen izquierdo / derecho se puede establecer en negativo para permitir que el texto entre en las "alas" del hexágono.

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

Puede filas y celdas de destino individuales en esas filas para cambiar las imágenes, o span ajustes de texto, u opacidad, o acomodar una imagen más grande (para cambiarla al lugar que desee), etc. Eso es lo que los siguientes hacen para la segunda fila.

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

128
2018-04-09 02:41



En realidad se puede hacer con solo un elemento por hexágono y pseudoelementos para la imagen de fondo y el texto.

manifestación

BASIC HTML estructura:

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

Puede tener más filas, solo necesita tener n hexágonos en filas impares y n+/-1 hexágonos en filas pares.

Pertinente 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); 
}

51
2017-10-25 13:05



Proporcionaré una demostración simple de cómo crear una forma hexagonal.

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


2
2018-04-09 03:24



Aquí hay otro enfoque que utiliza COMPASS / SCSS, que permite establecer fácilmente el tamaño y el diseño de los hexágonos:

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


1
2018-05-03 10:59



si eres capaz de implementar el truco de formas div, entonces simplemente dale a cada div position:relative(Inicialmente tendrías que posicionarlos uno por uno, al establecer también top y left)


0
2018-04-08 13:00



Puede crear una cuadrícula hexagonal totalmente receptiva utilizando solo CSS. La idea es crear una forma parental como máscara usando CSS2.1 overflow: hidden, que es compatible con casi todos los navegadores, incluso Internet Explorer 6.

Es una técnica sorprendentemente simple que se puede usar para crear una cuadrícula sensible de todo tipo de formas, solo requiere pensar fuera de la caja para resolver el problema.

Tengo una extensa guía paso a paso sobre cómo hacer esta técnica aquí: https://www.codesmite.com/article/how-to-create-pure-css-hexagonal-grids

Esta es la mejor manera que he encontrado hasta ahora, no requiere javascript y es fluido y receptivo.

También utilicé la técnica en una plantilla HTML gratuita que incluye imágenes dentro de los hexágonos que puedes ver y descargar aquí: https://www.codesmite.com/freebie/hexa-free-responsive-portfolio-template


0
2018-01-21 06:54



AFAIK, no hay forma de hacerlo en CSS puro. Su mejor opción sería utilizar el recorte de máscara para fondos como se explica aquí: http://www.cssbakery.com/2009/06/background-image.html (Esto solo funcionará si el fondo de su página es de color sólido o puede ajustar y colocar su máscara para que coincida con el fondo de la página.

Entonces podrías usar csstextwrap para que quepa en el texto: http://www.csstextwrap.com/examples.php

Hubo un montón de preguntas similares en SO. P.ej. ¿Alguna forma de tener texto en div llenar una forma de triángulo?


-2
2018-04-08 19:46