transparent border (padding?) on circular image [duplicate] - html

I would like to make a transparent cut out half circle shape using only CSS3. The only requirement is that all the elements that form the shape must be black or transparent.
I cannot use a black rectangle with a white circle on top of it because the half circle has to be transparent and let the background show through.
Desired shape :

May be can do it with CSS :after pseudo property like this:
body {
background: green;
}
.rect {
height: 100px;
width: 100px;
background: rgba(0, 0, 0, 0.5);
position: relative;
margin-top: 100px;
margin-left: 100px;
}
.circle {
display: block;
width: 100px;
height: 50px;
top: -50px;
left: 0;
overflow: hidden;
position: absolute;
}
.circle:after {
content: '';
width: 100px;
height: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;
border-radius: 100px;
background: rgba(0, 0, 0, 0);
position: absolute;
top: -100px;
left: -40px;
border: 40px solid rgba(0, 0, 0, 0.5);
}
<div class="rect"> <span class="circle"></span></div>
View on JSFiddle

You can use box-shadows to make the transparent cut out circle :
body {
background: url(http://i.imgur.com/qi5FGET.jpg) no-repeat;
background-size: cover;
}
div {
display: inline-block;
width: 300px; height: 300px;
position: relative;
overflow: hidden;
}
div:before {
content: '';
position: absolute;
bottom: 50%;
width: 100%; height: 100%;
border-radius: 100%;
box-shadow: 0px 300px 0px 300px #000;
}
.transparent {
opacity: 0.5;
}
<div></div>
<div class="transparent"></div>
This can be responsive with percentage lengths:
body {
background: url(http://lorempixel.com/output/people-q-c-640-480-1.jpg) no-repeat;
background-size: cover;
}
div {
width: 40%; height: 300px;
position: relative;
overflow: hidden;
}
div:before {
content: '';
position: absolute;
bottom: 50%;
width: 100%; height: 100%;
border-radius: 100%;
box-shadow: 0px 300px 0px 300px #000;
}
.transparent {
opacity: 0.5;
}
<div class="transparent"></div>

Using SVG:
Here is an alternate solution using SVG (though you haven't tagged it). Advantages of using SVG are:
It has better browser support when compared to radial-gradients.
SVG can support images inside the shape unlike the box-shadow approach.
While SVG is not supported by <= IE8 whereas box-shadow is, fallbacks can be provided.
svg {
height: 150px;
width: 150px;
}
polygon {
fill: black;
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<!-- Sample 1 - Using Clip Path -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<defs>
<clipPath id='clipper'>
<path d='M0,0 a50,50 0 1,0 100,0 l 0,100 -100,0' />
</clipPath>
</defs>
<polygon points='0,0 100,0 100,100 0,100' clip-path='url(#clipper)' />
</svg>
<!-- Sample 2 - Using Path -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<pattern id='bg' width='100' height='100' patternUnits='userSpaceOnUse'>
<image xlink:href='http://lorempixel.com/100/100/nature/1' height='100' width='100' />
</pattern>
<path d='M0,0 a50,50 0 1,0 100,0 l 0,100 -100,0 0,-100' fill='url(#bg)' />
</svg>
Using CSS:
CSS also has clip-path specifications and we can try something like in the below snippet.
.shape {
position: relative;
width: 100px;
height: 100px;
background-color: purple;
}
.shape:after {
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 100%;
width: 100%;
background: white;
-webkit-clip-path: ellipse(50% 20% at 50% 0%);
clip-path: ellipse(50% 20% at 50% 5%);
}
.shape.image{
background: url(http://lorempixel.com/100/100);
}
#shape-2 {
width: 100px;
height: 100px;
background-color: purple;
-webkit-clip-path: ellipse(50% 20% at 50% 20%);
clip-path: ellipse(50% 20% at 50% 20%);
}
/* Just for demo */
.shape{
float: left;
margin: 20px;
}
#shape-2 {
margin: 150px 20px 0px;
}
<div class="shape"></div>
<div class="shape image"></div>
<br/>
<div id="shape-2"></div>
But unlike SVG clip-path, the pure CSS version (that is, without using an inline or external SVG) doesn't seem to be able to support a path. It only supports shapes and so in this case, if you use the clip-path on the parent directly it would just produce an ellipse (like shown in the snippet). To overcome this, we would have to put the clip-path on a child (or a pseudo element) and this would mean that the clipped area would not be transparent.
Using Canvas:
The same can be done using Canvas also. Canvas commands are pretty similar to SVG and their advantages are also pretty similar. However, Canvas are raster based and hence doesn't scale as well as SVG does.
window.onload = function() {
/* Canvas example with path */
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'http://lorempixel.com/150/300';
ctx.beginPath();
ctx.moveTo(110, 0);
ctx.arc(60, 0, 50, 0, 3.14, false);
ctx.lineTo(10, 145);
ctx.lineTo(110, 145);
ctx.closePath();
ctx.fill();
/* Use below for using image as a fill */
/*img.onload = function(){
var ptrn = ctx.createPattern(img,'no-repeat');
ctx.fillStyle = ptrn;
ctx.fill();
}*/
}
/* Canvas example with clip path */
var canvasClip = document.getElementById('canvas-clip');
if (canvasClip.getContext) {
var ctxClip = canvasClip.getContext('2d');
ctxClip.beginPath();
ctxClip.moveTo(10, 145);
ctxClip.lineTo(10, 0);
ctxClip.arc(60, 0, 50, 0, Math.PI * 2, true);
ctxClip.lineTo(110, 145);
ctxClip.lineTo(10, 145);
ctxClip.clip();
ctxClip.fillStyle = 'tomato';
ctxClip.fill();
}
}
canvas {
height: 150px;
width: 300px;
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<canvas id='canvas'></canvas>
<canvas id='canvas-clip'></canvas>
Using Masks:
This shape can be created by using CSS (or) SVG masks also. CSS masks have very poor support and work currently only in Webkit powered browsers but SVG masks have much better support and should work in IE9+.
/* CSS Mask */
.shape {
width: 150px;
height: 150px;
background-color: black;
-webkit-mask-image: radial-gradient(circle closest-corner at 50% 0%, transparent 98%, white 99%);
mask-image: radial-gradient(circle closest-corner at 50% 0%, transparent 98%, white 99%);
}
/* End of CSS Mask */
svg {
height: 150px;
width: 150px;
}
polygon#shape {
fill: black;
mask: url(#masker);
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<!-- CSS Mask -->
<div class='shape'></div>
<!-- SVG Mask -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<defs>
<mask id='masker' x='0' y='0' width='100' height='100'>
<polygon points='0,0 100,0 100,100 0,100' fill='#fff' />
<circle r='50' cx='50' cy='0' fill='#000' />
</mask>
</defs>
<polygon points='0,0 100,0 100,100 0,100' id='shape' />
</svg>

You can do it really easily with a radial gradient.
DEMO
Result:
HTML:
<div class='shape'></div>
Relevant CSS:
.shape {
margin: 0 auto;
width: 10em; height: 16em;
/* WebKit browsers, old syntax */
background: -webkit-radial-gradient(50% 0, circle, transparent 30%, black 30%);
/* IE10, current versions of Firefox and Opera */
background: radial-gradient(circle at 50% 0, transparent 30%, black 30%);
}
See http://caniuse.com/#feat=css-gradients for detailed info on compatibility.

Try this.
body{
background-color:#333;
passing:0px;
height:0px;
}
#app{
background:#333 url('https://source.unsplash.com/random') no-repeat;
background-size:cover;
width:360px;
height:560px;
position:relative;
overflow:hidden;
}
.app-bar{
width:100%;
height:50px;
position:absolute;
bottom:0px;
left:0;
}
.app-bar .bar{
line-height:50px;
position:relative;
width:100%;
height:50px;
background-image: radial-gradient(circle 35px at 315px 0, transparent 700px, #f44336 50px);
}
.app-bar .bar i{
color:#FFF;
display:block;
line-height:50px;
float:left;
width:50px;
text-align:center;
cursor:pointer;
margin-top:0px;
}
.app-bar .bar i:hover{
background-color:rgba(0,0,0,.1);
}
.app-bar .bar button{
padding:0px;
box-sizing:border;
text-align:center;
margin:0px;
bordeR:0px;
outline:0px;
width:60px;
height:60px;
line-height:60px;
cursor:pointer;
color:#FFFFFF;
display:block;
border-radius:50%;
position:absolute;
top:-30px;
left:100%;
margin-left:-75px;
background-color:#f44336;
transition: all .2s ease;
}
.app-bar .bar button span{
line-height:60px;
font-size:30px;
}
.app-bar .bar button:hover{
transform:rotate(45deg);
transition: all .2s ease;
}
<div id="app">
<div class="app-bar">
<div class="bar">
<i class="material-icons">menu</i>
<i class="material-icons">search</i>
<button class="button">
<span class="material-icons">add</span>
</button>
</div>
</div>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/material-design-icons/3.0.1/iconfont/material-icons.min.css" >

Kyle Sevenokas did some good work. And I built off of that. Checkout the http://jsfiddle.net/FcaVX/1/
I basically collapsed the white div for the circle and gave it white borders. The OP question talked about the colors elements that make up the shape; nothing about its borders right?

I needed rounded corners only on the bottom of a responsive image. I started from #sandeep fiddle and improved it for my needs:
.rect
{
height: 85vh;
position: relative;
background-color: red;
width: 60vw;
}
.circle-helper{
display: block;
width: 100%;
padding-bottom: 50%;
bottom: 0;
left: 0;
overflow: hidden;
position: absolute;
background-color: transparent;
}
.circle{
display: block;
width: 100%;
padding-bottom: 100%;
// height: 500px;
bottom: 0;
left: 0;
overflow: hidden;
position: absolute;
background-color: transparent;
}
.circle:after{
box-sizing: content-box;
content: '';
width: 100%;
height: 100%;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
background: rgba(0,0,0,0);
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
border: 300px solid blue;
}
top: 50%
left: 50%
border: 300px solid blue
https://jsfiddle.net/mop00j22/

Right now, the only way I can think of would be to use a lot of 1-pixel wide black divs next to eachother with varying height. It's technically possible this way but should be deeply frowned upon. Also; you won't have anti-aliassing unless you want to go through the trouble of adding 1x1 pixel divs and do the anti-aliassing manually.
It might be more helpful if you gave an example of how you wanted to use this. Why does it need to be black/transparent only? As stated by omarello, the best solution on most circumstances is probably a simple GIF or PNG image with transparency.

Related

How can I cut a shape inside an element? [duplicate]

I'm trying to create what is in essence the reverse of a CSS clip-path. When using clip-path, an image or div is clipped so that only the shape you specify remains and the rest of the background is effectively deleted.
I would like it so that if I clip a shape it basically punches a hole in the upper most layer and removes the shape, not the background. Is this possible? I'd also be open to an SVG solution, but I am new to SVG so be kind :)
Basically, in the code below I have a blue square positioned absolutely inside a red square and want to be able to punch a shape out of the blue square so the red layer below shows through where the shape used to be. In reality there will an image as the background layer, so I can't accept a pseudo effect that mimics what I want but doesn't actually punch the shape out.
Any assistance would be amazing!
codepen: https://codepen.io/emilychews/pen/GQmyqx
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: red;
}
#innerbox {
width: 100%;
height: 100%;
background: blue;
top: 0;
left: 0;
position: absolute;
}
<div id="box">
<div id="innerbox"></div>
</div>
You can put the image above the blue part and you apply the clip-path on it then the result will be the same as if you have created a hole inside the blue part to see the image below:
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: blue;
}
#innerbox {
background: url(https://picsum.photos/400/400/) center/cover;
position: absolute;
inset: 0;
z-index:1;
clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
}
<div id="box">
<div id="innerbox"></div>
</div>
Another idea is to consider multiple background and you will have better support than clip-path and also less of code:
body {
height: 100vh;
margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background:
linear-gradient(to bottom right,#0000 49%,blue 50%) bottom/100% 60%,
linear-gradient(to top right,#0000 49%,blue 50%) top/100% 60%,
linear-gradient(blue,blue) left/20% 100%,
url(https://picsum.photos/400/400/) center/cover;
background-repeat:no-repeat;
}
<div id="box">
</div>
UPDATE
If you want some opacity, here is an idea where you have to duplicate the content using clip-path (a drawback):
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: blue;
}
#innerbox,#innerbox-2 {
background: url(https://picsum.photos/400/400/) center/cover;
position: absolute;
inset: 0;
z-index:2;
}
#innerbox {
/* if you initially planned to have x opacity so you need to set 1-x here*/
opacity:0.4;
}
#innerbox-2 {
z-index:1;
clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
animation:animate 5s linear alternate infinite;
}
#keyframes animate {
from {
clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
}
to {
clip-path:polygon(20% 50%, 90% 50%, 80% 10%);
}
}
<div id="box">
<div id="innerbox">
<h1>Title</h1>
<p>Some content</p>
</div>
<div id="innerbox-2">
<h1>Title</h1>
<p>Some content</p>
</div>
</div>
UPDATE 2
You can consider SVG to do your initial requirement. Simply use an SVG instead of a div where you will have a mask.
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: blue;
background: url(https://picsum.photos/400/400/) center/cover;
}
#innerbox {
position: absolute;
inset: 0;
z-index:1;
}
<div id="box">
<svg viewBox="0 0 200 200" id="innerbox" preserveAspectRatio="none">
<defs>
<mask id="hole">
<rect width="100%" height="100%" fill="white"/>
<!-- the hole defined a polygon -->
<polygon points="20,20 20,180 180,100 " fill="black"/>
</mask>
</defs>
<!-- create a rect, fill it with the color and apply the above mask -->
<rect fill="blue" width="100%" height="100%" mask="url(#hole)" />
</svg>
</div>
You can also use the same SVG as background:
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: blue;
background: url(https://picsum.photos/400/400/) center/cover;
}
#innerbox {
position: absolute;
inset: 0;
z-index:1;
background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><defs><mask id="hole"><rect width="100%" height="100%" fill="white"/> <polygon points="20,20 20,180 180,100 " fill="black"/></mask></defs><rect fill="blue" width="100%" height="100%" mask="url(%23hole)" /></svg>');
}
<div id="box">
<div id="innerbox"></div>
</div>
Update 3 (what I recommend in 2020)
You can use CSS mask to get the effect you want with mask-composite
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://picsum.photos/400/400/) center/cover;
}
#innerbox {
position: absolute;
inset: 0;
-webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100% 100%;
mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100% 100%;
background: blue;
}
<div id="box">
<div id="innerbox"></div>
</div>
And the inverted version using the same shape
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://picsum.photos/400/400/) center/cover;
}
#innerbox {
position: absolute;
inset: 0;
-webkit-mask:
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100% 100%,
linear-gradient(#fff,#fff);
-webkit-mask-composite:destination-out;
mask:
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100% 100%,
linear-gradient(#fff,#fff);
mask-composite:exclude;
background:blue;
}
<div id="box">
<div id="innerbox"></div>
</div>
This ranks high on Google and the answer didn't solve my problem b/c I cannot touch my background image so here is another way of doing this:
Create a frame with the clip-path.
body {
width: 100%;
height: 100vh;
padding: 0;
margin: 0;
display: grid;
place-items: center;
}
#clip,
#background {
width: 400px;
height: 400px;
}
#clip {
clip-path: polygon(0% 0%, 0% 100%, 25% 100%, 25% 25%, 75% 25%, 75% 75%, 25% 75%, 25% 100%, 100% 100%, 100% 0%);
position: absolute;
background: #fff;
opacity: 0.8;
}
#background {
background: url(https://picsum.photos/400/400/) center/cover;
z-index: -1;
}
<div id="background">
<div id="clip"></div>
</div>
I put the clip-div inside the image because of convenience but you can also have it outside. However, make sure that you are okay with the limited browser support of clip-path.
To expand upon #leonheess great work with the aid of var() and calc(), you can setup variables for x/y/width/height and easily move around your square based on js familiar properties.
#clip-container {
--windowposition-x: 50px;
--windowposition-y: 50px;
--windowposition-height: 100px;
--windowposition-width: 100px;
}
body {
width: 100%;
height: 100vh;
padding: 0;
margin: 0;
display: grid;
place-items: center;
background: url(https://picsum.photos/400/400/) center/cover;
}
#clip-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(197, 185, 185, 0.7);
clip-path: polygon(0% 0%,
0% 100%,
var(--windowposition-x) 100%,
var(--windowposition-x) var(--windowposition-y),
calc(var(--windowposition-x) + var(--windowposition-width)) var(--windowposition-y),
calc(var(--windowposition-x) + var(--windowposition-width)) calc(var(--windowposition-y) + var(--windowposition-height)),
var(--windowposition-x) calc(var(--windowposition-y) + var(--windowposition-height)),
var(--windowposition-x) 100%,
100% 100%,
100% 0%);
}
<div id="clip-container"></div>
If you really wanted you could even take this a step further and define your css vars in your html like:
body {
width: 100%;
height: 100vh;
padding: 0;
margin: 0;
display: grid;
place-items: center;
background: url(https://picsum.photos/400/400/) center/cover;
}
#clip-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(197, 185, 185, 0.7);
clip-path: polygon(0% 0%,
0% 100%,
var(--windowposition-x) 100%,
var(--windowposition-x) var(--windowposition-y),
calc(var(--windowposition-x) + var(--windowposition-width)) var(--windowposition-y),
calc(var(--windowposition-x) + var(--windowposition-width)) calc(var(--windowposition-y) + var(--windowposition-height)),
var(--windowposition-x) calc(var(--windowposition-y) + var(--windowposition-height)),
var(--windowposition-x) 100%,
100% 100%,
100% 0%);
}
<div id="clip-container" style="--windowposition-x: 75px;--windowposition-y: 75px;--windowposition-height: 75px;--windowposition-width: 75px;"></div>

