css top tilted skew with background-image - css

enter image description here
I want to make a similar effect to this one not changing html code , using only CSS , In HTML i have got only one div with class "square" , Thank you for your support in advance .

i think that is what you want
.container {
font-size: 16px;
background: #fff;
margin: 0 auto;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-perspective: 28em;
-moz-perspective: 28em;
perspective: 28em;
position: relative;
top: 100px;
}
.box {
position: absolute;
width: 14em;
height: 14em;
left: 50%;
margin-left: -7em;
backface-visibility: hidden;
}
.anim {
transition: all 0.5s ease-in-out;
}
.b0 {
transform: translateX(-11.7em) rotateY(30deg) ;
}
.box img {
width: 100%;
height: 100%;
border-radius: 5px;
}
#media(max-width: 768px) {
.container {
font-size: 12px;
}
}
#media(max-width: 560px) {
.container {
font-size: 8px;
}
}
<div class="container">
<div class="box anim b0">
<img src="http://www.skitzone.com/wp-content/uploads/2010/06/I_am_nothing__in_the_dark_by_islandtime-630x630-500x500.jpg" alt="" />
</div>
</div>

The requirement is to cut the top in a sloping manner.
This snippet does this by putting the linear-gradient that is required for the border into a before pseudo element, using clip-path to get the required cutting off of the top, and putting the image as background on an after pseudo element.
.square {
width: 20vmin;
height: 20vmin;
clip-path: polygon(0 0, 100% 20%, 100% 100%, 0 100%);
position: relative;
}
.square::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(red, blue);
background-image: linear-gradient(to right, #a2ca3c 0%, #0a7cff 50%, #a2ca3c 100%);
z-index: -1;
}
.square::after {
content: '';
position: absolute;
--borderW: 3%;
top: var(--borderW);
left: var(--borderW);
width: calc(100% - (2 * var(--borderW)));
height: calc(100% - (2 * var(--borderW)));
background-image: url(https://pesi.pl/img/main-bg.jpg);
background-size: cover;
background-position: center center;
background-repeat: no-repeat no-repeat;
clip-path: polygon(var(--borderW) var(--borderW), calc(100% - var(--borderW)) calc(20% + var(--borderW)), calc(100% - var(--borderW)) calc(100% - var(--borderW)), var(--borderW) calc(100% - var(--borderW)));
z-index: -1;
}
<div class="square"></div>
Obviously you will want to decide on exactly what width you want the border to be and whether the border is included in the overall size of the .square element (as here).

Related

How to add Shadow to Triangle made with css `clip-path`?

i have created A triangle with css clip-path property to have few content inside.
.triangle {
background-color: grey;
-webkit-clip-path: polygon(50% 10%, 0% 100%, 100% 100%);
clip-path: polygon(50% 10%, 0% 100%, 100% 100%);
height: 100%;
width: 100%;
overflow: hidden;
position: relative;
filter: drop-shadow(9px 9px 9px rgba(255, 23, 23, 0.5));
img {
width: 100%;
position: relative;
left: 0;
top: 5%;
#media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
width: 110%;
}
}
&::after {
background-color: black;
content: "";
display: block;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
transition: opacity .5s;
opacity: 0;
}
}
i have put few content inside and for hover border effect i have created another triangle hidden back of this triangle.
I want to have SHADOW arround this triangle on hover. as shown in image given below.
I have tried ::before but not working, and everyother solution avaialable is not working with clip-path triangle.
Here is an idea without clip-path where the trick is to rely on cascading skew transformation to create the triangle shape and to keep the initial aspect of the content:
.tri {
margin: 40px;
width: 250px;
height: 200px;
border-left: 2px solid orange;
border-bottom: 2px solid orange;
overflow: hidden;
transform-origin: bottom;
transform: skewX(-32deg);
filter:drop-shadow(0 0 5px red);
}
.tri>.container {
height: 100%;
border-right: 2px solid orange;
overflow: hidden;
transform: skewX(51.35deg);
transform-origin: bottom;
}
.tri>.container>div {
transform-origin: bottom;
transform: skewX(-32deg);
height: 100%;
/* Irrelevant styles */
text-align: center;
display: flex;
flex-direction: column;
justify-content:center;
color:#fff;
background:
linear-gradient(rgba(0,0,0,0.2),rgba(0,0,0,0.2)),
url(https://picsum.photos/id/10/1000/800) center/cover;
}
body {
background:grey;
}
<div class="tri">
<div class="container">
<div>
<h1>Title</h1>
<p>some text here</p>
</div>
</div>
</div>
Just add a parent element to triangle and add drop-shadow to the parent element.
Try this:
.triangleParent {
filter: drop-shadow(9px 9px 9px rgba(255, 23, 23, 0.5));
}
.triangle {
background-color: grey;
-webkit-clip-path: polygon(50% 10%, 0% 100%, 100% 100%);
clip-path: polygon(50% 10%, 0% 100%, 100% 100%);
height: 100%;
width: 100%;
overflow: hidden;
position: relative;
filter: drop-shadow(9px 9px 9px rgba(255, 23, 23, 0.5));
}
.triangle img {
width: 100%;
position: relative;
left: 0;
top: 5%;
#media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
width: 110%;
}
}
.triangle::after {
background-color: black;
content: "";
display: block;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
transition: opacity .5s;
opacity: 0;
}
<div class="triangleParent">
<div class="triangle">
<img src="https://images.pexels.com/photos/414612/pexels-photo-414612.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" />
</div>
</div>

