Transparent Arrow/Triangle Indented Over an Image

Transparent arrow/triangle indented over an image

There are several approaches to make a transparent arrow over an image with CSS. The two I will describe involve pseudo elements to minimize markup and have the same output. You can also see an SVG approach at the end of this answer :

Transparent arrow over an image

The transparent effect on the black part arround the arrow is made with rgba() colors that allow transparency. But you can use opacity on the pseudo elements if you prefer.


1. SkewX()

You can use the CSS3 skewX() property on two pseudo elements to make the transparent arrow. The main asset of this approach is that the transparent arrow can be responsive but it also allows you to put a border on the black shape and around the traingle.

The responsiveness of the shape is made with the padding-bottom property to maintain it's aspect ratio (this technique is described here).

DEMO

.wrap {  position: relative;  overflow: hidden;  width: 70%;  margin: 0 auto;}.wrap img {  width: 100%;  height: auto;  display: block;}.arrow {  position: absolute;  bottom: 0;  width: 100%;  padding-bottom: 3%;  background-color: rgba(0, 0, 0, 0.8);}.arrow:before,.arrow:after {  content: '';  position: absolute;  bottom: 100%;  width: 50%;  padding-bottom: inherit;  background-color: inherit;}.arrow:before {  right: 50%;  -ms-transform-origin: 100% 100%;  -webkit-transform-origin: 100% 100%;  transform-origin: 100% 100%;  -ms-transform: skewX(45deg);  -webkit-transform: skewX(45deg);  transform: skewX(45deg);}.arrow:after {  left: 50%;  -ms-transform-origin: 0 100%;  -webkit-transform-origin: 0 100%;  transform-origin: 0 100%;  -ms-transform: skewX(-45deg);  -webkit-transform: skewX(-45deg);  transform: skewX(-45deg);}
<div class="wrap">  <img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" />  <div class="arrow"></div></div>

Transparent arrow in between 2 sections

There is clip-path property in CSS. Support is not wery good, but it works.

section {  width: 300px;  height: 200px;}
.first { background: red; -webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 85%, 60% 85%, 50% 100%, 40% 85%, 0 85%); clip-path: polygon(0% 0%, 100% 0%, 100% 85%, 60% 85%, 50% 100%, 40% 85%, 0 85%);}
.second { background: green; margin-top: -30px;}
<section class="first"></section><section class="second"></section>

Inside transparent arrow on the top

As stated in the question, your case is a bit different from the example that was provided by web-tiki. In the example that you were referring to, the border with the transparent cut was included as the bottom border for the image whereas you need it as the top border of the plain text area.

The expected output can be achieved with the same skew technique described in that answer. However, it needs to be tweaked a bit to match your case.

  • First thing is, the skewed pseudo-elements (that produce the border) should be added to the container of plain text area and not the top section which holds the image. This part you have already done correctly.
  • Next, you need to position the border such that even with the border the height of your text container will be equal to the other two images placed by its side. For this, you need to position the elements that form the border within the plain text container (top: 0%) instead of above it (bottom: 100% in your code).
  • Then, if the text container has a non-transparent background, you need to clip it such that it is not present behind the elements that is creating the border effect. This can be achieved by adding a padding-top on the text container equal to the height of the border pseudo-elements and then setting background-clip: content-box to it.
  • Finally, you need to move the entire bottom part up by the same number of pixels as the height of the border in order for the top image to be seen through the transparent cut out area. This can be done by adding a negative margin-top to the bottom container.

Putting it altogether your code should be similar to the below snippet to achieve the effect that you need. (Note: Your fiddle has way too much code and so I have created a simpler sample for the demo).

