前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >首页文章卡片修改

首页文章卡片修改

作者头像
Akilar
发布2022-04-11 16:48:05
1K0
发布2022-04-11 16:48:05
举报
文章被收录于专栏:Akilarの糖果屋Akilarの糖果屋

更新记录

2022-03-31:内测版v0.08

  1. 应洪哥意见调整了配色。
  2. 虚化图片边界。
  3. 调整a标签作用域,点击标题和描述版块均可跳转文章。
  4. 禁用手机端描述版块点击动作,避免来不及触发快门动画就跳转文章。

2022-03-31:内测版v0.07

  1. 发布预览截图
  2. 编写开发思路
  3. 吐槽贰猹

参考方向

教程原贴

本帖的卡片原设为贰猹提供

Flex布局参数解释

Transition属性实现平滑过渡动画

CSS伪类实现三角形绘制

思路讲解

在很久很久以前,到底有多久呢,我查了下聊天记录,

贰猹和我交流了下他对主题首页卡片的设计想法,效果很不错。原本呢,贰猹是打算等自己学好了前端就把这个卡片写出来的。然后,就这么咕咕咕了一个寒假(其实是被木木抓起来关进小黑屋里写友链朋友圈后端API,写不好不给饭吃)。冰老师在鸽之灵,看到后继有鸽,也会很欣慰吧。 然后我就忍不住了啊,这么优秀的设计,等贰猹写出来我要等到啥时候。二话不说,征求了贰猹的授权以后,咱就开始动手进行试做。

可以看到贰猹的设计里,有用到三角形的结构。然而在div,span这些传统的html元素中,是没有三角形的。最多通过调整border-radius做出圆形。所以这里就要用到border的特性了。

在传统的盒子布局中,border是占用盒子的位置内部位置的。所以,通过调整盒子四条边的border,同时把内部元素的长宽都设为0,就可以拼出三角形。缺点则是border没法设置background-image,没法直接把拼出的三角形当成相框来用。所以就需要用到z-index属性控制卡片层级,通过叠加拼接遮盖的方式,来实现形状的组合。 又因为relative和absolute定位下,元素的长宽属性的所谓100%对应的是不同等级的父级元素。(一个父级,一个祖父级?大概是这样子),总之我硬是用calc方法强行把伪类三角计算到了合适的位置。

编写手机端样式时,在F12界面调试伪类三角平移量的时候,突发奇想,可以用动画写个快门效果,所以最后的作品,手机端摒弃了贰猹原设里的倒三角描述卡片,转为类平行四边形的边框。同时加了悬停显示快门效果的遮罩动画。

我是打算先独享一个月再发布具体教程的,谁知道贰猹咕咕咕信誓旦旦的说给他一个月,早就把我的样式抠出来了。

那就让我们拭目以待吧。反正等他抠出来我再发布教程貌似也没啥问题。

2022 年 4 月 7 日更新。

在尝试找到界面曲面化来实现 3D 效果方案时,看到了 SAO 血条的 2D 实现方案,让我了解到一个新的 CSS 属性,clip-path,它可以通过 polygon 直接剪裁出多边形。非常的好用!而且还支持 animation。比如旧版方案里手机端的那个快门效果。 如果我用伪类实现,代码量是这样的:

然后若我用 clip-path 去实现,代码量是这样的:

差距啊!

我现在只觉得好多好多旧版方案都显得辣眼睛。要大改!侧栏的 SAO 卡片效果要改,直接画出好看的边框,首页的文章卡片要改,反正不能再搞不靠谱的三角形伪类拼接。还有以前写的 SAO 血条,啊,那个项目我是打算废弃了。换成新版友链方案怎么样,左边是一排血条,点击再右边显示好看的角色属性卡片这样子。用 clip-path 的话,血条那个形状已经完全不成问题了的说。哦,对了,还有 twikoo 评论的美化,聊天框这下子好整多了。调整好 margin 直接剪裁。flex 定位的 order 属性也可以用上去。这样自适应一定会好看许多。

好多好多项目要改,这就是技术负债啊。流下了没有技术的泪水。

魔改步骤

预览效果

修改[Blogroot]\themes\butterfly\layout\includes\mixins\post-ui.pug,将整个文件的内容替换为以下代码:

