国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Table of Contents
Catalog
Non-transparent solution
Summary
Home Web Front-end CSS Tutorial Different Ways to Get CSS Gradient Shadows

Different Ways to Get CSS Gradient Shadows

Mar 09, 2025 am 10:03 AM

Different Ways to Get CSS Gradient Shadows

I often ask a question: Can I create shadows with gradient colors instead of solid colors? There are no special properties in CSS to achieve this (believe me, I've looked for it), and any blog posts you find about this are basically some similar gradient CSS tricks. We'll cover some of these tips next.

But first...is another article about gradient shadows? Really?

Yes, this is another post on this topic, but it's different. Together, we will push the limits and find a solution that covers something I have never seen anywhere else: Transparency. Most tips work when elements have non-transparent backgrounds, but what if we have transparent backgrounds? We will discuss this situation here!

Before we get started, let me introduce my gradient shadow generator. You just need to adjust the configuration and you can get the code. But keep reading because I will help you understand all the logic behind generating the code.

Catalog

  • Non-transparent solution
  • Transparent Solution
  • Add rounded corners
  • Summary

Non-transparent solution

Let's start with solutions that work for 80% of common situations. The most typical case is that you are using an element with a background and you need to add a gradient shadow to it. There is no need to consider transparency here.

The solution is to rely on a pseudo-element that defines the gradient. You put it behind the actual element and apply a blur filter to it.

<code>.box {
  position: relative;
}
.box::before {
  content: "";
  position: absolute;
  inset: -5px; /* 控制擴(kuò)散 */
  transform: translate(10px, 8px); /* 控制偏移量 */
  z-index: -1; /* 將元素置于后面 */
  background: /* 你的漸變色在這里 */;
  filter: blur(10px); /* 控制模糊 */
}</code>

The code looks a lot, because it does have a lot. Here's how to use box-shadow instead of a gradient if we use solid colors instead of gradients.

<code>box-shadow: 10px 8px 10px 5px orange;</code>

This should give you a good idea of ??what the value in the first piece of code does. We have X and Y offsets, fuzzy radius, and diffusion distance. Note that we need a negative diffusion distance value from the inset property.

This is a demo showing gradient shadows side by side with classic box-shadow:

If you look closely, you will notice that the two shadows are slightly different, especially the blurred parts. This is not surprising, because I'm pretty sure the algorithm for filter attributes is different from that of box-shadow. It's no big deal, because the end result is very similar.

This solution is good, but still has some disadvantages related to the z-index:-1 declaration. Yes, there is a "stack context" happening there!

I applied a transformation to the main element, and then the shadow is no longer below the element. This is not a mistake, but a logical result of stacking contexts. Don't worry, I won't start giving boring explanations of stacking contexts (I've done this in Stack Overflow threads), but I'll still show you how to fix it.

The first solution I recommend is to use 3D conversion:

<code>.box {
  position: relative;
}
.box::before {
  content: "";
  position: absolute;
  inset: -5px; /* 控制擴(kuò)散 */
  transform: translate(10px, 8px); /* 控制偏移量 */
  z-index: -1; /* 將元素置于后面 */
  background: /* 你的漸變色在這里 */;
  filter: blur(10px); /* 控制模糊 */
}</code>

We do not use z-index: -1, but use a negative translation along the Z axis. We put everything in translate3d(). Don't forget to use transform-style: preserve-3d on the main element; otherwise, the 3D conversion will not take effect.

As far as I know, this solution has no side effects...but maybe you will see one. If so, please share in the comment section and let's try to find a solution!

If for some reason you can't use 3D conversion, another solution is to rely on two pseudo-elements—::before and::after. One creates a gradient shadow, the other copys the main background (and other styles you might need). This way, we can easily control the stacking order of two pseudo-elements.

<code>box-shadow: 10px 8px 10px 5px orange;</code>

It is important to note that we are forcing the to create a stacking context by declaring z-index: 0 on it or any other attribute that does the same. Also, don't forget that the pseudo-element treats the fill box of the main element as a reference. Therefore, if the main element has borders, this needs to be considered when defining the pseudo-element style. You will notice that I use inset: -2px on ::after to consider borders defined on main elements.

As I said, this solution may be good enough in most cases as long as you don't need to support transparency, you want a gradient shadow. But we came to challenge and push the limits, so even if you don’t need what you want to talk about next, please keep paying attention. You may learn new CSS tips that you can use elsewhere.

Transparent Solution

Let's start where we end in 3D transformation and remove the background from the main element. I will start with a shadow where both the offset and diffusion distance are equal to 0.

The idea is to find a way to crop or hide everything inside an area of ??the element (within a green border) while retaining the external content. We will use clip-path for this. But you might be wondering how clip-path can be cropped inside an element

. Indeed, there is no way to do this, but we can simulate it with a specific polygon pattern:

Look! We get a gradient shadow that supports transparency. All we did was add a clip-path to the previous code. Here is a diagram to illustrate the polygon part.
<code>.box {
  position: relative;
  transform-style: preserve-3d;
}
.box::before {
  content: "";
  position: absolute;
  inset: -5px;
  transform: translate3d(10px, 8px, -1px); /* (X, Y, Z) */
  background: /* .. */;
  filter: blur(10px);
}</code>

The blue area is the part that is visible after applying the clip-path. I only use blue to illustrate the concept, but in reality, we only see shadows within the area. As you can see, we define four points, and their values ??are very large (B). My big value is 100vmax, but it can be whatever big value you want. The idea is to make sure we have enough shadow space. We have four more points that are the corner points of the pseudo-element.

Arrows indicate the path that defines the polygon. We start from (-B, -B) and until we reach (0,0). In total, we need 10 points. Not 8 points, because the two points ((-B,-B) and (0,0)) are repeated twice in the path.

We also need to do the last thing , which is to consider the diffusion distance and the offset. The above demonstration works simply because this is a special case, both the offset and diffusion distance are equal to 0.

Let's define diffusion and see what happens. Remember, we use negative value inset to do this:

The pseudo-element is now larger than the main element, so the clip-path clip is more than we need. Remember, we always need to crop the part of the main element

inside (the area inside the green border in the example). We need to adjust the position of the four points in the clip-path.

<code>.box {
  position: relative;
}
.box::before {
  content: "";
  position: absolute;
  inset: -5px; /* 控制擴(kuò)散 */
  transform: translate(10px, 8px); /* 控制偏移量 */
  z-index: -1; /* 將元素置于后面 */
  background: /* 你的漸變色在這里 */;
  filter: blur(10px); /* 控制模糊 */
}</code>
We defined a CSS variable --s for diffusion distance and updated the polygon points. I didn't touch where I used the big value. I only update the points that define the angle of the pseudo-element. I increase all zero values ??--s and reduce 100% of the values ??--s.

The offset is the same logic. When we convert pseudo-elements, the shadows are misaligned and we need to correct the polygon again and move the points to the opposite direction.

<code>box-shadow: 10px 8px 10px 5px orange;</code>
There are two more variables for offsets: --x and --y. We use them inside transform and we also updated the clip-path value. We still don't touch polygon points with large values, but we offset all other points - we reduce --x from X coordinates, and --y from Y coordinates.

Now we only need to update some variables to control the gradient shadow. When we do this, let's also turn the fuzzy radius into a variable:

Do we still need 3D conversion skills?

It all depends on the border. Don't forget that the reference for pseudo-elements is the fill box, so if you apply borders to the main element, you will have overlap. You can keep the 3D conversion trick or update the inset value to consider borders.

This is the version used to replace 3D conversion with the updated inset value in the previous demonstration:

I think this is a more appropriate approach, because the diffusion distance will be more accurate, as it starts with border-box instead of padding-box. But you need to adjust the inset value according to the border of the main element. Sometimes the border of the element is unknown and you have to use the previous solution.

Using the previous non-transparent solution, you may encounter stacking context issues. With transparent solutions, you may encounter border issues. Now you have options and ways to solve these problems. 3D conversion trick is my favorite solution as it fixes all issues (online generators will consider it too)

Add rounded corners

If you try to add border-radius to elements when using the non-transparent solution we started, this is a fairly simple task. You just need to inherit the same value from the main element and you're done.

Defining border-radius: inherit is a good idea even if you don't have rounded corners. This considers any potential rounded corners you may want to add in the future or rounded corners from elsewhere.

The situation of dealing with transparent solutions is different. Unfortunately, this means finding another solution because clip-path cannot handle the curve. This means we will not be able to crop the area inside the main element.

We add the mask attribute to the blend.

This part is very tedious and I have a hard time finding a general solution that does not rely on magic numbers. I ended up with a very complex solution that only uses one pseudo-element, but the code is a mess and covers only some specific situations. I don't think it's worth exploring this path.

To simplify the code, I decided to insert an extra element. The following are the marks:

<code>.box {
  position: relative;
}
.box::before {
  content: "";
  position: absolute;
  inset: -5px; /* 控制擴(kuò)散 */
  transform: translate(10px, 8px); /* 控制偏移量 */
  z-index: -1; /* 將元素置于后面 */
  background: /* 你的漸變色在這里 */;
  filter: blur(10px); /* 控制模糊 */
}</code>

I use custom element to avoid any potential conflicts with external CSS. I can use

, but because it is a common element, it's easy to be positioned by another CSS rule from elsewhere, which can break our code. The first step is to locate the element and deliberately create the overflow:
<code>box-shadow: 10px 8px 10px 5px orange;</code>

The code may look a little strange, but we will explain the logic behind it step by step. Next, we use the pseudo-element of to create a gradient shadow.

<code>.box {
  position: relative;
  transform-style: preserve-3d;
}
.box::before {
  content: "";
  position: absolute;
  inset: -5px;
  transform: translate3d(10px, 8px, -1px); /* (X, Y, Z) */
  background: /* .. */;
  filter: blur(10px);
}</code>

As you can see, the pseudo-element uses the same code as all previous examples. The only difference is that the 3D transformation is defined on the element, not on the pseudo-element. Currently, we have a gradient shadow without transparency function:

Please note that the area of ??the element is defined with a black outline. Why do I do this? Because of this, I can apply a mask on it to hide the parts inside the green area and keep the overflowing part where we need to see the shadow.

I know this is a bit tricky, but unlike clip-path, the mask attribute does not take into account the area of ??the element outside to show and hide the content. That's why I had to introduce extra elements – to simulate the "outer" area.

Also, note that I'm using a combination of borders and inset to define the area. This allows me to keep the padding-box of the extra element the same as the main element so that the pseudo-element does not require additional calculations.

Another useful thing that gets from using extra elements is that the elements are fixed and only the pseudo-elements are moving (using translate). This will allow me to easily define the mask, which is the last step of this trick.

Completed! We have gradient shadows, and it supports border-radius! You might expect a complex mask value with lots of gradients inside, but not! We only need two simple gradients and a mask-composite to complete the magic.
<code>.box {
  position: relative;
  z-index: 0; /* 我們強(qiáng)制創(chuàng)建一個堆疊上下文 */
}
/* 創(chuàng)建陰影 */
.box::before {
  content: "";
  position: absolute;
  z-index: -2;
  inset: -5px;
  transform: translate(10px, 8px);
  background: /* .. */;
  filter: blur(10px);
}
/* 復(fù)制主元素樣式 */
.box::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  /* 繼承在主元素上定義的所有裝飾 */
  background: inherit;
  border: inherit;
  box-shadow: inherit;
}</code>

Let's isolate the

element to understand what's going on there:

The following are the results we got:
<code>clip-path: polygon(-100vmax -100vmax,100vmax -100vmax,100vmax 100vmax,-100vmax 100vmax,-100vmax -100vmax,0 0,0 100%,100% 100%,100% 0,0 0)</code>

Notice how the internal radius matches the border-radius of the main element. I defined a large border (150px) and a border-radius equal to the large border

plus

main element radius. Externally, I have a radius equal to 150px R. Internally, I have 150px R - 150px = R. We have to hide the inner (blue) part and make sure the border (red) part is still visible. To do this, I defined two mask layers - one covering only the content-box area and the other covering the border-box area (default). I then exclude one from the other to show the border.

<code>.box {
  position: relative;
}
.box::before {
  content: "";
  position: absolute;
  inset: -5px; /* 控制擴(kuò)散 */
  transform: translate(10px, 8px); /* 控制偏移量 */
  z-index: -1; /* 將元素置于后面 */
  background: /* 你的漸變色在這里 */;
  filter: blur(10px); /* 控制模糊 */
}</code>

I use the same technique to create borders that support gradients and border-radius. Ana Tudor also has a good article about mask compounding, and I invite you to read it.

Are there any disadvantages of this method?

Yes, this is definitely not perfect. The first problem you may encounter is related to using borders on the main element. If you don't consider it, this can lead to a slight misalignment of the radius. This problem exists in our example, but you may have a hard time noticing it.

Fixed relatively easy: add border width to the inset of the element.

<code>box-shadow: 10px 8px 10px 5px orange;</code>

Another disadvantage is the large value we use for borders (150px in the example). This value should be large enough to contain shadows, but not too large to avoid overflow and scrollbar issues. Fortunately, the online generator will take all parameters into account to calculate the optimal value.

The last drawback I realize is when you use complex border-radius. For example, if you want to apply a different radius to each corner, you have to define a variable for each side. This is not a real drawback, I think, but it may make your code a little harder to maintain.

<code>.box {
  position: relative;
  transform-style: preserve-3d;
}
.box::before {
  content: "";
  position: absolute;
  inset: -5px;
  transform: translate3d(10px, 8px, -1px); /* (X, Y, Z) */
  background: /* .. */;
  filter: blur(10px);
}</code>

For simplicity, the online generator only considers a uniform radius, but you now know how to modify the code if you want to consider complex radius configurations.

Summary

We have reached the end! The magic behind the gradient shadow is no longer a mystery. I'm trying to cover all possibilities and any issues you might have. If I missed something or you found any issues, feel free to report it in the comments section and I will check it out.

Again, considering that the de facto solution will cover most of your use cases, many of these may be redundant. However, it is good to understand the “why” and “how” behind the technique and how to overcome its limitations. Also, we got a great practice in playing CSS editing and matte.

Of course, you can always use the online generator to avoid trouble.

The above is the detailed content of Different Ways to Get CSS Gradient Shadows. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

What is 'render-blocking CSS'? What is 'render-blocking CSS'? Jun 24, 2025 am 12:42 AM

CSS blocks page rendering because browsers view inline and external CSS as key resources by default, especially with imported stylesheets, header large amounts of inline CSS, and unoptimized media query styles. 1. Extract critical CSS and embed it into HTML; 2. Delay loading non-critical CSS through JavaScript; 3. Use media attributes to optimize loading such as print styles; 4. Compress and merge CSS to reduce requests. It is recommended to use tools to extract key CSS, combine rel="preload" asynchronous loading, and use media delayed loading reasonably to avoid excessive splitting and complex script control.

External vs. Internal CSS: What's the Best Approach? External vs. Internal CSS: What's the Best Approach? Jun 20, 2025 am 12:45 AM

ThebestapproachforCSSdependsontheproject'sspecificneeds.Forlargerprojects,externalCSSisbetterduetomaintainabilityandreusability;forsmallerprojectsorsingle-pageapplications,internalCSSmightbemoresuitable.It'scrucialtobalanceprojectsize,performanceneed

Does my CSS must be on lower case? Does my CSS must be on lower case? Jun 19, 2025 am 12:29 AM

No,CSSdoesnothavetobeinlowercase.However,usinglowercaseisrecommendedfor:1)Consistencyandreadability,2)Avoidingerrorsinrelatedtechnologies,3)Potentialperformancebenefits,and4)Improvedcollaborationwithinteams.

