Générer un motif hexagonal répétitif avec CSS3

donc, je dois faire un motif hexagonal répétitif, en utilisant CSS. Si des images sont nécessaires, je peux aller là-bas, mais je préfère juste utiliser CSS si possible.

Voici une idée de ce que j'essaie de créer:

enter image description here

fondamentalement, j'ai juste besoin d'un moyen de créer les formes hexagonales, et puis superposer texte/images sur eux. Je n'ai pas encore beaucoup de code, parce que je ne sais pas vraiment par où commencer. Le le problème est que je pourrais juste utiliser <div> s en forme d'hexagone comme montré dans ( http://css-tricks.com/examples/ShapesOfCSS / ), mais alors ils ne seraient pas se connecter. Je pourrais utiliser un motif hexagonal répétitif, mais alors je ne serais pas en mesure de spécifier l'emplacement exact du texte ou des images dont j'ai besoin dans des formes spécifiques. Merci pour toute aide à l'avance.

77
demandé sur web-tiki 2012-04-08 16:45:45

7 réponses

(bien que la réponse D'Ana soit venue des mois après la mienne, probablement en utilisant la mienne comme une base pour" penser à partir de", le fait qu'elle ait pu trouver une méthode en utilisant un seul div vaut la peine de promouvoir, donc vérifier sa réponse trop --mais notez que le contenu dans l'hexagone est plus limité.)

C'était une question vraiment étonnante. Merci pour la poser. La grande chose est le fait que:

Ce Violon Prouve Que Vous Pouvez Le Faire!

violon D'origine utilisé (modifié plus tard dans edit to fiddle link ci-dessus)--il a utilisé imgur.com images, qui ne semblaient pas être très fiables dans le chargement, de sorte que le nouveau violon utilise photobucket.com ( let me know if there are persistent image loading issues ). J'ai gardé le lien original parce que le code d'explication ci-dessous va avec cela (il ya quelques différences dans background-size ou position au nouveau violon).

l'idée m'est venue presque instantanément après avoir lu votre question, mais a pris un certain temps à mettre en œuvre. J'ai d'abord essayé d'obtenir un simple "hex" avec un seul div et juste des pseudo éléments, mais comme je pouvais le dire, il n'y avait aucun moyen de juste tourner le background-image (dont j'avais besoin), donc j'ai dû ajouter quelques éléments supplémentaires div pour obtenir les côtés droit/gauche de l'hex, de sorte que je pourrais alors utilisez les pseudo-éléments comme moyen de rotation background-image .

j'ai testé en IE9, FF, et Chrome. Théoriquement tout navigateur supportant CSS3 transform il devrait fonctionner dans.

première mise à jour principale (explication ajoutée)

j'ai un peu de temps maintenant pour poster une explication de code, alors voici:

tout D'abord, les hexagones sont définis par des relations de 30/60 degrés et la trigonométrie, donc ceux-ci seront les angles clés impliqués. Deuxièmement, nous commençons avec une "rangée" pour la grille hexadécimale pour résider dans. Le HTML est défini comme (les éléments supplémentaires div aident à construire l'hexagone):

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

nous allons utiliser inline-block pour l'hexagone display , mais nous ne voulons pas qu'ils enveloppent accidentellement à la ligne suivante et ruiner la grille, donc white-space: nowrap résout cette question. Le margin sur cette rangée va dépendre de combien d'espace vous voulez entre les hex, et certains essais peuvent être nécessaires pour obtenir ce que vous voulez.

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

en utilisant les enfants immédiats des .hexrow qui sont juste des éléments div , nous formons la base pour la forme hexagonale. Le width conduira l'horizontale du sommet de l'hexagone, le height est dérivé de ce nombre puisque tous les côtés sont de longueur égale sur un hexagone régulier. De nouveau, marge va dépendre de l'espacement, mais c'est là que le "chevauchement" de la chaque hexagone va se produire pour faire apparaître la grille. Le background-image est défini une fois, ici. Le déplacement à gauche de l'hexagone permet au moins d'accommoder la largeur ajoutée pour le côté gauche de l'hexagone. En supposant que vous voulez un texte centré, le text-align gère l'horizontale (bien sûr) mais le line-height qui correspond au height va permettre un centrage 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;
}

chacun Impair nombre hex nous sommes va décaler vers le bas par rapport à la "ligne" et chaque même shift. Le calcul du déplacement ( Largeur x cos (30) / 2) est également identique à (hauteur / 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)) */
}

