A tutorial about a technique that uses box shadows for creating a realistic shading effect on simple objects.
When working with 3D transformed elements, you might notice that they
don’t have any shading and appear to be very flat. In real life,
objects block light and have shadows. Surfaces can be matte, reflective,
and everything in between. Indeed, we can do better.
If you need to cast light onto complicated geometry, there are options available such as Photon, but they’re very processor intensive. In this article, I’ll show you a solution that can be applied to objects that only have a few faces. Our example will be a 3D movie gallery with glossy posters and, when the posters are rotated, the sides will contain matte information cards with meta data about the film.
For each
Our library will contain two more movies in addition to this one. The
metadata is a bit lengthy and there are also a few image assets you’ll
need, but everything is included in the code download. Let’s get to styling.
First, let’s get some of the basics out of the way. We need to center our
Next, we want to style the scene class with an explicit width and
height (the same as our posters). If you’d like to provide additional
detail needed for high resolution displays then you could use images
that are twice as large.
The
Finally, we’ll add the
Similar
Here’s where the movement happens. We’ll apply a transition to the
Then we’ll transform each
Observant coders will notice that, while we have translated the
scene, we never actually rotated any elements that would give semblance
of geometry and build an object. Let’s create each 3D poster now. Each
With the geometry of our posters ready, we can transform them into place. The
The
We’ll use the pseudo-element
Further down in the CSS, we style the metadata contained inside the .info class. None of this is particularly relevant to this demo, as it’s mostly just formatting some text and imagery. The real magic happens later on.
Here’s where we create our pseudo-lighting using the
If we
Just like for the poster, we also want to apply a shadow to the other side of the box. For the
Last but not least, we need to add the poster images and still preview images to each movie. I’ve done this using the
You’ll notice that we’ve used Modernizr in the demo to detect support
for 3D transforms and provide a simple fallback for browsers that don’t
support it.
That’s it! As I suggested in the intro, this technique can be applied to simple geometry. Some of you may be wondering why I didn’t use a gradient to create a more controlled shadow over top the poster images. At the time of this article, transitions cannot be applied to gradients, so while this might work for static geometry, the illusion would be broken as soon as the element is animated.
by Nick PettitIf you need to cast light onto complicated geometry, there are options available such as Photon, but they’re very processor intensive. In this article, I’ll show you a solution that can be applied to objects that only have a few faces. Our example will be a 3D movie gallery with glossy posters and, when the posters are rotated, the sides will contain matte information cards with meta data about the film.
The Markup
Our page is going to have a few different parts. First, we need a simple wrapper to center everything on the page. Next, we’ll create an unordered list that will contain all of our 3D posters. We’ll add the class “stage” to theul
and “scene” to each li
. In our CSS, the stage element will act as a container for the scene elements, which will be their own 3D environment with the perspective
property applied.
1
2
3
4
5
6
7
| < div class = "wrapper" > < ul class = "stage" > < li class = "scene" ></ li > < li class = "scene" ></ li > < li class = "scene" ></ li > </ ul > </ div > |
li
, we need to add quite a bit of markup. This
will contain our movie poster as well as all the metadata about each
movie. In a more robust movie library, this could be done dynamically
with some backend code. We’ll keep things simple for the purposes of
this example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| < li class = "scene" > < div class = "movie" > < div class = "poster" ></ div > < div class = "info" > < header > < h1 >It's a Wonderful Life</ h1 > < span class = "year" >1946</ span > < span class = "rating" >PG</ span > < span class = "duration" >130 minutes</ span > </ header > < p > In
Bedford Falls, New York on Christmas Eve, George Bailey is deeply
troubled. Prayers for his well-being from friends and family reach
Heaven. Clarence Odbody, Angel Second Class, is assigned to visit Earth
to save George, thereby earning his wings. Franklin and Joseph, the head
angels, review George's life with Clarence. </ p > </ div > </ div > </ li > |
The CSS
Note that the CSS will not contain any vendor prefixes, but you will find them in the files.First, let’s get some of the basics out of the way. We need to center our
wrapper
and then remove the default list styling from the stage
class.
1
2
3
4
5
6
7
8
9
| .wrapper { margin : 0 auto 100px auto ; max-width : 960px ; } .stage { list-style : none ; padding : 0 ; } |
The
margin
between each scene will provide sufficient spacing so that they don’t overlap each other. Then we’ll float
all of the list items to the left so that they line up next to one
another in a nice gallery. This is similar to how most top-level website
navigation is created.Finally, we’ll add the
perspective
property. This will
allow us to create a 3D scene in the nested elements, and the value of
1000px will give the objects a decent amount of depth. A lower value
would be a bit too dramatic, but you can experiment with this and see
what works best for you.
1
2
3
4
5
6
7
| .scene { width : 260px ; height : 400px ; margin : 30px ; float : left ; perspective : 1000px ; } |
.scene
, we also need to set an explicit width and height on .movie
.
This will help each poster look correct when it’s being transformed.
Next, we’ll set the transform-style to preserve-3d so that we can
transform elements in 3D space. Finally, we’ll translate it along the Z
plane by -130 pixels. This will give the posters a little bit more room
to move around and really pop towards the viewer.
1
2
3
4
5
6
7
| .movie { width : 260px ; height : 400px ; transform-style : preserve-3d ; transform : translateZ ( -130px ); transition : transform 350 ms; } |
.movie
class. The transition timing is set to a rapid 350ms, but if you’d like a more dramatic effect, you could slow it down.Then we’ll transform each
.movie
on :hover
.
This will rotate the 3D poster along the Y axis and then move it
towards the screen along the Z plane. You could rotate the poster by a
full 90 degrees, but I prefer to leave it slightly offset to maintain
the 3D effect while hovered.
1
2
3
| .movie:hover { transform : rotateY ( -78 deg) translateZ ( 20px ); } |
.poster
and .info
card needs to be positioned absolutely, otherwise they’ll push one
another out of the way. We don’t want that, because we’re going to
position them using transforms. Next, we need to set an explicit
dimensions on both of the classes so that each of the two sides is
exactly the same.
1
2
3
4
5
6
7
8
| .movie .poster, .movie .info { position : absolute ; width : 260px ; height : 400px ; background-color : #fff ; backface-visibility : hidden ; } |
.poster
just needs to be moved 130px along the Z plane (because remember, we moved the .movie
back by this amount). The background size has been set to cover so that
when we apply our poster backgrounds, they’ll fill the geometry. They
should anyway since they’re sized correctly, so this is really just a
precautionary measure.The
.info
needs to be translated by the same amount as the .poster
,
but it also needs to be rotated. We want to form a square box, so we’ll
rotate it 90 degrees. I’ve added some styling after the transformation,
but this is mostly just for aesthetic reasons.
1
2
3
4
5
6
7
8
9
10
11
| .movie .poster { transform : translateZ ( 130px ); background-size : cover ; background-repeat : no-repeat ; } .movie .info { transform : rotateY ( 90 deg) translateZ ( 130px ); border : 1px solid #B8B5B5 ; font-size : 0.75em ; } |
::after
to create another face that will have a subtle box shadow beneath the movie box:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| .movie::after { content : '' ; width : 260px ; height : 260px ; position : absolute ; bottom : 0 ; box-shadow : 0 30px 50px rgba( 0 , 0 , 0 , 0.3 ); transform-origin : 100% 100% ; transform : rotateX ( 90 deg) translateY ( 130px ); transition : box-shadow 350 ms; } .movie:hover::after { box-shadow : 20px -5px 50px rgba( 0 , 0 , 0 , 0.3 ); } |
Further down in the CSS, we style the metadata contained inside the .info class. None of this is particularly relevant to this demo, as it’s mostly just formatting some text and imagery. The real magic happens later on.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| .info header { color : #FFF ; padding : 7px 10px ; font-weight : bold ; height : 195px ; background-size : contain; background-repeat : no-repeat ; text-shadow : 0px 1px 1px rgba( 0 , 0 , 0 , 1 ); } .info header h 1 { margin : 0 0 2px ; font-size : 1.4em ; } .info header .rating { border : 1px solid #FFF ; padding : 0px 3px ; } .info p { padding : 1.2em 1.4em ; margin : 2px 0 0 ; font-weight : 700 ; color : #666 ; line-height : 1.4em ; border-top : 10px solid #555 ; } |
box-shadow
property. For the .poster
class, we add an inset box shadow with an X and Y offset of 0px
. The blur radius will be set to 40px
and the shadow is set to rgba(255,255,255,0)
(which is white “shadow” set to 100% transparency). Remember, there’s a transition applied to all the children of .movie
, so if we set a starting state for the shadow, we can then animate it using a :hover
state.If we
:hover
over the .movie
, it will reset the values of the box-shadow
for the .poster
and animate them with a transition. In this new state, the poster is
still inset, but this time it has an X offset of 300px and an opacity of
0.8 for the white color. This will effectively move the box-shadow over
top the poster with some fuzziness along the edge. The transparency
will help to gel the shadow with the poster image, which will make the
poster look like it has a glossy finish.
1
2
3
4
5
6
7
8
9
10
11
12
13
| .movie .poster, .movie .info, .movie .info header { transition : box-shadow 350 ms; } .movie .poster { box-shadow : inset 0px 0px 40px rgba( 255 , 255 , 255 , 0 ); } .movie:hover .poster { box-shadow : inset 300px 0px 40px rgba( 255 , 255 , 255 , 0.8 ); } |
.info
panel, we want a dark shadow to disappear as the element is rotating
forward and then reappear when the paper texture recedes back into the
gap between each 3D poster. On our page, with the glossy poster on the
left and the shadow on the right, it will make it appear as though
there’s a light source coming from the left side of the page.
1
2
3
4
5
6
7
8
9
| .movie .info, .movie .info header { box-shadow : inset -300px 0px 40px rgba( 0 , 0 , 0 , 0.5 ); } .movie:hover .info, .movie:hover .info header { box-shadow : inset 0px 0px 40px rgba( 0 , 0 , 0 , 0 ); } |
:nth-child
pseudo class, but again, this would probably be done elsewhere in a dynamic website.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| .scene:nth-child( 1 ) .movie .poster { background-image : url (../img/poster 01 .jpg); } .scene:nth-child( 2 ) .poster { background-image : url (../img/poster 02 .jpg); } .scene:nth-child( 3 ) .poster { background-image : url (../img/poster 03 .jpg); } .scene:nth-child( 1 ) .info header { background-image : url (../img/still 01 .jpg); } .scene:nth-child( 2 ) .info header { background-image : url (../img/still 02 .jpg); } .scene:nth-child( 3 ) .info header { background-image : url (../img/still 03 .jpg); } |
That’s it! As I suggested in the intro, this technique can be applied to simple geometry. Some of you may be wondering why I didn’t use a gradient to create a more controlled shadow over top the poster images. At the time of this article, transitions cannot be applied to gradients, so while this might work for static geometry, the illusion would be broken as soon as the element is animated.
source: http://tympanus.net/codrops/2013/08/27/3d-shading-with-box-shadows/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+tympanus+%28Codrops%29
0 komentar:
Post a Comment