[ACCEPTED]-Transparent arrow/triangle indented over an image-css-shapes
There are several approaches to make a transparent arrow over 33 an image with CSS. The two I will describe 32 involve pseudo elements to minimize markup 31 and have the same output. You can also see 30 an SVG approach at the end of this answer 29 :
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 28 elements to make the transparent arrow. The 27 main asset of this approach is that the 26 transparent arrow can be responsive but it also allows 25 you to put a border on the black shape and 24 around the traingle.
The responsiveness of 23 the shape is made with the padding-bottom
property to 22 maintain it's aspect ratio (this technique 21 is described here).
.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>
Browser support for the transform : skew()
property 20 is IE9+ (see canIuse).
2. Border
The asset of this technique is 19 browser support so if you need IE8 support 18 this one is for you. The drawback is that 17 the shape can't be responsive because border 16 can't use % widths.
.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%;
height: 20px;
background-color: rgba(0, 0, 0, 0.8);
}
.arrow:before,
.arrow:after {
content: '';
position: absolute;
bottom: 100%;
width: 50%;
box-sizing: border-box;
}
.arrow:before {
right: 50%;
border-bottom: 20px solid rgba(0, 0, 0, 0.8);
border-right: 20px solid transparent;
}
.arrow:after {
left: 50%;
border-bottom: 20px solid rgba(0, 0, 0, 0.8);
border-left: 20px solid transparent;
}
<div class="wrap">
<img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" />
<div class="arrow"></div>
</div>
3. Play with it!
Example : if you can 15 change the black transparent color to the 14 same as your background color (white here), you 13 can make an transparent triangle/arrow with 12 the same background image as the block 11 :
.wrap {
position: relative;
overflow: hidden;
width: 50%;
margin: 0 auto;
background-color:#fff;
}
.wrap img {
width: 100%;
height: auto;
display: block;
}
.wrap:before, .wrap:after {
content:'';
position: absolute;
bottom: 0;
width: 50%;
background-color: inherit;
padding-bottom:3%;
}
.wrap: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);
}
.wrap: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>
4. Tooltip with a triangle over an image.
If you need to use this shape over another image, background 10 gradient or whatever non plain color, you 9 will need to use a different approach in 8 order to see the image all around the shape 7 like this:
The point is to use the same image 6 twice. Once in the div element and once 5 in the triangle and to postion them exactly 4 at the same place with absolute positioning. The 3 arrow is made with transform:rotate();
.
body{
padding-top:100px;
background:url('https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg')no-repeat center center;
background-size:cover;
}
.wrap, .img {
display:inline-block;
position:relative;
}
.tr{
position:absolute;
overflow:hidden;
top:-25px; left:100px;
width:50px; height:50px;
-webkit-transform:rotate(45deg);
-ms-transform:rotate(45deg);
transform:rotate(45deg);
}
.tr img{
position:absolute;
top:-15px; left:-100px;
-webkit-transform-origin: 125px 40px;
-ms-transform-origin: 125px 40px;
transform-origin: 125px 40px;
-webkit-transform:rotate(-45deg);
-ms-transform:rotate(-45deg);
transform:rotate(-45deg);
}
.img{
overflow:hidden;
width: 600px; height:100px;
}
.img img{
position:absolute;
top:-40px;
}
<div class="wrap">
<div class="img">
<img src="https://farm7.staticflickr.com/6092/6227418584_d5883b0948.jpg" alt="" />
</div>
<div class="tr">
<img src="https://farm7.staticflickr.com/6092/6227418584_d5883b0948.jpg" alt="" />
</div>
</div>
DEMO with box shadows.
5. SVG and cliPath
DEMO using an svg 2 tag and clipPath.
This might be a semanticaly 1 better approach if you are making graphics.
Simple Approach
Use pseudo element with
box-shadow
andtransform: rotate();
Add
overflow: hidden;
to main 1 div.
Snippet :
body {
margin: 0;
padding: 0;
background: url(http://i.imgur.com/EinPKO3.jpg);
background-size: cover;
}
div {
height: 100px;
width: 100%;
position: absolute;
bottom: 0;
overflow: hidden;
}
div:before {
position: absolute;
top: -50px;
left: calc(50% - 35px);
content: "";
height: 50px;
width: 50px;
background: transparent;
-webkit-transform-origin: 0% 100%;
-moz-transform-origin: 0% 100%;
-ms-transform-origin: 0% 100%;
transform-origin: 0% 100%;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
box-shadow: 0 0 0 5000px rgba(0, 0, 0, 0.6);
}
<div></div>
Here is a solution using CSS clip-path that doesn't 1 overflow the wrapper.
.wrap {
position:relative;
width:480px;
height:270px;
background-image:url(http://placehold.it/480x270);
}
.wrap:after {
content:"";
display:block;
position:absolute;
left:0;
right:0;
bottom:0;
height:50px;
background-color:rgba(0, 0, 0, 0.7);
-webkit-clip-path:polygon(0 0, calc(50% - 30px) 0, 50% 50%, calc(50% + 30px) 0, 100% 0, 100% 100%, 0 100%);
-moz-clip-path:polygon(0 0, calc(50% - 30px) 0, 50% 50%, calc(50% + 30px) 0, 100% 0, 100% 100%, 0 100%);
clip-path:polygon(0 0, calc(50% - 30px) 0, 50% 50%, calc(50% + 30px) 0, 100% 0, 100% 100%, 0 100%);
}
<div class="wrap"></div>
We can make this with linear-gradients. No 5 pseudo-element. I used some CSS variables 4 to control everything easily. This is more 3 flexible.
.a {
/* you can change these variables */
--arrow-width: 20px;
--rgba: rgba(0, 0, 0, 0.5);
--bottom-height: 50px;
width: 100%;
height: 300px;
background: linear-gradient(to right, var(--rgba) 0 calc(50% - var(--arrow-width)), transparent calc(50% - var(--arrow-width)) calc(50% + var(--arrow-width)), var(--rgba) 0 calc(50% + var(--arrow-width) * 2)) 0 calc(100% - var(--bottom-height)) / 100% var(--arrow-width),
linear-gradient(to bottom right, transparent 0 50%, var(--rgba) 50.1% 100%) calc(50% + (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width),
linear-gradient(to bottom left, transparent 0 50%, var(--rgba) 50.1% 100%) calc(50% - (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width),
linear-gradient(var(--rgba), var(--rgba)) 0 100%/ 100% calc(var(--bottom-height)),
url(https://picsum.photos/id/600/360) 50% 50% / cover;
background-repeat: no-repeat;
}
<div class="a"></div>
By changing the variables:
.a {
/* you can change these variables */
--arrow-width: 50px;
--rgba: rgba(0, 0, 0, 0.5);
--bottom-height: 70px;
width: 100%;
height: 300px;
background: linear-gradient(to right, var(--rgba) 0 calc(50% - var(--arrow-width)), transparent calc(50% - var(--arrow-width)) calc(50% + var(--arrow-width)), var(--rgba) 0 calc(50% + var(--arrow-width) * 2)) 0 calc(100% - var(--bottom-height)) / 100% var(--arrow-width),
linear-gradient(to bottom right, transparent 0 50%, var(--rgba) 50.1% 100%) calc(50% + (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width),
linear-gradient(to bottom left, transparent 0 50%, var(--rgba) 50.1% 100%) calc(50% - (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width),
linear-gradient(var(--rgba), var(--rgba)) 0 100%/ 100% calc(var(--bottom-height)),
url(https://picsum.photos/id/600/360) 50% 50% / cover;
background-repeat: no-repeat;
}
<div class="a"></div>
To better 2 understand the trick here is the gradients 1 with different colors:
.a {
/* you can change these variables */
--arrow-width: 50px;
--bottom-height: 70px;
width: 100%;
height: 300px;
background: linear-gradient(to right, red 0 calc(50% - var(--arrow-width)), transparent calc(50% - var(--arrow-width)) calc(50% + var(--arrow-width)), blue 0 calc(50% + var(--arrow-width) * 2)) 0 calc(100% - var(--bottom-height)) / 100% var(--arrow-width),
linear-gradient(to bottom right, transparent 0 50%, yellow 50.1% 100%) calc(50% + (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width),
linear-gradient(to bottom left, transparent 0 50%, green 50.1% 100%) calc(50% - (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width),
linear-gradient(purple, purple) 0 100%/ 100% calc(var(--bottom-height)),
url(https://picsum.photos/id/600/360) 50% 50% / cover;
background-repeat: no-repeat;
}
<div class="a"></div>
Masking:
.a {
/* you can change this variable */
--arrow-width: 30px;
width: 100%;
height: 300px;
--mask: linear-gradient(#000, #000) 0 0/100% calc(100% - var(--arrow-width)) no-repeat,
linear-gradient(to top right, transparent 0 50%, #000 50.1% 100%) calc(50% - var(--arrow-width) / 2) 100% / var(--arrow-width) var(--arrow-width) no-repeat,
linear-gradient(to top left, transparent 0 50%, #000 50.1% 100%) calc(50% + var(--arrow-width) / 2) 100% / var(--arrow-width) var(--arrow-width) no-repeat;
-webkit-mask: var(--mask);
mask: var(--mask);
background: url(https://picsum.photos/id/600/360) 50% 50% / cover;
}
<div class="a"></div>
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.