纯CSS实现侧栏卡片显隐

2023-03-08 21:52:17 浏览数 (1)

更新记录

2023-02-06:原理阐述

  1. 使用纯CSS实现侧栏显隐按钮

点击查看参考教程

参考方向

教程原贴

详细了解label的特性

MDN web docs-label

原理讲解

以前我有写过一篇基于Butterfly的手机端fixed定位侧栏布局魔改方案,抛开被洪哥忽悠而起的这么长的标题不谈,在这篇中是通过编写一个手机端fixed定位的样式,并通过js监测到对应的点击动作后,给相应的侧栏卡片添加上这个样式。同时也是通过js不断的进行样式初始化和class的增减。

最近一直在看一些纯CSS的项目,我了解到可以通过input中的单选框radio或者多选框checkbox的checked状态搭配兄弟选择器和相邻选择器例如 h1 p {margin-top:50px;},实现持续性的样式变换。以下就是一个简单的示例,input标签本身不是闭合标签,所以没法直接拿它来做盒子,我这里是把它作为一个锚点来使用。和它邻接的元素就能被赋予持续性的样式改动。

代码语言:javascript复制
input.card-widget-visible[type="radio"]
  display: none
  &:checked
    &   div.card-widget
      display: block;
.card-widget
  display: none;

不管是依赖纯css还是靠js,都能实现效果。从实现来看,js更加的方便。而css的逻辑更加直白,比如点了一个侧栏就关了已经打开的另一个侧栏,在处理这种互斥性很强的逻辑时,通过input标签中的radio单选框来实现无疑会是一个很省心的方案。

魔改步骤

用过基于Butterfly的手机端fixed定位侧栏布局魔改方案这篇方案的同学可以先通读下全文,自己判断那个方案更好用一些。如果觉得这个更好,那就把老方案的改动逆向还原一下。

首先,我们要给侧栏卡片添加一下锚点。在[Blogroot]themesbutterflylayoutincludeswidget目录下,有很多的card_开头的pug文件那个目录,按照以下格式给他们添加一行锚点。这里主要是input标签的id需要唯一又不能与当前页面的其他id起冲突,保险起见,命名方式就是侧栏卡片的class anchor或者id anchor这样的格式。这些锚点的值非常的重要。关系到后面能不能正常选中卡片。所以务必别写错别字。我之前把anchor写成archer,锚点变弓兵,排查了一上午。注意下面只是其中一个示例,建议是每个都按这格式加一遍。当然目录卡片card-toc和两个自定义卡片card_top_selfcard_bottom_self不用加。

代码语言:javascript复制
  if theme.aside.card_author.enable
    input#card-info-anchor.card-widget-visible(type="radio" name="card-widget-visible" value="card-info")
    .card-widget.card-info

新建[Blogroot]themesbutterflylayoutincludeswidgetmobile_index.pug,作为手机端的菜单栏。

代码语言:javascript复制
#fixed-cardwidget-dashboard
  input#dashboard-anchor.card-widget-visible(type="radio" name="card-widget-visible" value="dashboard")
  //- 侧栏吸附按钮,悬停时显示圆球,点击展开
  label.fixed-cardwidget-hover-button(for='dashboard-anchor')  
  //- 侧栏版块显隐控制按钮
  .fixedcard-anchor-container
    //- post
    if is_post()
      each postitem in theme.fixed_card_widget.post
        .fixedcard-anchor-item
          label.card-widget-visible(title=postitem.title for=postitem.anchor)
            i(class=postitem.icon)
    else
      each pageitem in theme.fixed_card_widget.page
        .fixedcard-anchor-item
          label.card-widget-visible(title=pageitem.title for=pageitem.anchor)
            i(class=pageitem.icon) 

//- 默认启用关闭按钮
input#quit-anchor.card-widget-visible(type="radio" name="card-widget-visible" value="quit" checked)
//- 关闭版块背景蒙版
label.quit-visible(for='quit-anchor')

新建[Blogroot]themesbutterflysourcecss_customfixed_card_widget.styl,写入样式

代码语言:javascript复制
//选项菜单
input.card-widget-visible[type="radio"]
  display: none
  &:checked
    &   div.card-widget
      visibility visible!important
      display block!important
      position fixed!important
      bottom 0
      left 0
      top 0
      right 0
      margin auto
      margin-bottom auto!important
      margin-top auto!important
      max-width 300px
      max-height 500px
      width auto
      height: fit-content
      z-index: 22
      animation cardVisible 0.3s linear forwards!important
      & > div
        max-height 460px
        overflow scroll
        &::-webkit-scrollbar
          display: none
// 宽屏状态下不显示侧栏显隐控制按钮
@media screen and (min-width: 900px)
  #fixed-cardwidget-dashboard
    display:none;
  label.quit-visible
    display: none;
