0

"Ugh, yet another css octagon".

This is something different, I swear. I did read similar questions on StackOverflow.

I would like to have the following on my page:

html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
.octagon {
  display: inline-block;
  position: relative;
  overflow: hidden;
  -webkit-transform: rotate(22.5deg) scale(0.9) translateY(-4px);
  -moz-transform: rotate(22.5deg) scale(0.9) translateY(-4px);
  -ms-transform: rotate(22.5deg) scale(0.9) translateY(-4px);
  -o-transform: rotate(22.5deg) scale(0.9) translateY(-4px);
  transform: rotate(22.5deg) scale(0.9) translateY(-4px);
}
div.octagon > * {
  position: relative;
  overflow: hidden;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  -o-transform: rotate(45deg);
  transform: rotate(45deg);
  background: transparent;
  border: 4px solid;
  margin: 0;
}
div.octagon > *:after {
  position: absolute;
  /* There needs to be a negative value here to cancel
       * out the width of the border. It's currently -4px,
       * but if the border were 5px, then it'd be -5px.
       */
  top: -4px;
  right: -4px;
  bottom: -4px;
  left: -4px;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  -o-transform: rotate(45deg);
  transform: rotate(45deg);
  content: '';
  border: inherit;
}
div.octagon > * > img {
  display: block;
  -webkit-transform: rotate(-67.5deg) scale(1.1) translateZ(0);
  -moz-transform: rotate(-67.5deg) scale(1.1) translateZ(0);
  -ms-transform: rotate(-67.5deg) scale(1.1) translateZ(0);
  -o-transform: rotate(-67.5deg) scale(1.1) translateZ(0);
  transform: rotate(-67.5deg) scale(1.1) translateZ(0);
  backface-visibility: hidden;
}
.green .octagon {
  color: green;
}
/* Grouping */

.octagons {
  position: relative;
  display: inline-block;
  /* To take dimension of the main octagon */
  margin-left: 30px;
  font-size: 0;
  /* Remove white space */
}
.background.octagon {
  position: absolute;
  width: 100%;
  height: 100%;
}
.background.octagon > * {
  width: 100%;
  height: 100%;
}
.left.octagon {
  left: -30px;
}
.right.octagon {
  right: -30px;
}
<div class="green octagons">
  <div class="left background octagon">
    <div>&nbsp;</div>
  </div>

  <div class="right background octagon">
    <div>&nbsp;</div>
  </div>

  <div class="octagon">
    <p>
      <img src="https://placeholdit.imgix.net/~text?txtsize=25&amp;txt=People&amp;w=175&amp;h=175" alt="" width="175" height="175" />
    </p>
  </div>
</div>

As you probably see, this is a "div soup". Because the main octagon needs to clip the image, it needs to have the same variable dimension as the image. Also, the octagons have border and are responsive, so I can't use "border hack".

The two background octagons only need the borders, but it need to be the same dimension as the image as well.

I can't use SVG because the image will be entered by end-user.

My question is then: Is there a cleaner way to do this?

Sơn Trần-Nguyễn
  • 2,188
  • 1
  • 26
  • 30
  • We have a WYSIWYG editor and we let user upload image in as an `` tag. – Sơn Trần-Nguyễn Jul 21 '16 at 04:24
  • Why does a user-provided image keep you from using SVG? Have a look at this question [Fill SVG path element with a background image](http://stackoverflow.com/questions/3796025/fill-svg-path-element-with-a-background-image) and the follow-up on using [base64 images](http://stackoverflow.com/questions/29975138/how-can-i-get-pngbase64-with-images-inside-of-svg-in-google-charts). – hsan Jul 21 '16 at 07:46
  • I want the octagon to take the dimension of the image, not let the image fill the octagon. As above, the WYSIWYG editor only lets us insert as `` tag, and our end user is not tech savy to write HTML. Regardless, SVG is not the requirement. – Sơn Trần-Nguyễn Jul 21 '16 at 08:31

0 Answers0