Implement a rectangle shape with a transparent triangular cut at bottom - html

I want to create a non-rectangular image with CSS3, I think implement something like below image
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?

<----------------------------------------------- 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

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>

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.

Related

CSS diagonal div background

For a website I'm developing I need to include some diagonal shaped borders to a div. These are the main examples which I need to recreate.
double diagonal top border, triangle shaped
Now been scouting the web on how to achieve this, and my first thought as well would be by using ::before. However I can't get it to work without it being positioned absolute which messes up the entire page.
This is my code I have tried to achieve something like this:
.slider-container{
background-color: $blue;
width: 100%;
overflow: hidden;
position: relative;
.col-md-3{
img{
padding: 40px;
width: 100%;
max-width: 400px;
margin: auto;
}
}
&::before {
background: red;
bottom: 100%;
content: '';
display: block;
height: 100%;
position: absolute;
right: 0;
transform-origin: 100% 100%;
transform: rotate(-15deg);
width: 150%;
}
}
<section id="slider">
<div class="container-fluid">
<div class="row slider-container">
<div class="col-md-3">
<p>imgae 1</p>
</div>
<div class="col-md-3">
<p>imgae 2</p>
</div>
<div class="col-md-3">
<p>imgae 3</p>
</div>
<div class="col-md-3">
<p>imgae 4</p>
</div>
</div>
</div>
</section>
Note: it won't work in here but this is the result I get result
With just css and a bit tweaking based on your divs size you could create something like this:
.myclass {
width: 100px;
height: 100px;
background: linear-gradient(45deg, black 0%, black 26%, transparent 26%), linear-gradient(-45deg, black 0%, black 27%, transparent 27%)
}
.myclass2 {
width: 100px;
height: 100px;
background: linear-gradient(-45deg, blue 0%, blue 27%, transparent 27%), linear-gradient(45deg, blue 0%, blue 26%, red 26%)
}
With transparency:
<div class="myclass">My content here</div>
<br/>
Not as easy with transparent:
<div class="myclass2">My content here</div>
Edit: Just tested this in chrome, you might need special linear-gradients for older/other browsers.
The most simple way to achieve this would probably be to use a background image, though the effect may prove to be inconsistent on smaller devices. For this reason, you may want to consider using a hard-stop gradient.
.grad {
background: lightblue; /* For browsers that don't support gradients */
background: -webkit-linear-gradient(170deg, white 0%, white, 15%, lightblue 15%, lightblue 100%);
background: -o-linear-gradient(170deg, white 0%, white, 15%, lightblue 15%, lightblue 100%);
background: -moz-linear-gradient(170deg, white 0%, white, 15%, lightblue 15%, lightblue 100%);
background: linear-gradient(170deg, white 0%, white, 15%, lightblue 15%, lightblue 100%);
width: 100%;
padding: 20px;
}
<div class="grad">
<h1>Hard-stop gradient</h1>
<p>Using this type of gradient, you can create an angled background without using a background image.</p>
</div>
Using this, you can create a gradient from 0% to 15% that is white on both ends, followed by a gradient from 15% to 100% that's fully black. This completely removes the fading effect, giving you your angled background. It's probably the most efficient way as well since it only requires one line of CSS.
Something like this?
div {
background: yellow;
height: 150px;
overflow: hidden;
position: relative;
width: 300px;
}
div::before {
background: red;
bottom: 100%;
content: '';
display: block;
height: 100%;
position: absolute;
right: 0;
transform-origin: 100% 100%;
transform: rotate(-15deg);
width: 150%;
}
<div></div>
You can use clip-path.
body {
margin: 0;
padding: 0;
color: #ffffff;
}
.wrapper {
min-height: 100vh;
min-width: 100vw;
max-width: 100vw;
width: 100vw;
background-color: red;
}
.bg {
min-height: 100vh;
min-width: 100vw;
background-color: blue;
clip-path: polygon(80% 0, 100% 0, 100% 100%, 50% 100%);
}
<div class="wrapper">
<div class="bg"></div>
</div>
For me, the linear-gradient is not smooth ...
I would suggest either clip-path or svg:
svg {
display: block;
width: 100%;
height: 55px;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 10" preserveAspectRatio="none">
<polygon points="100 0 100 10 0 10" fill="white" />
</svg>
.arrow-right {
width: 0;
height: 0;
border-top: 60px solid green;
border-bottom: 60px solid transparent;
border-left: 60px solid green;
}

html/css: how to create a hexagonal image-placeholder

This is (almost) what I want to create:
HTML
<div class="hexagon1">
<div class="hexagon-in1">
<div class="hexagon-in2">
</div>
</div>
</div>
CSS
.hexagon1 {
overflow: hidden;
visibility: hidden;
-webkit-transform: rotate(120deg);
-moz-transform: rotate(120deg);
-ms-transform: rotate(120deg);
-o-transform: rotate(120deg);
transform: rotate(120deg);
width: 400px;
height: 200px;
margin: 0 0 0 -80px;
}
.hexagon-in1 {
overflow: hidden;
width: 100%;
height: 100%;
-webkit-transform: rotate(-60deg);
-moz-transform: rotate(-60deg);
-ms-transform: rotate(-60deg);
-o-transform: rotate(-60deg);
transform: rotate(-60deg);
}
.hexagon-in2 {
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-position: 50%;
background-image: url(http://placekitten.com/240/240);
visibility: visible;
-webkit-transform: rotate(-60deg);
-moz-transform: rotate(-60deg);
-ms-transform: rotate(-60deg);
-o-transform: rotate(-60deg);
transform: rotate(-60deg);
}
The problem is, that I need a border on the hexagon and if possible I would like to place the picture inside an img-tag. I tried adding the border on either div but I only got a border on top and bottom of the hexagon because of the visibility-hidden or the overflow-hidden attribute.
This is what I've found so far while googling:
http://csshexagon.com/
https://www.queness.com/post/13901/create-beautiful-hexagon-shapes-with-pure-css3
https://github.com/web-tiki/responsive-grid-of-hexagons
I've also found some questions concerning this matter here on Stackoverflow but neither of them explained how exactly you could create a hexagon. Also the hexagons in the examples are all standing on an edge, which is not what I want (as demonstrated in the code). I only need one hexagon and not a grid as well.
When I tried to change the styles of the examples it always ended in a desastrous chaos. This is why I would like to know how to create and to calculate the divs which are used to create a hexagon with border and a picture inside.
Which rate does the width have to the height?
How can I create a border that has the same width on each side?
Where do I have to place the picture as background-image?
How big should the picture be (in percentage to the divs)?
What transformations do you really need to create the hexagon? (I saw an example which used scale, rotate and translate to get a picture inside)
How can the rotation be calculated?
How do I calculate the margin needed?
As I am quite the novice in web-designing can someone explain this as simple as possible? It would suffice if someone can show me according to the example-code above how the numbers are calculated. I know that a hexagon has an inner angle of 120° and that's about it.
Thanks for your help in anticipation. :)
EDIT
Another page I found about hexagons but only to create the shape and not really putting either an image in it nor having a border around it:
http://jtauber.github.io/articles/css-hexagon.html
I will refer you to go with SVG approach to create this shape. Its really easy and also if you are considering a responsive web layout it can be achieved with this easily.
Reason for this approach -
1. You donot have to write much css.
2. Inline SVG is the modern web approach .
3. Scalable and durable.
4. Responsive
The polygon tag in the svg makes the shape that you want and with the css we can target the things we want to achieve like border in this case. Image has been linked using pattern.
Below is the snippet with example of what you need.
svg {
width: 30%;
margin: 0 auto;
}
#hex {
stroke-width: 2;
stroke: red;
}
<svg viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="https://dummyimage.com/600x400/red/fff" x="-25" width="150" height="100" />
</pattern>
</defs>
<polygon id="hex" points="50 1 95 25 95 75 50 99 5 75 5 25" fill="url(#img)"/>
</svg>
<svg viewbox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="https://farm4.staticflickr.com/3165/5733278274_2626612c70.jpg" x="-40" width="150" height="100" />
</pattern>
</defs>
<polygon id="hex" points="25 8 75 8 100 50 75 92 25 92 0 50" fill="url(#img)" />
</svg>
Important Note
Be informed that this solution does not work for those who want to create something similar supported by all browsers as for the time being IE does not support the clip-path-property used in this example!!
I've found a way to do it thanks to #SahilDhir although it's more of a workaround:
HTML
<div class="poligon">
<img src="http://lorempixel.com/g/600/400/">
</div>
CSS
.poligon {
display: inline-block;
position: relative;
width: 200px;
height: 180px;
background: red;
box-sizing: border-box;
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
.poligon img {
position: absolute;
top: 2px; /* equal to border thickness */
left: 2px; /* equal to border thickness */
width: 196px; /* container height - (border thickness * 2) */
height: 176px; /* container height - (border thickness * 2) */
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
Note that I did not calculate much here, but rather tried achieving a six-sided figure.
I will have the problem that my picture will have a transparent background, but I thought that I might produce a linear gradient to fill the background polygon. I will have to try that out first though ^^
I will not mark this as the final answer as my questions have not yet been answered truly. I still want to be able to create a hexagon as the one in the example I gave above where I would be able to adapt the heights and widths as well as the border thicknesses the way I want.
EDIT
As I did not find a better solution I have improved the one here and figured out the calculations needed:
HTML
<div class="poligon">
<div class="hex-background">
<img src="https://img.clipartfest.com/953d8641fe933437bbc41d48e6fc8492_yellow20stars20clipart-christmas-stars-clipart-without-background_532-506.png">
</div>
</div>
CSS
.poligon {
display: inline-block;
position: relative;
width: 120px;
height: 103.92px; /* width * 0.866 */
background: red;
box-sizing: border-box;
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
.hex-background {
position: absolute;
background-color: white;
top: 2px; /* equal to border thickness */
left: 2px; /* equal to border thickness */
width: 116px; /* container width - (border thickness * 2) */
height: 99.92px; /* container height - (border thickness * 2) */
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
.poligon img {
position: absolute;
width: 116px; /* container width - (border thickness * 2) */
height: 99.92px; /* container height - (border thickness * 2) */
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
The clip-path part is correct if you want a same-sided hexagon.
With the picture above you can see how I found those numbers ;) If you have further questions about this, don't hesitate to ask. I'll try to explain it the best I can.
I needed something similar, and the easiest way to do it is with two hexagons, one on top of the other.
Using the shapes provided by The Shapes of CSS:
#hexagon1 {
width: 100px;
height: 55px;
background: red;
position: absolute;
z-index: 2;
}
#hexagon1:before {
content: "";
position: absolute;
top: -25px;
left: 0;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 25px solid red;
}
#hexagon1:after {
content: "";
position: absolute;
bottom: -25px;
left: 0;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-top: 25px solid red;
}
#hexagon2 {
width: 101px;
height: 56px;
background: black;
position: relative;
z-index: 1;
}
#hexagon2:before {
content: "";
position: absolute;
top: -26px;
left: 0;
width: 0;
height: 0;
border-left: 51px solid transparent;
border-right: 51px solid transparent;
border-bottom: 26px solid black;
}
#hexagon2:after {
content: "";
position: absolute;
bottom: -26px;
left: 0;
width: 0;
height: 0;
border-left: 51px solid transparent;
border-right: 51px solid transparent;
border-top: 26px solid black;
}
Here's a CodePen I made for you: http://codepen.io/vogelbeere/pen/peYjNe

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>