Make text box appear to the right of wrapper/clip-path

I have based my code out of this CSS Shapes Layout Pyramid from codepen: https://codepen.io/s-gupta/pen/jOMGbMX
I'm quite happy with the shape of my pyramid, but I also want a text box to appear to the right of each pyramid step when you hover over the element. I based my text box code on https://www.w3schools.com/css/css_tooltip.asp
However, as you see, the text box appears within the wrapper/pyramid, not outside of it. The text in the text box will be quite long, so it cannot be within the pyramid.
How can I make it go outside (and preferably to the right of the pyramid) ?
I'm quite new to CSS/HTML, but I'm trying to learn - Hope somebody out there can help me :)
body {
/*background: #333;
font-family: "SF UI Text", "Avenir", "Helvetica", arial, san-serif;
color: #888;*/
}
.wrapper {
margin: 5vh auto 0;
}
.pyramid {
float: left;
shape-outside:polygon(310px 0px, 130px 405px, 558px 405px);
padding-right:60px;
width: 700px;
height: 500px;
}
.zone {
padding:40px 0;
margin: 0 auto;
text-align:center;
color: black;
background-blend-mode:darken;
transition: 0.5s;
}
.zone:nth-child(1){
background:rgba(248,153,46); /* url("https://pixabay.com/static/uploads/photo/2016/01/05/13/34/laugenbrotchen-1122509_960_720.jpg") center / cover;*/
width: 20%;
clip-path:url("#part1");
clip-path:polygon(50% 0%,0%,100% 100%, 0% 100%);
/*-webkit-clip-path:polygon(50% 0%,100% 100%, 0% 100%);*/
}
.zone:nth-child(2){ background:rgba(248,153,46);
width: 40%;
clip-path:url("#part2");
clip-path:polygon(40% 0%,0%,60% 0, 100% 100%,0% 100%);
/*-webkit-clip-path:polygon(25% 0%,75% 0, 100% 100%,0% 100%);*/
}
.zone:nth-child(3){
width: 60%;
background:rgba(248,153,46);
clip-path:url("#part3");
clip-path:polygon(30% 0,0%, 70% 0, 100% 100%,0% 100%);
/*-webkit-clip-path:polygon(16.5% 0, 83% 0, 100% 100%,0% 100%);*/
}
.zone:nth-child(4){
background:rgba(248,153,46);
width: 80%;
clip-path:url("#part4");
clip-path:polygon(20% 0, 0%,80% 0, 100% 100%,0% 100%);
/*-webkit-clip-path:polygon(12.5% 0,87.5% 0, 100% 100%,0% 100%);*/
}
.zone:nth-child(5){
background:rgba(248,153,46);
width: 100%;
clip-path:url("#part5");
clip-path:polygon(10% 0, 0%,100% 0, 100% 100%,0% 100%);
/*-webkit-clip-path:polygon(12.5% 0,87.5% 0, 100% 100%,0% 100%);*/
}
/*.zone:hover {
background-color: rgba(118,113,113);
color: white;
}
*/
.zone .arrowtext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
padding: 5px 0;
border-radius: 6px;
top: -5px;
left: 105%;
}
.zone .arrowtext::after {
content: " ";
position: relative;
top: 50%;
right: 100%; /* To the left of the tooltip */
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent black transparent transparent;
}
.zone:hover {
background-color: rgba(118,113,113);
color: white;
}
.zone:hover .arrowtext{
visibility: visible;
}
<div class="wrapper">
<div class="pyramid">
<div class="zone">0. zero
<span class="arrowtext">Tooltip text</span></div>
<div class="zone">1. One</div>
<div class="zone">2. Two</div>
<div class="zone">3. Three</div>
<div class="zone">4. Four</div>
</div>
<svg width="0" height="0">
<defs>
<clipPath id="part1" clipPathUnits= "objectBoundingBox">
<polygon points= "0.5 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part2" clipPathUnits= "objectBoundingBox">
<polygon points= "0.25 0,0.75 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part3" clipPathUnits= "objectBoundingBox">
<polygon points= "0.165 0,0.83 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part4" clipPathUnits= "objectBoundingBox">
<polygon points= "0.125 0,0.875 0, 1 1, 0 1"/>
</clipPath>
<clipPath id="part5" clipPathUnits= "objectBoundingBox">
<polygon points= "0.1 0,0.9 0, 1 1, 0 1"/>
</clipPath>
</defs>
</svg>
And further, how could I make the arrowtext go over several sentences? I figured I can make the width wider and reduce the clip path so that the triangle takes up less of the area. That solves the problem of making whole 1-2 lines visible, but what about getting text that goes over 2 lines? I've tried z-index for example, but does not work. In other words I'm looking for a way to make the text expand further than only the height of the hovered element or zone.
Here is a simplified version where I am reducing the size for the sake of the demo (feel free to update them).
The trick is to create triangle shapes using pseudo element on each "zone" element. By making them relative to "pyramid" they will overlap (creating the illusion of only one). Then by using clip-path:inset(0) on "zone" each one will show one portion on the triangle.
.pyramid {
width: 400px;
margin: auto;
z-index: 0;
position: relative; /* relative on "pyramid" and not "zone" */
}
/* build the triangle as pseudo element fo "zone" */
.zone:before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
background: rgba(248, 153, 46);
/* the pyramid shape */
clip-path: polygon(50% 0, 100% 100%, 0 100%);
transition: 0.5s;
}
.zone {
padding: 20px 0;
text-align: center;
cursor: pointer;
color: black;
clip-path: inset(0); /* clip the triangle to only the shape of each "zone"*/
}
/* using an extra div to correctly place the tooltip*/
.zone > div {
display:inline-block;
position:relative;
}
/* update color on hover */
.zone:hover {
color: white;
}
.zone:hover:before {
background: rgba(118, 113, 113);
}
/**/
.zone .arrowtext {
position: absolute;
visibility: hidden;
white-space:nowrap;
background-color: black;
color: #fff;
padding: 5px;
border-radius: 6px;
top: -5px;
left: 105%;
}
.zone:hover .arrowtext {
visibility: visible;
}
<div class="pyramid">
<div class="zone">
<div>0. zero<span class="arrowtext">Tooltip text</span></div>
</div>
<div class="zone">1. One</div>
<div class="zone">2. Two</div>
<div class="zone">3. Three</div>
<div class="zone">4. Four</div>
</div>

