CSS shadow tricks and details you didn’t know

ChokCoco
13 min readJul 15, 2022

--

The title of this article is CSS shadow tricks and details. CSS shadows, but not necessarily box-shadowand filter:drop-shadow, why? Because shadows can also be simulated using other properties, and there are all kinds of shadows. Let me tell you the story below~

one-sided projection

Let’s talk about one-sided projection first. About box-shadow, most of the time, we use it to generate a two-sided projection, or a four-sided projection. as follows:

OK, what if you want to generate a one-sided projection?

Let’s take a look at the usage definition of box-shadow:

{
box-shadow : none | [inset? && [ <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>? ] ]#
}

Take box-shadow: 1px 2px 3px 4px #333as an example , the meanings of the four values ​​are: offset value in x direction, offset value in y direction, blur radius, and expansion radius.

Here’s a little trick, the expansion radius can be negative .

Going on, if the shadow’s blur radius matches the negative dilation radius, then we won’t see any shadows, because the resulting shadow will be contained below the original element unless a directional offset is given to it. So at this time, we can achieve one-sided projection by giving an offset value in one direction:

CodePen Demo — css one-sided projectionClick to preview

Projection Background / Background Animation

Continuing with the above.

Obviously, 0=-0, so when box-shadowthe blur radius and expansion radius of are 0, we can also get a shadow of the same size as the element, but it is occluded by the element itself, and we try to offset it.

The CSS code is as follows:

div {
width: 80px;
height: 80px;
border: 1px solid #333;
box-sizing: border-box;
box-shadow: 80px 80px 0 0 #000;
}

Got the following result:

what’s the point? It doesn’t seem to make sense.

Well, it really doesn’t seem to work. However, we noticed that it box-shadowis possible to set up multiple layers, that is, multiple layers of shadows, and to perform transition animations (tween animations). However background-image: linear-gradient(), that is, the gradient background cannot be tween animation.

Where does this go. Okay, let’s come back, using the above features, we can box-shadowuse to achieve a background image that can only be achieved with gradients:

box-shadow, the CSS code to implement it is as follows (could be more simplified) :

.shadow {
position: relative;
width: 250px;
height: 250px;
}

