2

I know this question has been asked in another form very popularly here: How do CSS triangles work?

and I have extensively read the entire thread, but it does not address what I'm trying to do.

I want to make a cross-browser equilateral triangle clip that is responsive.

I found a lot of css like this that uses pixels:

#triangle-up {
    width: 0;
    height: 0;
    border-left: 60px solid transparent;
    border-right: 60px solid transparent;
    border-bottom: 100px solid red;
}

But it's not responsive. I'm currently drawing it using polygon below like so:

.tri-Up {
    -webkit-clip-path: polygon(50% 0, 0 100%, 100% 100%);
    clip-path: polygon(50% 0, 0 100%, 100% 100%);
}

But this is not compatible in Firefox. I've been exploring this question for weeks, but have yet to find a way to clip a equilateral triangle, have it be responsive, and have it work in firefox, chrome, and Safari.

Any thoughts or attempts/success at this would garner much of my appreciation and respect.

Community
  • 1
  • 1
singmotor
  • 3,930
  • 12
  • 45
  • 79
  • What do you mean, it's not responsive? – Oriol Jan 30 '15 at 23:49
  • The first set of code is not "responsive" in that it doesn't change size depending on the size of the div it's in. The second set does, (it uses percents) which is important because I'm using the bootstrap framework. So when my page gets smaller I need the triangles to get smaller – singmotor Jan 30 '15 at 23:57

2 Answers2

2

Yeah it can be done, I needed that a while ago, and found a solution to this issue right here:

  • you can use a <div> or some other that you think it can represent a triangle, and a :pseudo selector from it (actually you can use 2x <div> and leave out the :pseudo selector)
  • the :pseudo selector can be used to represent the triangle itself, like you posted in your question, with border prop.
  • the parent <div> acts like a mask that either shrinks/grows the :pseudo selector, using a combination of width and padding specified in percetage
  • as this mask grows, with your container, more of the triangle is revealed and as soon as it shrinks, it covers up the triangle
  • the border prop set on the :pseudo element acts like a max-width to which the triangle will grow, so you can specify some larger values to it, to the point you think that will the max that it needs to be

Kudos for the author of this solution, and more about this:

Check out the demo here or the snippet bellow:

*,
*:after,
*before {
  box-sizing: border-box;
}
h3 {
  margin: 10px;
  text-align: center;
}
.small-container {
  max-width: 10%;
  float: left;
}
.medium-container {
  max-width: 30%;
  float: left;
}
.large-container {
  float: left;
  max-width: 50%;
}
.fancy-triangle {
  width: 50%;
  height: 0;
  padding-left: 50%;
  padding-bottom: 50%;
  overflow: hidden;
}
.fancy-triangle:after {
  content: "";
  display: block;
  width: 0;
  height: 0;
  margin-left: -2000px;
  border-left: 2000px solid transparent;
  border-right: 2000px solid transparent;
  border-bottom: 2000px solid #4679BD;
}
<h3>Now isnt that nice?</h3>
<div class='fancy-triangle'></div>

UPDATE

Ok, since you need to actually mask a image in a sorta responsive triangle, the above method wont cut it.

Instead, you could use a svg and some percentage clip path points like so:

  • use the svg to draw up a triangle, used to clip the image if the clip-path isnt working properly custom points/shapes
  • then use the clip-path to draw a triangle with custom percentage points representing a triangle

Alternatively, you could a position absolute on the <img> wrapper, and set the width/height in some percentage values that will be bound to a set parent with a position relative, that will then grow/shrink with it.


UPDATE V3

Instead of using a <img> tag you could alternatively use a <svg> with the src attr of you're image and it should work out pretty nice.

.fancy-triangle-image {
    max-width: 1200px;
    -webkit-clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
    clip-path: url(#triangle);
}
.fancy-triangle-image img{
    width: 100%;
}
<div class='fancy-triangle-image'>
    <img src='http://insolitebuzz.fr/wp-content/uploads/2014/10/test-all-the-things.jpg'/>
</div>
<svg display="none;">
  <defs>
    <clipPath id="triangle">
      <polygon points="150 0, 300 300, 0 300" />
   </clipPath>
  </defs>
</svg>
Community
  • 1
  • 1
RGLSV
  • 2,018
  • 1
  • 22
  • 37
  • wow, @Crispy-George thanks for responding! This does look great. The classes that I described above were applied to an tag inside a
    (the image is masked into a triangle and the ultimate goal is to transition to a circle on hover. So should I apply the "fancy-triangle" class to the
    around the embedded (and set the background to the image) or apply the class to the tag itself?
    – singmotor Jan 31 '15 at 01:06
  • @Acoustic77 no problem, however in the case you're describing, I don't think it will work, since the :pseudo stuff, is a triangle, not a mask, the container just wraps around it, making it larger or smaller; you're looking for something even fancier, stand by for an update :) – RGLSV Jan 31 '15 at 01:17
  • @Acoustic77 check it out and take it for a spin – RGLSV Jan 31 '15 at 01:49
  • you're amazing and a life-saver! I've NEARLY got it. I set the polygon points as "50,0 0,100 100,100" (the same as the percentages for the -webkit-clip-path polygon that worked before) and the triangle is almost equilateral but not quite. the left and right sides are taller than the base. Any thoughts on that? Again thank you so much for all of these, been trying to do this for weeks – singmotor Jan 31 '15 at 19:07
  • @Acoustic77 ok, lets bring it home :) which method did you use? – RGLSV Jan 31 '15 at 19:14
  • I used your V3 update one, and like I said, it's really close. Would you like to just move this to chat? – singmotor Jan 31 '15 at 20:33
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/69970/discussion-between-acoustic77-and-crispy-george). – singmotor Jan 31 '15 at 20:38
1

The best bet I can think of is using vw as your unit on the triangle, as this is the only responsive unit that you can use in the border property. See gist here http://sassmeister.com/gist/1b0d70bf4cc35ff05fec

Browser support for vw is pretty good. http://caniuse.com/#search=vw

JustH
  • 1,372
  • 8
  • 8
  • Hmm, that's interesting, I didn't know about vm. It's not a full solution though because the triangles are inside divs, and I need them to fill the divs, not the window – singmotor Jan 30 '15 at 23:59
  • Hmm.... in that case their may not be a pure css solution since the border width shape is a hack, and support for the shape specification isn't great right now. you might need to use a JS fallback for firefox – JustH Jan 31 '15 at 00:09