How to cut box corner Using CSS with transparent background?

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>

Two diagonal div slips with CSS

I'm trying to create a background with two diagonal splits, with one over the other one.
I tried using two linear-gradient on the background but it didn't work.
Any can help me solve this with CSS?
This can be done using linear-gradient background images but it would need gradients instead of just one.
.diagonal-background {
height: 200px;
width: 200px;
background: linear-gradient(to bottom left, transparent 50%, #EEE 50.5%),
linear-gradient(to bottom right, transparent 50%, #CCC 50.5%);
/* just for demo */
line-height: 200px;
text-align: center;
}
<div class='diagonal-background'>
Some content</div>
1- You can do this (adjust your needs):
CSS
div {
display: inline-block;
background: #FCFCFE;
position: relative;
width: 200px;
height: 200px;
overflow: hidden;
}
.bg1 {
position: absolute;
top: 50px;
display: inline-block;
transform: rotate(45deg);
width: 300px;
height: 300px;
left: -160px;
background: #F8F7FA;
z-index: 1;
}
.bg2 {
position: absolute;
top: 50px;
display: inline-block;
transform: rotate(-45deg);
width: 300px;
height: 300px;
right: -160px;
background: #F2F3F6;
z-index: 1;
}
HTML
<div>
<div class="bg2"></div>
<div class="bg1"></div>
</div>
DEMO HERE
2- Or you can use pseudo elements (adjust your needs):
CSS
div {
display: inline-block;
background: #FCFCFE;
position: relative;
width: 200px;
height: 200px;
overflow: hidden;
}
div:after {
position: absolute;
content:"";
top: 50px;
display: inline-block;
transform: rotate(45deg);
width: 300px;
height: 300px;
left: -160px;
background: #F8F7FA;
z-index: 1;
}
div:before{
position: absolute;
content:"";
top: 50px;
display: inline-block;
transform: rotate(-45deg);
width: 300px;
height: 300px;
right: -160px;
background: #F2F3F6;
z-index: 1;
}
HTML
<div></div>
DEMO HERE

background image, linear gradient jagged edged result needs to be smooth edged

I'm trying to make the bottom of an image pointed. I've tried to get this effect by producing two triangles at the bottom. They must be responsive. and after searching all over the internet with a lot of examples that don't work for my requirement this is the best so far I've managed to produce.
body,
html {
height: 100%
}
.image {
width: 1410px;
margin-right: auto;
margin-left: auto;
height: 500px;
overflow: hidden;
position: relative;
}
.pointer {
height: 50px;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.triangleWrapper {
width: 50%;
height: 50px;
float: left;
}
.lefttriangle {
width: 100%;
height: 10px;
left: 0px;
top: 0px;
background-image: linear-gradient(to right top, #ffffff 50%, transparent 50%);
}
.righttriangle {
width: 100%;
height: 10px;
right: 0px;
top: 0px;
background: linear-gradient(to left top, #ffffff 50%, transparent 50%)
}
<div class="image">
<img src="http://placekitten.com/1410/500">
<div class="pointer">
<div class="triangleWrapper">
<div style="height: 100%;" class="lefttriangle"></div>
</div>
<div class="triangleWrapper">
<div style="height: 100%;" class="righttriangle"></div>
</div>
</div>
</div>
CodePen Demo
It works exactly how I want it to as it is responsive without the need for media queries. BUT it has a jagged edge on the triangle line that isn't 90deg.
How do I get this to produce a smooth line in most if not all modern browsers? I'm not asking for backward compatibility.
Any help is greatly appreciated!
Unfortunately, this always happens when we use angled linear-gradient images and currently the only way to overcome this behavior seems to be to avoid hard-stopping of the colors (that is, don't make the stop point of one color as the start point of the next). Making the second color start a little farther away from the stop point of the first color would kind of create a blurred area and make it look more smoother. This is still not 100% perfect but is better than having jagged edges.
.lefttriangle {
width: 100%;
height: 10px;
left: 0px;
top: 0px;
background-image: linear-gradient(to right top, #ffffff 48%, transparent 50%); /* note the change of stop and start points */
}
.righttriangle {
width: 100%;
height: 10px;
right: 0px;
top: 0px;
background: linear-gradient(to left top, #ffffff 48%, transparent 50%); /* note the change of stop and start points */
}
body,
html {
height: 100%
}
.image {
width: 1410px;
margin-right: auto;
margin-left: auto;
height: 500px;
overflow: hidden;
position: relative;
}
.pointer {
height: 50px;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.triangleWrapper {
width: 50%;
height: 50px;
float: left;
}
.lefttriangle {
width: 100%;
height: 10px;
left: 0px;
top: 0px;
background-image: linear-gradient(to right top, #ffffff 48%, transparent 50%);
}
.righttriangle {
width: 100%;
height: 10px;
right: 0px;
top: 0px;
background: linear-gradient(to left top, #ffffff 48%, transparent 50%);
}
<div class="image">
<img src="http://placekitten.com/1410/500">
<div class="pointer">
<div class="triangleWrapper">
<div style="height: 100%;" class="lefttriangle"></div>
</div>
<div class="triangleWrapper">
<div style="height: 100%;" class="righttriangle"></div>
</div>
</div>
</div>
Alternate Implementations:
Clip Paths: You can use clip-path feature also to produce a similar effect. The advantage of using clip-path is that it is both responsive and also produces a transparent cut. The SVG based clip-path has better browser support than the CSS version. This is not yet supported in IE though.
body,
html {
height: 100%
}
.image {
width: 1410px;
margin-right: auto;
margin-left: auto;
height: 500px;
overflow: hidden;
position: relative;
}
.css-clip {
-webkit-clip-path: polygon(0% 0%, 0% 90%, 50% 100%, 100% 90%, 100% 0%);
clip-path: polygon(0% 0%, 0% 90%, 50% 100%, 100% 90%, 100% 0%);
}
.svg-clip {
-webkit-clip-path: url(#clipper);
-moz-clip-path: url(#clipper);
clip-path: url(#clipper);
}
<!-- CSS Clip-path - Lower browser support -->
<div class="image css-clip">
<img src="http://placekitten.com/1410/500">
</div>
<!-- SVG Clip-path - Better browser support -->
<svg width="0" height="0">
<defs>
<clipPath clipPathUnits="objectBoundingBox" id="clipper">
<path d="M0,0 0,0.9 0.5,1 1,0.9 1,0z" />
</clipPath>
</defs>
</svg>
<div class="image svg-clip">
<img src="http://placekitten.com/1410/500">
</div>
Using CSS Transform: You could also try using the approach mentioned in this answer. It achieves a pointed effect on the left side but it should be easy to adapt it to create a pointed effect on the bottom side.
body,
html {
height: 100%
}
.image {
width: 1410px;
margin-right: auto;
margin-left: auto;
height: 500px;
overflow: hidden;
position: relative;
}
.top-container,
.bottom-container {
position: absolute;
bottom: 0px;
height: 100%;
width: 50%;
overflow: hidden;
backface-visibility: hidden;
}
.top-container {
left: 0px;
transform-origin: right bottom;
transform: skewY(10deg);
}
.bottom-container {
right: 0px;
transform-origin: left bottom;
transform: skewY(-10deg);
background-position: 0% 100%;
}
.top-container:after,
.bottom-container:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
bottom: -62px; /* tan(10) * (width/2) / 2 */
background: url(http://placekitten.com/1410/500);
background-size: 200% 100%;
}
.top-container:after {
left: 0px;
transform: skewY(-10deg);
}
.bottom-container:after {
right: 0px;
transform: skewY(10deg);
background-position: 100% 0%;
}
<div class="image">
<div class='top-container'></div>
<div class='bottom-container'></div>
</div>
Just found an insanely good solution on codepen using calc(50% - 1px)
https://codepen.io/hellonico/pen/xEYXmL
background: linear-gradient(7deg, currentColor calc(50% - 1px), transparent 50%);
No blur whatsoever, just a smooth edge
EDIT: .. apparently not in Safari?..

transform-origins y-offset position when using calc()

In this demo below, I am using transform-origin like this:
transform-origin: 50% calc(100% + 6em);
The y-offset value is set at calc(100% + 6em), but what am I setting the value of the y-offset to? I can see that it is + 6em, but + 6em from where, exactly?
.container {
width: 400px;
height: 400px;
background: red;
margin: 0 auto;
cursor: pointer;
}
.me {
position: relative;
width: 200px;
height: 200px;
border: 2px solid #444;
background: pink;
margin: 20% auto;
transition: 2s;
transform: rotateZ(45deg);
transform-origin: 50% calc(100% + 6em);
cursor: pointer;
}
.container:hover .me {
transform: rotateZ(0deg);
}
<div class="container">
<div class="me"></div>
</div>
When the transform-origin is given two values, like in your example, it is setting the x-offset and the y-offset, using the "two-value syntax":
transform-origin: x-offset y-offset
The percentage value length is based on the element that the transform origin is set on.
The x-offset begins at the left of the element. 50% plots the x-offset position in the very middle of the element.
The y-offset begins at the top of the element. 100% + 6em plots the y-offset position at the bottom of the element plus an extra 6 em.
The x and y offset meet to form a single point, illustrated here where the two orange lines meet:
Offset position — live example
In this example, the position of the offset is shown with the two pseudo elements.
You can change the two values of the before and after pseudo elements at the bottom of the CSS to easily show where the offset point location is. Change the values as shown in the CSS comments to plot the point visually.
.container {
width: 400px;
height: 400px;
background: #000;
margin: 0 auto;
cursor: pointer;
position: relative;
margin-top: 100px;
}
.container:after {
content: '';
display: block;
height: 200px;
width: 200px;
position: absolute;
top: 0;
left: 0;
background: rgba(255, 255, 255, 0.5);
}
.me {
position: relative;
width: 200px;
height: 200px;
background: pink;
transition: 2s;
transform: rotateZ(45deg);
cursor: pointer;
}
.me:before {
content: '';
display: block;
height: 5px;
position: absolute;
margin-top: -5px;
left: 0;
background: #F90;
}
.me:after {
content: '';
display: block;
width: 5px;
position: absolute;
top: 0;
margin-left: -5px;
background: #F90;
}
.container:hover .me {
transform: rotateZ(0deg);
}
.me {
/* x-offset | y-offset */
transform-origin: 50% calc(100% + 6em);
}
.me:after {
height: calc(100% + 6em); /* Set to y-offset value */
left: 50%; /* Set to x-offset value */
}
.me:before {
width: 50%; /* Set to x-offset value */
top: calc(100% + 6em); /* Set to y-offset value */
}
<div class="container">
<div class="me"></div>
</div>

Resources