29

Is there a chance to place an image inside a hexagon shape? I'm used to hexagonal shaped cells in html, but I could'nt get it filled with an (background?) image.

Here is what I have tried :

.top {
  height: 0;
  width: 0;
  display: block;
  border: 20px solid red;
  border-top-color: transparent;
  border-right-color: transparent;
  border-bottom-color: red;
  border-left-color: transparent;
}
.middle {
  height: 20px;
  background: red;
  width: 40px;
  display: block;
}
.bottom {
  height: 0;
  width: 0;
  display: block;
  border: 20px solid red;
  border-top-color: red;
  border-right-color: transparent;
  border-bottom-color: transparent;
  border-left-color: transparent;
}
<div class="hexagon pic">
  <span class="top" style="background: url(http://placekitten.com/400/400/)"></span>
  <span class="middle" style="background: url(http://placekitten.com/400/400/)"></span>
  <span class="bottom" style="background: url(http://placekitten.com/400/400/)"></span>
</div>


<div class="hexagon">
  <span class="top" style="overflow: hidden;"><img src="http://placekitten.com/400/400/" /></span>
  <span class="middle" style="overflow: hidden;"><img src="http://placekitten.com/400/400/" /></span>
  <span class="bottom" style="overflow: hidden;"><img src="http://placekitten.com/400/400/" /></span>
</div>

<div class="hexagon">
  <span class="top"><img src="http://placekitten.com/400/400/" /></span>
  <span class="middle"><img src="http://placekitten.com/400/400/" /></span>
  <span class="bottom"><img src="http://placekitten.com/400/400/" /></span>
</div>

here is a fiddle: http://jsfiddle.net/jnz31/kGSCA/

3

7 Answers 7

74

With CSS3 almost everything is possible: http://jsfiddle.net/kizu/bhGn4/

There I used different rotations with overflow: hidden, so you can get a cross-browser (well, modern cross-broser) masks that even can be coverable and clickable on the masked area.

Sign up to request clarification or add additional context in comments.

4 Comments

i thought that i was a crack in html/css (what is not hard at all), but i dont get any of the stuff you did there. thanks!
Awesome... but what about adding a border to the hexagon?
Hey, I noticed the edges weren't smooth in Chrome and I added a fix: jsfiddle.net/bhGn4/1733
This is really great! Tell me please if this -ms-transform: rotate(120deg); among -60deg is error or it has to be like this?
30

The most flexible way of achieving a hexagon with an image is to use an inline SVG :

svg{
  width:30%;
}
<svg viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
      <image xlink:href="https://farm9.staticflickr.com/8461/8048823381_0fbc2d8efb.jpg" x="-25" width="150" height="100" />
    </pattern>
  </defs>
  <polygon points="50 1 95 25 95 75 50 99 5 75 5 25" fill="url(#img)"/>
</svg>

There are at least two ways of achieving the hexagonal image with SVG :

  • making an hexagonal polygon and filling the polygon with an image and the pattern element (approach I use in the previous snippet)
  • clipping the image with an hexagonal polygon (see next snippet)

svg{width:30%}
<svg viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <clipPath id="hexClip">
      <polygon points="50 1 99 25 99 75 50 99 1 75 1 25"/>
    </clipPath>
  </defs>  
  <image xlink:href="https://farm4.staticflickr.com/3165/5733278274_2626612c70.jpg" x="-25" width="150" height="100" clip-path="url(#hexClip)"/>
</svg>

The SVG approach allows control over many aspects of the hexagon shape and image. And they can be styled with CSS. Here is an example :

svg{
  width:30%;
  margin:0 auto;
}
#hex{
  stroke-width:2;
  stroke: teal;
  fill-opacity:0.6;
  transition:fill-opacity .8s;
}
svg:hover #hex {
  fill-opacity:1;
}
#text{
  stroke-width:0.5;
  stroke:teal;
  fill-opacity:0.4;
  fill:teal;
  transition:fill-opacity .8s;
}
svg:hover #text{
  fill-opacity:1;
}
<svg viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
      <image xlink:href="https://farm9.staticflickr.com/8461/8048823381_0fbc2d8efb.jpg" x="-25" width="150" height="100" />
    </pattern>
  </defs>
  <polygon id="hex" points="50 1 95 25 95 75 50 99 5 75 5 25" fill="url(#img)"/>
  <text id="text" font-size="20" x="50" y="50" text-anchor="middle">Some text</text>
</svg>

For another approach to make hexagons with an image inside check this question : Responsive grid of hexagons

4 Comments

Nice answer. But one thing is confusing me. Is there any special reason for using 1 and 99 co-ordinates isntead of 0 and 100?
@MuhammadUsman it is to prevent the stroke tobe clipped by the svg element
How do I scale up this thing? Right now if I just make the image bigger, it doesn't seem to fill the box completely.
@JCharette Just make the svg width bigger/smaller.
19

