Kathara
Kathara

Reputation: 1290

html/css: how to create a hexagonal image-placeholder

This is (almost) what I want to create:

HTML

<div class="hexagon1">
  <div class="hexagon-in1">
    <div class="hexagon-in2">
    </div>
  </div>
</div>

CSS

.hexagon1 {
  overflow: hidden;
  visibility: hidden;
  -webkit-transform: rotate(120deg);
  -moz-transform: rotate(120deg);
  -ms-transform: rotate(120deg);
  -o-transform: rotate(120deg);
  transform: rotate(120deg);
  width: 400px;
  height: 200px;
  margin: 0 0 0 -80px;
}

.hexagon-in1 {
    overflow: hidden;
    width: 100%;
    height: 100%;
    -webkit-transform: rotate(-60deg);
    -moz-transform: rotate(-60deg);
    -ms-transform: rotate(-60deg);
    -o-transform: rotate(-60deg);
    transform: rotate(-60deg);
}

.hexagon-in2 {
    width: 100%;
    height: 100%;
    background-repeat: no-repeat;
    background-position: 50%;
    background-image: url(http://placekitten.com/240/240);
    visibility: visible;
    -webkit-transform: rotate(-60deg);
    -moz-transform: rotate(-60deg);
    -ms-transform: rotate(-60deg);
    -o-transform: rotate(-60deg);
    transform: rotate(-60deg);
}

The problem is, that I need a border on the hexagon and if possible I would like to place the picture inside an img-tag. I tried adding the border on either div but I only got a border on top and bottom of the hexagon because of the visibility-hidden or the overflow-hidden attribute.

This is what I've found so far while googling:

http://csshexagon.com/

https://www.queness.com/post/13901/create-beautiful-hexagon-shapes-with-pure-css3

https://github.com/web-tiki/responsive-grid-of-hexagons

I've also found some questions concerning this matter here on Stackoverflow but neither of them explained how exactly you could create a hexagon. Also the hexagons in the examples are all standing on an edge, which is not what I want (as demonstrated in the code). I only need one hexagon and not a grid as well.

When I tried to change the styles of the examples it always ended in a desastrous chaos. This is why I would like to know how to create and to calculate the divs which are used to create a hexagon with border and a picture inside.

Which rate does the width have to the height?

How can I create a border that has the same width on each side?

Where do I have to place the picture as background-image?

How big should the picture be (in percentage to the divs)?

What transformations do you really need to create the hexagon? (I saw an example which used scale, rotate and translate to get a picture inside)

How can the rotation be calculated?

How do I calculate the margin needed?

As I am quite the novice in web-designing can someone explain this as simple as possible? It would suffice if someone can show me according to the example-code above how the numbers are calculated. I know that a hexagon has an inner angle of 120° and that's about it.

Thanks for your help in anticipation. :)

EDIT

Another page I found about hexagons but only to create the shape and not really putting either an image in it nor having a border around it:

http://jtauber.github.io/articles/css-hexagon.html

Upvotes: 2

Views: 1825

Answers (3)

Kathara
Kathara

Reputation: 1290

Important Note

Be informed that this solution does not work for those who want to create something similar supported by all browsers as for the time being IE does not support the clip-path-property used in this example!!


I've found a way to do it thanks to @SahilDhir although it's more of a workaround:

HTML

<div class="poligon">
  <img src="http://lorempixel.com/g/600/400/">
</div>

CSS

.poligon {
  display: inline-block;
  position: relative;
  width: 200px;
  height: 180px;
  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%);
}

.poligon img {
  position: absolute;
  top: 2px; /* equal to border thickness */
  left: 2px; /* equal to border thickness */
  width: 196px; /* container height - (border thickness * 2) */
  height: 176px; /* 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%);
}

Note that I did not calculate much here, but rather tried achieving a six-sided figure.

I will have the problem that my picture will have a transparent background, but I thought that I might produce a linear gradient to fill the background polygon. I will have to try that out first though ^^

I will not mark this as the final answer as my questions have not yet been answered truly. I still want to be able to create a hexagon as the one in the example I gave above where I would be able to adapt the heights and widths as well as the border thicknesses the way I want.

EDIT

As I did not find a better solution I have improved the one here and figured out the calculations needed:

HTML

<div class="poligon">
  <div class="hex-background">
    <img src="https://img.clipartfest.com/953d8641fe933437bbc41d48e6fc8492_yellow20stars20clipart-christmas-stars-clipart-without-background_532-506.png">
  </div>
</div>

CSS

.poligon {
  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: white;
  top: 2px; /* equal to border thickness */
  left: 2px; /* equal to border thickness */
  width: 116px; /* container width - (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%);
}

.poligon img {
  position: absolute;
  width: 116px; /* container width - (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%);
}

The clip-path part is correct if you want a same-sided hexagon.

Same-sided hexagon in colors

With the picture above you can see how I found those numbers ;) If you have further questions about this, don't hesitate to ask. I'll try to explain it the best I can.

Upvotes: 1

Sahil Dhir
Sahil Dhir

Reputation: 4250

I will refer you to go with SVG approach to create this shape. Its really easy and also if you are considering a responsive web layout it can be achieved with this easily.

Reason for this approach -

1. You donot have to write much css.

2. Inline SVG is the modern web approach .

3. Scalable and durable. 4. Responsive

The polygon tag in the svg makes the shape that you want and with the css we can target the things we want to achieve like border in this case. Image has been linked using pattern.

Below is the snippet with example of what you need.

svg {
  width: 30%;
  margin: 0 auto;
}

#hex {
  stroke-width: 2;
  stroke: red;
}
<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://dummyimage.com/600x400/red/fff" 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)"/>
</svg>

<svg viewbox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <defs>
      <pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
        <image xlink:href="https://farm4.staticflickr.com/3165/5733278274_2626612c70.jpg" x="-40" width="150" height="100" />
      </pattern>
    </defs>
    <polygon id="hex" points="25 8 75 8 100 50 75 92 25 92 0 50" fill="url(#img)" />
  </svg>

Upvotes: 2

Yvonne Aburrow
Yvonne Aburrow

Reputation: 2728

I needed something similar, and the easiest way to do it is with two hexagons, one on top of the other.

Using the shapes provided by The Shapes of CSS:

#hexagon1 {
    width: 100px;
    height: 55px;
    background: red;
    position: absolute;
  z-index: 2;
}
#hexagon1:before {
    content: "";
    position: absolute;
    top: -25px;
    left: 0;
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 25px solid red;
}
#hexagon1:after {
    content: "";
    position: absolute;
    bottom: -25px;
    left: 0;
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-top: 25px solid red;
}

#hexagon2 {
    width: 101px;
    height: 56px;
    background: black;
    position: relative;
  z-index: 1;
}
#hexagon2:before {
    content: "";
    position: absolute;
    top: -26px;
    left: 0;
    width: 0;
    height: 0;
    border-left: 51px solid transparent;
    border-right: 51px solid transparent;
    border-bottom: 26px solid black;
}
#hexagon2:after {
    content: "";
    position: absolute;
    bottom: -26px;
    left: 0;
    width: 0;
    height: 0;
    border-left: 51px solid transparent;
    border-right: 51px solid transparent;
    border-top: 26px solid black;
}

Here's a CodePen I made for you: http://codepen.io/vogelbeere/pen/peYjNe

Upvotes: 0

Related Questions