.shadow::before {
content: "";
position: absolute;
width: 50px;
height: 50px;
top: -50px;
left: -50px;
box-shadow:
50px 50px #000, 150px 50px #000, 250px 50px #000,
50px 100px #000, 150px 100px #000, 250px 100px #000,
50px 150px #000, 150px 150px #000, 250px 150px #000,
50px 200px #000, 150px 200px #000, 250px 200px #000,
50px 250px #000, 150px 250px #000, 250px 250px #000;
}To implement it with gradients, just do this:
.gradient {
width : 250px ;
height : 250px ;
background-image : linear-gradient ( 90deg , #000 0% , #000 50% , #fff 50% , #fff 100% );
background-size : 100px 100px ;
}

Why choose the more complex box-shadowone ? Because it can do motion tweens, like this, which you can't do with gradients:

CodePen Demo — box-shadow implements background animation

Of course, this is just an example Demo, there are many interesting effects with a little imagination, and another one:

CodePen Demo — CSS Checker Illusion (By David Khourshid)

Well, it’s interesting, but the actual use may not be large.

Stereographic projection

OK, let’s move on. The next topic is stereo projection .

This statement is very strange. The appearance of shadows is to make the original elements look more three-dimensional. What is the so-called three-dimensional projection here?

The so-called stereoscopic projection here is not necessarily the use of box-shadowor text-shadow, drop-shadowbut we use other elements or attributes to simulate the shadow of the element. The purpose of this is to break through some of the positioning limitations of box-shadowsuch elements. Make the position, size, and blur of the shadow more flexible .

OK, let’s take a look at such an element, we want to make it more three-dimensional by customizing the position of the shadow:

The div in the picture above just has a very shallow one box-shadow, which doesn't seem to have anything to do with the three-dimensional. Next, we use the pseudo-element of the div to generate a shape similar to the shape of the corners of the original image, and then shift it through transform. It may be so:

OK, and finally perform some blurring effects on the element generated by the pseudo element (filter or box-shadow can be used), you can achieve a three-dimensional effect where the corners look like they are torn:

The code is very simple, the CSS code is shown as follows:

div {
position: relative;
width: 600px;
height: 100px;
background: hsl(48, 100%, 50%);
border-radius: 20px;
}

div::before {
content: "";
position: absolute;
top: 50%;
left: 5%;
right: 5%;
bottom: 0;
border-radius: 10px;
background: hsl(48, 100%, 20%);
transform: translate(0, -15%) rotate(-4deg);
transform-origin: center center;
box-shadow: 0 0 20px 15px hsl(48, 100%, 20%);
}

So to summarize:

  • The key point of stereo projection is to facilitate pseudo-elements to generate an element with a size similar to the parent element, then rotate and position it to an appropriate position, and then assign shadow operations to it
  • The use of color is also very important. The color of the shadow is usually darker than the color itself. Here, hsl is used to indicate that the color is easier to manipulate, and l controls the brightness of the color.

There are many other scenarios:

CodePen Demo — Stereo projection

Text Stereoscopic Projection / Text Long Shadow

The above three-dimensional effect is completely inapplicable to text, so it is necessary to find another way to deal with the three-dimensional shadow effect of text.

Normally, we use text-shadow to generate text shadows like this:

<div> Txt Shadow</div>
-----
div {
text-shadow: 6px 6px 3px hsla(14, 100%, 30%, 1);
}

Well, it’s good, but it’s not solid enough. So to achieve three-dimensional text shadow, the most common method is to use multi-layer text shadow overlay.

Tips: box-shadowLike , text-shadowyou can stack multiple layers! But for a single element, drop-shadowit can only be one layer.

Well, the above text, let’s try to overlay a 50-layer text shadow. Well, 50 layers of handwriting, actually very fast~

Well, handwriting is really slow and error-prone, so here we need the help of SASS/LESS to write one that generates 50 layers of functionshadows . We offset each 1px to the right and down to generate a layer of text-shadow:

@function makeLongShadow($color) {
$val: 0px 0px $color;

@for $i from 1 through 50 {
$val: #{$val}, #{$i}px #{$i}px #{$color};
}

@return $val;
}

div {
text-shadow: makeLongShadow(hsl(14, 100%, 30%));
}

SCSS code above. After compilation, the following CSS is generated:

div {
text-shadow: 0px 0px #992400, 1px 1px #992400, 2px 2px #992400, 3px 3px #992400, 4px 4px #992400, 5px 5px #992400, 6px 6px #992400, 7px 7px #992400, 8px 8px #992400, 9px 9px #992400, 10px 10px #992400, 11px 11px #992400, 12px 12px #992400, 13px 13px #992400, 14px 14px #992400, 15px 15px #992400, 16px 16px #992400, 17px 17px #992400, 18px 18px #992400, 19px 19px #992400, 20px 20px #992400, 21px 21px #992400, 22px 22px #992400, 23px 23px #992400, 24px 24px #992400, 25px 25px #992400, 26px 26px #992400, 27px 27px #992400, 28px 28px #992400, 29px 29px #992400, 30px 30px #992400, 31px 31px #992400, 32px 32px #992400, 33px 33px #992400, 34px 34px #992400, 35px 35px #992400, 36px 36px #992400, 37px 37px #992400, 38px 38px #992400, 39px 39px #992400, 40px 40px #992400, 41px 41px #992400, 42px 42px #992400, 43px 43px #992400, 44px 44px #992400, 45px 45px #992400, 46px 46px #992400, 47px 47px #992400, 48px 48px #992400, 49px 49px #992400, 50px 50px #992400;
}

Take a look at the effect:

Well, it’s nice, it’s solid. However, it is ugly, and it is unspeakably strange.

Where is the problem? Shadows actually have changes in brightness and transparency. Therefore, for each progressive layer of text shadows, the brightness and transparency should be constantly changing. This requirement, SASS can be well implemented, the following are two SASS color functions:

  • fade-outChange the transparency of the color to make the color more transparent
  • desaturateChange the saturation value of the color to make the color less saturated

For SASS color functions, you can look here: Sass Basics — Color Functions

Let’s use the above two SASS color functions to modify our CSS code, mainly to modify the above makeLongShadowfunction function:

@function makelongrightshadow($color) {
$val: 0px 0px $color;

@for $i from 1 through 50 {
$color: fade-out(desaturate($color, 1%), .02);
$val: #{$val}, #{$i}px #{$i}px #{$color};
}

@return $val;
}

OK, let’s see the final result:

Well, great work, this time the effect is much better.

CodePen Demo — 3D Text Shadow

Of course, there are many ways to use CSS to generate three-dimensional text shadows. Here is another example. The text three-dimensional shadow is realized by using multiple linear gradients with transparent colors and background colors . Interested students can go to see the specific implementation:

Linear gradient with shadow to achieve striped three-dimensional shadow striped word

long projection

The three-dimensional shadow of the text is realized by the multi-layer shadow overlay mentioned above. It is also possible to apply it to containers such as div. Of course there is an interesting method here. Suppose we have a rectangular element and want to add a long projection to it, like this:

To generate this kind of long projection, the superimposed multi-layer shadows just mentioned can be used, and then the two pseudo elements of the element are used. In fact, the above picture is like this:

The key point is that we achieve the effect of long projection by transform: skew()transforming the background color from solid color to transparent color:

CodePen Demo — Linear Gradient Simulates Long Shadows

color projection

Generally speaking, the way we generate shadows is mostly box-shadow, filter: drop-shadow(), text-shadow. However, the shadows they generate are usually only monochromatic or monochromatic.

Is it possible to generate gradient shadows?

Well, of course not.

But by cleverly using the filter: blur, we can pretend to produce gradients or rich shadows.

Imagine a scenario where we have an image as follows:

Let’s use the filter to add a shadow effect similar to the original image color. The core CSS code is as follows:

.avator {
position: relative;
background: url($img) no-repeat center center;
background-size: 100% 100%;

&::after {
content: "";
position: absolute;
top: 10%;
width: 100%;
height: 100%;
background: inherit;
background-size: 100% 100%;
filter: blur(10px) brightness(80%) opacity(.8);
z-index: -1;
}
}

Take a look at the effect:

The simple principle is to use pseudo elements to generate a new image of the same size as the original image and superimpose it under the original image, and then use filter blur to combine filter: blur()with other brightness/contrast, transparency and other filters to create an illusory shadow, Shadow effect disguised as the original image.

Well, that’s the most important code isfilter: blur(10px) brightness(80%) opacity(.8);.

CodePen Demo — filter create shadow

Lighting effect using box-shadow

Well, the above are mainly some methods to achieve various shadows, and the next is the effect article. Let’s first take a look at some of the lighting effects box-shadowachieved .

box-shadow implements neon neon text effect

This effect is also called Neon. There are many similar effects on Codepen, which are essentially superposition of large-scale box-shadowtransition effects and white text:

CodePen Demo — box-shadow implements neon neon text effect

Use box-shadow to achieve shadow light show

Similar to the above effect, it is essentially a transition effect of multiple shadows, maybe a little 3D effect?

Reasonable collocation, better effect:

CodePen Demo — use box-shadow to implement shadow light show

Use drop-shadow | box-shadow to implement single-label vibrato LOGO

Well, since the title is called CSS shadow tricks and details you don’t know, then this article should also be a little tricky.

Let’s look at this first. A single tag implements the TikTok LOGO. Of course, because it is limited to one element, there are still many flaws in the details.

I thought that the reason for the imitation was that I saw this LOGO on a whim when I was using TikTok one day. I wrote a lot of CSS, and I would conditioned reflex when I saw anything. I wondered if this could be achieved with CSS.

Let’s take a look at TikTok LOGO first:

In fact, it is very simple. The main body is actually composed of 3 shapes similar to J with different colors. If one is picked out alone, it can be divided into three-quarter circles , | and .

Exactly, an element plus its two pseudo-elements can just make up these three shapes, we try to achieve the following, the simple CSS code is as follows:

<div></div>
---
div {
position: relative;
width: 37px;
height: 218px;
background: #fff;

&::before {
content: "";
position: absolute;
width: 100px;
height: 100px;
border: 37px solid #fff;
border-top: 37px solid transparent;
border-radius: 50%;
top: 123px;
left: -137px;
transform: rotate(45deg);
}

&::after {
content: "";
position: absolute;
width: 140px;
height: 140px;
border: 30px solid #fff;
border-right: 30px solid transparent;
border-top: 30px solid transparent;
border-left: 30px solid transparent;
top: -100px;
right: -172px;
border-radius: 100%;
transform: rotate(45deg);
}
}

The above code will generate the body of the entire shape:

Next is the turn of the filter: drop-shadow()stage , which can provide some effects for the rendering of the element before the element is rendered, and the most common one is to use it to render the overall shadow. We usually use it to achieve the small triangle of the dialog box and the shadow effect of the entire dialog box. As shown below, the left side is drop-shadowthe , and the right side is the use box-shadowof the normal effect.

This article assumes that the reader has already understood the basic usage of drop-shadow. The effect of the above picture comes from here: CodePen Demo — Drop-shadow vs box-shadow (2) By Kseso

OK, back to our body, below we use filter: drop-shadow()to generate a blue shadow on the left of the first layer of it, added to the body div:

div {
position: relative;
width: 37px;
height: 218px;
background: #fff;
filter:drop-shadow(-10px -10px 0 #24f6f0);

&::before,
&::after {
...
}
}

Get the following effect:

Well, next we just need to add another layer of red filter: drop-shadow()on the right side and you're done!

and many more! What’s wrong, as I mentioned above, like , it can be superimposed on multiple layers! But for a single element, it can only be one layer.box-shadowtext-shadowdrop-shadow

That is to say, it is no longer possible to use on the div to filter: drop-shadow()generate a red shadow on the other side, but fortunately, we still have two pseudo-elements filter: drop-shadow()and box-shadowhave not been used yet, after some attempts:

div {
position: relative;
width: 37px;
height: 218px;
background: #fff;
filter:drop-shadow(-10px -10px 0 #24f6f0) contrast(150%) brightness(110%);
box-shadow: 11.6px 10px 0 0 #fe2d52;

&::before {
....
filter: drop-shadow(16px 0px 0 #fe2d52);
}

&::after {
....
filter:drop-shadow(14px 0 0 #fe2d52);
}
}

We reuse the div box-shadowand two pseudo-elements respectively filter: drop-shadow(). Under the limitation of a single tag, the final result is as follows:

CodePen Demo — TikTok LOGO with a single tag

in conclusion:

  • The overall structure is mainly realized with the help of two pseudo elements, and a layer of overall shadow is generated with the help of drop-shadow
  • drop-shadow can only be a single layer of shadow, so another layer of shadow needs to be tried more
  • contrast(150%) brightness(110%) can enhance the contrast and brightness of the image, closer to the effect of the vibrato LOGO

Updated on 2022–07–09

Regarding the above-mentioned TikTok LOGO, a friend reminded that in fact, it should only be two J-shaped shapes overlapping together, the overlapping part is white, and the non-overlapping part is their respective primary colors.

At first, I thought it was complicated. I tried this effect. It can mix-blend-modealso . The implementation method is given below. Interested students can take a look:

CodePen Demo — Use mix-blend-mode to implement TikTok LOGO

Of course, there are many interesting techniques and details about CSS shadows, which will not be listed in this article due to space limitations.

Wrapping up

More wonderful CSS technical articles are summarized in my Github — iCSS.

Well, this is the end of this article, I hope it helps you :)

--

--