How to achieve "depth" with a 3d css transform - css

I am trying to create a "perspective mockup" using CSS. There are a fair amount of tutorials on how to achieve this with 3D layers in Photoshop, but I would like to do it with CSS. Here is an example of what I am trying to achieve:
And here is the code (using the raw image, https://i.imgur.com/foDEYpB.png):
#perspective {
width: 400px;
height: 500px;
position: absolute;
background-image: url("https://i.imgur.com/foDEYpB.png");
background-repeat: no-repeat;
background-size: cover;
top: 50%;
left: 50%;
margin-left: -200px;
margin-top: -250px;
transform: rotate3d(360, 120, -90, 60deg) rotateZ(-30deg);
box-shadow: -15px 15px 20px rgba(0, 0, 0, 0.5);
}
<div id='perspective'></div>
I am pretty close, but am unsure how to achieve the "depth" or "height" where the image looks raised. Zoomed in version of said "depth" where the image is repeated onto the sides:
P.S. if anyone knows the correct name for what I'm referring to as "depth", I'd love to know!

Try adding three type of images to make 3D effects. Use transform property with rotation for images to get the desired result.
Answer reference here.
.perspective {
position: relative;
width: 400px;
height: 500px;
transform-style: preserve-3d;
transition: all 500ms ease-in;
transform: rotateY(20deg) rotateX(60deg) rotateZ(-10deg);
transform: rotateY(15deg) rotateX(50deg) rotateZ(-15deg);
box-shadow: -40px 80px 80px -10px rgba(0, 0, 0, 0.7);
cursor: pointer;
margin-right: 30px;
display: inline-block;
margin-left: 30%;
}
.perspective img {
position: absolute;
top: 0px;
left: 0px;
width: 400px;
height: 500px;
transform: translateZ(16px);
}
.bottom,
.left {
position: absolute;
width: 400px;
height: 500px;
display: block;
transition: all 1s linear;
overflow: hidden;
border-radius: 3px;
transform: translateZ(16px);
filter: brightness(80%)
}
.left {
transform: rotateY(270deg) translateX(-1px);
transform-origin: center left;
width: 18px;
}
.bottom {
transform: rotateX(90deg) translateY(15px) translateZ(-480px);
transform-origin: bottom center;
height: 18px;
}
.bottom img {
transform: rotateX(180deg);
width: 100%;
height: 500px;
left: 0px;
}
<div class="perspective">
<img src="https://i.imgur.com/foDEYpB.png">
<div class="bottom"><img src="https://i.imgur.com/foDEYpB.png"></div>
<div class="left"><img src="https://i.imgur.com/foDEYpB.png"></div>
</div>