A new and easy approach would be to use css3 clip-path property.

From Documentation:

The clip-path CSS property prevents a portion of an element from getting displayed by defining a clipping region to be displayed i.e, only a specific region of the element is displayed.

Following css will show a rectangular element in hexagon shape:

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

Output Image:

Output Image shows image in hexagon shape

body {
  background: linear-gradient(orange, yellow);
  min-height: 100vh;
  margin: 0;
}
.hexagon {
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  background: url("https://i.imgur.com/waDgcnc.jpg") no-repeat;
  background-size: cover;
  margin: 10px auto;
  height: 200px;
  width: 200px;      
}
<div class="hexagon">
  
</div>

We can use this property to draw any shapes that we want. Below are a couple of examples:

div.pentagon {
  clip-path: polygon(50% 0, 100% 45%, 80% 100%, 20% 100%, 0 45%);
}
div.octagon {
  clip-path: polygon(33.33% 0%, 66.66% 0%, 100% 33.33%, 100% 66.66%, 66.66% 100%, 33.33% 100%, 0 66.66%, 0 33.33%);
}

Output Image:

Output Image showing other examples of clip path

body {
  background: linear-gradient(orange, yellow);
  min-height: 100vh;
  margin: 0;
}
div {
  background: url("https://i.imgur.com/waDgcnc.jpg") no-repeat;
  background-size: cover;
  margin: 10px 20px;
  height: 170px;
  width: 170px;
  float: left;
}

.pentagon {
  clip-path: polygon(50% 0, 100% 45%, 80% 100%, 20% 100%, 0 45%);
}

.octagon {
  clip-path: polygon(33.33% 0%, 66.66% 0%, 100% 33.33%, 100% 66.66%, 66.66% 100%, 33.33% 100%, 0 66.66%, 0 33.33%);
}
<div class="pentagon">
  
</div>
<div class="octagon">
  
</div>

Note: clip-path css property is not supported in IE and Edge. However future versions of Edge are expected to have support for this property.

1 Comment

7

You can do it by overlaying corners like this:

http://jsfiddle.net/Eric/kGSCA/3/

HTML:

<div class="hexagon pic">
    <span class="top"></span>
    <span class="bottom"></span>
</div>

CSS:

.hexagon {
    background: url(http://placekitten.com/400/400/);
    width: 400px;
    height: 346px;
    position: relative;
}

.hexagon span {
    position: absolute;
    display: block;
    border-left: 100px solid red;
    border-right: 100px solid red;
    width: 200px;
}

.top {
    top: 0;
    border-bottom: 173px solid transparent;
}

.bottom {
    bottom: 0;
    border-top: 173px solid transparent;
}

1 Comment

Like this one too. Working on older browsers. :)
2

here is a simple way if you need only one pic to place.

<style>
.hex{
    width:80px;
    height:80px;
    background-image: url(http://placekitten.com/400/400/);
    background-size: cover;
    position:relative;
    margin:10px;
}
.hex:before, .hex:after{
    content:"";
    position:absolute;
    top:0px;height:40px;width:0px; /* 40 = height/2 */
    z-index:1;
    border:20px solid #FFF; /*change #FFF to your bg color*/
}
.hex:before{
    left:-20px; /* -1*borderWidth */
    border-right:40px solid transparent;/* width/2 */
}
.hex:after{
    left:40px; /* width/2 */
    border-left:40px solid transparent;/* width/2 */
}
</style>
<div class="hex"></div>

need a border ? a background img will be easier & faster.

<div class="hex">
    <div style="position:absolute;top:-20px;left:-20px;bottom:-20px;right:-20px;
        z-index:2;background-image:url(/images/hexagon.png);">
    </div>
</div>

1 Comment

I love this one, because it's somewhat applicable to older browsers, but not completely, anyways. :)
0

I don't know if it's the answer you're looking for but you could lay a hexagon shaped transparent .png over the image you want to be a hexagon and let it act like a mask.

Just simply put the transparent png over the image with z-index

Comments

0

I don't think there's a way to do it with pure HTML/CSS without any external graphics. There may be some clever hacks using the techniques you linked to in the question, but they would be just that - clever hacks - so probably not best suited to use in a live web site (and as with most 'clever hacks', also probably with at least some cross-browser compatibility issues).

You could do it with Canvas or SVG.

Canvas is a bitmap graphics feature, and part of the HTML5 spec. SVG is a vector graphics language which can be used within an HTML page.

Both of these are features of modern browsers, and are therefore sadly lacking in most versions of Internet Explorer (IE8 and earlier).

Fortunately, however, IE does support a language similar to SVG called VML, and there are a number of javacript libraries that allow IE to use both Canvas and SVG by converting them to VML.

See also:

With any of the tools linked above, you could then use Canvas or SVG to draw a hexagonal (or any other) shape, and fill it with your graphic.

Hope that helps.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.