2

I want to create a non-rectangular image with CSS3, I think implement something like below image enter image description here

It is a square with a transparent triangle gap in bottom of it, I know I can implement it with some trick, as example with png image but I want create this with HTML element not with image, any body know how can I do that? Is that implementable with HTML and CSS?

Harry
  • 87,580
  • 25
  • 202
  • 214
Yuseferi
  • 7,931
  • 11
  • 67
  • 103
  • Is that triangle transparent or white in color? Also, is there anything you tried first? because am tempted to close vote for not sharing your code – Mr. Alien Nov 17 '14 at 06:32
  • @Mr.Alien it is transparent – Yuseferi Nov 17 '14 at 06:34
  • Since you haven't put much efforts, all I can suggest you is to use css clip – Mr. Alien Nov 17 '14 at 06:40
  • @zhilevan add to your OP that you want the triangle to be transparent. – Vucko Nov 17 '14 at 06:40
  • @zhilevan: Do you need to support older versions of IE? – Harry Nov 17 '14 at 07:28
  • possible duplicate of [Transparent CSS arrow/triangle](http://stackoverflow.com/questions/23758922/transparent-css-arrow-triangle) – web-tiki Nov 17 '14 at 08:11
  • @web-tiki: True, overlapping two skewed pseudo's is also a very good option. I think skew would also produce a sharper output in all browsers. Only drawback (as usual) is IE older versions :( – Harry Nov 17 '14 at 08:22

3 Answers3

2

<----------------------------------------------- clip-path solution ------------------------------------------------->

You could use clip-path to do this:

dabblet

.rect {
    position: absolute;
    width: 165px;
    height: 100px;
    background-color: black;
    -webkit-clip-path: polygon(0 0, 0 100%, 40% 100%, 50% 75%, 60% 100%, 100% 100%, 100% 0%);
}

body {
    background-color: lightblue;
}

Note: Firefox does not support this property.

Works fine on Chrome.

Check out the browser support for clip-path ----------> HERE.


<------------------------- <svg> solution - will support all browsers [except IE8] ------------------------->

Since, Firefox still supports clip-path: url(), you can create an inline svg element with a polygon element inside clipPath that defines the points. Give the clipPath element an id(#mask) and use it in CSS instead of polygon(0 0, 0 100%, 40% 100%, 50% 75%, 60% 100%, 100% 100%, 100% 0%);.

dabblet

HTML:

<div class="rect"></div>
<svg>
  <defs>
    <clipPath id="mask">
      <polygon points="0,0 0,100 66,100 82.5,75 99,100 165,100 165,0 " />
    </clipPath>
  </defs>
</svg>

CSS:

.rect {
    position: absolute;
    width: 165px;
    height: 100px;
    background-color: black;
    -webkit-clip-path: url(#mask);
    clip-path: url(#mask);
}
body {
    background-color: lightblue;
}

<---------------------------------------- <svg> solution without any CSS ---------------------------------------->

dabblet

HTML:

<svg>
    <polygon points="0,0 0,100 66,100 82.5,75 99,100 165,100 165,0" style="fill:black" />
</svg>

Check out browsers that supports svg ----------> HERE

Weafs.py
  • 22,731
  • 9
  • 56
  • 78
  • Thanks for your attetion,I test in chorme work correcty, but I need also firefox, do you have another solution? can we implement it with polygon or something like it? – Yuseferi Nov 17 '14 at 07:24
  • @zhilevan - Working on it as we speak. – Weafs.py Nov 17 '14 at 07:27
  • @zhilevan - Check out my updated answer, now it will support all browsers. – Weafs.py Nov 17 '14 at 07:57
  • 1
    +1. I would say SVG is a better option given it has IE9 support (which linear-gradients don't have). However, I don't think SVG is supported in IE8. You may want to indicate that. – Harry Nov 17 '14 at 08:05
  • but if I want use svg it think this is simple solution ` Sorry, your browser does not support inline SVG. ` :(. – Yuseferi Nov 17 '14 at 08:07
2

A simple approach

Use box-shadow on pseudoelement, and use overflow: hidden; on main element.

div {
    height: 150px;
    width: 200px;
    position: relative;
    overflow: hidden;
}
div:before{
    position: absolute;
    top: 100px;
    left: 67px;
    content: "";
    height: 50px;
    width: 50px;
    background: transparent;
    transform-origin:0% 100%;
    transform: rotate(52deg) skewX(10deg);
    -webkit-transform: rotate(52deg) skewX(10deg);
    box-shadow: 0 0 0 200px black;
}
<div></div>
The Pragmatick
  • 5,379
  • 27
  • 44
1

One way to produce this transparent cut at the bottom is to use a couple of skewed pseudo-elements and position them such that they leave a triangle shaped gap at the bottom. Below is a sample snippet demonstrating this approach.

body {
  background: url("http://lorempixel.com/200/400");
}
.shape {
  height: 200px;
  width: 200px;
  overflow: hidden;
  position: relative;
}
.shape:before {
  height: 100%;
  width: 100%;
  position: absolute;
  content: '';
  background: black;
  left: 0px;
  top: 0px;
  -webkit-transform: skew(-30deg);
  -moz-transform: skew(-30deg);
  transform: skew(-30deg);
  -webkit-transform-origin: 25% -25%;
  -moz-transform-origin: 25% -25%;
  transform-origin: 25% -25%;
}
.shape:after {
  height: 100%;
  width: 100%;
  position: absolute;
  content: '';
  right: 0px;
  top: 0px;
  background: black;
  -webkit-transform: skew(30deg);
  -moz-transform: skew(30deg);
  transform: skew(30deg);
  -webkit-transform-origin: 25% -25%;
  -moz-transform-origin: 25% -25%;
  transform-origin: 25% -25%;
}
<div class="shape"></div>

Note: This below snippet is only to show that achieving a shape with transparent cut is possible by using overlapping gradient backgrounds. However, my advice would be to not use this approach as much as possible because gradients produce jagged corners a lot of the times.

You can use two overlapping linear-gradient backgrounds on a div to achieve this effect. The angles of the triangle can be modified by modifying the gradient's angles. This is tested and found to be working fine in Mozilla FireFox, Chrome, Safari and Opera.

body {
  background: url("http://lorempixel.com/200/400");
}
.shape {
  height: 200px;
  width: 400px;
  background: -webkit-linear-gradient(-10deg, black 50%, transparent 50%), -webkit-linear-gradient(10deg, transparent 50%, black 50%);
  background: -moz-linear-gradient(-10deg, black 50%, transparent 50%), -moz-linear-gradient(10deg, transparent 50%, black 50%);
  background: linear-gradient(100deg, black 50%, transparent 50%), linear-gradient(-100deg, black 50%, transparent 50%);
}
<div class="shape"></div>

One potential drawback of this approach is that the edges aren't really sharp in Chrome (atleast in older versions of Chrome) whereas it is sharp in the others.

Harry
  • 87,580
  • 25
  • 202
  • 214