preface

It has always been said that light and shadow are twins, that where there is light there is shadow. In fact, if there is no contrast of light intensity, there will be no shadow. We perceive the world by reflecting light from surfaces, and if everything absorbed light at all, the world would be dark.

Only by understanding the light can we master the shadow. A good designer is always a light master, and can convey to the reader the texture, the sense of space and the texture of the object through the complex light and shadow. They draw out the design draft is beautiful, which can suffer the majority of front compatriots! In the browser, we can only use a few CSS properties, and we have our hands tied while trying to restore the design. After all, the AE and C4D designers use look like cannons compared to the CSS pistols we use!

Common lighting effects

The good news is that we can take performance as an excuse and continue to keep things simple. For example, when it comes to light and shadow effects, everyone’s first reaction is to start painting directly with box-shadow, text-shaodw and drop-shadow. For most scenes, these attributes are quite useful and can be used for a variety of effects, such as single-side projection, hollow projection, and projected animation. If it involves colored shadows, long shadows, or reflections, you need to combine them with other CSS properties.

Color projection, you can make the pseudo-element inherit the background of the parent element, and then add a blur filter. This idea can also be used to create frosted-glass.

.avator {
  position: relative;
  background: 'xxx';
}
.avator::after {
  content: "";
  position: absolute;
  top: 10%;
  width: 100%;
  height: 100%;
  /* The pseudo-element inherits the parent element background */
  background: inherit;
  /* Add some weird filters to adjust the parameters */
  filter: blur(10px) brightness(80%) opacity(.8);
  z-index: -1;
}
Copy the code

Reflections can be made using the box-reflect property -webkit-box-reflect. Compatibility is good, and it works in all browsers except Firefox and Internet Explorer. Another method is to copy the parent element with a pseudo-element and transform the position backwards.

On the other side of the shadow are highlights. The idea of drawing highlights can directly replicate the idea of drawing shadows, but need to change the color of the projection to translucent white.

Another approach is to simulate highlights with background gradients or pseudo-elements. If combined with CSS animation, you can easily achieve sweeping and other effects.

body:before {
  content: "";
  position: absolute;
  top: 0;
  width: 200vw;
  height: 35px;
  background-color: rgba(255.255.255.0.4);
  transform: rotate(45deg);
  animation: scan-light 2s ease-in infinite;
}
@keyframes scan-light {
  from {
    right: -100vw;
  }
  to {
    right: 40vw; }}Copy the code

Advanced lighting effects

texture

The above mentioned methods of drawing light and shadow are mainly used to convey the shape and position of objects. For example, reflections and gradient highlights can be used to convey texture, showing surfaces that are smooth enough for specular reflection. Of course, this is the ideal situation. Objects rarely have smooth surfaces, and even surfaces that are visible to the naked eye are pockmarked and unsightly on a microscopic level.

Once we started using CSS to simulate advanced light and shadow, the first challenge was how to deal with matte surfaces. The following is a simple way to achieve a frosted surface, which is widely used in common scenarios.

We attach images to the surface of an object as it looks, a method called texture mapping. Taking a simple material map as an example, we first use PS to create a solid color background, and then randomly fill some pixels with slightly brighter highlights and slightly darker linegradient-material, respectively, to obtain a result similar to the one below.

This material is then tiled into the background of the document to get a surface texture that looks like frosted metal (this may not work well due to image compression, so go directly to Codepen for details).

Different highlights and shadow details can give a different impression. Here’s an illustration of a snowflake TV, for example, where the contrast between highlights and shadows is much higher than on a frosted metal surface.

The inconveniences of using images are that there is no way to preview while tweaking details, and Photoshop can be out of the technology stack on the front end. Fortunately, we still have the why-SVG artifact. Here is a set of “standard” material generation code that can be used to generate a wide variety of materials.

<svg width="0" height="0">
  <filter id="surface">
    <feTurbulence type="fractalNoise" baseFrequency='0.03 0.06' numOctaves="30" />
    <feDiffuseLighting lighting-color='#ffe8d5' surfaceScale='2'>
      <feDistantLight elevation='10' />
    </feDiffuseLighting>
  </filter>
