Lets take a humble single element link
<span>example</span>
, which usually appears like so:
And let’s turn it into a hexagon:
example
Useful? Possibly. Fun? Let’s find out.
TL;DR? Final code at the bottom of the page.
For starters, we need to tell the span to act like a block element – otherwise none of the padding or margins will work.
Now we have two of the three measurements needed. These triangles can be used to find out the lengths that we need.
Now we have the ratios of each side of the triangle and now can use this to make the rectangles that will make up the final hexagon. We don’t need to double the dimensions, as all we’re interested in at the moment are the ratios.
In an ideal world, this would just work:
But it doesn’t. Ah well. So instead we’re going to use this:
We now have the first building block needed to make the first part of our hexagon. Now, onto the pseudo-elements!
The
::before
and ::after
pseudo-elements need to be the same dimensions as the parent rectangle. To keep things simple, we’re telling the pseudo-classes to inherit the same characteristics from their parent element – if the dimensions of a change, the dimensions of it’s pseudo-element children will also change.
But
::before
and ::after
just need a bit more work to get them to actually show up. Content.
And now we have a lovely… slightly larger rectangle that hides the main a element. So
z-index
needs to be used – and for z-index
to be actually work, every element needs to be defined as position: relative
orposition: absolute
.
In addition to the position and z-index, the ::before and ::after pseudo elements will need their left and top characteristics defined. Because the parent element is position: relative, the pseudo-elements are contained within.
And here’s where it gets strange. Even though the
z-index
of the pseudo elements is lower than the main element, it still obscures it. But if we add a text into the a element, the text will appear above the pseudo-elements – but the background does not.
Although this appears to disobey the
z-index
, the z-index
of the a works in relation to other elements outside of it – but not the pseudo-elements and the content within it. The pseudo-elements and the content obey each other’s z-index
, but ignore that of the parent element. If we twisted the layout so we could see the z-axis, we’d see this:
Now for the rotation. This uses CSS3 transforms, so will currently work in every modern browser apart from Internet Explorer 8. (Can I Use has the latest info on this). Personally, I think this is okay – the fallback for browsers that don’t support rotations is that it will just appear as a rectangle.
The rotation is dead simple:
transform: rotate(45deg)
will twist the element by 45 degrees clockwise; anticlockwise rotation is done with a negative/minus angle. So, with the hexagon the ::before
and ::after
elements need to be rotated by -60 degrees and 60 degrees.
The eagle-eyed will have no doubt noticed that the CSS so far will only work in Firefox 16+ and Internet Explorer 10+; unfortunately the remedy is the malaise of CSS – the vendor prefix. The W3C version – the non vendor prefixed version – should to go last so it isn’t overridden.
And now you have a lovely hexagon, where there once was only a span.