点击查看更新记录

更新记录

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标签本身不是闭合标签,所以没法直接拿它来做盒子,我这里是把它作为一个锚点来使用。和它邻接的元素就能被赋予持续性的样式改动。

1
2
3
4
5
6
7
input.card-widget-visible[type="radio"]
display: none
&:checked
& + div.card-widget
display: block;
.card-widget
display: none;

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

魔改步骤

  1. 用过基于Butterfly的手机端fixed定位侧栏布局魔改方案这篇方案的同学可以先通读下全文,自己判断那个方案更好用一些。如果觉得这个更好,那就把老方案的改动逆向还原一下。
  2. 首先,我们要给侧栏卡片添加一下锚点。在[Blogroot]\themes\butterfly\layout\includes\widget目录下,有很多的card_开头的pug文件那个目录,按照以下格式给他们添加一行锚点。这里主要是input标签的id需要唯一又不能与当前页面的其他id起冲突,保险起见,命名方式就是侧栏卡片的class+anchor或者id+anchor这样的格式。这些锚点的值非常的重要。关系到后面能不能正常选中卡片。所以务必别写错别字。我之前把anchor写成archer,锚点变弓兵,排查了一上午。注意下面只是其中一个示例,建议是每个都按这格式加一遍。当然目录卡片card-toc和两个自定义卡片card_top_selfcard_bottom_self不用加。
    1
    2
    3
      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
  3. 新建[Blogroot]\themes\butterfly\layout\includes\widget\mobile_index.pug,作为手机端的菜单栏。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #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')
  4. 新建[Blogroot]\themes\butterfly\source\css\_custom\fixed_card_widget.styl,写入样式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    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: 40%;
    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 2px 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(-17deg)
    &:nth-child(2)
    transform: rotate(17deg)
    &:nth-child(3)
    transform: rotate(-51deg)
    &:nth-child(4)
    transform: rotate(51deg)
    &:nth-child(5)
    transform: rotate(-85deg)
    &:nth-child(6)
    transform: rotate(85deg)
    .fixedcard-anchor-container
    display: none;
    flex-direction: column;
    align-items: center;
    position relative
    left: -80px
    width: auto
    .fixedcard-anchor-item
    display: flex;
    padding: 0px;
    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: 50px;
    height: 50px;
    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: 130px
    opacity: 1
  5. 然后我们要到[Blogroot]\themes\butterfly\layout\includes\layout.pug中引入一下手机端的菜单,只有当配置项中的aside.mabile为false,也就是手机端默认隐藏侧栏卡片的时候,才启用侧栏卡片显隐按钮。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      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
  6. [Blogroot]\_config.butterfly.yml中添加配置项。注意这里的anchor就是第2步中我们给各个侧栏卡片添加的矛盾的id。icon是fontawesome图标。熟悉魔改的话可以自己试着改成其他图标。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    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的牛角尖,哪种方式实现起来容易就选哪种。维护的事情以后再说咯。