代码语言:javascript
复制
mixin postUI(posts)
  each article , index in page.posts.data
    .recent-post-item
      -
        let link = article.link || article.path
        let title = article.title || _p('no_title')
        const position = theme.cover.position
        let leftOrRight = position === 'both'
          ? index%2 == 0 ? 'left' : 'right'
          : position === 'left' ? 'left' : 'right'
        let post_cover = article.cover
        let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : ''
      -
      .recent-post-content(class=leftOrRight)
        a.article-content(href=url_for(link) title=subtitle)
          //- Display the article introduction on homepage
          case theme.index_post_content.method
            when false
              - break
            when 1
              .article-content-text!= article.description
            when 2
              if article.description
                .article-content-text!= article.description
              else
                - const content = strip_html(article.content)
                - let expert = content.substring(0, theme.index_post_content.length)
                - content.length > theme.index_post_content.length ? expert += ' ...' : ''
                .article-content-text!= expert
            default
              - const content = strip_html(article.content)
              - let expert = content.substring(0, theme.index_post_content.length)
              - content.length > theme.index_post_content.length ? expert += ' ...' : ''
              .article-content-text!= expert
        .recent-post-info
          a.article-title(href=url_for(link) title=subtitle)
            .article-title-link= title
          .recent-post-meta                
            .article-meta-wrap
              if (is_home() && (article.top || article.sticky > 0))
                span.article-meta
                  i.fas.fa-thumbtack.sticky
                  span.sticky= _p('sticky')
                  span.article-meta-separator |
              if (theme.post_meta.page.date_type)
                span.post-meta-date
                  if (theme.post_meta.page.date_type === 'both')
                    i.far.fa-calendar-alt
                    span.article-meta-label=_p('post.created')
                    time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))=date(article.date, config.date_format)
                    span.article-meta-separator |
                    i.fas.fa-history
                    span.article-meta-label=_p('post.updated')
                    time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated))=date(article.updated, config.date_format)
                  else
                    - let data_type_updated = theme.post_meta.page.date_type === 'updated'
                    - let date_type = data_type_updated ? 'updated' : 'date'
                    - let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt'
                    - let date_title = data_type_updated ? _p('post.updated') : _p('post.created')
                    i(class=date_icon)
                    span.article-meta-label=date_title
                    time(datetime=date_xml(article[date_type]) title=date_title + ' ' + full_date(article[date_type]))=date(article[date_type], config.date_format)
              if (theme.post_meta.page.categories && article.categories.data.length > 0)
                span.article-meta
                  span.article-meta-separator |
                  i.fas.fa-inbox
                  each item, index in article.categories.data
                    a(href=url_for(item.path)).article-meta__categories #[=item.name]
                    if (index < article.categories.data.length - 1)
                      i.fas.fa-angle-right.article-meta-link
              if (theme.post_meta.page.tags && article.tags.data.length > 0)
                span.article-meta.tags
                  span.article-meta-separator |
                  i.fas.fa-tag
                  each item, index in article.tags.data
                    a(href=url_for(item.path)).article-meta__tags #[=item.name]
                    if (index < article.tags.data.length - 1)
                      span.article-meta-link #[='•']

              mixin countBlockInIndex
                - needLoadCountJs = true
                span.article-meta
                  span.article-meta-separator |
                  i.fas.fa-comments
                  if block
                    block
                  span.article-meta-label= ' ' + _p('card_post_count')

              if theme.comments.card_post_count
                case theme.comments.use[0]
                  when 'Disqus'
                  when 'Disqusjs'
                    +countBlockInIndex
                      a(href=full_url_for(link) + '#disqus_thread')
                  when 'Valine'
                    +countBlockInIndex
                      a(href=url_for(link) + '#post-comment' itemprop="discussionUrl")
                        span.valine-comment-count(data-xid=url_for(link) itemprop="commentCount")
                  when 'Waline'
                    +countBlockInIndex
                      a(href=url_for(link) + '#post-comment')
                        span.waline-comment-count(id=url_for(link))
                  when 'Twikoo'
                    +countBlockInIndex
                      a.twikoo-count(href=url_for(link) + '#post-comment')
                  when 'Facebook Comments'
                    +countBlockInIndex
                      a(href=url_for(link) + '#post-comment')
                        span.fb-comments-count(data-href=urlNoIndex(article.permalink))
        .recent-post-cover
          img.article-cover(src=url_for(post_cover) onerror=`this.onerror=null;this.src='`+ url_for(theme.error_img.post_page) + `'` alt=subtitle)

    if theme.ad && theme.ad.index
      if (index + 1) % 3 == 0
        .recent-post-item.ads-wrap!=theme.ad.index
  1. 修改[Blogroot]\themes\butterfly\source\css\_page\homepage.styl,将整个文件的内容替换为以下代码:
代码语言:javascript
复制
//default color:
:root
  --recent-post-bgcolor: rgba(255, 255, 255, 0.9)
  --article-content-bgcolor: #49b1f5
  --recent-post-triangle: #fff
  --recent-post-cover-shadow: #ffffff
