Related
I'm looking to "cut" the top left corner of a div, like if you had folded the corner of a page down.
I'd like to do it in pure CSS, are there any methods?
If the parent element has a solid color background, you can use pseudo-elements to create the effect:
div {
height: 300px;
background: red;
position: relative;
}
div:before {
content: '';
position: absolute;
top: 0; right: 0;
border-top: 80px solid white;
border-left: 80px solid red;
width: 0;
}
<div></div>
http://jsfiddle.net/2bZAW/
P.S. The upcoming border-corner-shape is exactly what you're looking for. Too bad it might get cut out of the spec, and never make it into any browsers in the wild :(
CSS Clip-Path
Using a clip-path is a new, up and coming alternative. Its starting to get supported more and more and is now becoming well documented. Since it uses SVG to create the shape, it is responsive straight out of the box.
CanIUse
Clip Path Generator
div {
width: 200px;
min-height: 200px;
-webkit-clip-path: polygon(0 0, 0 100%, 100% 100%, 100% 25%, 75% 0);
clip-path: polygon(0 0, 0 100%, 100% 100%, 100% 25%, 75% 0);
background: lightblue;
}
<div>
<p>Some Text</p>
</div>
CSS Transform
I have an alternative to web-tiki's transform answer.
body {
background: lightgreen;
}
div {
width: 200px;
height: 200px;
background: transparent;
position: relative;
overflow: hidden;
}
div.bg {
width: 200%;
height: 200%;
background: lightblue;
position: absolute;
top: 0;
left: -75%;
transform-origin: 50% 50%;
transform: rotate(45deg);
z-index: -1;
}
<div>
<div class="bg"></div>
<p>Some Text</p>
</div>
If you need a transparent cut out edge, you can use a rotated pseudo element as a background for the div and position it to cut out the desired corner:
body {
background: url(http://i.imgur.com/k8BtMvj.jpg);
background-size: cover;
}
div {
position: relative;
width: 50%;
margin: 0 auto;
overflow: hidden;
padding: 20px;
text-align: center;
}
div:after {
content: '';
position: absolute;
width: 1100%; height: 1100%;
top: 20px; right: -500%;
background: rgba(255,255,255,.8);
transform-origin: 54% 0;
transform: rotate(45deg);
z-index: -1;
}
<div>
... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>
</div>
Note that this solution uses transforms and you need to add the required vendor prefixes. For more info see canIuse.
To cut the bottom right edge, you can change the top, transform and transform-origin properties of the pseudo element to:
body {
background: url(http://i.imgur.com/k8BtMvj.jpg);
background-size: cover;
}
div {
position: relative;
width: 50%;
margin: 0 auto;
overflow: hidden;
padding: 20px;
text-align: center;
}
div:after {
content: '';
position: absolute;
width: 1100%; height: 1100%;
bottom: 20px; right: -500%;
background: rgba(255,255,255,.8);
transform-origin: 54% 100%;
transform: rotate(-45deg);
z-index: -1;
}
<div>
... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>
</div>
Here is another approach using CSS transform: skew(45deg) to produce the cut corner effect. The shape itself involves three elements (1 real and 2 pseudo-elements) as follows:
The main container div element has overflow: hidden and produces the left border.
The :before pseudo-element which is 20% the height of the parent container and has a skew transform applied to it. This element prodcues the border on the top and cut (slanted) border on the right side.
The :after pseudo-element which is 80% the height of the parent (basically, remaining height) and produces the bottom border, the remaining portion of the right border.
The output produced is responsive, produces a transparent cut at the top and supports transparent backgrounds.
div {
position: relative;
height: 100px;
width: 200px;
border-left: 2px solid beige;
overflow: hidden;
}
div:after,
div:before {
position: absolute;
content: '';
width: calc(100% - 2px);
left: 0px;
z-index: -1;
}
div:before {
height: 20%;
top: 0px;
border: 2px solid beige;
border-width: 2px 3px 0px 0px;
transform: skew(45deg);
transform-origin: right bottom;
}
div:after {
height: calc(80% - 4px);
bottom: 0px;
border: 2px solid beige;
border-width: 0px 2px 2px 0px;
}
.filled:before, .filled:after {
background-color: beige;
}
/* Just for demo */
div {
float: left;
color: beige;
padding: 10px;
transition: all 1s;
margin: 10px;
}
div:hover {
height: 200px;
width: 300px;
}
div.filled{
color: black;
}
body{
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<div class="cut-corner">Some content</div>
<div class="cut-corner filled">Some content</div>
The below is another method to produce the cut corner effect by using linear-gradient background images. A combination of 3 gradient images (given below) is used:
One linear gradient (angled towards bottom left) to produce the cut corner effect. This gradient has a fixed 25px x 25px size.
One linear gradient to provide a solid color to the left of the triangle that causes the cut effect. A gradient is used even though it produces a solid color because we can control size, position of background only when images or gradients are used. This gradient is positioned at -25px on X-axis (basically meaning it would end before the place where the cut is present).
Another gradient similar to the above which again produces a solid color but is positioned at 25px down on the Y-axis (again to leave out the cut area).
The output produced is responsive, produces transparent cut and doesn't require any extra elements (real or pseudo). The drawback is that this approach would work only when the background (fill) is a solid color and it is very difficult to produce borders (but still possible as seen in the snippet).
.cut-corner {
height: 100px;
width: 200px;
background-image: linear-gradient(to bottom left, transparent 50%, beige 50%), linear-gradient(beige, beige), linear-gradient(beige, beige);
background-size: 25px 25px, 100% 100%, 100% 100%;
background-position: 100% 0%, -25px 0%, 100% 25px;
background-repeat: no-repeat;
}
.filled {
background-image: linear-gradient(black, black), linear-gradient(black, black), linear-gradient(black, black), linear-gradient(black, black), linear-gradient(to bottom left, transparent calc(50% - 1px), black calc(50% - 1px), black calc(50% + 1px), beige calc(50% + 1px)), linear-gradient(beige, beige), linear-gradient(beige, beige);
background-size: 2px 100%, 2px 100%, 100% 2px, 100% 2px, 25px 25px, 100% 100%, 100% 100%;
background-position: 0% 0%, 100% 25px, -25px 0%, 0px 100%, 100% 0%, -25px 0%, 100% 25px;
}
/* Just for demo */
*{
box-sizing: border-box;
}
div {
float: left;
color: black;
padding: 10px;
transition: all 1s;
margin: 10px;
}
div:hover {
height: 200px;
width: 300px;
}
body{
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<div class="cut-corner">Some content</div>
<div class="cut-corner filled">Some content</div>
You could use linear-gradient. Let's say the parent div had a background image, and you needed a div to sit on top of that with a gray background and a dog-eared left corner. You could do something like this:
.parent-div { background: url('/image.jpg'); }
.child-div {
background: #333;
background: linear-gradient(135deg, transparent 30px, #333 0);
}
See it on CodePen
Further reading:
CSS Gradients on CSS-Tricks
Beveled corners & negative border-radius with CSS3 gradients
I have an online generator for some of the below code: https://css-generators.com/custom-corners/
You can use mask and CSS variables to have better control over the whole shape. It's responsive, transparent and allow any kind of background:
.box {
--all:0px;
width:200px;
height:150px;
display:inline-block;
margin:10px;
background:red;
-webkit-mask:
linear-gradient( 45deg, transparent 0 var(--bottom-left,var(--all)) ,#fff 0) bottom left,
linear-gradient( -45deg, transparent 0 var(--bottom-right,var(--all)),#fff 0) bottom right,
linear-gradient( 135deg, transparent 0 var(--top-left,var(--all)) ,#fff 0) top left,
linear-gradient(-135deg, transparent 0 var(--top-right,var(--all)) ,#fff 0) top right;
-webkit-mask-size:50.5% 50.5%;
-webkit-mask-repeat:no-repeat;
}
body {
background:grey;
}
<div class="box" style="--top-left:20px"></div>
<div class="box" style="--top-right:20px;--bottom-right:50px;background:radial-gradient(red,yellow)"></div>
<div class="box" style="--all:30px;background:url(https://picsum.photos/id/104/200/200)"></div>
<div class="box" style="--all:30px;--bottom-right:0px;background:linear-gradient(red,blue)"></div>
<div class="box" style="--all:50%;width:150px;background:green"></div>
<div class="box" style="--all:12%;width:150px;background:repeating-linear-gradient(45deg,#000 0 10px,#fff 0 20px)"></div>
And below in case you want to consider border:
.box {
--all:0px;
--b:pink;
width:200px;
height:150px;
display:inline-block;
margin:10px;
border:5px solid var(--b);
background:
linear-gradient( 45deg, var(--b) 0 calc(var(--bottom-left,var(--all)) + 5px) ,transparent 0) bottom left /50% 50%,
linear-gradient( -45deg, var(--b) 0 calc(var(--bottom-right,var(--all)) + 5px),transparent 0) bottom right/50% 50%,
linear-gradient( 135deg, var(--b) 0 calc(var(--top-left,var(--all)) + 5px) ,transparent 0) top left /50% 50%,
linear-gradient(-135deg, var(--b) 0 calc(var(--top-right,var(--all)) + 5px) ,transparent 0) top right /50% 50%,
var(--img,red);
background-origin:border-box;
background-repeat:no-repeat;
-webkit-mask:
linear-gradient( 45deg, transparent 0 var(--bottom-left,var(--all)) ,#fff 0) bottom left,
linear-gradient( -45deg, transparent 0 var(--bottom-right,var(--all)),#fff 0) bottom right,
linear-gradient( 135deg, transparent 0 var(--top-left,var(--all)) ,#fff 0) top left,
linear-gradient(-135deg, transparent 0 var(--top-right,var(--all)) ,#fff 0) top right;
-webkit-mask-size:50.5% 50.5%;
-webkit-mask-repeat:no-repeat;
}
body {
background:grey;
}
<div class="box" style="--top-left:20px"></div>
<div class="box" style="--top-right:20px;--bottom-right:50px;--img:radial-gradient(red,yellow);--b:white;"></div>
<div class="box" style="--all:30px;--img:url(https://picsum.photos/id/104/200/200) center/cover;--b:orange;"></div>
<div class="box" style="--all:30px;--bottom-right:0px;--img:linear-gradient(red,blue)"></div>
<div class="box" style="--all:50%;width:150px;--img:green;--b:red;"></div>
<div class="box" style="--all:12%;width:150px;--img:repeating-linear-gradient(45deg,#000 0 10px,#fff 0 20px)"></div>
Let's also add some radius:
.box {
--all:0px;
--b:pink;
width:200px;
height:150px;
display:inline-block;
margin:10px;
filter:url(#round);
}
.box::before {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background:var(--img,red);
-webkit-mask:
linear-gradient( 45deg, transparent 0 var(--bottom-left,var(--all)) ,#fff 0) bottom left,
linear-gradient( -45deg, transparent 0 var(--bottom-right,var(--all)),#fff 0) bottom right,
linear-gradient( 135deg, transparent 0 var(--top-left,var(--all)) ,#fff 0) top left,
linear-gradient(-135deg, transparent 0 var(--top-right,var(--all)) ,#fff 0) top right;
-webkit-mask-size:50.5% 50.5%;
-webkit-mask-repeat:no-repeat;
}
body {
background:grey;
}
<div class="box" style="--top-left:20px"></div>
<div class="box" style="--top-right:20px;--bottom-right:50px;--img:radial-gradient(red,yellow);--b:white;"></div>
<div class="box" style="--all:30px;--img:url(https://picsum.photos/id/104/200/200) center/cover;--b:orange;"></div>
<div class="box" style="--all:30px;--bottom-right:0px;--img:linear-gradient(red,blue)"></div>
<div class="box" style="--all:50%;width:150px;--img:green;--b:red;"></div>
<div class="box" style="--all:12%;width:150px;--img:repeating-linear-gradient(45deg,#000 0 10px,#fff 0 20px)"></div>
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="round">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
This code allows you to cut corners on each side of the rectangle:
div {
display:block;
height: 300px;
width: 200px;
background: url('http://lorempixel.com/180/290/') no-repeat;
background-size:cover;
-webkit-clip-path: polygon(10px 0%, calc(100% - 10px) 0%, 100% 10px, 100% calc(100% - 10px), calc(100% - 10px) 100%, 10px 100%, 0% calc(100% - 10px), 0% 10px);
clip-path: polygon(10px 0%, calc(100% - 10px) 0%, 100% 10px, 100% calc(100% - 10px), calc(100% - 10px) 100%, 10px 100%, 0% calc(100% - 10px), 0% 10px);
}
http://jsfiddle.net/2bZAW/5552/
If you need a diagonal border instead of a diagonal corner, you can stack 2 divs with each a pseudo element:
DEMO
http://codepen.io/remcokalf/pen/BNxLMJ
.container {
padding: 100px 200px;
overflow: hidden;
}
div.diagonal {
background: #da1d00;
color: #fff;
font-family: Arial, Helvetica, sans-serif;
width: 300px;
height: 300px;
padding: 70px;
position: relative;
margin: 30px;
float: left;
}
div.diagonal2 {
background: #da1d00;
color: #fff;
font-family: Arial, Helvetica, sans-serif;
width: 300px;
height: 300px;
padding: 70px;
position: relative;
margin: 30px;
background: #da1d00 url(http://www.remcokalf.nl/background.jpg) left top;
background-size: cover;
float: left;
}
div.diagonal3 {
background: #da1d00;
color: #da1d00;
font-family: Arial, Helvetica, sans-serif;
width: 432px;
height: 432px;
padding: 4px;
position: relative;
margin: 30px;
float: left;
}
div.inside {
background: #fff;
color: #da1d00;
font-family: Arial, Helvetica, sans-serif;
width: 292px;
height: 292px;
padding: 70px;
position: relative;
}
div.diagonal:before,
div.diagonal2:before {
content: '';
position: absolute;
top: 0;
left: 0;
border-top: 80px solid #fff;
border-right: 80px solid transparent;
width: 0;
}
div.diagonal3:before {
content: '';
position: absolute;
top: 0;
left: 0;
border-top: 80px solid #da1d00;
border-right: 80px solid transparent;
width: 0;
z-index: 1;
}
div.inside:before {
content: '';
position: absolute;
top: -4px;
left: -4px;
border-top: 74px solid #fff;
border-right: 74px solid transparent;
width: 0;
z-index: 2;
}
h2 {
font-size: 30px;
line-height: 1.3em;
margin-bottom: 1em;
position: relative;
z-index: 1000;
}
p {
font-size: 16px;
line-height: 1.6em;
margin-bottom: 1.8em;
}
#grey {
width: 100%;
height: 400px;
background: #ccc;
position: relative;
margin-top: 100px;
}
#grey:before {
content: '';
position: absolute;
top: 0;
left: 0;
border-top: 80px solid #fff;
border-right: 80px solid #ccc;
width: 400px;
}
<div id="grey"></div>
<div class="container">
<div class="diagonal">
<h2>Header title</h2>
<p>Yes a CSS diagonal corner is possible</p>
</div>
<div class="diagonal2">
<h2>Header title</h2>
<p>Yes a CSS diagonal corner with background image is possible</p>
</div>
<div class="diagonal3">
<div class="inside">
<h2>Header title</h2>
<p>Yes a CSS diagonal border is even possible with an extra div</p>
</div>
</div>
</div>
We had the problem of different background colors for our cutted elements. And we only wanted upper right und bottom left corner.
body {
background-color: rgba(0,0,0,0.3)
}
.box {
position: relative;
display: block;
background: blue;
text-align: center;
color: white;
padding: 15px;
margin: 50px;
}
.box:before,
.box:after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 100%;
border-bottom: 15px solid blue;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
}
.box:before{
border-left: 15px solid blue;
}
.box:after{
border-right: 15px solid blue;
}
.box:after {
bottom: auto;
top: 100%;
border-bottom: none;
border-top: 15px solid blue;
}
/* Active box */
.box.active{
background: white;
color: black;
}
.active:before,
.active:after {
border-bottom: 15px solid white;
}
.active:before{
border-left: 15px solid white;
}
.active:after{
border-right: 15px solid white;
}
.active:after {
border-bottom: none;
border-top: 15px solid white;
}
<div class="box">
Some text goes here. Some text goes here. Some text goes here. Some text goes here.<br/>Some text goes here.<br/>Some text goes here.<br/>Some text goes here.<br/>Some text goes here.<br/>Some text goes here.<br/>
</div>
<div class="box">
Some text goes here.
</div>
<div class="box active">
Some text goes here.
<span class="border-bottom"></span>
</div>
<div class="box">
Some text goes here.
</div>
You can use clip-path, as Stewartside and Sviatoslav Oleksiv mentioned. To make things easy, I created a sass mixin:
#mixin cut-corners ($left-top, $right-top: 0px, $right-bottom: 0px, $left-bottom: 0px) {
clip-path: polygon($left-top 0%, calc(100% - #{$right-top}) 0%, 100% $right-top, 100% calc(100% - #{$right-bottom}), calc(100% - #{$right-bottom}) 100%, $left-bottom 100%, 0% calc(100% - #{$left-bottom}), 0% $left-top);
}
.cut-corners {
#include cut-corners(10px, 0, 25px, 50px);
}
According to Harry's linear-gradient solution (answered Oct 14 '15 at 9:55), it says that opacity background isn't possible, I tried it and yep, it isn't.
But! I found a workaround. No it's not super optimised, but it worked. So here's my solution. Since Harry doesn't use pseudo element, we can achieve this by creating one.
Set position relative to the container and create a pseudo element with the same linear-gradient properties. In other words, just clone it. Then put a transparent background for the container, and lets say a black background for the clone. Put a position absolute on it, a z-index of -1 and an opacity value (ie. 50%). It will do the job. Again it's a workaround and it's not perfect but it works just fine.
.cut-corner {
position: relative;
color: white;
background-repeat: no-repeat;
background-image: linear-gradient(white, white), linear-gradient(white, white), linear-gradient(white, white), linear-gradient(white, white), linear-gradient(to bottom left, transparent calc(50% - 1px), white calc(50% - 1px), white calc(50% + 1px), transparent calc(50% + 1px)), linear-gradient(transparent, transparent), linear-gradient(transparent, transparent);
background-size: 2px 100%, 2px 100%, 100% 2px, 100% 2px, 25px 25px, 100% 100%, 100% 100%;
background-position: 0% 0%, 100% 25px, -25px 0%, 0px 100%, 100% 0%, -25px 0%, 100% 25px;
}
.cut-corner:after {
content: "";
position: absolute;
left: 0;
bottom: 0;
right: 0;
top: 0;
z-index: -1;
opacity: 0.5;
background-repeat: no-repeat;
background-image: linear-gradient(white, white), linear-gradient(white, white), linear-gradient(white, white), linear-gradient(white, white), linear-gradient(to bottom left, transparent calc(50% - 1px), white calc(50% - 1px), white calc(50% + 1px), black calc(50% + 1px)), linear-gradient(black, black), linear-gradient(black, black);
background-size: 2px 100%, 2px 100%, 100% 2px, 100% 2px, 25px 25px, 100% 100%, 100% 100%;
background-position: 0% 0%, 100% 25px, -25px 0%, 0px 100%, 100% 0%, -25px 0%, 100% 25px;
}
/* Just for demo */
div {
padding: 10px;
}
body{
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<div class="cut-corner">
Some content<br>
Some content<br>
Some content<br>
Some content
</div>
With a small edit to Joseph's code, the element does not require a solid background:
div {
height: 300px;
background: url('http://images2.layoutsparks.com/1/190037/serene-nature-scenery-blue.jpg');
position: relative;
}
div:before {
content: '';
position: absolute;
top: 0; right: 0;
border-top: 80px solid white;
border-left: 80px solid rgba(0,0,0,0);
width: 0;
}
http://jsfiddle.net/2bZAW/1921/
This use of 'rgba(0,0,0,0)' allows the inner 'corner' to be invisible
.
You can also edit the 4th parameter 'a', where 0 < a < 1, to have a shadow for more of a 'folded-corner' effect:
http://jsfiddle.net/2bZAW/1922/ (with shadow)
NOTE: RGBA color values are supported in IE9+, Firefox 3+, Chrome, Safari, and in Opera 10+.
by small modification of Joshep's code...You can use this code which seems like right corner folded down as per your requirement.
div {
height: 300px;
background: red;
position: relative;
}
div:before {
content: '';
position: absolute;
top: 0; right: 0;
border-top: 80px solid white;
border-left: 80px solid blue;
width: 0;
}
Another one solution:
html:
<div class="background">
<div class="container">Hello world!</div>
</div>
css:
.background {
position: relative;
width: 50px;
height: 50px;
border-right: 150px solid lightgreen;
border-bottom: 150px solid lightgreen;
border-radius: 10px;
}
.background::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
border: 25px solid lightgreen;
border-top-color: transparent;
border-left-color: transparent;
}
.container {
position: absolute;
padding-left: 25px;
padding-top: 25px;
font-size: 38px;
font-weight: bolder;
}
https://codepen.io/eggofevil/pen/KYaMjV
I recently cut off the top right corner and overlaid the tabs like folders. Complete code noob, so ignore the shitty code, but I did this by combining a square, a triangle, and a rectangle... This may or may not be a new approach, but hopefully, someone finds it helpful.
https://i.stack.imgur.com/qFMRz.png
Here is the HTML:
<!DOCTYPE html>
<html lang ="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="folders">
<div class="container">
<div class="triangleOne">
<p class="folderNames">Home</p>
</div>
<div class="triangleOneCut">
</div>
<div class="triangleOneFill">
</div>
</div>
<div class="container2">
<div class="triangleOne blue">
<p class="folderNames">About</p>
</div>
<div class="triangleOneCut blueCut">
</div>
<div class="triangleOneFill blue">
</div>
</div>
<div class="container3">
<div class="triangleOne green">
<p class="folderNames">Contact</p>
</div>
<div class="triangleOneCut greenCut">
</div>
<div class="triangleOneFill green">
</div>
</div>
</div>
</body>
</html>
Here is the CSS:
.triangleOne {
height: 50px;
width: 40px;
background: red;
border-radius: 5px 0px 0px 5px;
position: absolute;
}
.triangleOneCut {
content: '';
position: absolute;
top: 0; left: 40px;
border-top: 10px solid transparent;
border-left: 10px solid red;
width: 0;
}
.triangleOneFill {
content: '';
position: absolute;
top: 10px; left: 40px;
width: 10px;
height: 40px;
background-color: red;
border-radius: 0px 0px 5px 0px;
}
.container {
position: relative;
height: 50px;
width: 50px;
display: inline-block;
z-index: 3;
}
.container2 {
position: relative;
height: 50px;
width: 50px;
display: inline-block;
left: -10px;
z-index: 2;
}
.container3 {
position: relative;
height: 50px;
width: 50px;
display: inline-block;
left: -20px;
z-index: 1;
}
.blue {
background-color: blue;
}
.green {
background-color: green;
}
.blueCut {
border-left: 10px solid blue;
}
.greenCut {
border-left: 10px solid green;
}
.folders {
width: 160px;
height: 50px;
/* border: 10px solid white; */
margin: auto;
padding-left: 25px;
margin-top: 100px;
}
.folderNames {
text-align: right;
padding-left: 2px;
color: white;
margin-top: 1.5px;
font-family: monospace;
font-size: 6.5px;
border-bottom: double 1.5px white;
}
Here's a solution for if you don't want a solid-color background, i.e. just a border with square-cut corners.
.container {
width: 100px;
height: 100px;
background-color: white;
border: 1px solid black;
position: relative;
}
.border {
position: absolute;
width: 100%;
height: 100%;
}
.border:before {
content: '';
position: absolute;
border-top: 15px solid white;
border-left: 15px solid white;
width: 0;
}
.border:after {
content: '';
position: absolute;
width: 16px;
height: 1px;
background: black;
}
.tl:before { top: -5px; left: -5px; transform: rotate(-45deg); }
.tl:after { top: 5px; left: -3px; transform: rotate(-45deg);}
.tr:before { top: -5px; right: -5px; transform: rotate(45deg); }
.tr:after { top: 5px; right: -3px; transform: rotate(45deg); }
.bl:before { bottom: -5px; left: -5px; transform: rotate(45deg); }
.bl:after { bottom: 5px; left: -3px; transform: rotate(45deg); }
.br:before { bottom: -5px; right: -5px; transform: rotate(-45deg); }
.br:after { bottom: 5px; right: -3px; transform: rotate(-45deg); }
<html>
<body>
<div class="container">
<div class="border tl"></div>
<div class="border tr"></div>
<div class="border bl"></div>
<div class="border br"></div>
</div>
</body>
</html>
I want to cut left top corner of a box using CSS like this.
keep in mind that background is transparent.
Nearly the same solution as OriDrori's answer but more flexible (if you need fixed-width cutted corner).
This gradient will look the same regardless of .card width and height.
body {
background: purple;
}
.card {
width: 200px;
height: 200px;
background: linear-gradient(135deg, transparent 20px, white 20px);
}
<div class="card"></div>
You can use a simple linear gradient for that:
body {
background: purple;
}
.card {
width: 200px;
height: 200px;
background: linear-gradient(to bottom right, transparent 5%, white 5%);
}
<div class="card"></div>
You can use clip-path
https://developer.mozilla.org/en/docs/Web/CSS/clip-path
and use something like this:
div#test{
background:red;
width:200px;
height: 200px;
-webkit-clip-path: polygon(22% 0, 100% 0, 100% 100%, 0 100%, 0 20%);
clip-path: polygon(22% 0, 100% 0, 100% 100%, 0 100%, 0 20%);
}
<div id="test"></div>
With a pseudo and transform you can do that, and it has good browser support (from IE9)
body {
background: url(https://picsum.photos/400/300) center / cover;
}
div {
position: relative;
width: 200px;
height: 200px;
overflow: hidden;
}
div::before {
content: '';
position: absolute;
left: calc(50% + 25px); /* 25px is height/width of the cut */
top: calc(50% + 25px);
width: 141.5%;
height: 141.5%;
transform: translate(-50%,-50%) rotate(45deg);
background: #eee;
opacity: 0.8;
}
<div></div>
As pointed out, if you need it to scale on different aspect ratio's, use this
body {
background: url(https://picsum.photos/400/300) center / cover;
}
div {
position: relative;
width: 80vw;
height: 80vh;
overflow: hidden;
}
div::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 1000%;
height: 5000%;
transform: rotate(45deg) translate(25px,-50%); /* 25px for the cut height/width */
transform-origin: left top;
background: #eee;
opacity: 0.8;
}
<div></div>
I am trying to achieve this effect in CSS:
This is my code:
#test {position: relative;margin: 100px;}
#test::after {
background-color: maroon;
box-shadow: 0 -50px 10px 7px gray;
height: 45px;
left: -15px;
position: absolute;
top: 40px;
transform: perspective(150px) rotateX(-45deg);
transform-origin: center bottom 0;
width: 60px;
content: "";
}
<div id="test"></div>
but I am not achieving the expected result with the cast shadow. I wonder if its even possible to do this with CSS only?
Fiddle Demo
Maybe something like this? I added another element representing the shadow:
#shadow {
height: 90px;
left: -15px;
position: absolute;
top: 30px;
background: rgba(0, 0, 0, 0);
width: 60px;
transform: perspective(50px) rotateX(25deg);
box-shadow: 0 -106px 20px 17px #808080;
}
https://jsfiddle.net/zcyy09mp/4/
As mentioned in my comment, I would generally recommend the approach used in my fiddle (which is, use another pseudo-element) or the one in Martin's answer (which is, to use an extra element) but as you've mentioned that the other pseudo-element is already used and you are trying to avoid any extra elements, the other approach is to use gradients as background for the parent element. By using the appropriate side-to-side gradients with background-position, background-size, we can not only get the shape but also an effect very similar to the blurred nature of the shadow.
Below is a sample snippet: (the output is also reasonably responsive as you can see by hovering it)
#test {
position: relative;
height: 100px;
width: 100px;
margin: 100px;
background: linear-gradient(to bottom right, transparent 45%, gray 55%), linear-gradient(to bottom left, transparent 45%, gray 55%), linear-gradient(to bottom, transparent, gray), linear-gradient(gray, gray);
background-repeat: no-repeat;
background-size: 30px 95%, 30px 95%, calc(100% - 60px) 8px, calc(100% - 60px) calc(100% - 8px);
background-position: 0% 100%, 100% 100%, 50% 4px, 50% 100%;
}
#test::after {
position: absolute;
content: "";
background-color: maroon;
width: 100%;
height: 45%;
left: 0px;
top: 100%;
transform: perspective(150px) rotateX(-45deg);
transform-origin: center top 0;
}
/* just for demo */
#test {
transition: all 1s;
}
#test:hover {
height: 200px;
width: 200px;
}
<div id="test"></div>
In the below snippet, I have given a different color for each of the gradient just to visually show how it is achieved.
#test {
position: relative;
height: 100px;
width: 100px;
margin: 100px;
background: linear-gradient(to bottom right, transparent 45%, red 55%), linear-gradient(to bottom left, transparent 45%, blue 55%), linear-gradient(to bottom, transparent, green), linear-gradient(rebeccapurple, rebeccapurple);
background-repeat: no-repeat;
background-size: 30px 95%, 30px 95%, calc(100% - 60px) 8px, calc(100% - 60px) calc(100% - 8px);
background-position: 0% 100%, 100% 100%, 50% 4px, 50% 100%;
}
#test::after {
position: absolute;
content: "";
background-color: maroon;
width: 100%;
height: 45%;
left: 0px;
top: 100%;
transform: perspective(150px) rotateX(-45deg);
transform-origin: center top 0;
}
/* just for demo */
#test {
transition: all 1s;
}
#test:hover {
height: 200px;
width: 200px;
}
<div id="test"></div>
According to the W3 spec, "the 'box-shadow' property attaches one or more drop-shadows to the box". The shadow you want to create is not a drop shadow so there is no CSS that would make the shadow in the picture.
The closest you could achieve is pushing the shadow off one edge by using a negative spread radius:
body {
padding-top: 50px;
}
#test {
margin: 0 auto;
background-color: maroon;
box-shadow: 0 -20px 7px -6px black;
height: 45px;
width: 60px;
transform: perspective(150px) rotateX(-45deg);
transform-origin: center bottom 0;
}
<div id="test"></div>
How can I create border corner spacing with CSS like the picture below? The height of the content is not fixed.
You can't do it using just border but you can achieve this using after and box-shadows
see more about after and box-shadow
div {
width: 200px;
height: 100px;
background: #BB67E0;
position: relative;
margin: 50px;
text-align: center;
line-height: 100px;
font-size:30px;
color:#fff;
}
div:after {
position: absolute;
content: "";
width: 2px;
height: 80px;
background: black;
left: -10px;
top: 10px;
box-shadow: 220px 0 0 0 black;
}
div:before {
position: absolute;
content: "";
height: 2px;
width: 180px;
background: black;
left: 10px;
top: -10px;
box-shadow: 0 120px 0 0 black;
}
<div>content div</div>
If you want to use relative height you will have to remove the bottom border or you can use jquery to change the position of the box-shadow
Note:I have given contenteditable to the div so as to see the change when more content is added
div {
width: 200px;
min-height: 100px;
background: #BB67E0;
position: relative;
margin: 50px;
text-align: center;
line-height: 100px;
font-size:30px;
color:#fff;
}
div:after {
position: absolute;
content: "";
width: 2px;
height: 90%;
background: black;
left: -10px;
top: 5%;
box-shadow: 220px 0 0 0 black;
}
div:before {
position: absolute;
content: "";
height: 2px;
width: 90%;
background: black;
left: 10px;
top: -10px;
}
<div contenteditable="true">content div</div>
Edit: This can change the width and height according to your need i got the idea Idea from misterMansam's wonderful answer
div {
width: 200px;
min-height: 100px;
background: #BB67E0;
position: relative;
margin: 50px;
text-align: center;
line-height: 100px;
font-size:30px;
font-size:30px;
color:#fff;
color:#fff;
}
div:after {
position: absolute;
content: "";
width: 90%;
left:5%;
top:0;
height:110%;
top:-5%;
border-top:2px solid black;
border-bottom:2px solid black;
}
div:before {
position: absolute;
content: "";
width: 110%;
left:-5%;
top:0%;
height:100%;
border-left:2px solid black;
border-right:2px solid black;
}
<div contenteditable="true">Content</div>
Using border-image:
We can make use of the border-image to assign a linear-gradient as the border image on all the four sides. We would need a pseudo-element (overlapping the parent container) because the gradient can go only in one direction. Gradients can support percentage based values and hence can adapt to different container dimensions. This can be verified by hovering on the div in the snippet.
The main drawback of this approach is that the border-image property has low browser support. But it is pretty useful when only IE11+ need to be supported because unlike box-shadow it doesn't require fixed dimensions, is not as complex as clip-path and also leaves a spare pseudo-element for other potential usage.
.border-spacing{
position: relative;
height: 100px;
width: 300px;
padding: 10px;
background: rgb(187, 103, 224);
background-clip: content-box;
border-image: linear-gradient(to bottom, transparent 25%, black 15%, black 75%, transparent 75%);
border-image-slice: 4;
border-image-width: 4px;
border-image-repeat: round;
/* Just for demo */
text-align: center;
line-height: 100px;
color: white;
}
.border-spacing:after{
position: absolute;
content: '';
top: -2px; /* half of border-image-slice */
left: -2px; /* half of border-image-slice */
height: calc(100% - 20px); /* 100% - 2 * padding */
width: calc(100% - 20px); /* 100% - 2 * padding */
padding: 10px;
border-image: linear-gradient(to right, transparent 25%, black 15%, black 75%, transparent 75%);
border-image-slice: 4;
border-image-width: 4px;
border-image-repeat: round;
}
/* Just for demo */
.border-spacing{
transition: all 1s;
}
.border-spacing:hover{
height: 150px;
width: 450px;
line-height: 150px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="border-spacing">Content div</div>
Using background-image:
We can make use of the background-image to assign a linear-gradient as the border image on all four sides. We would need a pseudo-element (overlapping the parent container) because the gradient can go only in one direction. Gradients can support percentage based values and hence can adapt to different container dimensions. This can be verified by hovering on the div in the snippet.
Drawback of this approach is also very similar to the previous one in the sense the linear-gradient is only supported by IE10+. Advantages are same as mentioned for the earlier one.
.border-spacing{
position: relative;
height: 100px;
width: 300px;
padding: 10px;
background-image: linear-gradient(to bottom, transparent 25%, black 15%, black 75%, transparent 75%), linear-gradient(to bottom, transparent 25%, black 15%, black 75%, transparent 75%), linear-gradient(to right, transparent 25%, black 15%, black 75%, transparent 75%), linear-gradient(to right, transparent 25%, black 15%, black 75%, transparent 75%);
background-size: 4px 100%, 4px 100%, 100% 4px, 100% 4px;
background-position: 0px 0px, 100% 0px, 0px 0px, 0px 100%;
background-repeat: no-repeat;
/* Just for demo */
text-align: center;
line-height: 100px;
color: white;
}
.border-spacing:after{
position: absolute;
content: '';
top: 10px;
left: 10px;
height: calc(100% - 20px);
width: calc(100% - 20px);
z-index: -1;
background: rgb(187, 103, 224);
}
/* Just for demo */
.border-spacing{
transition: all 1s;
}
.border-spacing:hover{
height: 150px;
width: 450px;
line-height: 150px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="border-spacing">Content div</div>
I admit this approach is insane but - as an experiment - if you support only modern browser and you play a bit(*) using clip-path property (used to cut off the corners) you could try this:
http://codepen.io/anon/pen/qOBzJO
div {
width: 300px;
padding: 10px;
margin: 50px;
background: violet;
background-clip: content-box;
border: 3px #000 solid;
clip-path: polygon(0 20%, 10px 20%, 10px 10px, 15% 10px, 15% 0,
85% 0, 85% 10px, calc(100% - 10px) 10px, calc(100% - 10px) 20%, 100% 20%,
100% 80%, calc(100% - 10px) 80%, calc(100% - 10px) calc(100% - 10px),
85% calc(100% - 10px), 85% 100%, 15% 100%, 15% calc(100% - 10px),
10px calc(100% - 10px), 10px 85%, 0 85%);
-webkit-clip-path: polygon(0 20%, 10px 20%, 10px 10px, 15% 10px, 15% 0, 85% 0,
85% 10px, -webkit-calc(100% - 10px) 10px, -webkit-calc(100% - 10px) 20%,
100% 20%, 100% 80%, -webkit-calc(100% - 10px) 80%,
-webkit-calc(100% - 10px) -webkit-calc(100% - 10px),
85% -webkit-calc(100% - 10px), 85% 100%, 15% 100%, 15%
-webkit-calc(100% - 10px), 10px -webkit-calc(100% - 10px), 10px 85%, 0 85%);
}
Some values are in percentage, that's why vertical lines are shorter in the taller div (this can be solved using fixed values anyway), but as you can see height is not involved in the solution. Another benefit of this approach is the responsiveness (try to stretch the codepen output panel)
(*): I lied. it's not really only "a bit" :)
Flexible on all four sides
The :before pseudo element creates the left and right border
The :after pseudo element creates the top and bottom border
The spacing of the borders is controlled with top, right, bottom, and left (having both a left and right property stretches the element between them, same as the top and bottom)
The borders will always remain the designated offset distance.
Here is a good way to visualise how the pseudo elements are layed out:
Example
div {
background: purple;
height: 50vh;
width: 50vw;
margin: 50px auto;
position: relative;
min-height: 200px;
min-width: 200px;
}
div:before,
div:after {
content: '';
position: absolute;
top: 60px;
left: -20px;
right: -20px;
bottom: 60px;
border: solid 4px #000;
}
div:before {
border-top: none;
border-bottom: none;
}
div:after {
top: -20px;
left: 60px;
right: 60px;
bottom: -20px;
border-left: none;
border-right: none;
}
<div></div>
Single corner space
Sorry for digging but I've made my own interpretation of #misterManSam solution: I wanted to reach the free space in one corner to place the icon on it in my project.
div {
background: purple;
height: 200px;
width: 200px;
margin: 50px auto;
position: relative;
min-height: 200px; /* Just adjust as you wish */
min-width: 200px; /* Just adjust as you wish */
}
div:before { /* Bottom half Borders */
content: '';
position: absolute;
top: 60px; /* Height of left border */
/* Higher value - smaller border line */
left: -20px; /* Margin between div edge */
right: -20px; /* Margin between div edge */
bottom: -20px; /* Margin between div edge */
border: solid 3px #000;
border-top: none;
}
div:after { /* Top half Borders */
content: '';
position: absolute;
top: -20px; /* Margin between div edge */
left: 60px; /* Height of top border */
/* Higher value - smaller border line */
right: -20px; /* Margin between div edge */
bottom: 60px;
border: solid 3px #000;
border-left: none;
border-bottom: none;
}
HTML
<div></div>
Pure HTML + CSS.
https://codepen.io/nigtellios/pen/LYZevGv
Writing an app that uses CSS to define icons, avoiding dependency on external image files. This works fine for circles, squares, triangles, diamonds, which is almost enough.
I wonder if it's possible to create slightly more complex icons like the two grid shaped ones on the right using CSS? It need not support IE8.
.icon {
height: 20px;
width: 20px;
background-color: steelblue;
display: inline-block;
}
.icon-circle {
border-radius: 10px;
}
.icon-square {
border-radius: 0
}
<div class="icon icon-circle"></div>
If you use pseudo elements :before and :after, you can make those icons without images. And you can even make them responsive (see my fiddle).
I used the pseudo elements to create the "white lines" so you will be able to make both last icons like this:
div {
width: 20%;
padding-bottom: 20%;
margin: 5% 10%;
background-color: #6095C9;
position: relative;
float: left;
}
div:after,
div:before {
content: "";
position: absolute;
background-color: #fff;
}
.one:before,
.two:before {
margin: 0 48%;
width: 4%;
height: 100%;
}
.one:after,
.two:after {
margin: 48% 0;
height: 4%;
width: 100%;
}
.two:before {
height: 50%;
bottom: 0;
}
<div class="one"></div>
<div class="two"></div>
FIDDLE
Here is another method to achieve the shapes using gradients instead of pseudo-elements. You can play around with the background sizes to produce different effects (like in shape3).
The advantage of this over the pseudo-element method is that it doesn't require any extra real/pseudo-elements but the drawback is that the browser support for linear-gradients is still poor compared to pseudo-elements.
div {
margin: 10px;
height: 50px;
width: 50px;
background-color: steelblue;
transition: all 1s;
}
.shape1 {
background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
background-size: 100% 50%, 50% 100%;
}
.shape2 {
background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
background-size: 100% 50%, 50% 50%, 100%, 100%;
background-repeat: repeat-y, repeat-x;
}
.shape3{
background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
background-size: 100% 50%, 50% 50%, 100%, 100%;
background-position: 0% 0%, 0% 100%, 0% 0%;
background-repeat: repeat-y, repeat-x;
}
.shape4 {
background-image: linear-gradient(to top, white 2px, transparent 2px), linear-gradient(to left, white 2px, transparent 2px);
background-size: 100% 25%, 25% 100%;
background-position: 0% 100%, 100% 100%;
background-repeat: repeat-y, repeat-x;
}
.large {
height: 150px;
width: 150px;
}
/* Just for demo */
div {
float: left;
}
.small{
clear:both;
}
div:hover {
background-color: crimson;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="shape1 small"></div>
<div class="shape1 large"></div>
<div class="shape2 small"></div>
<div class="shape2 large"></div>
<div class="shape3 small"></div>
<div class="shape3 large"></div>
<div class="shape4 small"></div>
<div class="shape4 large"></div>
You may be able to use a single element here without actually using pseudo elements at all with the help of box-shadow's.
So, say you have a square div element:
div {
height: 20vw;
width: 20vw;
background: tomato;
}
<div></div>
You could then add a box shadow, without a spread, by using:
div {
height: 20vw;
width: 20vw;
background: tomato;
box-shadow: 21vw 0 tomato;
}
<div></div>
you can even use multiple box shadows by seperating them with a ,:
div {
height: 20vw;
width: 20vw;
background: tomato;
box-shadow: 21vw 0 tomato, 0 21vw tomato, 21vw 21vw tomato;
}
<div></div>
You would even be able to overlap them:
div {
height: 20vw;
width: 20vw;
background: tomato;
box-shadow: 21vw 0 tomato, 0vw 21vw tomato, 16vw 21vw tomato, 21vw 21vw tomato;
}
<div></div>
So creating such wouldn't be overly taxing on browser compatibility nor pseudo elements (which could be used for other purposes).
div {
height:20vw;
width:20vw;
background:tomato;
box-shadow:0 0 0 tomato;
-webkit-animation: boxshadowmult 8s infinite;
animation: boxshadowmult 8s infinite;
}
#-webkit-keyframes boxshadowmult {
0%, 24% {
box-shadow:0 0 0 tomato;
}
25%, 49% {
height:20vw;
width:10vw;
box-shadow:11vw 0 0 tomato;
}
50%, 74% {
height:10vw;
width:10vw;
box-shadow:11vw 0 0 tomato, 6vw 11vw 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
}
75%, 100% {
height:10vw;
width:10vw;
box-shadow:11vw 0 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
}
}
#keyframes boxshadowmult {
0%, 24% {
box-shadow:0 0 0 tomato;
}
25%, 49% {
height:20vw;
width:10vw;
box-shadow:11vw 0 0 tomato;
}
50%, 74% {
height:10vw;
width:10vw;
box-shadow:11vw 0 0 tomato, 6vw 11vw 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
}
75%, 100% {
height:10vw;
width:10vw;
box-shadow:11vw 0 0 tomato, 0 11vw 0 tomato, 11vw 11vw 0 tomato;
}
}
/*demo only*/
html{height:100%;
background: rgb(79,79,79); /* Old browsers */
background: -moz-radial-gradient(center, ellipse cover, rgba(79,79,79,1) 0%, rgba(34,34,34,1) 100%); /* FF3.6+ */
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(79,79,79,1)), color-stop(100%,rgba(34,34,34,1))); /* Chrome,Safari4+ */
background: -webkit-radial-gradient(center, ellipse cover, rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-radial-gradient(center, ellipse cover, rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* Opera 12+ */
background: -ms-radial-gradient(center, ellipse cover, rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* IE10+ */
background: radial-gradient(ellipse at center, rgba(79,79,79,1) 0%,rgba(34,34,34,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4f4f4f', endColorstr='#222222',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
}
<div></div>
Using :before and :after, you can create two more "boxes" to play with.
JSFiddle Demo
.icon {
width: 200px;
height: 95px;
background: blue;
}
.triple-square {
position: relative;
margin: 0 0 105px 0;
border-radius: 5px;
}
.triple-square:before {
content: " ";
position: absolute;
bottom: -105px;
left: 0;
height: 95px;
width: 95px;
background: blue;
border-radius: 5px;
}
.triple-square:after {
content: " ";
position: absolute;
bottom: -105px;
right: 0;
height: 95px;
width: 95px;
background: blue;
border-radius: 5px;
}
Here's another example to create 3 circles in a triangle shape...
http://jsfiddle.net/RrhxN/1/