How to create a div with an irregular shape?

Is it possible to create a div with an irregular shape with CSS? I already searched but I can't find a good example. The style is something like this:
/
/ \
/ \
/ \
/___________________________\
There should be a line on the top that connects it. Basically it has different height on the left and right side.
THE SVG WAY
Since the shape you request is not possible with only CSS, I suggest you use SVG to draw the shape.
The following piece of code will create the below shape:
<svg height="150" width="150">
<polygon points="20,10 100,30 120,100 0,100" style="fill:red;" />
</svg>
SVG is a powerful tool to make shapes otherwise impossible without using images. Read up on it here.
HTML & CSS Answer
This can be done by using perspective and transform. You create two divs: one that will get the perspective and one that will be transformed. Just know that anything in the .test-div will also be transformed, so if you put text in there, it will also get transformed.
.wrapper {
width: 100px;
height: 100px;
margin-left: 100px;
perspective: 150px;
}
.test {
height: 100px;
width: 100px;
background: red;
transform: rotateX(45deg);
}
<div class="wrapper">
<div class="test"></div>
</div>
Result
JSFIDDLE
This can also be done using CSS clip-path
div {
width: 200px;
height: 150px;
background: red;
-webkit-clip-path: polygon(20% 10%, 85% 30%, 100% 100%, 0% 100%);
clip-path: polygon(20% 10%, 85% 30%, 100% 100%, 0% 100%);
}
<div></div>
You can then just change the background element if you need an image.
div {
width: 200px;
height: 150px;
background: url(https://lorempixel.com/200/150/);
-webkit-clip-path: polygon(20% 10%, 85% 30%, 100% 100%, 0% 100%);
clip-path: polygon(20% 10%, 85% 30%, 100% 100%, 0% 100%);
}
<div></div>
In their current state, clip-paths aren't as widely supported as inline or imported SVG but is a much cleaner, and in some cases, easier variant to use.
Browser Support
You can try using overflow hidden and transforms, though the best approach will be svg.
HTML
<div class="out">
<div class="in"></div>
</div>
CSS
body { background:url(http://www.placecage.com/g/640/480) }
.out {
height: 100px;
width: 150px;
transform-origin: 0% 100%;
transform: skew(-10deg);
overflow: hidden;
}
.in {
height: 110px;
width: 148px;
position: relative;
left: -43px;
top: -7px;
transform-origin: 0% 0%;
transform: skew(30deg) rotate(10deg);
background: rgba(9,40,0,0.8);
transition: 0.5s ease;
}
.in:hover {
background: rgba(50,0,70,0.7);
transition: 0.5s ease;
}
FIDDLE : https://jsfiddle.net/xb1jxd7g/
Following it for diamond and make a way around to rotate it and you'll get your shape :
#diamond-shield {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom: 20px solid red;
position: relative;
top: -50px;
}
#diamond-shield:after {
content: '';
position: absolute;
left: -50px; top: 20px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top: 70px solid red;
}

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