</svg>
<style>
body {
  margin: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  filter: url(#surface);
}
</style>
Copy the code

FeDiffuseLighting is a noise filter that creates random material images. A feDiffuseLighting is a light source filter. FeDistantLight indicates the use of a parallel light source.

The light source? Does it have to be this complicated?

Do not be urgent first, illuminant also is a few kinds actually: dot shape light, parallel light, gather light. It’s the light bulb, the sun, and the theater lamp. Since we’re going to stay on the topic of surface materials for a while, we’ll just use parallel lights.

Now that we have a rough idea of what the SVG paragraph above means, we are happily tuning parameters.

First try lowering the distance from the light to the surface (reduce elevation) to increase the contrast between highlighted and shaded surfaces. Obtained the following texture that looks like some kind of soil.

Then I raised the lights, adjusted the lightning-color, and roughened the texture a bit to get a marble-like texture (maybe a bit like white vellum).

The white lime wall texture was achieved by increasing baseFrequency, adjusting the surface base height to get a smooth texture, and adjusting the light height to reduce the contrast between highlights and shadows.

<svg width="0" height="0">
  <filter id="surface">
    <feTurbulence type="fractalNoise" baseFrequency='95' numOctaves="80" result='noise' />
    <feDiffuseLighting in='noise' lighting-color='#fff' surfaceScale='1.4' result="grind">
      <feDistantLight azimuth='500' elevation='50' />
    </feDiffuseLighting>
    <feGaussianBlur in="grind" stdDeviation="6"/>
  </filter>
</svg>
Copy the code

You should notice that the white lime wall code has a feGaussianBlur filter compared to the standard template. In principle the filter is infinite overlay, can make a lot of fun effect. For example, some big guy drew clouds in SVG. Yes, you heard me right. Here is the cloud texture drawn in SVG.

Fresnel effect

Having said how to draw a rough surface, let’s take a look at the rules for drawing a smooth surface. When it comes to water and metals, which have relatively smooth surfaces, the Fresnel effect has to be mentioned.

If you stand on the edge of a lake and look down at the water at your feet, you will find that the water is transparent, and the reflection is not so strong that you can see the bottom. If you look at the lake in the distance, you will see the reflection of the mountains and the sky.

Each material has its own Fresnel value, based on its refractive index, which indicates how much light will be absorbed by the object and how much will bounce off the surface. Here’s an example from ChaosGroup.com.

There is a rough sphere. The edge of the sphere on the right reflects the sky light and appears to glow. The edge of the sphere on the left does not. If the sphere is rough, the Fresnel effect becomes very weak, so the picture on the left is correct; If the sphere resembles metal or water and has a smooth surface, the correct result should look like the picture on the right.

Once we understand the Fresnel effect, we can empirically draw objects with a high Fresnel effect out of thin air. Below is a water drop with CSS by Oscar Salazar. He used box-shadow to add a large amount of transparent white shadow to the lower edge of the water drop to simulate the Fresnel effect.

If you compare real water droplets, Oscar Salazar’s drawing isn’t “real.” But because of the amplification effect of water droplets, combined with the light and shadow effect, it is very eye-catching, giving people the feeling of “spiritual likeness”, so it will not feel that there is a problem with the painting.

Below is a frosted glass effect drawn by Envato Tuts+. On the left is the original, and on the right is a modified version with the Fresnel effect added. The revised version looks like a smooth-edged glass version rather than a piece of plastic that’s drawn -not-sure.

The scene of actual combat

Limited by technology, there are many kinds of light and shadow effects that are not mentioned in this article, a sequel will be made when the opportunity comes (goo goo goo). We’ll end with a CSS rendering of the book cover, as well as some of the techniques mentioned above. Material only two books cover pictures, click here to download the first one, click here the second refferer, the goal is to achieve the following effect compressed.

Take out the framework

First, look at the image. In the background is a piece of paper with a book on it. The light source is in the upper right corner, probably parallel, not far from the surface of the paper. Let’s start by building the frame with HTML.

<div class="display-container">
  <! -- Paper background texture layer -->
  <div class="paper" />
  <! -- Book cover -->
  <div class="book">
    <! -- Material layer of cover paper -->
    <div class="paper" />
    <! -- Automatic cover height with a picture -->
    <img class="corner" src="xxx" />
  </div>
</div>
Copy the code

Deal with texture

Then we use SVG to bring up a paper-like texture, light it, and set it to the background.

<svg width="0" height="0">
  <filter id="surface">
    <feTurbulence type="fractalNoise" baseFrequency='. 95. 95 ' numOctaves="80" result='noise' />
    <feDiffuseLighting in='noise' lighting-color='#004F85' surfaceScale=8 ' '. result="grind">
      <feDistantLight azimuth='500' elevation='50' />
    </feDiffuseLighting>
    <feGaussianBlur in="grind" stdDeviation="5"/>
  </filter>
</svg>
<div class="paper"></div>
<style>
  body {
    width: 100vw;
    height: 100vh;
    overflow: hidden;
  }
  .paper {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
  .paper::before {
    content: ' ';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    filter: url(#surface);
  }
  .paper::after {
    content: ' ';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: radial-gradient(ellipse at 100% 0%.rgba(255.255.255.0.25), rgba(255.255.255.0.18) 50%.rgba(255.255.255.0.15) 70%.rgba(0.0.0.1));
  }
</style>
Copy the code

Details of the cover

Next, start painting the cover of the book. Remember that there are three parts to work on: materials, highlights and shadows. The results are as follows.

There are a few small details to pay attention to.

  • Cover crease processing
  • Mimicking occluded shadows
  • Prevent edges from being too sharp

Let’s start with the crease treatment. Fold-mark is great if you have a physical book handy. Try using a flash light and see the shadow on the crease. You should see that the crease is nothing more than a combination of a bright side and a dark side. We can simulate this crease with a gradient.

.book-cover .book::after {
  content: ' ';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  background-repeat: no-repeat;
  background-image: / *1This gradient is the more obvious crease */linear-gradient(to right, rgba(0.0.0.0.1) 0.3%.rgba(255.255.255.0.09) 1.1%, transparent 1.3%/ *)2This one-pixel gradient is the left-most crease of the cover (no dark side) */linear-gradient(to right, rgba(0.0.0.0.2) 0.rgba(255.255.255.0.08) 0%, transparent 0.5%);
  background-size: 50% 100%.50% 100%;
  background-position: 0% top, 9% top;
}
Copy the code

And then there’s occluded shadows. The concept of occluded shadow is very simple. It means that two objects are close enough to block out light. The closer you get, the darker the occlusion-shadow. Corresponding to CSS, drop-shadow produces “solid” shadows, but cannot be superimposed; Box-shadow Creates an adjustable shadow range but spreads out. We can simulate a more realistic shadow effect by overlaying drop-shadow and box-shadow.

.book-cover .book {
  position: relative;
  /* Since shadows affect the visual center, move the book to the upper right */
  margin-top: -1vh;
  margin-right: -1vh;
  width: 32%;
  max-width: 600px;
  font-size: 0;
  box-shadow: 
    -55px 40px 30px 0 rgb(0 0 0 / 10%), 
    -27px 25px 35px -5px rgb(0 0 0 / 20%),
    -10px 10px 15px 5px rgb(0 0 0 / 10%), 
    -12px 12px 10px 0 rgb(0 0 0 / 20%),
    -7px 7px 8px 0 rgb(0 0 0 / 10%),
    -5px 5px 5px 0 rgb(0 0 0 / 20%),
    -2px 2px 3px 0 rgb(0 0 0 / 30%);
  filter: drop-shadow(-20px 20px 15px rgba(0.0.0.65));
}
Copy the code

The result is shown below. The position refers to the occluded shadow, the closer the book is the thicker the shadow; Position two is the effect of box-shadow spreading outwards, which is contrary to the position of light source and violates human cognitive experience, so it should be avoided.

Then there’s how to prevent edges from getting too sharp. Before processing, the edges of the book look like this. Because the image is compressed, no details can be seen, here is a direct introduction to the solution to prevent edge sharpening. Blur the bottom image by 1 pixel and the top image border-radius by 2 pixels. Done.

The finished product to show

Finally, put all the code together, tune the parameters, change the details, and you’re done. Hey hey, and put a picture of the effect. You can go to Codepen to see the final result.

What, you want to make a book that turns pages?

That has to go to kangkang turn. Js implementation turnjs. The effect is shown below, which is also useful to the Fresnel effect.

To read more

I hope this article can help you. I am a bionic lion. See you next time

Want to see how this article was created? You can find out from my blog project; Welcome Star & Follow; Also please come to my online blog, typesetting super Nice oh ~


  1. In human language: the material, shape and position of an object. ↩
  2. How to create a frosted glass effect using CSS?
  3. -webkit-box-reflect Attribute Introduction and Implementation of Element Mirror Reflection↩
  4. In fact, the gradient + random method can also generate similar to the matte metal texture map, so that you do not need to introduce external images, but too cumbersome, difficult to tune, as base64 is more convenient. ↩
  5. Forgive me, I’ve always subconsciously thought of SVG as a superset of CSS, just because you can draw with itAnd you can beat CSS in painting.↩
  6. Cloud Optimization (Big guy optimizes big guy)↩
  7. Understanding the Fresnel Effect of Glossiness↩
  8. “Looks like” is not the same as “reality.” Just like many painters break the physical limits of light and shadow in order to create atmosphere or achieve the desired effect. This is an empirical summary and, of course, it’s a matter of opinion. ↩
  9. This link should not be opened on third party pages due to the ANTI-theft mechanism of OSS. I did, however, open access to the empty Refferer, which allows you to open the image directly in your browser and save it. ↩
  10. Due to image compression, the performance of the demo will be reduced. You can practice to experience the full effectAnd the whole fun.↩
  11. Don’t tell me your book is new. ↩
  12. The “ambient occlusion” in the game’s graphics is a little easier to understand. ↩
  13. CSS can also turn pages, just not as well, see: The Mad Magazine fold-in Effect In CSS↩