Stephan-v
Stephan-v

Reputation: 20299

CSS triangle that doesn't work like a square?

I am wondering is there actually any way to create a triangle with a true triangle shape? Or a way to fake it to get as close as possible?

Whenever you draw a triangle with something like svg you are always stuck with a transparent triangle that is mirrored because elements are being drawn as boxes.

I made an example because I find it hard to explain this:

http://codepen.io/stephan-v/pen/gaxdjm

svg {
  width: 100px;
  height: 100px;
  position: absolute;
  right: 0;
  top: 0;
}
svg polygon {
  fill: rgba(168, 210, 71, 0.6);
  cursor: pointer;
}
svg polygon:hover {
  fill: rgba(168, 210, 71, 0.9);
  cursor: pointer;
}
article {
  position: relative;
  width: 200px;
  height: 200px;
  background-color: whitesmoke;
  border: 1px solid lightgrey;
}
article a {
  display: block;
  width: 100%;
  height: 100%;
}
<article>
  <a href="#">
  </a>
  <svg>
    <polygon points="0,0 100,0 100,100" />
  </svg>
</article>

I made the entire article a link and the svg triangle a link as well. But because the triangle is being rendered as a block there is a small part that is exactly the mirror image of the triangle that is not clickable.

For a project I would like to remove the part that cannot be clicked. That is the part in red:

triangle with a mirrored square

Upvotes: 3

Views: 1614

Answers (4)

Stewartside
Stewartside

Reputation: 20905

CSS Transform

This can be done with pure CSS by creating an element and rotating it to create the triangle effect.

I've simplified the code right down so you can get a clear understanding of exactly whats happening.

div {
  width: 200px;
  height: 200px;
  background: lightgrey;
  position: relative;
  overflow: hidden;
}
div > a {
  width: 50%;
  height: 50%;
  position: absolute;
  left: 65%;
  top: 0;
  transform-origin: left top;
  transform: rotate(-45deg);
  background: blue;
}
<div>
  <a href="#link"></a>
</div>

CSS Clip-path

An alternative is to use clip-path. It's not very well supported at the minute but seems to be the next up and coming feature for CSS to use.

div {
  width: 200px;
  height: 200px;
  background: lightgrey;
  position: relative;
  overflow: hidden;
}
div > a {
  width: 50%;
  height: 50%;
  position: absolute;
  left: 65%;
  top: 0;
  -webkit-clip-path: polygon(100% 0, 0 0, 100% 100%);
  clip-path: polygon(100% 0, 0 0, 100% 100%);
  background: blue;
}
<div>
  <a href="#link"></a>
</div>

Upvotes: 5

web-tiki
web-tiki

Reputation: 103760

A quick fix for you example would be to use pointer-event:none; on the svg element. more info on pointer-events on MDN. For browser support, see canIuse.

svg {
  width: 100px;
  height: 100px;
  position: absolute;
  right: 0;
  top: 0;
  pointer-events: none;
}
svg polygon {
  fill: rgba(168, 210, 71, 0.6);
  cursor: pointer;
}
svg polygon:hover {
  fill: rgba(168, 210, 71, 0.9);
  cursor: pointer;
}
article {
  position: relative;
  width: 200px;
  height: 200px;
  background-color: whitesmoke;
  border: 1px solid lightgrey;
}
article a {
  display: block;
  width: 100%;
  height: 100%;
}
<article>
  <a href="#"></a>
  <svg>
    <polygon points="0,0 100,0 100,100" />
  </svg>
</article>


Another approach would be to put the second link in a container and with rotations and overflow:hidden; you can achive the result you are looking for. Example :

div{
  position:relative;
  width:200px; height:200px;
  overflow:hidden;
}
a {display:block}

#l1{
  width:100%; height:100%;
  background:grey;
}
span{
  position:absolute;
  left:50%;top:0;
  width:50%; height:72%;
  transform-origin:0 0;
  transform:rotate(-45deg);
  overflow:hidden;
}
#l2{
  width: 100%; height:70%;
  transform-origin:inherit;
  transform:rotate(45deg);
  background:gold;
}
<div>
  <a id="l1" href="#link1"></a>
  <span>
    <a id="l2" href="#link2"></a>
   </span>
</div>

Upvotes: 2

Jahanzaib Asgher
Jahanzaib Asgher

Reputation: 252

#triangle {
  width: 0px;
  height: 0px;
  border-left: 30px solid transparent;
  border-right: 30px solid transparent;
  border-top: 30px solid #f00;
}
<div id='triangle'></div>

Hope this will help you.

Upvotes: 0

David Li
David Li

Reputation: 1290

Here's a code snippet for a pure CSS triangle using border manipulation:

#triangle{
    width: 0; 
    height: 0; 
    border-bottom: 25px solid transparent;
    border-right: 25px solid black;
}

That way you don't have to add it with SVG.

  • Note that this way may still work as a square, but you can set the z-index to bring it behind anything else you want to be clicked.

Upvotes: 0

Related Questions