Cross browser hexagon shape with image and border (no SVG or background image)

I have already asked once how to create a hexagonal shape in pure html / css. With a little help, I found a solution that works great in chrome and safari, but neither firefox nor IE support the clip property.

The problems I mentioned in the last question are several:

  • I cannot use SVG

    (if possible with and <img>-element

    instead of <image>-element

    )
  • I cannot use the image both background-image

    via CSS
  • Making a hexagon shape with borders doesn't help as I couldn't add an image inside
  • The image will be uploaded to <img>-tag

  • The image can either have no background or be a normal image as shown in the example shown
  • The hexagon must be on the side not on the edge

Many have asked a similar question - some could resolve it with svg, some didn't need a border, others didn't, but I couldn't find anything that fit my requirements.

body {
  background: orange;
}

.hex {
  display: inline-block;
  position: relative;
  width: 120px;
  height: 103.92px; /* width * 0.866 */
  background: red;
  box-sizing: border-box;
  -webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
  -moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}

.hex-background {
  position: absolute;
  background-color: orange; /*color of the main-background*/
  top: 2px; /* equal to border thickness */
  left: 2px; /* equal to border thickness */
  width: 116px; /* container height - (border thickness * 2) */
  height: 99.92px; /* container height - (border thickness * 2) */
  -webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
  -moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}

.hex img {
  position: absolute;
  width: 116px; /* container height - (border thickness * 2) */
  height: 99.92px; /* container height - (border thickness * 2) */
  -webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
  -moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
      

<div class="hex">
  <div class="hex-background">
    <img src="https://img.clipartfest.com/5e18aeec4df9d62fe5cb5e198e4c56c8_locked-padlock-lock-icon-lock-and-key-clipart-transparent-background_420-420.png">
  </div>
</div>
      

Run code


I prepared the code as it works in chrome here . As you can see, I can create a hexagonal shape, have a border, and load an image even with a transparent background into it.

Can anyone help me make this cross browser compatibility? Is this possible with the requirements I have? Could it be possible to achieve this with javascript or jquery?

As always, any help would be greatly appreciated.

EDIT

It seems almost impossible.

I have an idea that I'm not sure about, maybe:

Is it possible to get the source (like "lalala / lala.png") from the src through img element and exchange that img element for the construct needed for the svg approach with jquery or javascript?

given that:

<img src="lalala/lala.png">

      

in js:

get src /* result = "lalala/lala.png" */
delete <img src="lalala/lala.png">
put <svg width="a" height="b">
        <image xlink:href="lalala/lala.png" width="a" height="b" />
    </svg>
    where <img scr="lalala/lala.png> has been

      

Note

I have changed the requirements in the list above.

Why are there so many requirements? The problem is that the image to be displayed inside the hexagon is provided by a backend where the user can upload images (which will most likely be either .jpg or PNG format). The backend will provide these images in html constructs like this:

<img src="somepath/examplepic.png" alt="something"> 

      

Especially this part made it much more difficult than I previously thought. Many solutions to this problem included CSS styling

background-image: url("somepath/examplepic.png");

      

which doesn't work as the backend will provide the image as above. My sheet is prohibited.

svg approach doesn't work either because if you want the image to be cut to shape you have to use

<image xlink:href="lalala/lala.png" width="a" height="b" />

      

inside <svg>-element

that doesn't work either because it isn't <img>-element

.

So you can see that these requirements are not being met by me because I want to make it complex, but because of the environment I am working with.

+3


source to share


2 answers


I found this solution on the net, I am not the author (by Jeffrey Croft at Codepen) but I simplified it a bit and it should work, maybe this will help you get your solution:



    .hexa, .hexa div {
      margin: 0 auto;
      transform-origin: 50% 50%;
      overflow: hidden;
      width: 300px;
      height: 300px;
    }
    .hexa {
      width: 325px;
      height: 230px;
    }
    .hexa div {
      width: 100%;
      height: 100%;
    }
    .hexa {
      transform: rotate(120deg);
    }
    .hex1 {
      transform: rotate(-60deg);
    }
    .hex2 {
      transform: rotate(-60deg);
    }
      

    <div class="part">
      <h2>Hexagon</h2>
        <div class="hexa">
          <div class="hex1">
            <div class="hex2">
              <img src="http://nexceris.com/wp-content/uploads/2014/04/bokeh-cover-bg.jpg" alt="" width="320" height="313" />
            </div>
          </div>
        </div>
    </div>
      

Run code


Working fiddle: https://jsfiddle.net/9znph3sb/

+1


source


While it probably still doesn't fulfill all the constraints (I still think it's not clear where exactly they apply ... since I don't know this system), since the OP asked for demos, here we go:

  • I think only limited image is limited
  • I am guessing that the form can be static on the site or in CSS
  • then we just use positioning to stack things with each other.

div.inline{
  display:inline-block;
  width:100px;
  height:100px;
  position: relative;
}
#image{
  background-image:url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20standalone%3D%22no%22%3F%3E%0A%3Csvg%20width%3D%22100%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20height%3D%22100%22%3E%0A%3Ccircle%20r%3D%2240%22%20stroke%3D%22red%22%20cy%3D%2250%22%20cx%3D%2250%22%20fill%3D%22transparent%22/%3E%0A%3C/svg%3E%0A');
}
#imagebase64{
  background-image:url('data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHdpZHRoPSIxMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgaGVpZ2h0PSIxMDAiPg0KPGNpcmNsZSByPSI0MCIgc3Ryb2tlPSJyZWQiIGN5PSI1MCIgY3g9IjUwIiBmaWxsPSJ0cmFuc3BhcmVudCIvPg0KPC9zdmc+');
}
.relative{
  position: absolute;
  top:0;
  left:0;
}
      