CSS Case Sensitivity: Understanding What Matters CSS Case Sensitivity: Understanding What Matters Jun 20, 2025 am 12:09 AM

CSSismostlycase-insensitive,butURLsandfontfamilynamesarecase-sensitive.1)Propertiesandvalueslikecolor:red;arenotcase-sensitive.2)URLsmustmatchtheserver'scase,e.g.,/images/Logo.png.3)Fontfamilynameslike'OpenSans'mustbeexact.

What is Autoprefixer and how does it work? What is Autoprefixer and how does it work? Jul 02, 2025 am 01:15 AM

Autoprefixer is a tool that automatically adds vendor prefixes to CSS attributes based on the target browser scope. 1. It solves the problem of manually maintaining prefixes with errors; 2. Work through the PostCSS plug-in form, parse CSS, analyze attributes that need to be prefixed, and generate code according to configuration; 3. The usage steps include installing plug-ins, setting browserslist, and enabling them in the build process; 4. Notes include not manually adding prefixes, keeping configuration updates, prefixes not all attributes, and it is recommended to use them with the preprocessor.

What are CSS counters? What are CSS counters? Jun 19, 2025 am 12:34 AM

CSScounterscanautomaticallynumbersectionsandlists.1)Usecounter-resettoinitialize,counter-incrementtoincrease,andcounter()orcounters()todisplayvalues.2)CombinewithJavaScriptfordynamiccontenttoensureaccurateupdates.

CSS: When Does Case Matter (and When Doesn't)? CSS: When Does Case Matter (and When Doesn't)? Jun 19, 2025 am 12:27 AM

In CSS, selector and attribute names are case-sensitive, while values, named colors, URLs, and custom attributes are case-sensitive. 1. The selector and attribute names are case-insensitive, such as background-color and background-Color are the same. 2. The hexadecimal color in the value is case-sensitive, but the named color is case-sensitive, such as red and Red is invalid. 3. URLs are case sensitive and may cause file loading problems. 4. Custom properties (variables) are case sensitive, and you need to pay attention to the consistency of case when using them.

What is the conic-gradient() function? What is the conic-gradient() function? Jul 01, 2025 am 01:16 AM

Theconic-gradient()functioninCSScreatescirculargradientsthatrotatecolorstopsaroundacentralpoint.1.Itisidealforpiecharts,progressindicators,colorwheels,anddecorativebackgrounds.2.Itworksbydefiningcolorstopsatspecificangles,optionallystartingfromadefin

See all articles