Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

巧妙使用多种方式实现单侧阴影 #265

Open
chokcoco opened this issue May 27, 2024 · 0 comments
Open

巧妙使用多种方式实现单侧阴影 #265

chokcoco opened this issue May 27, 2024 · 0 comments

Comments

@chokcoco
Copy link
Owner

chokcoco commented May 27, 2024

最近,在几个不同的群里都遇到有人在问同一个问题,如何使用 CSS 实现如下所示的单侧阴影:

也就是正常而言,阴影应该是出现在多条边上的,而现在,我们只希望阴影固定只能出现在某一侧。

单侧阴影其实是一个非常老生常谈的话题,在 CSS 中之前也有比较巧妙的方式实现。当然,CSS 发展到今天,我们有了更多种不同方式来实现单侧阴影这个需求。本文,我们一共会介绍现阶段,实现单侧阴影可行的三种方式:

  1. 方法一:利用 overflow: hidden 隐藏三边
  2. 方法二:利用 box-shadow 扩张半径可为负值
  3. 方法三:使用 clip-path 实现任意方向上的裁剪

下面我们就一起来看看。

方法一:利用 overflow: hidden 隐藏三边

这个应该是最容易想到的方式了,其思路也非常好理解:

  1. 选定我们需要阴影的那一侧
  2. 另外三侧通过叠加一个容器,通过 overflow: hidden 解决

什么意思呢?通过下面这张示意图,一看就懂:

这样,利用父容器 overflow: hidden 的特性,我们将实际容器的 3 条边与父容器重叠,另外一侧留出足够的空间,这样就成功的实现了单侧投影。

完整的代码也很简单:

<div class="g-overflow"></div>
.g-overflow {
    position: relative;
    width: 200px;
    height: 300px;
    overflow: hidden;
    
    &:before {
        content: "";
        position: absolute;
        inset: 0 0 100px;
        border: 1px solid #000;
        box-shadow: 0 0 6px 2px;
    }
}

效果如下:

方法二:利用 box-shadow 扩张半径可为负值

第二种方法属于经典老方法,也非常有意思。

我们来看看 box-shadow 的用法定义:

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

box-shadow: 2px 4px 6px 8px #000 为例,其中的 4 个数值的含义分别是:

  1. x 方向偏移值;
  2. y 方向偏移值;
  3. 阴影的模糊半径;
  4. 阴影的扩张半径。

这里就需要介绍一个非常有用的技巧:阴影的扩张半径可以为负值

什么意思呢?我们可以设置元素的阴影的模糊半径与它的扩张半径一样,但是,扩张半径为相等的负值。

此时,元素将看不到任何阴影,这是由于生成的阴影将被遮挡在整个元素之下。

基于这种情况,我们只需要再给元素设定任意一个方向的偏移值,即可实现某个方向上的单侧阴影效果:

如此一来,我们看看完整的代码:

<div class="g-shadow"></div>
div {
    width: 200px;
    height: 200px;
    border: 1px solid #000;    
    box-shadow: 0 10px 8px -8px;
}

效果如下:

效果非常不错,当然,此种方式也有非常明显的缺点,就是阴影的大小相对元素而言较小,只能是缩在整个元素的下方。

譬如,我们将上述的阴影修改一些:

div {
  ...
  box-shadow: 0 20px 20px -20px;
}

此时的效果:

我们很难将整个阴影效果,扩散到更大的范围,如果我们想实现下述这么一个单侧阴影:

观察上述的阴影效果,整个阴影的范围和延伸的长度会更大,但是上面的利用扩张半径可为负值的方法就不太适用了,随着阴影的扩张半径这个参数的越来越大,为了匹配对应边的偏移值以及保证阴影不在其它几条边出现,阴影会呈现逐渐向中心收缩的效果。

所以利用扩张半径可为负值的方法,一般只适用于幅度较为浅的单侧阴影效果。

方法三:使用 clip-path 实现任意方向上的裁剪

还有一种非常有趣的奇技淫巧。

我们都知道,clip-path 可以实现对容器区域的裁剪。

MDN - clip-path:属性使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的隐藏。

大部分人都知道,可以使用 clip-path 在元素内部进行裁剪,譬如:

而大部分人可能不知道的是,我们还可以利用 clip-path 在元素的外部进行裁剪。利用这个技巧,我们也可以轻松的得到单侧阴影。

什么意思呢?看看下面的示意图你就明白了:

其中上图红框部分,就是 clip-path 代码发力的地方,它大概是这样:clip-path: polygon(0 0, 100% 0, 100% 200%, 0 200%);,元素区域外预留足够的空间,裁剪成一个矩形即可。

完整的代码如下:

<div class="g-clippath"></div>
.g-clippath {
    position: relative;
    width: 200px;
    height: 200px;
    border: 1px solid #000;    

    &::before {
        content: "";
        position: absolute;
        inset: 0;
        box-shadow: 0 0 6px 3px;
        clip-path: polygon(0 0, 100% 0, 100% 200%, 0 200%);
    }
}

效果如下:

此方式和上述第一种方式类似,但是场景会更加灵活。

上述三种方式,完整的代码及 DEMO 如下:CodePen Demo - Pure CSS 实现单侧阴影的多种方式

最后

总结一下,本文我们介绍了三种实现单侧阴影的方式:

  1. 方法一:利用 overflow: hidden 隐藏三边
  2. 方法二:利用 box-shadow 扩张半径可为负值
  3. 方法三:使用 clip-path 实现任意方向上的裁剪

这三种方式它们各有优缺点,实际使用的时候可以根据场景灵活考虑。当然,对于固定无动画、过渡交互的场景,遇到类似的单侧阴影效果,切图也不失为一种好的选择。

好了,本文到此结束,希望本文对你有所帮助 :)

想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 -- iCSS前端趣闻 😄

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

@chokcoco chokcoco changed the title 多种方式实现单侧阴影 巧妙使用多种方式实现单侧阴影 May 29, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

1 participant