.section {  height: 200px;  width: 500px;  background: url(http://lorempixel.com/500/200/nature/3);}.bottom-container {  margin-top: -15px;  height: 100px;  width: 500px;}.text,.middle-image,.right-image {  float: left;  height: 100%;  width: calc(100% / 3);}.middle-image {  background: url(http://lorempixel.com/200/100/nature/2);}.right-image {  background: url(http://lorempixel.com/250/100/nature/1);}.text {  position: relative;  box-sizing: border-box;  height: 100%;  padding-top: 15px;  text-align: center;  line-height: 85px;  background: #F7F7F7; /* Just for demo */  background-clip: content-box; /* needed only if your background is not transparent */  overflow: hidden;}.text:after,.text:before {  position: absolute;  content: '';  top: 0px;  height: 15px;  background: rgb(215,182,115);}.text:before {  left: 0px;  width: 25%;  transform-origin: left bottom;  transform: skew(45deg);}.text:after {  right: 0px;  width: 75%;  transform-origin: right bottom;  transform: skew(-45deg);}
<!-- prefix free library to avoid browser prefixes in CSS --><script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<section class="section"></section><div class="bottom-container"> <div class="text">Some text</div> <div class="middle-image"></div> <div class="right-image"></div></div>

Creating a transparent arrow above image in CSS3

To draw a transparent / inverted triangle in CSS3

you could use the CSS3 triangle technic, and make the inverted shape by combining the :before and :after pseudo objects, each to draw one part of the triangle.

You could do something like this:

.image {
position:relative;
height:200px;
width:340px;
background:orange;
}
.image:before, .image:after {
content:'';
position:absolute;
width:0;
border-left:20px solid white;
left:0;
}
.image:before {
top:0;
height:20px;
border-bottom:16px solid transparent;
}
.image:after {
top:36px;
bottom:0;
border-top:16px solid transparent;
}

here is an illustrative jsfiddle

I just used a plane orange background for the example ... but you can change it to image, and you hopefully get what you wanted =)


Edit: and a more final result could then be something like this

Transparent arrow on right side of image

There are two polygons with white background over the image, it is not an arrow but the space between the two polygons. Changin the width and the position of :before and :after you can move the triangle.

.wrap {  position: relative;  overflow: hidden;  width: 70%;  height:150px;  margin: 0 auto;  background-color:#fff;}.wrap img {  width: 100%;  height: auto;  display: block;}.wrap:before, .wrap:after {  content:'';  position: absolute;  bottom: 0;  width: 100%;  background-color: inherit;  padding-bottom:3%;}.wrap:before {
-ms-transform-origin: 100% 100%; -webkit-transform-origin: 100% 100%; transform-origin: 100% 100%; -ms-transform: skewX(45deg); -webkit-transform: skewX(45deg); transform: skewX(45deg);}.wrap:after { left: 97%; -ms-transform-origin: 0 100%; -webkit-transform-origin: 0 100%; transform-origin: 0 100%; -ms-transform: skewX(-45deg); -webkit-transform: skewX(-45deg); transform: skewX(-45deg);}
<div class="wrap">    <img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" /></div>

Image with cut out transparent triangle

With svg clipPath, it is pretty staightforward. Here is an example :

div {  position: relative;}svg {  position: absolute;  bottom: 0;  left: 0;  width: 100%;  height: auto;}
<div>  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis enim ultricies, ultricies arcu in, pharetra libero. Cras vel venenatis arcu. Nullam sem massa, semper at mauris a.</p>  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis enim ultricies, ultricies arcu in, pharetra libero. Cras vel venenatis arcu. Nullam sem massa, semper at mauris a.</p>  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis enim ultricies, ultricies arcu in, pharetra libero. Cras vel venenatis arcu. Nullam sem massa, semper at mauris a, tempor dictum lorem. Proin sit amet nunc vitae enim tempor rutrum vitae vel sem. Fusce lobortis velit sapien, vitae convallis ipsum ultricies ac. Donec tristique maximus finibus. Pellentesque tortor massa, ultricies quis rhoncus sit amet, luctus ac lorem. Donec eget metus fringilla, dignissim tellus ut, varius lacus. Etiam eu pulvinar est, vitae hendrerit est. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin tristique congue nisi at tincidunt. Cras sollicitudin tortor nulla, ut euismod diam pulvinar vitae. Fusce accumsan metus eget justo tincidunt porta. Morbi dictum a neque ut blandit.</p>  <svg id="svg-defs" viewBox="0 0 100 30">    <defs>      <clipPath id="clip-shape">        <polygon points="0 0, 40 0, 50 10, 60 0, 100 0, 100 500, 0 500"></polygon>      </clipPath>    </defs>    <image id="img-1" class="svg-image" width="100" height="50" clip-path="url(#clip-shape)" xlink:href="http://www.strayshots.com/images/Sunset-Cliffs-1.jpg"></image>  </svg></div>

How do I make an image fill div with an arrow?

You can do it with the clip-path: polygon():

.arrow_box {  position: relative;  background: #88b7d5;  width: 400px;  height: 200px;  -webkit-clip-path: polygon(0 0, 96% 0, 96% 43%, 100% 50%, 96% 57%, 96% 100%, 0 100%);  clip-path: polygon(0 0, 96% 0, 96% 43%, 100% 50%, 96% 57%, 96% 100%, 0 100%);}
.user-image { position: absolute; background-repeat: no-repeat; background-size: cover; width: 100%; height: 100%; background-position: center center; position: relative; object-fit: cover; z-index: 10; -webkit-clip-path: polygon(0 0, 96% 0, 96% 43%, 100% 50%, 96% 57%, 96% 100%, 0 100%); clip-path: polygon(0 0, 96% 0, 96% 43%, 100% 50%, 96% 57%, 96% 100%, 0 100%);}
<div class="arrow_box">  <img src="https://upload.wikimedia.org/wikipedia/commons/3/30/Amazona_aestiva_-upper_body-8a_%281%29.jpg" class="user-image" alt=""></div>

Image with bottom triangle that overlay another image

In the answer you linked to there are 2 approaches that allow the output you are looking for.

If you look under the 4th approach (Tooltip with a triangle over an image.) the technique shown is the same as what facebook uses for tooltips when you hover a name.

Tooltip with triangle over non plain content

Although this approach has a better browser support, I would prefer to use an svg approach (also provided in the post you linked to) with the clipPath element to make the triangle at the bottom.

Adapted to your use case, it could look like this :

*{margin:0;}svg{  display:block;  position:relative;  margin-bottom:-3.5%;  z-index:50;}svg:nth-child(2){  z-index:49;}svg:nth-child(3){  z-index:48;}
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 600 400">  <defs>    <clipPath id="clip">      <path d="M0 0 H600 V380 H320 L300 400 L280 380 H0z" />    </clipPath>  </defs>  <image xlink:href="http://lorempixel.com/600/400/people/1" width="600" height="400" clip-path="url(#clip)"/></svg><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 600 400">  <image xlink:href="http://lorempixel.com/600/400/nature/1" width="600" height="400" clip-path="url(#clip)"/></svg><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 600 400">  <image xlink:href="http://lorempixel.com/600/400/abstract/6" width="600" height="400" clip-path="url(#clip)"/></svg>

Hollow arrow in front of an image

If you want to minimise and remove all unsemantic markup you can do :

DEMO

This technique relies on pseudo elements and therefore prevents the use of unsemantic markup. Pseudo elements are supported by IE8+ see canIuse. It also needs the box-sizing property to enable responsive width (box-sizing: border-box is also supported by IE8+ see canIuse).

HTML :

<div class="wrap">
<img src="http://placekitten.com/800/350" />
<article>
<h1>Hellow World, meow</h1>
</article>
</div>

CSS :

body {
background:#fad;
padding:0;
margin:0;
}

$arrow_width: 20px;
$arrow_height: 20px;
$box_color: #d3d030;

.wrap {
img {
width:100%;
height:auto;
vertical-align:bottom;
}
article{
padding:20px;
background:$box_color;
color:#fff;
position:relative;
}
}
article:before, article:after{
content:'';
position:absolute;
width:50%;
bottom:100%;
box-sizing:border-box;
}
article:before{
left:0;
border-bottom:20px solid #D3D030;
border-right:20px solid transparent;
}
article:after{
right:0;
border-bottom:20px solid #D3D030;
border-left:20px solid transparent;
}


Related Topics



Leave a reply



Submit