Restrict a click to a specific shape
Asked Answered
K

6

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

Karena answered 31/5, 2014 at 13:29 Comment(3)
why not just use an image map?Rebane
It would be great if you could make a fiddle. You can also check this answer witch is similar to this one : https://mcmap.net/q/911171/-how-can-i-maintain-proper-boundaries-on-css-triangles-when-hovering-with-cursorElevenses
@Elevenses added the fiddle :) jsfiddle.net/T4BSg/2Karena
E
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);
}
Elevenses answered 5/6, 2014 at 12:23 Comment(6)
This is a cool solution, sadly it's not too extendable to other shapes though.Nerve
It can be adapted to other shapes, all the ones you can create in CSS and has the advantage of not using any JS.Elevenses
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.Karena
no worries @Karena choise is yours to make. Happy to have helped :)Elevenses
@NicolasBorda for triangles, you can use the technique described in this answer and this demo: triangle with hover effectElevenses
@Elevenses 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.Untune
N
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.sstatic.net/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> ");
})
Nerve answered 5/6, 2014 at 11:13 Comment(3)
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 ?Karena
Updated fiddle so clicks are notified of visually.Nerve
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 jsfiddle.net/dMw23Nerve
C
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

Coral answered 31/5, 2014 at 13:44 Comment(5)
@GaurangTandon use JavaScript as the last resort :)Coral
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.Karena
@Karena you can use two inline elements, like span to create top and bottom triangle - exampleCoral
@Coral Thanks again for the reply :) Perhaps I didnt explain me right, see this image taken from your fiddle: 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 :/Karena
@Karena then make four small spans and position them absolutly.Coral
L
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
    }
}
Leitmotiv answered 31/5, 2014 at 13:38 Comment(0)
P
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);
}
Pontoon answered 8/6, 2014 at 2:28 Comment(0)
G
1

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

Geneva answered 12/10, 2022 at 9:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.