Here is a hacky idea using multiple background to simulate such effect. The trick is to add 2 semi-transparent gradients to create the shadow effect then 2 other gradient to cut a small part of the corner to obtain the 3D shape.
The result may not be perfect for all the images:
.wrapper {
display:inline-block;
perspective:1000px;
}
.box {
margin: 50px;
width:200px;
height:200px;
transform: rotate3d(360, 120, -90, 60deg) rotateZ(-30deg);
background:
linear-gradient(to bottom right,transparent 49%,#fff 52%) bottom right/14px 10px,
linear-gradient(to top left,transparent 49%,#fff 52%) top left /10px 14px,
linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0.5)) 0 0px/10px 100%,
linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0.5)) 100% 100%/calc(100% - 10px) 10px,
url(https://picsum.photos/id/1061/1000/800) center/cover;
background-repeat:no-repeat;
}
<div class="wrapper" >
<div class="box" >
</div>
</div>
With your image you can have a specific gradient like below:
body {
background:#ccc;
}
.wrapper {
display:inline-block;
perspective:1000px;
}
.box {
margin: 50px;
width:200px;
height:250px;
transform: rotate3d(360, 120, -90, 60deg) rotateZ(-30deg);
background:
linear-gradient(to bottom right,transparent 49%,#ccc 52%) bottom right/16px 10px,
linear-gradient(to top left,transparent 49%,#ccc 52%) top left /10px 12px,
linear-gradient(#efefef,#efefef) 100% 100%/calc(100% - 10px) 10px,
linear-gradient(-226deg,#222428 13px,#ff4946 13px,#ff4946 77px,#592D30 77px,#592D30 100px,#222428 100px,#222428 108px,#efefef 108px,#efefef 161px) 0 0px/10px 100%,
url(https://i.imgur.com/foDEYpB.png) center/cover;
background-repeat:no-repeat;
}
<div class="wrapper">
<div class="box">
</div>
</div>

Related

View background with Border with 4 cuff-off corner

I am trying to give a div 4 cutoff corners
Like this
This is what I have done so far
But the problem with clip-path is that I can't get the background image present(in the body tag)enter image description here, I have to add the background image again in the innerWrap which does not look consistent.
is there any way to achieve the cut-off corner and without loosing the background image present in the body
.heroWrapper {
display: flex;
align-content: center;
justify-content: center;
padding: 0.06rem;
height: 100%;
background-color: v.$secondary;
clip-path: polygon(
0 0%,
10% 0,
90% 0,
100% 10%,
100% 90%,
90% 100%,
10% 100%,
0% 90%,
0% 10%
);
.heroInnerWrap {
width: 100%;
height: 100%;
margin: auto;
background: url("../bgImage.png");
background-size: contain;
clip-path: polygon(
0 0%,
10% 0,
90% 0,
100% 10%,
100% 90%,
90% 100%,
10% 100%,
0% 90%,
0% 10%
);
.borders {
position: absolute;
width: 15rem;
height: 15rem;
background: v.$primary;
}
}
.topright {
top: 0rem;
right: 0rem;
transform: rotate(45deg);
}
}
Just create a type of hexagon and mask it with it.
.hexagon {
top: 30vh;
left: 40%;
position: absolute;
margin: 0 auto;
background-color: blue;
border-radius: 10px;
width: 100px;
height: 63px;
box-sizing: border-box;
transition: all 1s;
border: 0.4vh solid transparent;
}
/* Creating pseudo-class */
.hexagon:before, .hexagon:after {
content: "";
border: inherit;
position: absolute;
top: -0.5vh;
left: -0.5vh;
background-color: dodgerblue;
border-radius: inherit;
height: 100%;
width: 100%;
}
/* Align them in such a way
that they form a hexagon */
.hexagon:before {
transform: rotate(60deg);
}
.hexagon:after {
transform: rotate(-60deg);
}
<!DOCTYPE html>
<html>
<head>
<title>
Draw a Curved Edge
Hexagon using CSS
</title>
<style>
</style>
</head>
<body style="text-align: center;">
<!-- Hexagon Division -->
<div class="hexagon"
id="hexagon">
</div>
</body>
</html>

How to create gradient color

I need to create the background color as like an below image.. how to acheive this background color using gradient?
Note: just background color for that pic no need for needle, tick and label.
You can get it by using radial-gradient.
Below i posted a working example to get it, You can play with radial-gradient properties to understand how it's work.
Working fiddle
Radial gradient
.round {
width:300px;
height:300px;
border-radius:50%;
background: rgba(0,0,0,0.8);
background-image:radial-gradient(circle at 50% 30%,#cacaca,#333);
-webkit-background-image:radial-gradient(circle at 50% 30%,#cacaca,#333);
position:relative;
overflow:hidden;
}
.round:after, .round:before {
content:'';
width:100%;
height:100%;
position:absolute;
border-radius:50%;
}
.round:before {
left:0;
top:30px;
transform: rotate(22deg);
transform-origin: -13% 52%;
-webkit-transform-origin: -13% 52%;
background-image: radial-gradient(circle at -11% 30%,#333,#999);
background-image: -webkit-radial-gradient(circle at -11% 30%,#333,#999);
opacity:0.2;
}
.round:after {
right:0;
top:30px;
transform: rotate(22deg);
transform-origin: 22% 125%;
-webkit-transform-origin: 22% 125%;
background-image: radial-gradient(circle at -45% 30%,#999,#333);
-webkit-background-image: radial-gradient(circle at -45% 30%,#999,#333);
opacity:0.2;
}
<div class="round"></div>
Close eh?
Let me know if you need fuller CSS breakdown but personally, I've never used radial gradients in CSS before but it seems to work well.
Here's what I used as a reference.
.container {
position: relative;
width: 300px;
height: 300px;
}
.radial-gradient {
position: absolute;
width: 100%;
height: 100%;
border-style: soild;
border-width: 5px;
border-radius: 50%;
background-image: radial-gradient(circle at 50% 30% , #C3C3C3 0%, #000000 100%);
}
<div class="container">
<div class="radial-gradient">
</div>
</div>
I am able to produce a similar effect using either a radial gradient or the box-shadow property.
Note 1: gradients are rendered differently across different browsers.
Note 2: too much blur in the box-shadow property is bad for performance
Examples (might need some fine-tuning on your end):
.circle {
height: 250px;
width: 250px;
border-radius: 100vw;
background: white;
margin: 1em auto;
}
.gradient {
background-position: -55px -86px;
background-image: radial-gradient(circle, rgb(249, 249, 249) -4%, #000000 81%);
background-repeat: no-repeat;
background-size: 136%;
}
.box-shadow {
box-shadow: inset -7px -28px 140px 48px rgba(0, 0, 0, 0.75);
}
.sample {
text-align: center;
border: 1px solid #444;
width: 300px;
margin: 1em;
}
<div class="sample">Gradient
<div class="circle gradient"></div>
</div>
<div class="sample">Box-shadow
<div class="circle box-shadow"></div>
</div>
Recommendation? Use a an image instead of CSS in this case.

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>

Achieve object projection effect with box-shadow

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>

Creating a partial box shadow on a skewed div

I'm trying to create a partial shadow on a skewed div, as close as I can get to this creative.
Right now I've been trying to do this with pseudo elements (before specifically) but I found that those elements behave strangely whenever I skew the element they are applied to. The pseudo element keeps appearing on top of my div, even though the z-index is set to -1. No matter what I do with z-index, it will stay on top of it. I want it to be behind the div it's applied to, and in front of the div below, like in the creative.
Here's my ::before code and a link to the codepen
CSS
/*! Shadows */
#test-title {
position: relative;
}
#test-title:before {
z-index: -1;
position: absolute;
content: "";
bottom: 15px;
left: 10px;
width: 50%;
top: 80%;
max-width:300px;
box-shadow: 0 15px 10px #777;
-webkit-transform: rotate(-3deg);
-moz-transform: rotate(-3deg);
-o-transform: rotate(-3deg);
-ms-transform: rotate(-3deg);
transform: rotate(-3deg);
}
http://codepen.io/kathryncrawford/pen/WwWEma
Skew the parent then unskew the child at the same degree.
* {
box-sizing: border-box
}
body {
padding: 40px 0
}
section {
width: 60vw;
clear: both;
overflow: hidden;
min-height: 100px;
margin: 0 auto;
position: relative;
background: #035076
}
section article {
width: 60%;
padding: 20px;
color: white;
margin: 0 auto
}
section:nth-child(even) {
transform: skew(-45deg) translate(5vw);
box-shadow: inset 0 0 2px 0 black;
}
section:nth-child(odd) {
transform: skew(45deg);
}
section:nth-child(even) article {
transform: skew(45deg) translate(5vw);
}
section:nth-child(odd) article {
transform: skew(-45deg);
}
section:before,
section:after {
content: '';
position: absolute;
}
section:nth-child(even):before {
width: 100%;
height: 0;
bottom: 100%;
left: 0;
z-index: 6;
opacity: 1;
transform: rotate(-10deg) translateY(-30px);
box-shadow: 0px 0px 64px 30px rgba(0, 0, 0, 0.8);
}
section:nth-child(odd):not(:first-child):before {
width: 100%;
height: 0;
bottom: 100%;
right: 0;
z-index: 6;
opacity: 1;
transform: rotate(10deg) translateY(-30px);
box-shadow: 0px 0px 64px 30px rgba(0, 0, 0, 0.8);
}
<section>
<article>What our clients say About Us</article>
</section>
<section>
<article>Read More!</article>
</section>
<section>
<article>Read More!</article>
</section>
<section>
<article>Read More!</article>
</section>
The easier approach would be to put the drop shadow at the top of each box after the first. This will solve all sorts of z-index issues, since each box sits 1 level higher than the box above it.. and it allows the shadow to sit inside the container instead of outside of it.
I've also changed your shadow styling to use a radial gradient* instead of a box shadow, as it is a bit easier to control in this situation, and is also closer to your design. I also did a bit of positioning to make it look a bit better too, and get the separate sides for skew1 and skew2
I've changed your last ruleset to this:
.test-info:before {
position: absolute;
content: "";
width: 100%;
left: 0;
top: 0;
height: 30px;
}
.test-info.skew1:before {
background: radial-gradient(ellipse farthest-side at 30% top, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 100%);
}
.test-info.skew2:before {
background: radial-gradient(ellipse farthest-side at 70% top, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 100%);
}
See Demo
* note: You may want to check/add additional browser support on the gradient that I put in before using it.
I have tried, it's not perfect, but, it is closer to desired look, imho:
<div id="test-title">
<h3>What our clients say about us</h3>
</div>
<div id="shadow1"></div>
So, i've added new html element(shadow), rather than using pseudo-elements... Now, i've set z-indexes and positions properly, to hide rotated shadow div behind first div, and added this css:
#shadow1 {
position:absolute;
width:50%;
height:150px;
background:black;
top:50px;
left:11%;
z-index:6;
opacity:1;
transform: rotate(-5deg);
box-shadow: 15px 56px 50px -12px rgba(0,0,0,0.80);
}
Demo: http://codepen.io/anon/pen/vGwNqY
You can play with rotation, box-shadow, position, height... but, this could be a good start (maybe). P.S. Similar logic could be applied to second div.
try to make box shadow for the second element using :before pseudo https://jsfiddle.net/0andpzsp/
.cont {
width: 1000px;
height: 500px;
}
div[class^="d"] {
width: 70%;
height: 50%;
position: relative;
margin-left: 40px;
margin-top: 50px;
}
.d0 {
background: linear-gradient(to right, #005f8a 0%,#00486c 50%,#003a59 100%);;
transform: skew(20deg)
}
.d1 {
background: linear-gradient(to right, #005f8a 0%,#00486c 50%,#003a59 100%);;
overflow: hidden;
top: -50px;
left: 20%;
transform: skewX(-20deg);
z-index: -1
}
.d1:before {
content: '';
border-radius: 30%;
position: absolute;
display: block;
width: 600px;
height: 70px;
z-index: 9999;
top: -100px;
left: -70px;
box-shadow: -50px 60px 90px 0px #000;
transform: rotate(-5deg)
}
<div class="cont">
<div class="d0"></div>
<div class="d1">
</div>
</div>

Resources