更新记录
2023-02-06:原理阐述
- 使用纯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_self
、card_bottom_self
不用加。
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
,作为手机端的菜单栏。
#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
,写入样式
//选项菜单
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,也就是手机端默认隐藏侧栏卡片的时候,才启用侧栏卡片显隐按钮。
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图标。熟悉魔改的话可以自己试着改成其他图标。
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的牛角尖,哪种方式实现起来容易就选哪种。维护的事情以后再说咯。