Responsive Hexagon Grid Layout Using CSS Grid and Container Queries

Category: CSS & CSS3 , Layout | January 23, 2026
Authort_afif
Last UpdateJanuary 23, 2026
LicenseMIT
Views35 views
Responsive Hexagon Grid Layout Using CSS Grid and Container Queries

This is a pure CSS responsive hexagon grid layout that arranges elements in a hexagonal pattern using CSS Grid Layout and container queries.

The layout uses CSS custom properties to define hexagon dimensions and calculates positioning offsets using trigonometric functions.

Container queries detect the parent element’s width and determine how many hexagons fit per row.

The grid adjusts spacing and alternating row offsets to maintain the characteristic honeycomb pattern across all screen sizes.

How to use it:

1. Create a container element with child divs representing each hexagon cell. Add content inside these divs or use ::before/::after pseudo-elements for decorative purposes.

<div class="container">
  <!-- Each div becomes a hexagon cell -->
  <div></div>
  <div></div>
  <div></div>
  <!-- Add as many cells as needed -->
</div>

2. Apply the following CSS rules to create the responsive hexagon layout.

.container {
  /* Define the base hexagon size - adjust this value to scale the entire grid */
  --s: 140px;
  /* Calculate gap size based on hexagon dimensions */
  /* Gap needs to account for hexagon overlap in honeycomb pattern */
  --g: calc(12px + var(--s)/2);
  
  /* Use flexbox for the grid container to enable wrapping */
  display: flex;
  gap: 4px var(--g); /* Vertical and horizontal gaps */
  flex-wrap: wrap; /* Allow hexagons to wrap to new rows */
  
  /* Bottom padding compensates for negative margins on hexagons */
  padding-bottom: calc(var(--s)*cos(30deg)/2);
  
  /* Enable container queries so children can respond to this element's width */
  container-type: inline-size;
}
.container > * {
  /* Set hexagon width from the custom property */
  width: var(--s);
  
  /* Calculate height using cosine to create proper hexagon proportions */
  /* aspect-ratio creates the elongated hexagon shape */
  aspect-ratio: 1/cos(30deg);
  
  /* Border radius creates the hexagon shape from a rectangle */
  /* 25% horizontal radius and 50% vertical radius produce hexagon edges */
  border-radius: 25% / 50%;
  
  /* Modern CSS property for beveled corners */
  corner-shape: bevel;
  
  /* Negative margin creates vertical overlap for honeycomb pattern */
  margin-bottom: calc(var(--s)*cos(30deg)/-2);
  
  /* Calculate how many hexagons fit per row based on container width */
  /* Uses container query width (100cqw) divided by hexagon width plus gap */
  --_n: round(down,(100cqw + var(--g))/(var(--s) + var(--g)));
  
  /* Calculate offset pattern for alternating rows */
  --_m: round(down,(100cqw - (var(--s) - var(--g))/2)/(var(--s) + var(--g)));
  
  /* Determine if current hexagon should be offset (alternating row pattern) */
  /* Uses modulo operation on sibling-index to create alternating behavior */
  --_c: round(down,1 - mod((sibling-index() - 1 + var(--_m))/(var(--_n) + var(--_m)),1));
  
  /* Apply left margin offset for alternating rows */
  /* Only applies to every other row to create honeycomb offset */
  margin-left: calc(var(--_c)*(var(--s) + var(--g))/2);
}

3. OPTIONAL. Add CSS styles to make the hexagons visible and numbered. OPTIONAL.

/* Initialize counter for numbering hexagons */
.container {
  counter-reset: num;
}
.container div {
  /* Center content inside each hexagon */
  display: grid;
  place-content: center;
  
  /* Increment the counter for each hexagon */
  counter-increment: num;
  
  /* Visual styling */
  border: 10px solid;
  box-sizing: border-box;
  font: bold 28px system-ui,sans-serif;
}
/* Display the counter value inside each hexagon */
.container div:before {
  content: counter(num);
}
/* Alternate colors for odd-numbered hexagons */
.container div:nth-child(odd) {
  color: #e92d00;
}

4. Replace the counter and border styling with your actual content styles. You can add background images, gradients, or any standard CSS properties to the hexagon cells.

Related Resources:

  • Grid Layout: 10 Best JavaScript & CSS Responsive Grid Layouts.

FAQs:

Q: Why does the hexagon shape break when I add content inside the cells?
A: The border-radius and aspect-ratio properties that create the hexagon shape can be disrupted by overflow. Add overflow: hidden to the .container > * selector to clip content within the hexagon boundaries. If you need scrollable content inside hexagons, you will need to create a nested element with its own overflow handling.

Q: How do I change the gap between hexagons without breaking the pattern?
A: The --g variable controls gap size but it’s calculated based on --s to maintain proper geometry. Change the 12px value in --g: calc(12px + var(--s)/2) to adjust the base gap. Increasing this value spreads hexagons apart while maintaining the honeycomb pattern. Decreasing it brings them closer together.

Q: The hexagons don’t align properly when I add borders or padding. How do I fix this?
A: Add box-sizing: border-box to the hexagon elements. This property makes borders and padding count toward the element’s total width rather than adding to it. The demo code already includes this, but if you override styles, you must maintain it for proper alignment.

Q: Can I make hexagons clickable links while preserving the layout?
A: Replace the <div> elements with <a> tags and apply all the same CSS classes. Anchor elements accept the same CSS properties as divs.

You Might Be Interested In:


Leave a Reply