Search code examples
htmlcsscss-shapes

How do I make a honeycomb grid using CSS?


I need to create a honeycomb grid wherein the 9 honeycomb filled with red color should always be at center when the screen width changes.

More likely my goal is to have the same effect as background-size: cover / object-fit: cover but for container / elements, so the black honeycomb will just overflow to the screen if the width has become smaller therefore the red honeycomb will always be at center.

enter image description here

This is what I am currently using as basis but I can't seem to the background-size: cover effect + this example is using inline to, so as the width becomes smaller the rows just keeps adding which I want to avoid.

.main {
  display: flex;
  --s: 100px;
  /* size  */
  --m: 4px;
  /* margin */
  --f: calc(1.732 * var(--s) + 4 * var(--m) - 1px);
}

.container {
  font-size: 0;
  /*disable white space between inline block element */
}

.container div {
  width: var(--s);
  margin: var(--m);
  height: calc(var(--s)*1.1547);
  display: inline-block;
  font-size: initial;
  clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
  background: red;
  margin-bottom: calc(var(--m) - var(--s)*0.2885);
}

.container div:nth-child(odd) {
  background: green;
}

.container::before {
  content: "";
  width: calc(var(--s)/2 + var(--m));
  float: left;
  height: 120%;
  shape-outside: repeating-linear-gradient( #0000 0 calc(var(--f) - 3px), #000 0 var(--f));
}
<div class="main">
  <div class="container">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>
</div>


Solution

  • What you actually need is two rows of centered elements where the second row is slightly shifted. You don't need that complex code (which I made btw).

    I have used 15 elements on the first container and 14 on the second one (minus one). You can add as many element as you want but you have to update the selector to correctly color your 9 elements.

    .container {
      overflow: hidden;
    } 
    .container > div {
      display: flex;
      gap: 6px;
      justify-content: center;
    }
    
    .container > div > div {
      width: 80px;
      aspect-ratio: 0.866;
      flex-shrink: 0;
      clip-path: polygon(0 25%,50% 0,100% 25%,100% 75%,50% 100%,0 75%);
      background: black;
    }
    .container > div:last-child {
       transform: translateY(calc(6px - 25%));
    }
    
    .container > div > div:nth-child(6),
    .container > div > div:nth-child(7),
    .container > div > div:nth-child(8),
    .container > div > div:nth-child(9),
    .container > div > div:nth-child(10) {
      background: red;
    }
    .container > div:last-child > div:nth-child(10) {
      background: black;
    }
    <div class="container">
      <div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
      </div>
      <div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
      </div>
    </div>