// 侧栏显隐控制按钮仅在手机端可见
@media screen and (max-width: 900px)
  #fixed-cardwidget-dashboard
    position: fixed
    display: flex
    background: transparent
    left: 0;
    top: 200px;
    flex-direction: row;
    align-items: flex-start;
    padding: 5px 50px 10px 0px;
    z-index: 21;
    *
      transition: all 0.3s ease-in-out
    &:hover label.fixed-cardwidget-hover-button,
    input#dashboard-anchor:checked ~ .fixed-cardwidget-hover-button
      border-radius: 50%
      width: w = 50px;
      height w
      border: 10px solid rgba(255,255,255,0.2);
      background: rgba(255,255,255,0.5);
      box-shadow: 0 0 15px inset rgba(0,0,0,0.8)
    label.fixed-cardwidget-hover-button
      display: block
      background: rgba(255,255,255,0.5)
      height: 50px;
      width: 6px;
      border-radius: 3px;
    input#dashboard-anchor
      display: none
      &:checked
        & ~ .fixedcard-anchor-container
          display: flex;
          .fixedcard-anchor-item
            animation buttonVisible 0.3s ease-in forwards
            &:nth-child(1)
              transform: rotate(-15deg)
            &:nth-child(2)
              transform: rotate(15deg)
            &:nth-child(3)
              transform: rotate(-45deg)
            &:nth-child(4)
              transform: rotate(45deg)
            &:nth-child(5)
              transform: rotate(-75deg)
            &:nth-child(6)
              transform: rotate(75deg)
    .fixedcard-anchor-container
      display: none;
      flex-direction: column;
      align-items: center;
      position relative
      left: -80px
      .fixedcard-anchor-item
        display: flex;
        padding: 10px;
        height: 50px;
        align-items: center;
        justify-content: flex-end;
        position: absolute;
        left: 50px;
        top: 0
        transform-origin: left;
        label.card-widget-visible
          display: flex;
          padding: 10px;
          width: 30px;
          height: 30px;
          align-items: center;
          justify-content: center;
          color: rgba(0,0,0,0.8);
          background: rgba(255,255,255,0.5)
          border-radius: 50%

input#quit-anchor
  display: none
  &:checked
    &  label.quit-visible
      display: none
label.quit-visible
  display: block
  position fixed
  z-index: 20;
  top: 0;
  left: 0;
  height: 100vh
  width: 100vw
  background: rgba(0,0,0,0.3)
  backdrop-filter: blur(5px)

// 卡片开启动画效果
@keyframes cardVisible
  from
    transform rotateX(90deg)
  to
    transform rotateX(0deg)
//- 按钮展开动画
@keyframes buttonVisible
  from
    width 0
    opacity: 0
  to
    width: 100px
    opacity: 1

然后我们要到[Blogroot]themesbutterflylayoutincludeslayout.pug中引入一下手机端的菜单,只有当配置项中的aside.mabile为false,也就是手机端默认隐藏侧栏卡片的时候,才启用侧栏卡片显隐按钮。

代码语言:javascript复制
  main#content-inner.layout(class=hideAside)
    if body
      div!= body
    else
      block content
      if theme.aside.enable && page.aside !== false
        include widget/index.pug
      //- 当侧栏开启但是手机端关闭时,引入手机端伸缩侧栏
      if theme.aside.enable && page.aside !== false && !theme.aside.mobile
        include widget/mobile_index.pug

[Blogroot]_config.butterfly.yml中添加配置项。注意这里的anchor就是第2步中我们给各个侧栏卡片添加的矛盾的id。icon是fontawesome图标。熟悉魔改的话可以自己试着改成其他图标。

代码语言:javascript复制
fixed_card_widget:
  enable: true
  page:
    - anchor: card-author-anchor
      icon: fa-solid fa-circle-user
      title: 用户信息
    - anchor: card-friend-link-anchor
      icon: far fa-address-book
      title: 通讯录
    - anchor: card-recent-post-anchor
      icon: fas fa-history
      title: 最新文章
    - anchor: card-newest-comments-anchor
      icon: fas fa-comment-dots
      title: 最新评论
    - anchor: card-tags-anchor
      icon: fas fa-tags
      title: 标签
    - anchor: card-webinfo-anchor
      icon: fas fa-chart-line
      title: 网站资讯
  post:
    - anchor: card-author-anchor
      icon: fas fa-address-book
      title: 用户信息
    - anchor: card-recommend-post-anchor
      icon: fas fa-dharmachakra
      title: 相关推荐

后记

这篇的内容本质上是我想和大家分享一下靠纯css实现持续性效果的变换。所以可以发散思维一下,这个是不是还能用在其他地方。比如可以写一个文件夹标签,点击以后显示文件夹打开,这个可以靠checkbox。而且要注意,input的id必须是唯一的,但是label的for可没要求要唯一。你可以写很多个label,for向同一个input。这样的话就可以复用控制按钮。思路的扩展很重要。

当然也不要像我一样钻纯css的牛角尖,哪种方式实现起来容易就选哪种。维护的事情以后再说咯。

0 人点赞