11

I have this image/polygon defined in css like this:

.post-wrapper {
    position: relative;
    width: 250px;
    height: 420px;
    float: left;
    background-color: #ddc;
    -webkit-clip-path: polygon(50% 100%, 100% 50%, 50% 0, 0 50%);
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover; 
}

you can see the image:

Maintain click event in CSS shape

It defines a sort of rectangle, this is a clickable image that redirects to another page, and people are able to click in any part of the rectangle but I only want them to click on the polygon. Anyone knows how can I do this here in my code?

Fidde

web-tiki
  • 99,765
  • 32
  • 217
  • 249
gn66
  • 803
  • 2
  • 12
  • 33

6 Answers6

7

CSS solution

You may maintain the boundaries of the diamond shape and make only the part with the image clickable by using css transform properties. The point is to use the skew property so that the link actualy has a diamond shape and therefore isn't clickable outside this shape (see following demo and screenshot). Then, you need to "counter transform" the content so it isn't skewed.

DEMO

screenshot :

diamond shape with proper boundaries

Relevant CSS :

a{
    width: 216px;
    height: 250px;
    overflow:hidden;
    display:inline-block;
    background:red;

    -webkit-backface-visibility:hidden; /* to reduce pixelisation on borders in chrome */

    -webkit-transform-origin:0 0;
    -ms-transform-origin:0 0;
    transform-origin:0 0;


    -webkit-transform: translate(55%,0) rotate(30deg) skewY(30deg);
    -ms-transform: translate(55%,0) rotate(30deg) skewY(30deg);
    transform: translate(55%,0) rotate(30deg) skewY(30deg);
}

.post-wrapper {
    width: 250px;
    height: 432px;
    background: url(http://lorempixel.com/output/people-h-c-250-432-8.jpg) center center;
    background-size: cover; 

    -webkit-transform-origin:0 0;
    -ms-transform-origin:0 0;
    transform-origin:0 0;

    -webkit-transform:   skewY(-30deg) rotate(-30deg) translate(-50%,0);
    -ms-transform:   skewY(-30deg) rotate(-30deg) translate(-50%,0);
    transform:   skewY(-30deg) rotate(-30deg) translate(-50%,0);
}
web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • This is a cool solution, sadly it's not too extendable to other shapes though. – Etheryte Jun 05 '14 at 13:42
  • It can be adapted to other shapes, all the ones you can create in CSS and has the advantage of not using any JS. – web-tiki Jun 05 '14 at 13:46
  • 1
    You see, i didnt accepted your answer as correct, but Its realy a good answer, Nit gave me more support so since his answer is correct and was first i accept it, but you're answer is quite amazing. Thanks for the reply and best wishes. – gn66 Jun 05 '14 at 14:39
  • no worries @gn66 choise is yours to make. Happy to have helped :) – web-tiki Jun 05 '14 at 14:42
  • @NicolasBorda for triangles, you can use the technique described in [this answer](http://stackoverflow.com/questions/7073484/how-does-this-css-triangle-shape-work/24808936#24808936) and this demo: [triangle with hover effect](http://codepen.io/web-tiki/pen/icClo) – web-tiki Feb 19 '15 at 17:04
  • @web-tiki thank you for that answer, I had come across that answer and you do a great job explaining everything. What I couldn't workout is how todo a an equilateral triangle, Could you please help with the values I need to alter to achieve this. – Nicolas Borda Mar 02 '15 at 06:41
5

This can easily be achieved with SVG paths and Javascript. Sample implementation is as follows:
Create a transparent SVG shape that covers the area you want to make clickable. Then attach a click listener to the path with Javascript.

Sample Jsfiddle.

HTML:

<div id="status"></div>
<div id="sample_image">
    <svg id="cover" preserveAspectRatio="none">
        <path d="M 70,266 L 196,56 320,266 196,478 z"></path>
    </svg>
</div>

CSS:

#sample_image {
    background-image: url('https://i.stack.imgur.com/m4zEw.png');
    width: 448px;
    height: 701px;
}

#cover {
    width: 100%;
    height: 100%;
}

#cover path {
    fill: transparent;
}

JS:

$('#cover path').on('click', function() {
    //Used only for sample output
    $('#status').append("<span>Click received.</span> ");
})
Etheryte
  • 24,589
  • 11
  • 71
  • 116
  • Can u explain your answer? Fiddle is realy not working so i'm not understanging what it does. How can I integrate the code u made, here: jsfiddle.net/T4BSg/2 ? – gn66 Jun 05 '14 at 11:24
  • Updated fiddle so clicks are notified of visually. – Etheryte Jun 05 '14 at 11:46
  • You haven't included jQuery as I have in my Fiddle. You don't need it, I've simply used it for ease of selectors for the example. See http://jsfiddle.net/dMw23/ – Etheryte Jun 05 '14 at 12:19
3

For a pure HTML/CSS solution, you can add an empty href on top of the image, with a fixed height and width. Like:

.clickable-href{
    display:inline-block;
    height:100px;
    width:100px;
    background:red; /* remove this to make the anchor transparent */
}

JSFiddle

Or if it's an img tag, then add a relative parent and use position:absolute the the anchor:

.relative a{
    display:inline-block;
    position:absolute;
    top:0;
    left:0;
    width:100px;
    height:100px;
    background:red; /* remove this to make the anchor transparent */
}

JSFiddle

Vucko
  • 20,555
  • 10
  • 56
  • 107
  • @GaurangTandon use JavaScript as the last resort :) – Vucko May 31 '14 at 13:52
  • 1
    First of all thanks for the reply! If I understood your answer you define a square to click. I want only to click inside the poligon/diamond in that specific shape. – gn66 Jun 04 '14 at 14:00
  • @gn66 you can use two _inline_ elements, like `span` to create top and bottom triangle - [example](http://jsfiddle.net/S5K72/4/) – Vucko Jun 04 '14 at 20:30
  • @Vucko Thanks again for the reply :) Perhaps I didnt explain me right, see this image taken from your fiddle: http://s7.postimg.org/ikwipqb8n/Prt_Scr_capture_6.jpg I just dont want that people can click on the red area, in your example and in mine they can, but they shouldn't :/ – gn66 Jun 05 '14 at 09:22
  • @gn66 then make four small `spans` and position them `absolutly`. – Vucko Jun 05 '14 at 10:56
1

You will have to use JavaScript I suppose. Get the coordinates of the click. Match if they are in the allowed range. And if they are not, use return false.

Read: Getting mouse position inside parent div with javascript/jQuery

Pseudo-Code:

element.onclick = function(){
    if(check range here){
        // user clicked in allowed range
    }else{
        // user did not click in allowed range
        return false; // stop event from working
    }
}
Community
  • 1
  • 1
Gaurang Tandon
  • 6,504
  • 11
  • 47
  • 84
1

There's a solution using the css3 transform property, leave you the JSfiddle Only using html and css

Reorder the tags:

<div class="post-wrapper"><a href="#"></a></div>

And the css:

.post-wrapper{
    position:relative;
    width: 250px;
    height: 420px;
    float: left;
    background-color: #ddc;
    -webkit-clip-path: polygon(50% 100%, 100% 50%, 50% 0, 0 50%);
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
    overflow: hidden;
}
.post-wrapper a{
    display:block;
    position:absolute;
    overflow: hidden;
    width: 400px;
    height: 400px;
    left: -30%;
    top: 2.3%;
    transform: rotate(45deg) scale(.6, .6) skew(10deg, 10deg) translate(0px);
    -webkit-transform: rotate(45deg) scale(.6, .6) skew(10deg, 10deg) translate(0px);
    -moz-transform: rotate(45deg) scale(.6, .6) skew(10deg, 10deg) translate(0px);
    -ms-transform: rotate(45deg) scale(.6, .6) skew(10deg, 10deg) translate(0px);
    -o-transform: rotate(45deg) scale(.6, .6) skew(10deg, 10deg) translate(0px);
}
eiqqen
  • 41
  • 4
0

I'm guessing this wasn't the case in 2014, but now browsers respect clip-path when establishing the clickable area for an element. Theoretically then, the example given (prefix notwithstanding) in the question should behave as was originally desired now.

Here is a codepen demonstrating this:

https://codepen.io/joshdavenport/pen/GRdPxyw

Demonstration of clip-path affecting

Josh Davenport-Smith
  • 5,456
  • 2
  • 29
  • 40