[data-theme="dark"]
  --recent-post-bgcolor: rgba(35,35,35,0.5)
  --article-content-bgcolor: #99999a
  --recent-post-triangle: #37e2dd
  --recent-post-cover-shadow: #232323
.recent-posts
  padding 0 15px 0 15px

  .recent-post-item
    margin-bottom 15px
    width 100%
    background var(--recent-post-bgcolor)
    overflow hidden
    border-radius 15px
    .recent-post-info
      .article-title-link
        display -webkit-box
        -webkit-box-orient vertical
        -webkit-line-clamp 2
        overflow hidden
    .article-content
      background var(--article-content-bgcolor)
      position relative
      display flex
      align-items: center;
      justify-content: center;
      .article-content-text
        transition: all .8s cubic-bezier(0.59, 0.01, 0.48, 1.17)
        display -webkit-box
        -webkit-box-orient vertical
        -webkit-line-clamp 4
        text-overflow: ellipsis
        overflow hidden
        color #fff
        text-shadow: 1px 2px 3px #000;
    .recent-post-cover
      position relative
      background transparent
      img
        &.article-cover
          height 100%
          width 100%
          object-fit cover

    .recent-post-info
      align-items center
      flex-direction column
      position relative
      background var(--recent-post-bgcolor)
      display flex
      color #000000
      .article-title
        height 50%
        font-size 24px
        display: flex
        align-items: center
        justify-content: flex-end
        flex-direction: column
        .article-title-link
          color: var(--text-highlight-color)
          transition: all .2s ease-in-out
          &:hover
            color: $text-hover
      .recent-post-meta
        height 50%
        display: flex
        align-items: center
        justify-content: flex-start
        flex-direction: column
      .article-meta-wrap
        font-size 12px
        color #969797
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 3;
        overflow: hidden;
        a
          color: var(--text-highlight-color)
          transition: all .2s ease-in-out
          color #969797
          &:hover
            color: $text-hover
    &.ads-wrap
      display: block !important
      height: auto !important
@media screen and (min-width:600px)
  .recent-post-item
    &:hover
      .recent-post-content
        &.both,
        &.right
          transform translateX(21%)
          transition: all .8s cubic-bezier(0.59, 0.01, 0.48, 1.17)
          &::before
            transition: all .8s cubic-bezier(0.59, 0.01, 0.48, 1.17)
            left: 50px;
          .article-content-text
            margin 20px 20px 20px 60px
        &.left
          transform translateX(-21%)
          transition: all .8s cubic-bezier(0.59, 0.01, 0.48, 1.17)
          &::before
            transition: all .8s cubic-bezier(0.59, 0.01, 0.48, 1.17)
            right: 50px;
          .article-content-text
            margin 20px 60px 20px 20px


    .recent-post-content
      background var(--recent-post-bgcolor)
      position relative
      height 200px
      width 130%
      z-index 0
      display flex
      overflow hidden
      border 0px solid
      &::before
        content: "";
        width: 0;
        height: 0;
        background: transparent;
        position: absolute;
        z-index: 3;
        top: calc(50% - 10px);
        border-top: 10px solid transparent;
        border-bottom: 10px solid transparent;
        transition: all .5s cubic-bezier(0.59, 0.01, 0.48, 1.17)
      &.both,
      &.right
        flex-direction: row;
        left calc(-23.07% - 41px)
        transition: all .5s cubic-bezier(0.59, 0.01, 0.48, 1.17)
        &::before
          left: calc(23.07% + 40px);
          border-left: 6px solid var(--recent-post-triangle);
        .recent-post-info
          &::before
            background linear-gradient(to right, var(--recent-post-cover-shadow), transparent)
            left calc(100% - 1px)
        .article-content
          &::before
            right -59px
            border-left 60px solid var(--article-content-bgcolor)
        .article-content-text
          margin 20px 20px 20px 0px
        .article-title
          padding 0px 30px 0px 70px
        .recent-post-meta
          padding 0px 20px 0px 70px
      &.left
        flex-direction: row-reverse;
        right 9px
        transition: all .5s cubic-bezier(0.59, 0.01, 0.48, 1.17)
        &::before
          right: calc(23.07% + 40px);
          border-right: 6px solid var(--recent-post-triangle);
        .recent-post-info
          &::before
            background linear-gradient(to left, var(--recent-post-cover-shadow), transparent)
            right calc(100% - 1px)
        .article-content
          &::before
            left -59px
            border-right 60px solid var(--article-content-bgcolor)
        .article-content-text
          margin 20px 0px 20px 20px
        .article-title
          padding 0px 70px 0px 30px
        .recent-post-meta
          padding 0px 70px 0px 20px

    .article-content
      width 30%
      height 200px
      left 0
      align-items center
      &::before
        content ""
        width 0
        height 0
        background transparent
        position absolute
        z-index 2
        top 0
        border-top 100px solid transparent
        border-bottom 100px solid transparent
    .recent-post-info
      width 60%
      height 200px
      &::before
        content ""
        width 200px
        height 200px
        position absolute
        z-index 1
        top 0
      .recent-post-meta
        & > .article-meta-wrap
          margin: 6px 0
          color: $theme-meta-color
          font-size: 90%

          & > .post-meta-date
            cursor: default

          .sticky
            color: $sticky-color

          i
            margin: 0 4px 0 0

          .article-meta-label
            if hexo-config('post_meta.page.label')
              padding-right: 4px
            else
              display: none

          .article-meta-separator
            margin: 0 6px

          .article-meta-link
            margin: 0 4px

          if hexo-config('post_meta.page.date_format') == 'relative'
            time
              display: none

          a
            color: $theme-meta-color

            &:hover
              color: $text-hover
              text-decoration: underline
    .recent-post-cover
      width 40%
      height 200px
