【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

这篇具有很好参考价值的文章主要介绍了【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近,群里聊到了一个很有意思的布局效果。大致效果如下所示,希望使用 CSS 实现如下所示的布局效果:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

正常而言,我们的 HTML 结构大致是如下所示:

<div class="g-container">
    <div class="g-nav">
        <ul>
            <li>Tab 1</li>
            <li>Tab 2</li>
            <li>Tab 3</li>
            <li>Tab 4</li>
        </ul>
    </div>
    <div class="g-main">
        <ul class="g-content">
            <li>...</li>
            <li>...</li>
            <li>...</li>
            <li>...</li>
        </ul>
    </div>
</div>

对于 Hover 导航 Tab 时候的内容切换,暂且不谈。本文,我们核心想探讨的是两个点:

  1. 一是对于如下所示的不规则布局,应该如何实现:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

并且,这里我们可能还需要给它加上阴影效果:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

  1. 如何配合 Hover 动作,实现整个切换效果

带着这两个问题,我们一起来尝试慢慢把这个效果实现。

借助伪元素实现不规则按钮

首先,我们需要实现这个效果:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

这个,其实在很多篇文章都有提及过:

  • 由小见大!不规则造型按钮解决方案
  • 使用 CSS 轻松实现高频出现的各类奇形怪状按钮

想一想,这里其实就是竖向的 Chrome 分 Tab 的效果:

像是这样:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

我们对这个按钮形状拆解一下,这里其实是 3 块的叠加:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

只需要想清楚如何实现两侧的弧形三角即可。这里还是借助了渐变 -- 径向渐变,其实他是这样,如下图所示,我们只需要把黑色部分替换为透明即可,使用两个伪元素即可:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

代码如下:

<div class="outside-circle"></div>
.outside-circle {
    position: relative;
    background: #e91e63;
    border-radius: 10px 10px 0 0;

    &::before {
        content: "";
        position: absolute;
        width: 20px;
        height: 20px;
        left: -20px;
        bottom: 0;
        background: #000;
        background:radial-gradient(circle at 0 0, transparent 20px, #e91e63 21px);
    }
    &::after {
        content: "";
        position: absolute;
        width: 20px;
        height: 20px;
        right: -20px;
        bottom: 0;
        background: #000;
        background:radial-gradient(circle at 100% 0, transparent 20px, #e91e63 21px);
    }
}

即可得到:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

我们照葫芦画瓢,即可非常轻松的实现竖向的相同的效果,示意图如下:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

利用 drop-shadow 实现按钮阴影

好,接下来,我们需要给按钮添加上阴影效果,像是这样:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

因为使用了两个伪元素,当前单个按钮在 Hover 状态下的大致代码如下:


li {
    position: relative;
    width: 160px;
    height: 36px;
    border-radius: 10px 0 0 10px;
    background: #ddd;

    &::before,
    &::after {
        content: "";
        position: absolute;
        right: 0;
        border-radius: unset;
    }

    &::before {
        width: 20px;
        height: 20px;
        top: -20px;
        background: radial-gradient(circle at 0 0, transparent, transparent 19.5px, #ddd 20px, #ddd);
    }
    &::after {
        width: 20px;
        height: 20px;
        bottom: -20px;
        background: radial-gradient(circle at 0 100%, transparent, transparent 19.5px, #ddd 20px, #ddd);
    }
}

如果使用 box-shadow 肯定是不行的,整个效果就会露馅:

尝试给按钮添加一个 box-shadow: 0 0 5px 0 #333

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

弯曲的连接处,明显没有阴影效果,怎么解决呢?

嗯哼,老读者一定也知道,这里我们需要对整个可见部分添加阴影,需要使用 filter:drop-shadow()

drop-shadow() 滤镜的作用用于创建一个符合元素(图像)本身形状(alpha 通道)的阴影。其中,最为常见的技巧,就是利用它生成不规则图形的阴影。

因此,我们把上述的 box-shadow 替换成:filter: drop-shadow(0 0 5px #ddd)

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

这样,我们就实现了基于单个不规则按钮的阴影效果。

但是,显然事情还没有结束。

修改布局结构,再借助利用 drop-shadow 实现统一阴影

记得我们上面提到过的 HTML 的布局吗?正常而言,右侧的主体内容和左侧的导航,结构是分离的:

<div class="g-container">
    <div class="g-nav">
        <ul>
            <li>Tab 1</li>
            // ...
        </ul>
    </div>
    <div class="g-main">
        <ul class="g-content">
            <li>...</li>
            // ...
        </ul>
    </div>
</div>

因此,这里最为麻烦的地方在于,左侧按钮的阴影,需要和右侧的主体内容连在一起!,所以当我们给右侧的 .g-main 也添加上相同的 filter:drop-shadow() 时,整个效果会变得非常奇怪:

// 当前被 Hover 的 li
.g-nav li {
    filter: drop-shadow(0 0 5px #ddd)
}
// 右侧的主体
.g-main {
    filter: drop-shadow(0 0 5px #ddd)
}

无论层级谁在上,整体阴影的展示都会瑕疵:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

所以,如果想要实现整个元素的阴影是一整个的整体的效果,我们就不得不另辟蹊径。

这里,我们的思路如下:

  1. 可以尝试在 .g-main 中,添加一组与 .g-nav 相同的结构,负责样式层面的展示
  2. 把新增的结构,利用绝对定位,让其与实际的导航位置重叠
  3. 在原本的 .g-nav 中,通过 :has() 伪类,传递实时的 Hover 状态

基于此,我们需要改造一下我们的结构:

<div class="g-container">
    <div class="g-nav">
        <ul>
            <li>Tab 1</li>
            <li>Tab 2</li>
            <li>Tab 3</li>
            <li>Tab 4</li>
        </ul>
    </div>
    <div class="g-main">
        <ul class="g-status">
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
        <ul class="g-content">
            <li>...</li>
            // ...
        </ul>
    </div>
</div>

仔细看上面的结构,我们多了一组 .g-stauts 结构,放置在了 .g-main 之下。其 li 个数与实际的导航 .g-nav 保持一致,并且高宽大小都是一模一样的。

并且,可以利用绝对定位,让其完全叠加在 .g-nav 的位置上。

然后,我们把上述类 Chrome Tab 样式的不规则按钮结构的 CSS 代码结构,都赋给 .g-status 下的 li。

此时,由于不规则按钮结构和右侧的主体内容结构,其实是在一个父 div 之下,所以,我们只需要给 .g-main 元素添加 filter: drop-shadow(),就可以实现一整个整体的阴影效果:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

最后,我们利用 :has() 伪类,传递实时的 Hover 状态,把内外的结构连接起来。

最为核心的代码如下:

.g-main {
    background: #ddd;
    filter: drop-shadow(0 0 3px #999);
}
.g-status {
    position:absolute;
    left: -160px;
    top: 0;
    width: 160px;

    li {
        width: 160px;
        height: 36px;
        position: relative;
        background: #ddd;
        opacity:0;

        &::before,
        &::after {
            content: "";
            position: absolute;
            right: 0;
            border-radius: unset;
        }
        &::before {
            width: 20px;
            height: 20px;
            top: -20px;
            background: radial-gradient(circle at 0 0, transparent, transparent 19.5px, #ddd 20px, #ddd);
        }
        &::after {
            width: 20px;
            height: 20px;
            bottom: -20px;
            background: radial-gradient(circle at 0 100%, transparent, transparent 19.5px, #ddd 20px, #ddd);
        }
    }
}
.g-status li {
    opacity: 0;
}
.g-nav:has(li:nth-child(1):hover) + .g-main {
    .g-status li:nth-child(1) {
        opacity: 1;
    }
}
.g-nav:has(li:nth-child(2):hover) + .g-main {
    .g-status li:nth-child(2) {
        opacity: 1;
    }
}
.g-nav:has(li:nth-child(3):hover) + .g-main {
    .g-status li:nth-child(3) {
        opacity: 1;
    }
}
.g-nav:has(li:nth-child(4):hover) + .g-main {
    .g-status li:nth-child(4) {
        opacity: 1;
    }
}

什么意思呢?解释一下:

  1. 事先把每一个 Tab 被 Hover 时的样式,都写在了 .g-stauts 中,并且再提醒一下,这个结构是在 .g-main 之下的。然后,默认设置隐藏即可;
  2. 实际触发 Hover 动画效果,是正常的 .g-nav 下的一个一个的 li 结构;
  3. .g-nav 下的一个一个的 li 被 Hover 时,我们通过 :has() 伪类,能够拿到此事件,并且根据当前是第几个元素被 hover,对应的控制实际在 .g-main 下的结构进行样式的展示;

不太了解的 :has() 伪类的小伙伴,可以先读一读这篇文章 -- 浅谈逻辑选择器 is、where、not、has,此伪类的诞生,填补了在之前 CSS 选择器中,没有父选择器的空缺。让我们能够在父元素节点上,根据子元素的状态变化,做出样式的调整。

这样,我们就最终实现了我们文章一开始的效果:

【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果

文章可能有部分内容没有阐述的很清晰,完整的代码其实行数非常之少,对文章内容还不太理解的建议戳进 DEMO 中看看。

完整的 DEMO 效果:CodePen Demo -- Tab Hover Effect

有小伙伴会有疑问,为什么不直接在 .g-nav 导航结构和 .g-main 结构的父节点直接添加 drop-shadow(),不是也可以实现一样的效果吗?

是的,对于本文贴出的代码效果,是可以实现一样的效果。但是,实际业务中,.g-nav 会更复杂,它们的共同父元素下也可能还有其他元素,实际情况远比本文贴出来的结构复杂,因此借助多一层虚拟 ul,实际上是更好的解法。

最后

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

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

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。文章来源地址https://www.toymoban.com/news/detail-855072.html

到了这里,关于【布局进阶】巧用 :has & drop-shadow 实现复杂布局效果的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 巧用CountDownLatch实现多线程并行工作

    【前言】       CountDownLatch 是JDK提供的一个同步工具,它可以让一个或多个线程挂起等待,一直等到其他线程执行完成才会继续执行。常用方法有 countDown 方法和 await 方法, CountDownLatch 在初始化时,需要指定一个整数n作为计数器。当调用 countDown 方法时,计数器会被减1;

    2024年02月13日
    浏览(43)
  • Windows巧用git实现笔记自动备份

    今天突然发现,可以 使用Gitee加上Windows定时任务 实现Windows端的笔记 自动备份,多端同步,历史回溯 ,效果非常不错。下面介绍一下: 安装git:https://git-scm.com/downloads: 注册并登录gitee,本地生成ssh key(详情百度),然后添加到gitee里: 新建仓库: 填写保存的文件夹名称为

    2024年02月04日
    浏览(33)
  • 巧用网关白名单实现接口免鉴权

    场景描述:一般系统中提供的接口都是经过统一配置鉴权的,比如不登录不能访问。但是,一些接口是需要开放给客户用的,我称作open API。那么这时候你不能要求客户先登录你的接口再去调用吧。那么,这时候就可以通过网关白名单来实现免鉴权 先说思路: 配置网关白名单

    2024年02月14日
    浏览(55)
  • 一文搞懂drag&drop浏览器拖放功能的实现

           拖放功能,即将一个元素从一个区域,通过拖拽,放置到另一个区域。常见的应用是将文件或图片从一个区域,拖放到另一个区域。中文常常把这表述成拖拽,实际上拖拽的描述并不准确,应该叫拖放,因为drag事件和drop事件是成对使用的,即拖拽和放置。        

    2024年04月27日
    浏览(28)
  • 巧用指标平台DataIndex,五步法轻松实现指标管理

    开发部门在做指标加工的全流程中,是否经常出现如下问题: · 业务部门看指标数据的时候,看到两个名称相似的指标,不清楚两个指标的差异性,来咨询开发部门指标计算口径,开发部门配合业务部门翻找代码,找出指标口径差异性,影响工作效率 · 业务部门看指标数据

    2024年02月08日
    浏览(37)
  • 【错误记录】约束布局报错 ( Missing Constraints in ConstraintLayout. This view is not constrained. It only has )

    约束布局中 , 如果不给组件添加约束 , 就会报如下错误 : Design 界面拖动添加约束操作 : 手动拖动 布局上下左右的 约束按钮 , 添加约束 ; Code 代码添加约束 : 在代码中 , 添加 如下 上下左右的 约束 ; app:layout_constraintBottom_toTopOf=“@+id/guideline3” app:layout_constraintEnd_toEndOf=“parent”

    2024年02月08日
    浏览(44)
  • 记录--巧用 overflow-scroll 实现丝滑轮播图

    前言: 近期我在项目中就接到了一个完成轮播图组件的需求。最开始我也像大家一样,直接选择使用了知名的开源项目 \\\"Swiper\\\" ,但是后来发现它在移动端项目中某些测试环境下会白屏一段时间。无论如何调试都不能修复这个问题,于是就自己上手写了个 轮播图 组件,实现代

    2024年02月11日
    浏览(22)
  • 【JUC进阶】03. Java对象头和内存布局

    为了后面更好的学习锁优化以及运作过程,需要我们对HotSpot虚拟机的Java对象内存布局有一定的了解,也作为技术储备。 在HotSpot虚拟机中,对象在堆内存中存储的布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。 而数组对象和普通对

    2024年02月10日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包