1

I'm trying to make a responsive hexagon image frame, but I'm stuck on aligning the inner hexagon. Does anyone know how to center the inner hexagon? Here's my code:

.inner {
  background-color: red;
  width: 95%;
  height: 0%;
  padding-bottom: 98%;
  margin-top: auto;
  margin-bottom: auto;
}

.outer {
  background-color: mediumspringgreen;
  width: 12%;
  height: 0%;
  padding-bottom: 13%;
}

.hexagon {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  -webkit-clip-path: polygon( 50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}
<div class="hexagon outer">
  <div class="hexagon inner">
    <img src="https://placekitten.com/400/400" class="absolute inset-0 h-full w-full" alt="" />
  </div>
</div>

My result:

My current result

Expected result:

Expected Result

  • 1
    Since the only part you actually seem to be struggling with is the centring, does this answer your question? [How to center an element horizontally and vertically](https://stackoverflow.com/questions/19461521/how-to-center-an-element-horizontally-and-vertically) – DBS Aug 19 '22 at 10:23

2 Answers2

1

Try it:

.inner {
    background-color: red;
    width: 95%;
    height: 0%;
    padding-bottom: 98%;
    margin-top: auto;
    margin-bottom: auto;
}

.outer {
    background-color: mediumspringgreen;
    width: 12%;
    height: 0%;
    padding-bottom: 13%;
}

.hexagon {
    display: flex;
    justify-content: center;
    align-items: center;
    -webkit-clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
    clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
    position: absolute;
    top: 50%;
    left: 50%;
    -moz-transform: translateX(-50%) translateY(-50%);
    -webkit-transform: translateX(-50%) translateY(-50%);
    transform: translateX(-50%) translateY(-50%);
}
<div class="hexagon outer">
    <div class="hexagon inner">
        <img src="https://placekitten.com/400/400" class="absolute inset-0 h-full w-full" alt="" />
    </div>
</div>
Dang Cao
  • 343
  • 2
  • 5
  • 13
1

It seems as you use the padding only for your inner div, the outer div only gets that height. I would have a container that you put the width on, then you can add padding to your outer hexagon and absolutely position your inner hexagon:

.container {
  width: 12%;
}

.inner {
  background-color: red;
  width: calc(100% - 10px);
  /* can change this to be a percentage if you want a variable width border.  with calc, the border will always be half of what you subtract */
  height: calc(100% - 10px);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.outer {
  background-color: blue;
  width: 100%;
  padding-top: 100%;
  position: relative;
}

.hexagon {
  clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
}

.img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="container">
  <div class="hexagon outer">
    <div class="hexagon inner">
      <img src="https://placekitten.com/400/400" class="img">
    </div>
  </div>
</div>

From comments solution using aspect ratio instead of padding and inset instead of calc on the width of inner:

.container {
  width: 12%;
}

.inner {
  background-color: red;
  /* insets the element 5px from the edges of
     the element against which its positioned: */
  inset: 5px;
  position: absolute;
}

.outer {
  /* allows one dimension to be set (here 'inline-size'/'width'),
     and the other dimension ('block-size'/'height') will be
     an equal width: */
  aspect-ratio: 1;
  background-color: blue;
  /* logical property, equivalent to 'width' in the English -
     left-to-right - language: */
  inline-size: 100%;
  position: relative;
}

.hexagon {
  clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
}

.img {
  width: 100%;
  object-fit: cover;
}
<div class="container">
  <div class="hexagon outer">
    <div class="hexagon inner">
      <img src="https://placekitten.com/400/400" class="img">
    </div>
  </div>
</div>
Pete
  • 57,112
  • 28
  • 117
  • 166
  • Pete: I closed the question as a dupe (rightly, I *think* though I'm happy to be convinced otherwise). That said, there is a slightly simpler alternative to your solution: [demo](https://jsfiddle.net/davidThomas/86femar9/), if you wanted to include that in your answer I would appreciate it. That way your answer becomes more-complete, and hopefully more useful to others in future. :) – David Thomas Aug 19 '22 at 11:08