nous utilisons 2 enfants div éléments pour créer les" ailes " de l'hexagone. Ils sont dimensionnés de la même façon que le rectangle principal hexadécimal, puis tournés, et poussés "au-dessous" de l'hexadécimal principal. Background-image est hérité de sorte que l'image est la même (bien sûr), parce que l'image dans le "wings "va être" aligné " à celui dans le rectangle principal. Les pseudo-éléments sont utilisés pour générer les images, car ils doivent être "relotées" à l'horizontale (puisque nous avons fait tourner le parent div d'entre eux pour créer les "ailes").

le :before de la première traduit son arrière-plan la largeur de la quantité négative égale à la partie principale de l'hexagone plus le décalage d'arrière-plan original de l'hexagone principal. Le :before de la seconde va changer le point d'origine de la traduction et de décaler les principaux largeur sur l'axe des x, et la moitié de la hauteur sur l'axe des ordonnées.

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

ce span contient votre texte. Le line-height est réinitialisé pour rendre les lignes de texte normales, mais le vertical-align: middle fonctionne depuis le line-height était plus grand sur le parent. Le white-space est réinitialisé pour permettre un nouvel emballage. La marge gauche / droite peut être définie à négatif pour permettre au texte d'aller dans les" ailes " de hexadécimal.

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

vous pouvez cibler des lignes et des cellules individuelles dans ces lignes pour changer les images, ou span paramètres de texte, ou opacité, ou accommoder une image plus grande (pour la déplacer à l'endroit que vous voulez), etc. C'est ce que font les suivants pour la deuxième rangée.

.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;
}
129
répondu ScottS 2017-05-23 12:03:09

il peut en fait être fait avec juste un élément par hexagone et pseudo-éléments pour l'image de fond et le texte.

démo

de Base HTML de la structure:

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

Vous pouvez avoir plus de lignes, vous avez juste besoin d'avoir n hexagones sur les lignes et les n+/-1 hexagones sur les même lignes.

pertinent 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
répondu Ana 2018-04-27 01:49:27

je vais fournir une démonstration simple de la façon de créer une forme hexagonale.

.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
répondu Starx 2018-05-02 08:48:58

Voici une autre approche utilisant COMPASS/ SCSS, qui permet de régler facilement la taille et la disposition des hexagones:

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

1
répondu Interdruper 2013-05-03 10:59:47

si vous êtes capable de mettre en œuvre l'astuce div shapes, alors donnez simplement à chaque div un position:relative (vous devriez d'abord les positionner tous un par un au début, en mettant aussi top et left )

0
répondu RozzA 2012-04-08 13:00:46

vous pouvez créer une grille hexagonale entièrement réactive en utilisant seulement CSS. L'idée est de créer une forme de parent comme masque en utilisant CSS2.1 overflow: caché qui est compatible avec presque tous les navigateurs, même Internet explorer 6.

c'est une technique étonnamment simple qui peut être utilisé pour créer une grille de réponse de toutes sortes de formes, il suffit de penser à l'extérieur de la boîte pour résoudre le problème.

j'ai un guide détaillé étape par étape comment faire cette technique ici: https://www.codesmite.com/article/how-to-create-pure-css-hexagonal-grids

C'est le meilleur moyen que j'ai trouvé jusqu'à présent, ne nécessite pas de javascript et est à la fois fluide et réactive.

j'ai également utilisé la technique dans un modèle HTML gratuit qui comprend des images à l'intérieur des hexagones que vous pouvez démo et télécharger ici: https://www.codesmite.com/freebie/hexa-free-responsive-portfolio-template

0
répondu Ash 2017-01-21 06:54:30

AFAIK, il n'y a aucun moyen de faire en CSS pur. Votre meilleur pari serait d'utiliser le découpage de masque pour les arrière-plans comme expliqué ici: http://www.cssbakery.com/2009/06/background-image.html (cela ne fonctionnera que si votre fond de page est de couleur unie ou si vous pouvez ajuster et positionner votre masque pour correspondre au fond de page.

alors vous pouvez utiliser csstextwrap pour s'adapter dans le texte: http://www.csstextwrap.com/examples.php

il y avait un tas de questions similaires sur SO. Par exemple: y a-t-il un moyen pour que le texte en div remplisse une forme triangulaire?

-2
répondu Alex Pakka 2017-05-23 11:33:13