@media screen and (max-width:600px)
  .recent-post-item
    height 400px
    .recent-post-content
      display flex
      flex-direction: column
      height 400px
      .article-content
        pointer-events none
        order: 1;
        height: 200px;
        position: absolute;
        width: calc(100% - 40px);
        z-index: 3;
        background: rgba(22,22,22,0.5);
        border-top-left-radius: 15px;
        border-top-right-radius: 15px;
        display: none
        opacity: 0
        .article-content-text
          height 120px
          color: white;
          width: 80%

      .recent-post-cover
        order: 2
        height 200px
        transition: all .5s
      .recent-post-info
        order: 3
        height 200px
        &::before
          content: '';
          width: 0;
          height: 0;
          position: absolute;
          z-index: 3;
          bottom: calc(100% - 4px);
          left: 0;
          border-bottom: 50px solid var(--recent-post-bgcolor);
          border-right: 300px solid transparent;
        &::after
          content: '';
          width: 0;
          height: 0;
          position: absolute;
          z-index: 3;
          bottom: calc(100% + 150px);
          right: 0;
          border-top: 50px solid var(--recent-post-bgcolor);
          border-left: 300px solid transparent;
        .article-title
          padding: 0px 35px 0px 35px
        .recent-post-meta
          padding: 0px 30px 0px 30px
    &:hover
      .article-content
        display: flex !important;
        animation: shutter-effect-content 0.5s 2 forwards linear
      .recent-post-info
        &::before
          animation: shutter-effect-left 0.5s 1 ease-in-out
        &::after
          animation: shutter-effect-right 0.5s 1 ease-in-out
      .recent-post-cover
        filter blur(2px)
@keyframes shutter-effect-right  {
  0%{
    bottom: calc(100% + 150px);
    border-top: 50px solid var(--recent-post-bgcolor);
    border-left: 300px solid transparent;
  }
  50%{
    bottom: 100%;
    border-top: 200px solid var(--recent-post-bgcolor);
    border-left: 600px solid transparent;
  }
  100%{
    bottom: calc(100% + 150px);
    border-top: 50px solid var(--recent-post-bgcolor);
    border-left: 300px solid transparent;
  }
}
@keyframes shutter-effect-left  {
  0%{
    bottom: calc(100% - 4px);
    border-bottom: 50px solid var(--recent-post-bgcolor);
    border-right: 300px solid transparent;
  }
  50%{
    bottom: calc(100% - 4px);
    border-bottom: 200px solid var(--recent-post-bgcolor);
    border-right: 600px solid transparent;
  }
  100%{
    bottom: calc(100% - 4px);
    border-bottom: 50px solid var(--recent-post-bgcolor);
    border-right: 300px solid transparent;
  }
}
@keyframes shutter-effect-content {
  from {
    opacity: 0
  }
  to {
    opacity: 1
  }
}

注意事项 样式配色因为采用了大量伪类,所以如果底色采用了半透明配色,可能因为卡片叠加加深导致接合边界非常明显的暴露出来。所以在配色上,我是不建议加半透明的。 因为部分伪类的偏移量是靠计算得出的,为了尽量满足自适应效果,部分位置保留了5%左右的容差。所以在一些极端屏宽比下,还是会出现一些样式不完美问题。(处女座不能用可真是遗憾呢

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 思路讲解
  • 魔改步骤
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档