How to have transparent scooped corners? [duplicate]

I would like to make a transparent cut out half circle shape using only CSS3. The only requirement is that all the elements that form the shape must be black or transparent.
I cannot use a black rectangle with a white circle on top of it because the half circle has to be transparent and let the background show through.
Desired shape :
May be can do it with CSS :after pseudo property like this:
body {
background: green;
}
.rect {
height: 100px;
width: 100px;
background: rgba(0, 0, 0, 0.5);
position: relative;
margin-top: 100px;
margin-left: 100px;
}
.circle {
display: block;
width: 100px;
height: 50px;
top: -50px;
left: 0;
overflow: hidden;
position: absolute;
}
.circle:after {
content: '';
width: 100px;
height: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;
border-radius: 100px;
background: rgba(0, 0, 0, 0);
position: absolute;
top: -100px;
left: -40px;
border: 40px solid rgba(0, 0, 0, 0.5);
}
<div class="rect"> <span class="circle"></span></div>
View on JSFiddle
You can use box-shadows to make the transparent cut out circle :
body {
background: url(http://i.imgur.com/qi5FGET.jpg) no-repeat;
background-size: cover;
}
div {
display: inline-block;
width: 300px; height: 300px;
position: relative;
overflow: hidden;
}
div:before {
content: '';
position: absolute;
bottom: 50%;
width: 100%; height: 100%;
border-radius: 100%;
box-shadow: 0px 300px 0px 300px #000;
}
.transparent {
opacity: 0.5;
}
<div></div>
<div class="transparent"></div>
This can be responsive with percentage lengths:
body {
background: url(http://lorempixel.com/output/people-q-c-640-480-1.jpg) no-repeat;
background-size: cover;
}
div {
width: 40%; height: 300px;
position: relative;
overflow: hidden;
}
div:before {
content: '';
position: absolute;
bottom: 50%;
width: 100%; height: 100%;
border-radius: 100%;
box-shadow: 0px 300px 0px 300px #000;
}
.transparent {
opacity: 0.5;
}
<div class="transparent"></div>
Using SVG:
Here is an alternate solution using SVG (though you haven't tagged it). Advantages of using SVG are:
It has better browser support when compared to radial-gradients.
SVG can support images inside the shape unlike the box-shadow approach.
While SVG is not supported by <= IE8 whereas box-shadow is, fallbacks can be provided.
svg {
height: 150px;
width: 150px;
}
polygon {
fill: black;
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<!-- Sample 1 - Using Clip Path -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<defs>
<clipPath id='clipper'>
<path d='M0,0 a50,50 0 1,0 100,0 l 0,100 -100,0' />
</clipPath>
</defs>
<polygon points='0,0 100,0 100,100 0,100' clip-path='url(#clipper)' />
</svg>
<!-- Sample 2 - Using Path -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<pattern id='bg' width='100' height='100' patternUnits='userSpaceOnUse'>
<image xlink:href='http://lorempixel.com/100/100/nature/1' height='100' width='100' />
</pattern>
<path d='M0,0 a50,50 0 1,0 100,0 l 0,100 -100,0 0,-100' fill='url(#bg)' />
</svg>
Using CSS:
CSS also has clip-path specifications and we can try something like in the below snippet.
.shape {
position: relative;
width: 100px;
height: 100px;
background-color: purple;
}
.shape:after {
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 100%;
width: 100%;
background: white;
-webkit-clip-path: ellipse(50% 20% at 50% 0%);
clip-path: ellipse(50% 20% at 50% 5%);
}
.shape.image{
background: url(http://lorempixel.com/100/100);
}
#shape-2 {
width: 100px;
height: 100px;
background-color: purple;
-webkit-clip-path: ellipse(50% 20% at 50% 20%);
clip-path: ellipse(50% 20% at 50% 20%);
}
/* Just for demo */
.shape{
float: left;
margin: 20px;
}
#shape-2 {
margin: 150px 20px 0px;
}
<div class="shape"></div>
<div class="shape image"></div>
<br/>
<div id="shape-2"></div>
But unlike SVG clip-path, the pure CSS version (that is, without using an inline or external SVG) doesn't seem to be able to support a path. It only supports shapes and so in this case, if you use the clip-path on the parent directly it would just produce an ellipse (like shown in the snippet). To overcome this, we would have to put the clip-path on a child (or a pseudo element) and this would mean that the clipped area would not be transparent.
Using Canvas:
The same can be done using Canvas also. Canvas commands are pretty similar to SVG and their advantages are also pretty similar. However, Canvas are raster based and hence doesn't scale as well as SVG does.
window.onload = function() {
/* Canvas example with path */
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'http://lorempixel.com/150/300';
ctx.beginPath();
ctx.moveTo(110, 0);
ctx.arc(60, 0, 50, 0, 3.14, false);
ctx.lineTo(10, 145);
ctx.lineTo(110, 145);
ctx.closePath();
ctx.fill();
/* Use below for using image as a fill */
/*img.onload = function(){
var ptrn = ctx.createPattern(img,'no-repeat');
ctx.fillStyle = ptrn;
ctx.fill();
}*/
}
/* Canvas example with clip path */
var canvasClip = document.getElementById('canvas-clip');
if (canvasClip.getContext) {
var ctxClip = canvasClip.getContext('2d');
ctxClip.beginPath();
ctxClip.moveTo(10, 145);
ctxClip.lineTo(10, 0);
ctxClip.arc(60, 0, 50, 0, Math.PI * 2, true);
ctxClip.lineTo(110, 145);
ctxClip.lineTo(10, 145);
ctxClip.clip();
ctxClip.fillStyle = 'tomato';
ctxClip.fill();
}
}
canvas {
height: 150px;
width: 300px;
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<canvas id='canvas'></canvas>
<canvas id='canvas-clip'></canvas>
Using Masks:
This shape can be created by using CSS (or) SVG masks also. CSS masks have very poor support and work currently only in Webkit powered browsers but SVG masks have much better support and should work in IE9+.
/* CSS Mask */
.shape {
width: 150px;
height: 150px;
background-color: black;
-webkit-mask-image: radial-gradient(circle closest-corner at 50% 0%, transparent 98%, white 99%);
mask-image: radial-gradient(circle closest-corner at 50% 0%, transparent 98%, white 99%);
}
/* End of CSS Mask */
svg {
height: 150px;
width: 150px;
}
polygon#shape {
fill: black;
mask: url(#masker);
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<!-- CSS Mask -->
<div class='shape'></div>
<!-- SVG Mask -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<defs>
<mask id='masker' x='0' y='0' width='100' height='100'>
<polygon points='0,0 100,0 100,100 0,100' fill='#fff' />
<circle r='50' cx='50' cy='0' fill='#000' />
</mask>
</defs>
<polygon points='0,0 100,0 100,100 0,100' id='shape' />
</svg>
You can do it really easily with a radial gradient.
DEMO
Result:
HTML:
<div class='shape'></div>
Relevant CSS:
.shape {
margin: 0 auto;
width: 10em; height: 16em;
/* WebKit browsers, old syntax */
background: -webkit-radial-gradient(50% 0, circle, transparent 30%, black 30%);
/* IE10, current versions of Firefox and Opera */
background: radial-gradient(circle at 50% 0, transparent 30%, black 30%);
}
See http://caniuse.com/#feat=css-gradients for detailed info on compatibility.
Try this.
body{
background-color:#333;
passing:0px;
height:0px;
}
#app{
background:#333 url('https://source.unsplash.com/random') no-repeat;
background-size:cover;
width:360px;
height:560px;
position:relative;
overflow:hidden;
}
.app-bar{
width:100%;
height:50px;
position:absolute;
bottom:0px;
left:0;
}
.app-bar .bar{
line-height:50px;
position:relative;
width:100%;
height:50px;
background-image: radial-gradient(circle 35px at 315px 0, transparent 700px, #f44336 50px);
}
.app-bar .bar i{
color:#FFF;
display:block;
line-height:50px;
float:left;
width:50px;
text-align:center;
cursor:pointer;
margin-top:0px;
}
.app-bar .bar i:hover{
background-color:rgba(0,0,0,.1);
}
.app-bar .bar button{
padding:0px;
box-sizing:border;
text-align:center;
margin:0px;
bordeR:0px;
outline:0px;
width:60px;
height:60px;
line-height:60px;
cursor:pointer;
color:#FFFFFF;
display:block;
border-radius:50%;
position:absolute;
top:-30px;
left:100%;
margin-left:-75px;
background-color:#f44336;
transition: all .2s ease;
}
.app-bar .bar button span{
line-height:60px;
font-size:30px;
}
.app-bar .bar button:hover{
transform:rotate(45deg);
transition: all .2s ease;
}
<div id="app">
<div class="app-bar">
<div class="bar">
<i class="material-icons">menu</i>
<i class="material-icons">search</i>
<button class="button">
<span class="material-icons">add</span>
</button>
</div>
</div>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/material-design-icons/3.0.1/iconfont/material-icons.min.css" >
Kyle Sevenokas did some good work. And I built off of that. Checkout the http://jsfiddle.net/FcaVX/1/
I basically collapsed the white div for the circle and gave it white borders. The OP question talked about the colors elements that make up the shape; nothing about its borders right?
I needed rounded corners only on the bottom of a responsive image. I started from #sandeep fiddle and improved it for my needs:
.rect
{
height: 85vh;
position: relative;
background-color: red;
width: 60vw;
}
.circle-helper{
display: block;
width: 100%;
padding-bottom: 50%;
bottom: 0;
left: 0;
overflow: hidden;
position: absolute;
background-color: transparent;
}
.circle{
display: block;
width: 100%;
padding-bottom: 100%;
// height: 500px;
bottom: 0;
left: 0;
overflow: hidden;
position: absolute;
background-color: transparent;
}
.circle:after{
box-sizing: content-box;
content: '';
width: 100%;
height: 100%;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
background: rgba(0,0,0,0);
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
border: 300px solid blue;
}
top: 50%
left: 50%
border: 300px solid blue
https://jsfiddle.net/mop00j22/
Right now, the only way I can think of would be to use a lot of 1-pixel wide black divs next to eachother with varying height. It's technically possible this way but should be deeply frowned upon. Also; you won't have anti-aliassing unless you want to go through the trouble of adding 1x1 pixel divs and do the anti-aliassing manually.
It might be more helpful if you gave an example of how you wanted to use this. Why does it need to be black/transparent only? As stated by omarello, the best solution on most circumstances is probably a simple GIF or PNG image with transparency.

Is it possible to create this shape (two partial circles joined together) with CSS?

I was trying to accomplish this border for two divs with CSS:
I tried just using border-radius, but the two partial circles aren't pressed together: http://jsfiddle.net/uwz6L79w/
.left {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
border-width: 4px;
border-color: black white black black;
border-style: solid;
border-radius: 60px
}
.right {
position: absolute;
left: 104px;
top: 0;
width: 100px;
height: 100px;
border-width: 4px;
border-color: black black black white;
border-style: solid;
border-radius: 60px;
}
<div class="left"></div>
<div class="right"></div>
I could just press them together further, but I'd have to have one div overlap the other, like this: http://jsfiddle.net/uwz6L79w/1/.
.left {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
border-width: 4px;
border-color: black white black black;
border-style: solid;
border-radius: 60px
}
.right {
position: absolute;
left: 70px;
top: 0;
width: 100px;
height: 100px;
border-width: 4px;
border-color: black black black white;
border-style: solid;
border-radius: 60px;
background: #f2f2f2;
}
<div class="left"></div>
<div class="right"></div>
Does anyone know how I could accomplish this without having the divs overlap?
SVG
This is also possible using SVG.
The SVG version is very short as it mainly only requires an Arc command to control its shape, size and position.
<svg width="50%" viewbox="0 0 100 50">
<path d="M50,35
a20,20 0 1,0 0,-20
a20,20 0 1,0 0,20z"
fill="white"
stroke="black">
</path>
</svg>
SVG stands for Scalable Vector Graphic. The web browser views it as an image but you can add text and normal HTML elements within an SVG.
It is well supported across all browsers as viewable here: CanIUse
SVG | MDN
Using Borders: Recommended
You could do it the same way as in your second snippet and use positioning like in the below snippet to avoid the two div elements from overlapping. Here the circles are produced by pseudo-elements and the overlapping part is cut out using overflow: hidden on their parents.
One thing to note here is that any hover effect should be added on the pseudo-elements and not the parent elements. This is because if the :hover is attached to parent then it would be triggered even when hovering outside the circle (because the parent is still a square).
Out of all the three solutions provided in this answer, this is the one that has the best browser support and would work even in IE8. Hence, this is the recommended one.
.left, .right {
position: relative;
float: left;
height: 200px;
width: 200px;
/* border: 1px solid; uncomment to see that they aren't overlapped */
overflow: hidden;
}
.left:after, .right:after {
position: absolute;
content: '';
height: calc(100% - 12px); /* 12px because of 6px border on either side */
width: calc(100% - 12px); /* 12px because of 6px border on either side */
border-radius: 50%;
border: 6px solid gray;
}
.left:after { right: -20px; }
.right:after { left: -20px; }
<div class='left'></div>
<div class='right'></div>
Using Radial Gradients:
If you don't want to use pseudo-elements and a overflow: hidden on the parent then you could also make use of radial-gradient background images to produce the circle and position them such that they end up producing the required effect. Below is a sample snippet for this approach.
The downside of this approach is the low browser support for radial-gradient. It would not work in IE9 and lower. Plus, the circles produced by radial gradients are generally jagged (rough edges) and when we modify the color stop positions to make it smoother, it gives a slightly blurred appearance.
.left, .right {
float: left;
height: 200px;
width: 200px;
/*border: 1px solid; uncomment to see that they aren't overlapped */
}
/* generally the below code should be enough to produce 6px thick circular border
.left {
background: radial-gradient(circle at 70% 50%, transparent calc(50% - 3px), gray calc(50% - 3px), gray calc(50% + 3px), transparent calc(50% + 3px));
}
.right {
background: radial-gradient(circle at 30% 50%, transparent calc(50% - 3px), gray calc(50% - 3px), gray calc(50% + 3px), transparent calc(50% + 3px));
}
*/
/* but it produces jagged edges and so we can change the color stops a bit like below
this produces smoother circles but the disadvantage is that they'd look a bit blurred */
.left {
background: radial-gradient(circle at 70% 50%, transparent calc(50% - 4px), gray calc(50% - 2px), gray calc(50% + 2px), transparent calc(50% + 4px));
}
.right {
background: radial-gradient(circle at 30% 50%, transparent calc(50% - 4px), gray calc(50% - 2px), gray calc(50% + 2px), transparent calc(50% + 4px));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='left'></div>
<div class='right'></div>
Using Clip Paths (CSS/SVG):
Another approach that could be used is to use clip-path. The advantage of this approach is that the hover effects would be triggered only when the cursor is within the circle (as can be seen in snippet). This is because the unnecessary portions are clipped.
Downside is again the poor browser support. CSS version of clip-path is supported only in Webkit but not in Firefox, IE whereas the SVG version (using inline SVG) is supported in Webkit, Firefox but not IE.
.left, .right {
float: left;
height: 200px;
width: 200px;
border-radius: 50%;
border: 6px solid gray;
}
/* CSS Clip Path - not supported by FF and IE */
.left.css-clip {
clip-path: polygon(0% 0%, 80% 0%, 80% 100%, 0% 100%);
}
.right.css-clip {
margin-left: -86px; /* 20% width * 2 (which is the clipped space) - border width */
clip-path: polygon(20% 0%, 100% 0%, 100% 100%, 20% 100%);
}
/* SVG Clip Path - supported by Webkit, FF but not IE */
.left.svg-clip {
clip-path: url(#clipper-left);
}
.right.svg-clip {
margin-left: -86px; /* 20% width * 2 (which is the clipped space) - border width */
clip-path: url(#clipper-right);
}
/* Just for demo */
h3{ clear: both; }
.left:hover, .right:hover{ background: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<h3>CSS Clip Path</h3>
<div class='left css-clip'></div>
<div class='right css-clip'></div>
<h3>SVG Clip Path</h3>
<div class='left svg-clip'></div>
<div class='right svg-clip'></div>
<!-- Inline SVG for SVG Clip Path -->
<svg width='0' height='0'>
<defs>
<clipPath id='clipper-left' clipPathUnits='objectBoundingBox'>
<path d='M0,0 .8,0 .8,1 0,1z' />
</clipPath>
<clipPath id='clipper-right' clipPathUnits='objectBoundingBox'>
<path d='M.2,0 1,0 1,1 .2,1z' />
</clipPath>
</defs>
</svg>
Here's a solution using just a single <div>.
.shape is a transparent circle with a 10px red border.
.shape::before is an opaque white circle with a 10px red border.
.shape::after is an opaque white circle (no border).
.shape {
margin: 6px auto;
}
.shape, .shape::before, .shape::after {
display: block;
position: relative;
width: 160px;
height: 160px;
border-radius: 160px;
}
.shape, .shape::before {
border: 10px solid #f00;
}
.shape::before, .shape::after {
content: "";
background-color: rgba(255, 255, 255, 1);
}
.shape::before {
top: -10px;
left: -150px;
}
.shape::after {
top: -180px;
}
<div class="shape"></div>
Here's a quick example I came up with. I haven't tested it in different browsers but it should be fairly well-supported.
HTML:
<div class="one"></div>
<div class="two"></div>
CSS:
div {
background: #fff;
border-radius: 50%;
float: left;
height: 100px;
position: relative;
width: 100px;
}
.one:after,
.two:after{
/* adjust this to set the border color */
background: #666;
border-radius: 50%;
content: "";
position: absolute;
z-index: -1;
/* adjust these to set the border width */
top: -5px;
right: -5px;
bottom: -5px;
left: -5px;
}
.two {
/* adjust this to set the overlap of the circles */
margin-left: -20px;
}
Live Demo
I'm coming back to this question (after 6 weeks), purely because the top-voted answer piqued my academic curiosity in svg, which I've rarely come across and never taken the time to learn.
Since I'm now learning svg, this question (which sent me off on my quest to learn it in the first place) seemed like the ideal challenge against which to try out some new skills.
So here is an alternative svg solution, the equivalent of my single <div> css solution above:
svg {
width: 310px;
height: 180px;
}
svg circle {
stroke: rgb(255,0,0);
stroke-width: 10;
fill: rgb(255,255,255);
}
svg circle:nth-of-type(3) {
stroke: rgb(255,255,255);
}
<svg viewbox="0 0 310 180">
<circle cx="90" cy="90" r="80" />
<circle cx="220" cy="90" r="80" />
<circle cx="90" cy="90" r="70" />
</svg>

Two gradients with two distinct sections with just one div element

I was wondering if it is possible to create a background effect like in the image below using just one div.
I know how to achieve it with two divs, but my situation would make it really easy if it could be done in one div (maybe using :after ???). The code for the gradients is:
.bg-green {
background-image: linear-gradient(-180deg, #95D428 0%, #20560B 100%);
}
.bg-red {
background-image: linear-gradient(-180deg, #F5515F 0%, #8E0A1E 100%;
}
Thanks :)
Yes, this is possible using a single div with a :pseudo-element.
What you could do is add the second linear-gradient to its :after :pseudo-element. Notice the use of rgba(r, b, g, a) instead of hex colors. This way you could control the opacity of the second linear-gradient by changing its alpha value.
body, html {
height: 100%;
margin: 0;
}
div {
width: 100%;
height: 100%;
position: relative;
background: linear-gradient(110deg, #5EDC29 45%, #FF0058 45%, #FF0058 100%);
z-index: -1;
}
div:after {
content: '';
position: absolute;
width: 100%;
height: 100%;
background-image: linear-gradient(-180deg, transparent 0%, rgba(0,0,0,0.6) 100%);
}
<div></div>
If you want the exact same gradient colors that you've posted in your question, you'll need clipPath.
body {
background: #222222;
margin: 0;
}
.bg {
width: 500px;
height: 300px;
background: linear-gradient(-180deg, #F5515F 0%, #8E0A1E 100%);
}
.bg-2 {
position: absolute;
width: 500px;
height: 300px;
top: 0;
z-index: -1;
background-image: linear-gradient(-180deg, #95D428 0%, #20560B 100%);
}
<svg width="500" height="300">
<defs>
<clipPath id="shape">
<path d="M300,0 L501,0 L501,301 L175,301z" />
</clipPath>
</defs>
<foreignObject clip-path="url(#shape)" width="500" height="300">
<div class="bg"></div>
</foreignObject>
</svg>
<div class="bg-2"></div>
You can get this effect, but you will need to set overflow hidden on the div and to set the background in a after pseudo class
.test {
width: 400px;
height: 300px;
border: solid 1px black;
position: relative;
overflow: hidden;
}
.test:after {
content: "";
position: absolute;
width: 160%;
height: 160%;
top: -30%;
left: -30%;
background-image: linear-gradient(-210deg, #95D428 0%, #20560B 100%), linear-gradient(-210deg, #F5515F 0%, #8E0A1E 100%);
background-position: top left, top right;
background-size: 50% 100%;
background-repeat: no-repeat;
-webkit-transform: rotate(30deg);
}
<div class="test"></div>
The after is rotated to get the inclined separation. The dimensions need to be bigger so as not to show missing corners.
And then, you assign the 2 linear gradients as 2 separate background-images,inclined an additional 30deg to compensate for the base inclination