<!doctype html>
<html><head><title>How to include SVG demo: inline, css, data-url …</title></head><body>

  <div class="inline" id="image">
    <span class="relative" style="top:30%;left:1ex;font-size:20px;">&nbsp;data-url<br>CSS:SVG</span>
  </div>
  <div class="inline" id="imagebase64">
    <span class="relative" style="top:30%;left:1ex;font-size:20px;">&nbsp;data-url<br>CSS:B64</span>
  </div>
  <div class="inline">
    <span class="relative" style="top:30%;left:1ex;font-size:20px;">&nbsp;inline SVG/XML</span>
    <svg height="100" width="100">
      <circle cx="50" cy="50" r="40" stroke="red" stroke-width="1" fill="transparent" />
    </svg>
  </div>

<!-- did not work without version etc. here -->
  <div class="inline">
    <img src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20standalone%3D%22no%22%3F%3E%0A%3Csvg%20width%3D%22100%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20height%3D%22100%22%3E%0A%3Ccircle%20r%3D%2240%22%20stroke%3D%22red%22%20cy%3D%2250%22%20cx%3D%2250%22%20fill%3D%22transparent%22/%3E%0A%3C/svg%3E%0A" width="100" height="100" />
    <span class="relative" style="top:30%;left:1ex;font-size:20px;">&nbsp;data-url<br>IMG/SVG<br></span>
  </div>

<div class="clear"></div>

  <div class="inline"><!-- 1st layer -->
    <img src="https://img.clipartfest.com/5e18aeec4df9d62fe5cb5e198e4c56c8_locked-padlock-lock-icon-lock-and-key-clipart-transparent-background_420-420.png" width="100" height="100" />
    <div class="relative"><!-- 2nd layer on top -->
      <svg height="100" width="100">
        <circle cx="50" cy="50" r="49" stroke="red" stroke-width="3" fill="transparent" />
      </svg>
    </div>
  </div>

<!-- final symbol with SVG hexagon -->
<div class="inline">
  <img src="https://img.clipartfest.com/5e18aeec4df9d62fe5cb5e198e4c56c8_locked-padlock-lock-icon-lock-and-key-clipart-transparent-background_420-420.png" width="100" height="100" />
  <div class="relative">
    <!-- viewBox does the scaling -->
    <svg id="color-fill" xmlns="http://www.w3.org/2000/svg" version="1.1" width="100" height="100" viewBox="0 0 300 300" xmlns:xlink="http://www.w3.org/1999/xlink">
      <polygon class="hex" points="299,150 225,280 75,280 1,150 75,20 225,20" stroke="red" stroke-width="9" fill="transparent"></polygon>
    </svg>
  </div>
</div>

</body></html>
      

Run code




  • different approaches svg inline, like data url inline, like data url in css only (can be inlined via style attribute) and base64 (I wouldn't recommend svg anymore, but for png / jpg / gif etc .)
  • See also the final svg example over the image to have the desired border shape.

Tools / Links

+1


source







All Articles